From bc13c702f3f672d52072d7abf301ccedb63b70e2 Mon Sep 17 00:00:00 2001 From: Darksome Date: Wed, 7 May 2025 09:16:51 +0000 Subject: [PATCH 01/79] WIP --- .gitignore | 3 + Cargo.lock | 4 + contracts/foundry.toml | 9 + contracts/remappings.txt | 1 + contracts/soldeer.lock | 6 + contracts/src/Cluster/Cluster.sol | 159 ++++++++++++++++ contracts/src/Cluster/Maintenance.sol | 24 +++ contracts/src/Cluster/Migration.sol | 75 ++++++++ contracts/src/Cluster/NodeOperators.sol | 75 ++++++++ contracts/src/Cluster/Nodes.sol | 44 +++++ contracts/test/Suite.sol | 110 ++++++++++++ crates/contract/Cargo.toml | 9 + crates/contract/src/lib.rs | 230 ++++++++++++++++++++++++ crates/contract/src/network.sol | 1 + flake.lock | 6 +- flake.nix | 6 +- 16 files changed, 756 insertions(+), 6 deletions(-) create mode 100644 contracts/foundry.toml create mode 100644 contracts/remappings.txt create mode 100644 contracts/soldeer.lock create mode 100644 contracts/src/Cluster/Cluster.sol create mode 100644 contracts/src/Cluster/Maintenance.sol create mode 100644 contracts/src/Cluster/Migration.sol create mode 100644 contracts/src/Cluster/NodeOperators.sol create mode 100644 contracts/src/Cluster/Nodes.sol create mode 100644 contracts/test/Suite.sol create mode 100644 crates/contract/Cargo.toml create mode 100644 crates/contract/src/lib.rs create mode 100644 crates/contract/src/network.sol diff --git a/.gitignore b/.gitignore index 64081ea6..e98574c6 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,9 @@ target/ /bin /crates/*/target/ /crates/*/Cargo.lock +/contracts/dependencies/ +/contracts/out/ +/contracts/cache/ .direnv .env .envrc diff --git a/Cargo.lock b/Cargo.lock index 42e0ade5..b3fa18d9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6857,6 +6857,10 @@ dependencies = [ "wcn_rpc", ] +[[package]] +name = "wcn_contract" +version = "0.1.0" + [[package]] name = "wcn_core" version = "0.1.0" diff --git a/contracts/foundry.toml b/contracts/foundry.toml new file mode 100644 index 00000000..9977ac1c --- /dev/null +++ b/contracts/foundry.toml @@ -0,0 +1,9 @@ +[profile.default] +src = "src" +out = "out" +libs = ["dependencies"] + +[dependencies] +forge-std = "1.9.7" + +# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options diff --git a/contracts/remappings.txt b/contracts/remappings.txt new file mode 100644 index 00000000..58a28133 --- /dev/null +++ b/contracts/remappings.txt @@ -0,0 +1 @@ +forge-std-1.9.7/=dependencies/forge-std-1.9.7/ diff --git a/contracts/soldeer.lock b/contracts/soldeer.lock new file mode 100644 index 00000000..d68d1044 --- /dev/null +++ b/contracts/soldeer.lock @@ -0,0 +1,6 @@ +[[dependencies]] +name = "forge-std" +version = "1.9.7" +url = "https://soldeer-revisions.s3.amazonaws.com/forge-std/1_9_7_28-04-2025_15:55:08_forge-std-1.9.zip" +checksum = "8d9e0a885fa8ee6429a4d344aeb6799119f6a94c7c4fe6f188df79b0dce294ba" +integrity = "9e60fdba82bc374df80db7f2951faff6467b9091873004a3d314cf0c084b3c7d" diff --git a/contracts/src/Cluster/Cluster.sol b/contracts/src/Cluster/Cluster.sol new file mode 100644 index 00000000..e66988db --- /dev/null +++ b/contracts/src/Cluster/Cluster.sol @@ -0,0 +1,159 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import './Nodes.sol'; +import './NodeOperators.sol'; +import './Migration.sol'; +import './Maintenance.sol'; + +struct Settings { + uint8 minOperators; + uint8 minNodes; +} + +struct View { + NodeOperatorView[] operators +} + +contract Cluster { + using NodeOperatorsLib for NodeOperators; + using MigrationLib for Migration; + using MaintenanceLib for Maintenance; + + event MigrationStarted(address[] operatorsToRemove, NewNodeOperator[] operatorsToAdd, uint128 version); + event MigrationDataPullCompleted(address operator, uint128 version); + event MigrationCompleted(uint128 version); + event MigrationAborted(uint128 version); + + event MaintenanceStarted(address operator, uint128 version); + event MaintenanceFinished(address operator, uint128 version); + + event NodeSet(address operator, Node node, uint128 version); + event NodeRemoved(address operator, uint256 id, uint128 version); + + address owner; + + Settings settings; + NodeOperators operators; + Migration migration; + Maintenance maintenance; + + uint64 keyspaceVersion; + uint128 version; + + constructor(Settings memory initialSettings, NewNodeOperator[] memory initialOperators) { + owner = msg.sender; + settings = initialSettings; + + validateOperatorsCount(initialOperators.length); + + for (uint256 i = 0; i < initialOperators.length; i++) { + validateNodesCount(initialOperators[i].nodes.length); + operators.add(initialOperators[i]); + } + } + + modifier onlyOwner() { + require(msg.sender == owner, "not the owner"); + _; + } + + modifier onlyMember() { + require(operators.exists(msg.sender), "not a member"); + _; + } + + function startMigration(address[] calldata operatorsToRemove, NewNodeOperator[] calldata operatorsToAdd) external onlyOwner { + require(!maintenance.inProgress(), "maintenance is in progress"); + + for (uint256 i = 0; i < operatorsToRemove.length; i++) { + require(operators.exists(operatorsToRemove[i]), "unknown operator"); + } + + for (uint256 i = 0; i < operatorsToAdd.length; i++) { + validateNodesCount(operatorsToAdd[i].nodes.length); + require(!operators.exists(operatorsToAdd[i].addr), "operator already exists"); + } + + validateOperatorsCount((operators.length() - operatorsToRemove.length + operatorsToAdd.length)); + + migration.start(operators.slots, operatorsToRemove, operatorsToAdd); + version++; + emit MigrationStarted(operatorsToRemove, operatorsToAdd, version); + } + + function completeMigration() external onlyMember { + migration.completeDataPull(msg.sender); + version++; + emit MigrationDataPullCompleted(msg.sender, version); + + if (migration.pullingOperatorsCount > 0) { + return; + } + + for (uint256 i = 0; i < migration.operatorsToRemove.length; i++) { + operators.remove(migration.operatorsToRemove[i]); + } + + for (uint256 i = 0; i < migration.operatorsToAdd.length; i++) { + operators.add(migration.operatorsToAdd[i]); + } + + keyspaceVersion++; + + migration.complete(); + version++; + + emit MigrationCompleted(version); + } + + function abortMigration() external onlyOwner { + migration.abort(); + version++; + emit MigrationAborted(version); + } + + function startMaintenance() external onlyMember { + require(!migration.inProgress(), "migration is in progress"); + + maintenance.start(msg.sender); + version++; + emit MaintenanceStarted(msg.sender, version); + } + + function finishMaintenance() external onlyMember { + maintenance.finish(msg.sender); + version++; + emit MaintenanceFinished(msg.sender, version); + } + + function setNode(Node calldata node) external onlyMember { + operators.setNode(msg.sender, node); + version++; + emit NodeSet(msg.sender, node, version); + } + + function removeNode(uint256 id) external onlyMember { + operators.removeNode(msg.sender, id); + version++; + emit NodeRemoved(msg.sender, id, version); + } + + function updateSettings(Settings calldata newSettings) external onlyOwner { + settings = newSettings; + } + + function validateOperatorsCount(uint256 value) view internal { + require(value >= settings.minOperators, "too few operators"); + require(value <= 256, "too many operators"); + } + + function validateNodesCount(uint256 value) view internal { + require(value >= settings.minNodes, "too few nodes"); + require(value <= 256, "too many nodes"); + } + + function view() public view returns (View) { + + } +} diff --git a/contracts/src/Cluster/Maintenance.sol b/contracts/src/Cluster/Maintenance.sol new file mode 100644 index 00000000..00bd0817 --- /dev/null +++ b/contracts/src/Cluster/Maintenance.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +struct Maintenance { + address slot; +} + +library MaintenanceLib { + function start(Maintenance storage self, address operator) public { + require(operator != address(0), "invalid address"); + require(self.slot == address(0), "already occupied"); + self.slot = operator; + } + + function finish(Maintenance storage self, address operator) public { + require(operator != address(0), "invalid address"); + require(self.slot == operator, "not occupied"); + delete self.slot; + } + + function inProgress(Maintenance calldata self) public pure returns (bool) { + return (self.slot != address(0)); + } +} diff --git a/contracts/src/Cluster/Migration.sol b/contracts/src/Cluster/Migration.sol new file mode 100644 index 00000000..c6475096 --- /dev/null +++ b/contracts/src/Cluster/Migration.sol @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import "./NodeOperators.sol"; + +struct Migration { + address[] operatorsToRemove; + NewNodeOperator[] operatorsToAdd; + + mapping(address => bool) pullingOperators; + uint8 pullingOperatorsCount; +} + +library MigrationLib { + using MigrationLib for Migration; + + function start( + Migration storage self, + NodeOperator[] storage currentOperators, + address[] calldata operatorsToRemove, + NewNodeOperator[] calldata operatorsToAdd + ) public { + require(!inProgress(self), "migration already in progress"); + require(operatorsToRemove.length > 0 || operatorsToRemove.length > 0, "nothing to do"); + + self.operatorsToRemove = operatorsToRemove; + self.operatorsToAdd = operatorsToAdd; + + for (uint256 i = 0; i < currentOperators.length; i++) { + if (currentOperators[i].addr != address(0)) { + self.pullingOperators[currentOperators[i].addr] = true; + self.pullingOperatorsCount++; + } + } + + for (uint256 i = 0; i < operatorsToRemove.length; i++) { + self.operatorsToRemove.push(operatorsToRemove[i]); + self.pullingOperators[operatorsToRemove[i]] = false; + self.pullingOperatorsCount--; + } + + for (uint256 i = 0; i < operatorsToAdd.length; i++) { + self.operatorsToAdd.push(operatorsToAdd[i]); + self.pullingOperators[operatorsToAdd[i].addr] = true; + self.pullingOperatorsCount++; + } + } + + function completeDataPull(Migration storage self, address operator) public { + require(self.pullingOperators[operator], "already completed"); + self.pullingOperators[operator] = false; + self.pullingOperatorsCount--; + } + + function complete(Migration storage self) public { + require(inProgress(self), "not in progress"); + require(self.pullingOperatorsCount == 0, "data pull in progress"); + self.cleanup(); + } + + function abort(Migration storage self) public { + require(inProgress(self), "not in progress"); + self.cleanup(); + } + + function cleanup(Migration storage self) internal { + delete self.operatorsToRemove; + delete self.operatorsToAdd; + delete self.pullingOperatorsCount; + } + + function inProgress(Migration storage self) public view returns (bool) { + return (self.operatorsToRemove.length != 0 || self.operatorsToAdd.length != 0); + } +} diff --git a/contracts/src/Cluster/NodeOperators.sol b/contracts/src/Cluster/NodeOperators.sol new file mode 100644 index 00000000..68b6f0c3 --- /dev/null +++ b/contracts/src/Cluster/NodeOperators.sol @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import './Nodes.sol'; + +struct NodeOperator { + address addr; + Nodes nodes; + bytes data; +} + +struct NodeOperatorView { + address addr; + Node[] nodes; + bytes data; +} + +struct NodeOperators { + NodeOperator[] slots; + mapping(address => uint8) indexes; + uint8[] freeSlotIndexes; +} + +library NodeOperatorsLib { + using NodesLib for Nodes; + using NodeOperatorsLib for NodeOperators; + + function add(NodeOperators storage self, NodeOperatorView calldata operator) public { + uint8 idx; + + if (self.freeSlotIndexes.length > 0) { + idx = self.freeSlotIndexes[self.freeSlotIndexes.length - 1]; + self.freeSlotIndexes.pop(); + } else { + require(self.slots.length < 256, "too many operators"); + idx = uint8(self.slots.length); + self.slots.push(); + } + + NodeOperator storage op = self.slots[idx]; + op.addr = operator.addr; + op.data = operator.data; + for (uint256 i = 0; i < operator.nodes.length; i++) { + op.nodes.set(operator.nodes[i]); + } + } + + function remove(NodeOperators storage self, address addr) public { + require(addr != address(0), "invalid address"); + + uint8 idx = self.indexes[addr]; + require((idx != 0 || self.slots[0].addr == addr), "operator doesn't exist"); + + delete self.indexes[addr]; + delete self.slots[idx]; + self.freeSlotIndexes.push(idx); + } + + function exists(NodeOperators storage self, address addr) public view returns (bool) { + require(addr != address(0), "invalid address"); + return ((self.indexes[addr] != 0 || self.slots[0].addr == addr)); + } + + function length(NodeOperators storage self) public view returns (uint8) { + return uint8(self.slots.length - self.freeSlotIndexes.length); + } + + function setNode(NodeOperators storage self, address operator, Node calldata node) public { + self.slots[self.indexes[operator]].nodes.set(node); + } + + function removeNode(NodeOperators storage self, address operator, uint256 id) public { + self.slots[self.indexes[operator]].nodes.remove(id); + } +} diff --git a/contracts/src/Cluster/Nodes.sol b/contracts/src/Cluster/Nodes.sol new file mode 100644 index 00000000..1b0b2312 --- /dev/null +++ b/contracts/src/Cluster/Nodes.sol @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +struct Node { + uint256 id; + bytes data; +} + +struct Nodes { + Node[] slots; + mapping(uint256 => uint8) indexes; + uint8[] freeSlotIndexes; +} + +library NodesLib { + function set(Nodes storage self, Node calldata node) public { + require(node.id != 0, "invalid id"); + + uint8 idx; + + if (self.freeSlotIndexes.length > 0) { + idx = self.freeSlotIndexes[self.freeSlotIndexes.length - 1]; + self.freeSlotIndexes.pop(); + } else { + require(self.slots.length < 256, "too many nodes"); + idx = uint8(self.slots.length); + self.slots.push(); + } + + self.indexes[node.id] = idx; + self.slots[idx] = node; + } + + function remove(Nodes storage self, uint256 id) public { + require(id != 0, "invalid id"); + + uint8 idx = self.indexes[id]; + require((idx != 0 || self.slots[0].id == id), "node doesn't exist"); + + delete self.slots[idx]; + self.freeSlotIndexes.push(idx); + } +} + diff --git a/contracts/test/Suite.sol b/contracts/test/Suite.sol new file mode 100644 index 00000000..a1757c83 --- /dev/null +++ b/contracts/test/Suite.sol @@ -0,0 +1,110 @@ +pragma solidity ^0.8.20; + +import {Test} from "../dependencies/forge-std-1.9.7/src/Test.sol"; +import "../src/Cluster/Cluster.sol"; + +contract ClusterTestSuite is Test { + mapping(address => uint256) privateKeys; + + function newNodeOperator(uint256 privateKey, uint256 nodesCount) internal pure returns (NewNodeOperator memory) { + Node[] memory nodes = new Node[](nodesCount); + for (uint256 i = 0; i < nodesCount; i++) { + nodes[i] = Node({ id: i + 1 , data: bytes("Some node specific data") }); + } + + return NewNodeOperator({ + addr: vm.addr(privateKey), + nodes: nodes, + data: bytes("Some operator specific data") + }); + } + + function newCluster() internal returns (Cluster) { + return newCluster(Settings({ minOperators: 5, minNodes: 2 })); + } + + function newCluster(Settings memory settings) internal returns (Cluster) { + return newCluster(settings, settings.minOperators, settings.minNodes); + } + + function newCluster(Settings memory settings, uint256 operatorsCount, uint256 nodesCount) internal returns (Cluster) { + NewNodeOperator[] memory operators = new NewNodeOperator[](operatorsCount); + for (uint256 i = 0; i < operatorsCount; i++) { + operators[i] = newNodeOperator(i + 1, nodesCount); + } + + return new Cluster(settings, operators); + } + + constructor() { + for (uint256 k = 1; k <= 10; k++) { + privateKeys[vm.addr(k)] = k; + } + } + + function test_canNotCreateClusterWithTooFewOperators() public { + vm.expectRevert("too few operators"); + newCluster(Settings({ minOperators: 3, minNodes: 1 }), 2, 1); + } + + function test_canNotCreateClusterWithTooFewNodes() public { + vm.expectRevert("too few nodes"); + newCluster(Settings({ minOperators: 3, minNodes: 2 }), 3, 1); + } + + function test_canNotCreateClusterWithTooManyOperators() public { + vm.expectRevert("too many operators"); + newCluster(Settings({ minOperators: 3, minNodes: 1 }), 257, 1); + } + + function test_canNotCreateClusterWithTooManyNodes() public { + vm.expectRevert("too many nodes"); + newCluster(Settings({ minOperators: 3, minNodes: 2 }), 3, 257); + } + + function test_canCreateClusterWithMinNumberOfOperatorsAndNodes() public { + newCluster(Settings({ minOperators: 3, minNodes: 2 }), 3, 2); + } + + function test_canCreateClusterWithMaxNumberOfOperators() public { + newCluster(Settings({ minOperators: 3, minNodes: 2 }), 256, 2); + } + + function test_canCreateClusterWithMaxNumberOfNodes() public { + newCluster(Settings({ minOperators: 3, minNodes: 2 }), 3, 256); + } + + function startMigration(Cluster cluster, uint256 callerPrivateKey, uint256 removeCount, uint256 addCount) { + vm.prank(vm.addr(callerPrivateKey)); + + address[] operatorsToRemove = new address[](removeCount); + for (uint256 i = 0; i < removeCount; i++) { + operatorsToRemove[i] = ; + } + + NewNodeOperator[] operatorsToAdd = new NewNodeOperator[](addCount); + + cluster.startMigration() + } + + function test_arbitraryKeypairCanNotStartMigration() public { + Cluster cluster = newCluster(); + newCluster(Settings({ minOperators: 3, minNodes: 2 }), 3, 256); + } + + // uint256 testNumber; + + // function setUp() public { + // testNumber = 42; + // } + + // function test_NumberIs42() public { + // assertEq(testNumber, 42); + // } + + // /// forge-config: default.allow_internal_expect_revert = true + // function testRevert_Subtract43() public { + // vm.expectRevert(); + // testNumber -= 43; + // } +} diff --git a/crates/contract/Cargo.toml b/crates/contract/Cargo.toml new file mode 100644 index 00000000..0b8c220f --- /dev/null +++ b/crates/contract/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "wcn_contract" +version = "0.1.0" +edition = "2021" + +[dependencies] + +[lints] +workspace = true diff --git a/crates/contract/src/lib.rs b/crates/contract/src/lib.rs new file mode 100644 index 00000000..990a7f26 --- /dev/null +++ b/crates/contract/src/lib.rs @@ -0,0 +1,230 @@ +use std::{ + collections::{HashMap, HashSet}, + net::SocketAddrV4, +}; + +mod ed25519 { + pub type PublicKey = [u8; 32]; +} + +type Address = [u8; 20]; + +// Just for demonstration purposes, should actually be a SlotMap. +type SlotMap = HashMap; + +#[derive(Clone)] +struct Operator { + ed25519_pub: ed25519::PublicKey, + nodes: HashMap, +} + +#[derive(Clone)] +struct NewOperator { + address: Address, + inner: Operator, +} + +#[derive(Clone)] +struct Node { + // potentially more fields in the future +} + +#[derive(Clone, Copy)] +struct Keyspace { + version: u64, +} + +struct Migration { + remove: Vec
, + add: Vec, + + /// Set of operators who still need to pull the data to finish the + /// migration. + pulling_operators: HashSet
, + + new_keyspace: Keyspace, +} + +struct Region { + operators: SlotMap, + + under_maintenance: Option
, + + keyspace: Keyspace, + + migration: Option, +} + +struct Contract { + regions: Vec, + + version: u128, +} + +impl Contract { + const MAX_OPERATORS_PER_REGION: usize = 256; + + /// Begins a data migration process by adding/removing operators to/from a + /// region. + /// + /// Requires "Admin" signature. + fn start_migration(&mut self, region_id: u8, remove: Vec
, add: Vec) { + let region = &mut self.regions[region_id as usize]; + + assert!(region.migration.is_some(), "migration already in progress"); + assert!(!remove.is_empty() || !add.is_empty(), "nothing to do"); + + for addr in &remove { + assert!(region.operators.contains_key(addr), "unknown operator"); + } + + for new in &add { + assert!( + new.inner.nodes.len() >= 2, + "operators should have at least 2 nodes" + ); + + assert!( + !region.operators.contains_key(&new.address), + "operator already exists" + ); + } + + let mut pulling_operators: HashSet<_> = region + .operators + .keys() + .chain(add.iter().map(|new| &new.address)) + .copied() + .collect(); + + for addr in &remove { + pulling_operators.remove(addr); + } + + region.migration = Some(Migration { + remove: remove.clone(), + add: add.clone(), + pulling_operators, + new_keyspace: Keyspace { + version: region.keyspace.version + 1, + }, + }); + + self.version += 1; + // emit_migration_started(region_id, remove, add, self.version); + } + + /// Removes an operator from [`Migration::pending_operators`]. + /// + /// Requires "Operator" signature. + fn complete_migration(&mut self, region_id: u8, operator: Address) { + let region = &mut self.regions[region_id as usize]; + + let migration = region.migration.as_mut().expect("no migration"); + + assert!( + migration.pulling_operators.remove(&operator), + "already completed" + ); + + self.version += 1; + + if !migration.pulling_operators.is_empty() { + // emit_operator_migration_completed(region_id, operator, self.version); + return; + } + + region.keyspace = migration.new_keyspace; + + for addr in &migration.remove { + region.operators.remove(addr); + } + + // TODO: prefer replacing removed nodes. + + for new in &migration.add { + region.operators.insert(new.address, new.inner.clone()); + } + + drop(migration); + region.migration = None; + + // emit_migration_completed(region_id, self.version); + } + + /// Aborts an ongoing data migration. + /// + /// Requires "Admin" signature. + fn abort_migration(&mut self, region_id: u8) { + let region = &mut self.regions[region_id as usize]; + + assert!(region.migration.is_some(), "no migration"); + + region.migration = None; + self.version += 1; + // emit_migration_aborted(region_id, self.version); + } + + /// Acquires the maintenance slot for the provided operator. + /// + /// Requires "Operator" signature. + fn start_maintenance(&mut self, region_id: u8, operator: Address) { + let region = &mut self.regions[region_id as usize]; + + assert!(region.migration.is_none(), "ongoing migration"); + assert!(region.under_maintenance.is_none(), "occupied"); + + region.under_maintenance = Some(operator); + self.version += 1; + + // emit_maintenance_started(region_id, operator, version); + } + + /// Releases the maintenance slot occupied by the provided operator. + /// + /// Requires "Operator" signature. + fn finish_maintenance(&mut self, region_id: u8, operator: Address) { + let region = &mut self.regions[region_id as usize]; + + assert_eq!( + region.under_maintenance.as_ref(), + Some(&operator), + "not occupied by the provided operator" + ); + + region.under_maintenance = None; + self.version += 1; + + // emit_maintenance_finished(region_id, operator, version); + } + + /// Adds a (coordinator) node. + /// + /// Requires "Operator" signature. + fn add_node(&mut self, region_id: u8, operator: Address, node_addr: SocketAddrV4) { + let region = &mut self.regions[region_id as usize]; + let operator = region + .operators + .get_mut(&operator) + .expect("unknown operator"); + + assert!(!operator.nodes.contains_key(&node_addr), "already exists"); + operator.nodes.insert(node_addr, Node {}); + // emit_node_added(region_id, operator, node_addr, node); + } + + /// Removes a (coordinator) node. + /// + /// Requires "Operator" signature. + fn remove_node(&mut self, region_id: u8, operator: Address, node_addr: SocketAddrV4) { + let region = &mut self.regions[region_id as usize]; + let operator = region + .operators + .get_mut(&operator) + .expect("unknown operator"); + + assert!(operator.nodes.contains_key(&node_addr), "not found"); + operator.nodes.remove(&node_addr); + // emit_node_removed(region_id, operator, node_addr); + } +} diff --git a/crates/contract/src/network.sol b/crates/contract/src/network.sol new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/crates/contract/src/network.sol @@ -0,0 +1 @@ + diff --git a/flake.lock b/flake.lock index c78621e7..917983d2 100644 --- a/flake.lock +++ b/flake.lock @@ -41,11 +41,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1729256560, - "narHash": "sha256-/uilDXvCIEs3C9l73JTACm4quuHUsIHcns1c+cHUJwA=", + "lastModified": 1746141548, + "narHash": "sha256-IgBWhX7A2oJmZFIrpRuMnw5RAufVnfvOgHWgIdds+hc=", "owner": "nixos", "repo": "nixpkgs", - "rev": "4c2fcb090b1f3e5b47eaa7bd33913b574a11e0a0", + "rev": "f02fddb8acef29a8b32f10a335d44828d7825b78", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 6188020c..f530c2d3 100644 --- a/flake.nix +++ b/flake.nix @@ -85,9 +85,9 @@ jq jsonnet jsonnet-language-server - # setting LIBCLANG_PATH manually breaks globally installed `ssh` binary and transitively breaks git - # so we use a local version of `ssh` in this dev env (maybe there is a better way to fix it) - # openssh + + solc + foundry ]; shellHook = '' From 81bd234c36e6d905f4863b70299ccad894d2a261 Mon Sep 17 00:00:00 2001 From: Github Bot Date: Wed, 7 May 2025 09:18:55 +0000 Subject: [PATCH 02/79] Bump VERSION to 250507.0 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 35b8fbbd..dc2f8a38 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -250331.5 +250507.0 From 8b4b5a28b5e9e0ee22b77d7b75d63485e991ca4c Mon Sep 17 00:00:00 2001 From: Darksome Date: Wed, 7 May 2025 13:39:26 +0000 Subject: [PATCH 03/79] impl ClusterView --- contracts/src/Cluster/Cluster.sol | 25 +++++++++++----- contracts/src/Cluster/Migration.sol | 38 +++++++++++++++++++++++-- contracts/src/Cluster/NodeOperators.sol | 16 +++++++++++ contracts/src/Cluster/Nodes.sol | 19 +++++++++++++ contracts/test/Suite.sol | 32 ++++++++++----------- 5 files changed, 105 insertions(+), 25 deletions(-) diff --git a/contracts/src/Cluster/Cluster.sol b/contracts/src/Cluster/Cluster.sol index e66988db..a809c52d 100644 --- a/contracts/src/Cluster/Cluster.sol +++ b/contracts/src/Cluster/Cluster.sol @@ -11,8 +11,13 @@ struct Settings { uint8 minNodes; } -struct View { - NodeOperatorView[] operators +struct ClusterView { + NodeOperatorsView operators; + MigrationView migration; + Maintenance maintenance; + + uint64 keyspaceVersion; + uint128 version; } contract Cluster { @@ -20,7 +25,7 @@ contract Cluster { using MigrationLib for Migration; using MaintenanceLib for Maintenance; - event MigrationStarted(address[] operatorsToRemove, NewNodeOperator[] operatorsToAdd, uint128 version); + event MigrationStarted(address[] operatorsToRemove, NodeOperatorView[] operatorsToAdd, uint128 version); event MigrationDataPullCompleted(address operator, uint128 version); event MigrationCompleted(uint128 version); event MigrationAborted(uint128 version); @@ -41,7 +46,7 @@ contract Cluster { uint64 keyspaceVersion; uint128 version; - constructor(Settings memory initialSettings, NewNodeOperator[] memory initialOperators) { + constructor(Settings memory initialSettings, NodeOperatorView[] memory initialOperators) { owner = msg.sender; settings = initialSettings; @@ -63,7 +68,7 @@ contract Cluster { _; } - function startMigration(address[] calldata operatorsToRemove, NewNodeOperator[] calldata operatorsToAdd) external onlyOwner { + function startMigration(address[] calldata operatorsToRemove, NodeOperatorView[] calldata operatorsToAdd) external onlyOwner { require(!maintenance.inProgress(), "maintenance is in progress"); for (uint256 i = 0; i < operatorsToRemove.length; i++) { @@ -153,7 +158,13 @@ contract Cluster { require(value <= 256, "too many nodes"); } - function view() public view returns (View) { - + function getView() public view returns (ClusterView memory) { + return ClusterView({ + operators: operators.getView(), + migration: migration.getView(operators.slots), + maintenance: maintenance, + keyspaceVersion: keyspaceVersion, + version: version + }); } } diff --git a/contracts/src/Cluster/Migration.sol b/contracts/src/Cluster/Migration.sol index c6475096..b18d7d5e 100644 --- a/contracts/src/Cluster/Migration.sol +++ b/contracts/src/Cluster/Migration.sol @@ -5,12 +5,19 @@ import "./NodeOperators.sol"; struct Migration { address[] operatorsToRemove; - NewNodeOperator[] operatorsToAdd; + NodeOperatorView[] operatorsToAdd; mapping(address => bool) pullingOperators; uint8 pullingOperatorsCount; } +struct MigrationView { + address[] operatorsToRemove; + NodeOperatorView[] operatorsToAdd; + + address[] pullingOperators; +} + library MigrationLib { using MigrationLib for Migration; @@ -18,7 +25,7 @@ library MigrationLib { Migration storage self, NodeOperator[] storage currentOperators, address[] calldata operatorsToRemove, - NewNodeOperator[] calldata operatorsToAdd + NodeOperatorView[] calldata operatorsToAdd ) public { require(!inProgress(self), "migration already in progress"); require(operatorsToRemove.length > 0 || operatorsToRemove.length > 0, "nothing to do"); @@ -72,4 +79,31 @@ library MigrationLib { function inProgress(Migration storage self) public view returns (bool) { return (self.operatorsToRemove.length != 0 || self.operatorsToAdd.length != 0); } + + function getView(Migration storage self, NodeOperator[] storage currentOperators) public view returns (MigrationView memory) { + address[] memory toRemove = new address[](self.operatorsToRemove.length); + for (uint256 i = 0; i < self.operatorsToRemove.length; i++) { + toRemove[i] = self.operatorsToRemove[i]; + } + + NodeOperatorView[] memory toAdd = new NodeOperatorView[](self.operatorsToAdd.length); + for (uint256 i = 0; i < self.operatorsToAdd.length; i++) { + toAdd[i] = self.operatorsToAdd[i]; + } + + address[] memory pulling = new address[](self.pullingOperatorsCount); + uint256 j; + for (uint256 i = 0; i < currentOperators.length; i++) { + if (currentOperators[i].addr != address(0) && self.pullingOperators[currentOperators[i].addr]) { + pulling[j] = currentOperators[i].addr; + j++; + } + } + + return MigrationView({ + operatorsToRemove: toRemove, + operatorsToAdd: toAdd, + pullingOperators: pulling + }); + } } diff --git a/contracts/src/Cluster/NodeOperators.sol b/contracts/src/Cluster/NodeOperators.sol index 68b6f0c3..5d1097e1 100644 --- a/contracts/src/Cluster/NodeOperators.sol +++ b/contracts/src/Cluster/NodeOperators.sol @@ -21,6 +21,10 @@ struct NodeOperators { uint8[] freeSlotIndexes; } +struct NodeOperatorsView { + NodeOperatorView[] slots; +} + library NodeOperatorsLib { using NodesLib for Nodes; using NodeOperatorsLib for NodeOperators; @@ -72,4 +76,16 @@ library NodeOperatorsLib { function removeNode(NodeOperators storage self, address operator, uint256 id) public { self.slots[self.indexes[operator]].nodes.remove(id); } + + function getView(NodeOperators storage self) public view returns (NodeOperatorsView memory) { + NodeOperatorView[] memory slots = new NodeOperatorView[](length(self)); + for (uint256 i = 0; i < self.slots.length; i++) { + slots[i] = NodeOperatorView({ + addr: self.slots[i].addr, + nodes: self.slots[i].nodes.getView(), + data: self.slots[i].data + }); + } + return NodeOperatorsView({ slots: slots }); + } } diff --git a/contracts/src/Cluster/Nodes.sol b/contracts/src/Cluster/Nodes.sol index 1b0b2312..ce7295fb 100644 --- a/contracts/src/Cluster/Nodes.sol +++ b/contracts/src/Cluster/Nodes.sol @@ -40,5 +40,24 @@ library NodesLib { delete self.slots[idx]; self.freeSlotIndexes.push(idx); } + + function length(Nodes storage self) public view returns (uint8) { + return uint8(self.slots.length - self.freeSlotIndexes.length); + } + + function getView(Nodes storage self) public view returns (Node[] memory) { + Node[] memory nodes = new Node[](length(self)); + uint256 j; + for (uint256 i = 0; i < self.slots.length; i++) { + if (self.slots[i].id != 0) { + nodes[j] = Node({ + id: self.slots[i].id, + data: self.slots[i].data + }); + j++; + } + } + return nodes; + } } diff --git a/contracts/test/Suite.sol b/contracts/test/Suite.sol index a1757c83..bf825868 100644 --- a/contracts/test/Suite.sol +++ b/contracts/test/Suite.sol @@ -6,13 +6,13 @@ import "../src/Cluster/Cluster.sol"; contract ClusterTestSuite is Test { mapping(address => uint256) privateKeys; - function newNodeOperator(uint256 privateKey, uint256 nodesCount) internal pure returns (NewNodeOperator memory) { + function newNodeOperator(uint256 privateKey, uint256 nodesCount) internal pure returns (NodeOperatorView memory) { Node[] memory nodes = new Node[](nodesCount); for (uint256 i = 0; i < nodesCount; i++) { nodes[i] = Node({ id: i + 1 , data: bytes("Some node specific data") }); } - return NewNodeOperator({ + return NodeOperatorView({ addr: vm.addr(privateKey), nodes: nodes, data: bytes("Some operator specific data") @@ -28,7 +28,7 @@ contract ClusterTestSuite is Test { } function newCluster(Settings memory settings, uint256 operatorsCount, uint256 nodesCount) internal returns (Cluster) { - NewNodeOperator[] memory operators = new NewNodeOperator[](operatorsCount); + NodeOperatorView[] memory operators = new NodeOperatorView[](operatorsCount); for (uint256 i = 0; i < operatorsCount; i++) { operators[i] = newNodeOperator(i + 1, nodesCount); } @@ -74,23 +74,23 @@ contract ClusterTestSuite is Test { newCluster(Settings({ minOperators: 3, minNodes: 2 }), 3, 256); } - function startMigration(Cluster cluster, uint256 callerPrivateKey, uint256 removeCount, uint256 addCount) { - vm.prank(vm.addr(callerPrivateKey)); + // function startMigration(Cluster cluster, uint256 callerPrivateKey, uint256 removeCount, uint256 addCount) { + // vm.prank(vm.addr(callerPrivateKey)); - address[] operatorsToRemove = new address[](removeCount); - for (uint256 i = 0; i < removeCount; i++) { - operatorsToRemove[i] = ; - } + // address[] operatorsToRemove = new address[](removeCount); + // for (uint256 i = 0; i < removeCount; i++) { + // operatorsToRemove[i] = ; + // } - NewNodeOperator[] operatorsToAdd = new NewNodeOperator[](addCount); + // NodeOperatorView[] operatorsToAdd = new NodeOperatorView[](addCount); - cluster.startMigration() - } + // cluster.startMigration() + // } - function test_arbitraryKeypairCanNotStartMigration() public { - Cluster cluster = newCluster(); - newCluster(Settings({ minOperators: 3, minNodes: 2 }), 3, 256); - } + // function test_arbitraryKeypairCanNotStartMigration() public { + // Cluster cluster = newCluster(); + // newCluster(Settings({ minOperators: 3, minNodes: 2 }), 3, 256); + // } // uint256 testNumber; From 65fd668eb5e4bfff68e0e714e7700268771d1c0f Mon Sep 17 00:00:00 2001 From: Darksome Date: Wed, 7 May 2025 13:42:47 +0000 Subject: [PATCH 04/79] transferOwnership --- contracts/src/Cluster/Cluster.sol | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/contracts/src/Cluster/Cluster.sol b/contracts/src/Cluster/Cluster.sol index a809c52d..caa487c7 100644 --- a/contracts/src/Cluster/Cluster.sol +++ b/contracts/src/Cluster/Cluster.sol @@ -68,6 +68,10 @@ contract Cluster { _; } + function transferOwnership(address newOwner) external onlyOwner { + owner = newOwner; + } + function startMigration(address[] calldata operatorsToRemove, NodeOperatorView[] calldata operatorsToAdd) external onlyOwner { require(!maintenance.inProgress(), "maintenance is in progress"); From ed6b201c82449eb09583b15f5145efd1804997cb Mon Sep 17 00:00:00 2001 From: Darksome Date: Wed, 7 May 2025 16:46:10 +0000 Subject: [PATCH 05/79] more tests --- contracts/src/Cluster/Migration.sol | 2 +- contracts/src/Cluster/NodeOperators.sol | 10 +- contracts/test/Suite.sol | 232 +++++++++++++++++------- 3 files changed, 180 insertions(+), 64 deletions(-) diff --git a/contracts/src/Cluster/Migration.sol b/contracts/src/Cluster/Migration.sol index b18d7d5e..c13d1255 100644 --- a/contracts/src/Cluster/Migration.sol +++ b/contracts/src/Cluster/Migration.sol @@ -28,7 +28,7 @@ library MigrationLib { NodeOperatorView[] calldata operatorsToAdd ) public { require(!inProgress(self), "migration already in progress"); - require(operatorsToRemove.length > 0 || operatorsToRemove.length > 0, "nothing to do"); + require(operatorsToRemove.length > 0 || operatorsToAdd.length > 0, "nothing to do"); self.operatorsToRemove = operatorsToRemove; self.operatorsToAdd = operatorsToAdd; diff --git a/contracts/src/Cluster/NodeOperators.sol b/contracts/src/Cluster/NodeOperators.sol index 5d1097e1..7c0d21eb 100644 --- a/contracts/src/Cluster/NodeOperators.sol +++ b/contracts/src/Cluster/NodeOperators.sol @@ -30,6 +30,8 @@ library NodeOperatorsLib { using NodeOperatorsLib for NodeOperators; function add(NodeOperators storage self, NodeOperatorView calldata operator) public { + require(!exists(self, operator.addr), "operator already exists"); + uint8 idx; if (self.freeSlotIndexes.length > 0) { @@ -41,6 +43,7 @@ library NodeOperatorsLib { self.slots.push(); } + self.indexes[operator.addr] = idx; NodeOperator storage op = self.slots[idx]; op.addr = operator.addr; op.data = operator.data; @@ -62,7 +65,12 @@ library NodeOperatorsLib { function exists(NodeOperators storage self, address addr) public view returns (bool) { require(addr != address(0), "invalid address"); - return ((self.indexes[addr] != 0 || self.slots[0].addr == addr)); + + if (self.slots.length > 0) { + return ((self.indexes[addr] != 0 || self.slots[0].addr == addr)); + } + + return false; } function length(NodeOperators storage self) public view returns (uint8) { diff --git a/contracts/test/Suite.sol b/contracts/test/Suite.sol index bf825868..73b651d9 100644 --- a/contracts/test/Suite.sol +++ b/contracts/test/Suite.sol @@ -1,40 +1,16 @@ +// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import {Test} from "../dependencies/forge-std-1.9.7/src/Test.sol"; +import {Vm} from "../dependencies/forge-std-1.9.7/src/Vm.sol"; +import "../dependencies/forge-std-1.9.7/src/console.sol"; + import "../src/Cluster/Cluster.sol"; contract ClusterTestSuite is Test { - mapping(address => uint256) privateKeys; - - function newNodeOperator(uint256 privateKey, uint256 nodesCount) internal pure returns (NodeOperatorView memory) { - Node[] memory nodes = new Node[](nodesCount); - for (uint256 i = 0; i < nodesCount; i++) { - nodes[i] = Node({ id: i + 1 , data: bytes("Some node specific data") }); - } - - return NodeOperatorView({ - addr: vm.addr(privateKey), - nodes: nodes, - data: bytes("Some operator specific data") - }); - } - - function newCluster() internal returns (Cluster) { - return newCluster(Settings({ minOperators: 5, minNodes: 2 })); - } + using TestClusterLib for TestCluster; - function newCluster(Settings memory settings) internal returns (Cluster) { - return newCluster(settings, settings.minOperators, settings.minNodes); - } - - function newCluster(Settings memory settings, uint256 operatorsCount, uint256 nodesCount) internal returns (Cluster) { - NodeOperatorView[] memory operators = new NodeOperatorView[](operatorsCount); - for (uint256 i = 0; i < operatorsCount; i++) { - operators[i] = newNodeOperator(i + 1, nodesCount); - } - - return new Cluster(settings, operators); - } + mapping(address => uint256) privateKeys; constructor() { for (uint256 k = 1; k <= 10; k++) { @@ -44,67 +20,199 @@ contract ClusterTestSuite is Test { function test_canNotCreateClusterWithTooFewOperators() public { vm.expectRevert("too few operators"); - newCluster(Settings({ minOperators: 3, minNodes: 1 }), 2, 1); + newTestCluster(vm, Settings({ minOperators: 3, minNodes: 1 }), 2, 1); } function test_canNotCreateClusterWithTooFewNodes() public { vm.expectRevert("too few nodes"); - newCluster(Settings({ minOperators: 3, minNodes: 2 }), 3, 1); + newTestCluster(vm, Settings({ minOperators: 3, minNodes: 2 }), 3, 1); } function test_canNotCreateClusterWithTooManyOperators() public { vm.expectRevert("too many operators"); - newCluster(Settings({ minOperators: 3, minNodes: 1 }), 257, 1); + newTestCluster(vm, Settings({ minOperators: 3, minNodes: 1 }), 257, 1); } function test_canNotCreateClusterWithTooManyNodes() public { vm.expectRevert("too many nodes"); - newCluster(Settings({ minOperators: 3, minNodes: 2 }), 3, 257); + newTestCluster(vm, Settings({ minOperators: 3, minNodes: 2 }), 3, 257); } function test_canCreateClusterWithMinNumberOfOperatorsAndNodes() public { - newCluster(Settings({ minOperators: 3, minNodes: 2 }), 3, 2); + newTestCluster(vm, Settings({ minOperators: 3, minNodes: 2 }), 3, 2); } function test_canCreateClusterWithMaxNumberOfOperators() public { - newCluster(Settings({ minOperators: 3, minNodes: 2 }), 256, 2); + newTestCluster(vm, Settings({ minOperators: 3, minNodes: 2 }), 256, 2); } function test_canCreateClusterWithMaxNumberOfNodes() public { - newCluster(Settings({ minOperators: 3, minNodes: 2 }), 3, 256); + newTestCluster(vm, Settings({ minOperators: 3, minNodes: 2 }), 3, 256); + } + + function test_arbitraryKeypairCanNotStartMigration() public { + newTestCluster(vm) + .prepareMigration(0, 1) + .addOperator(10) + .setCaller(42) + .startMigration("not the owner"); + } + + function test_memberKeypairCanNotStartMigration() public { + newTestCluster(vm) + .prepareMigration(0, 1) + .addOperator(10) + .setCaller(1) + .startMigration("not the owner"); + } + + function test_ownerKeypairCanStartMigration() public { + newTestCluster(vm) + .prepareMigration(0, 1) + .addOperator(10) + .startMigration(); + } + + function test_canNotStartMigrationWithTooManyOperators() public { + newTestCluster(vm, Settings({ minOperators: 3, minNodes: 2 })) + .generateMigration(0, 256 - 3 + 1) + .startMigration("too many operators"); + } + + function test_canNotStartMigrationWithTooFewOperators() public { + newTestCluster(vm, Settings({ minOperators: 3, minNodes: 2 })) + .generateMigration(2, 1) + .startMigration("too few operators"); + } + + function test_canStartMigrationWhenAddedOperatorsReplenishRemoved() public { + newTestCluster(vm, Settings({ minOperators: 3, minNodes: 2 })) + .generateMigration(3, 3) + .startMigration(); + } +} + +struct TestCluster { + Cluster inner; + + Vm vm; + + address[] operatorsToRemove; + uint256 operatorsToRemoveLen; + + NodeOperatorView[] operatorsToAdd; + uint256 operatorsToAddLen; +} + +function newTestCluster(Vm vm) returns (TestCluster memory) { + return newTestCluster(vm, Settings({ minOperators: 5, minNodes: 2 })); +} + +function newTestCluster(Vm vm, Settings memory settings) returns (TestCluster memory) { + return newTestCluster(vm, settings, settings.minOperators, settings.minNodes); +} + +function newTestCluster(Vm vm, Settings memory settings, uint256 operatorsCount, uint256 nodesCount) returns (TestCluster memory) { + NodeOperatorView[] memory operators = new NodeOperatorView[](operatorsCount); + for (uint256 i = 0; i < operatorsCount; i++) { + operators[i] = newNodeOperator(vm.addr(i + 1), nodesCount); + } + + return TestCluster({ + inner: new Cluster(settings, operators), + vm: vm, + operatorsToRemove: new address[](0), + operatorsToRemoveLen: 0, + operatorsToAdd: new NodeOperatorView[](0), + operatorsToAddLen: 0 + }); +} + +library TestClusterLib { + function setCaller(TestCluster memory self, uint256 callerPrivateKey) public returns (TestCluster memory) { + self.vm.prank(self.vm.addr(callerPrivateKey)); + return self; } - // function startMigration(Cluster cluster, uint256 callerPrivateKey, uint256 removeCount, uint256 addCount) { - // vm.prank(vm.addr(callerPrivateKey)); + function generateMigration(TestCluster memory self, uint256 operatorsToRemove, uint operatorsToAdd) public view returns (TestCluster memory) { + prepareMigration(self, operatorsToRemove, operatorsToAdd); - // address[] operatorsToRemove = new address[](removeCount); - // for (uint256 i = 0; i < removeCount; i++) { - // operatorsToRemove[i] = ; - // } + ClusterView memory clusterView = self.inner.getView(); - // NodeOperatorView[] operatorsToAdd = new NodeOperatorView[](addCount); + for (uint256 i = 0; i < clusterView.operators.slots.length; i++) { + if (operatorsToRemove == 0) { + break; + } + if (clusterView.operators.slots[i].addr != address(0)) { + removeOperator(self, clusterView.operators.slots[i].addr); + operatorsToRemove--; + } + } + require(operatorsToRemove == 0); - // cluster.startMigration() - // } + for (uint256 i = 0; i < operatorsToAdd; i++) { + addOperator(self, i + 100); + } + + return self; + } + + function prepareMigration(TestCluster memory self, uint256 operatorsToRemove, uint256 operatorsToAdd) public pure returns (TestCluster memory) { + self.operatorsToRemove = new address[](operatorsToRemove); + self.operatorsToRemoveLen = 0; + self.operatorsToAdd = new NodeOperatorView[](operatorsToAdd); + self.operatorsToAddLen = 0; + return self; + } + + function addOperator(TestCluster memory self, uint256 privateKey) public pure returns (TestCluster memory) { + return addOperator(self, privateKey, 2); + } + + function addOperator(TestCluster memory self, uint256 privateKey, uint256 nodesCount) public pure returns (TestCluster memory) { + Node[] memory nodes = new Node[](nodesCount); + for (uint256 i = 0; i < nodesCount; i++) { + nodes[i] = Node({ id: i + 1 , data: bytes("Some node specific data") }); + } + + self.operatorsToAdd[self.operatorsToAddLen] = NodeOperatorView({ + addr: self.vm.addr(privateKey), + nodes: nodes, + data: bytes("Some operator specific data") + }); + self.operatorsToAddLen++; - // function test_arbitraryKeypairCanNotStartMigration() public { - // Cluster cluster = newCluster(); - // newCluster(Settings({ minOperators: 3, minNodes: 2 }), 3, 256); - // } + return self; + } - // uint256 testNumber; + function removeOperator(TestCluster memory self, address operator) public pure returns (TestCluster memory) { + self.operatorsToRemove[self.operatorsToRemoveLen] = operator; + self.operatorsToRemoveLen++; + return self; + } - // function setUp() public { - // testNumber = 42; - // } + function startMigration(TestCluster memory self, bytes calldata revertBytes) public returns (TestCluster memory) { + self.vm.expectRevert(revertBytes); + startMigration(self); + return self; + } - // function test_NumberIs42() public { - // assertEq(testNumber, 42); - // } + function startMigration(TestCluster memory self) public returns (TestCluster memory) { + self.inner.startMigration(self.operatorsToRemove, self.operatorsToAdd); + return self; + } +} + +function newNodeOperator(address addr, uint256 nodesCount) pure returns (NodeOperatorView memory) { + Node[] memory nodes = new Node[](nodesCount); + for (uint256 i = 0; i < nodesCount; i++) { + nodes[i] = Node({ id: i + 1 , data: bytes("Some node specific data") }); + } - // /// forge-config: default.allow_internal_expect_revert = true - // function testRevert_Subtract43() public { - // vm.expectRevert(); - // testNumber -= 43; - // } + return NodeOperatorView({ + addr: addr, + nodes: nodes, + data: bytes("Some operator specific data") + }); } + From 471018f0059ffe55c139de430122e2d623e20d12 Mon Sep 17 00:00:00 2001 From: Darksome Date: Wed, 7 May 2025 17:41:34 +0000 Subject: [PATCH 06/79] remove Rust prototype --- crates/contract/Cargo.toml | 9 -- crates/contract/src/lib.rs | 230 -------------------------------- crates/contract/src/network.sol | 1 - 3 files changed, 240 deletions(-) delete mode 100644 crates/contract/Cargo.toml delete mode 100644 crates/contract/src/lib.rs delete mode 100644 crates/contract/src/network.sol diff --git a/crates/contract/Cargo.toml b/crates/contract/Cargo.toml deleted file mode 100644 index 0b8c220f..00000000 --- a/crates/contract/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[package] -name = "wcn_contract" -version = "0.1.0" -edition = "2021" - -[dependencies] - -[lints] -workspace = true diff --git a/crates/contract/src/lib.rs b/crates/contract/src/lib.rs deleted file mode 100644 index 990a7f26..00000000 --- a/crates/contract/src/lib.rs +++ /dev/null @@ -1,230 +0,0 @@ -use std::{ - collections::{HashMap, HashSet}, - net::SocketAddrV4, -}; - -mod ed25519 { - pub type PublicKey = [u8; 32]; -} - -type Address = [u8; 20]; - -// Just for demonstration purposes, should actually be a SlotMap. -type SlotMap = HashMap; - -#[derive(Clone)] -struct Operator { - ed25519_pub: ed25519::PublicKey, - nodes: HashMap, -} - -#[derive(Clone)] -struct NewOperator { - address: Address, - inner: Operator, -} - -#[derive(Clone)] -struct Node { - // potentially more fields in the future -} - -#[derive(Clone, Copy)] -struct Keyspace { - version: u64, -} - -struct Migration { - remove: Vec
, - add: Vec, - - /// Set of operators who still need to pull the data to finish the - /// migration. - pulling_operators: HashSet
, - - new_keyspace: Keyspace, -} - -struct Region { - operators: SlotMap, - - under_maintenance: Option
, - - keyspace: Keyspace, - - migration: Option, -} - -struct Contract { - regions: Vec, - - version: u128, -} - -impl Contract { - const MAX_OPERATORS_PER_REGION: usize = 256; - - /// Begins a data migration process by adding/removing operators to/from a - /// region. - /// - /// Requires "Admin" signature. - fn start_migration(&mut self, region_id: u8, remove: Vec
, add: Vec) { - let region = &mut self.regions[region_id as usize]; - - assert!(region.migration.is_some(), "migration already in progress"); - assert!(!remove.is_empty() || !add.is_empty(), "nothing to do"); - - for addr in &remove { - assert!(region.operators.contains_key(addr), "unknown operator"); - } - - for new in &add { - assert!( - new.inner.nodes.len() >= 2, - "operators should have at least 2 nodes" - ); - - assert!( - !region.operators.contains_key(&new.address), - "operator already exists" - ); - } - - let mut pulling_operators: HashSet<_> = region - .operators - .keys() - .chain(add.iter().map(|new| &new.address)) - .copied() - .collect(); - - for addr in &remove { - pulling_operators.remove(addr); - } - - region.migration = Some(Migration { - remove: remove.clone(), - add: add.clone(), - pulling_operators, - new_keyspace: Keyspace { - version: region.keyspace.version + 1, - }, - }); - - self.version += 1; - // emit_migration_started(region_id, remove, add, self.version); - } - - /// Removes an operator from [`Migration::pending_operators`]. - /// - /// Requires "Operator" signature. - fn complete_migration(&mut self, region_id: u8, operator: Address) { - let region = &mut self.regions[region_id as usize]; - - let migration = region.migration.as_mut().expect("no migration"); - - assert!( - migration.pulling_operators.remove(&operator), - "already completed" - ); - - self.version += 1; - - if !migration.pulling_operators.is_empty() { - // emit_operator_migration_completed(region_id, operator, self.version); - return; - } - - region.keyspace = migration.new_keyspace; - - for addr in &migration.remove { - region.operators.remove(addr); - } - - // TODO: prefer replacing removed nodes. - - for new in &migration.add { - region.operators.insert(new.address, new.inner.clone()); - } - - drop(migration); - region.migration = None; - - // emit_migration_completed(region_id, self.version); - } - - /// Aborts an ongoing data migration. - /// - /// Requires "Admin" signature. - fn abort_migration(&mut self, region_id: u8) { - let region = &mut self.regions[region_id as usize]; - - assert!(region.migration.is_some(), "no migration"); - - region.migration = None; - self.version += 1; - // emit_migration_aborted(region_id, self.version); - } - - /// Acquires the maintenance slot for the provided operator. - /// - /// Requires "Operator" signature. - fn start_maintenance(&mut self, region_id: u8, operator: Address) { - let region = &mut self.regions[region_id as usize]; - - assert!(region.migration.is_none(), "ongoing migration"); - assert!(region.under_maintenance.is_none(), "occupied"); - - region.under_maintenance = Some(operator); - self.version += 1; - - // emit_maintenance_started(region_id, operator, version); - } - - /// Releases the maintenance slot occupied by the provided operator. - /// - /// Requires "Operator" signature. - fn finish_maintenance(&mut self, region_id: u8, operator: Address) { - let region = &mut self.regions[region_id as usize]; - - assert_eq!( - region.under_maintenance.as_ref(), - Some(&operator), - "not occupied by the provided operator" - ); - - region.under_maintenance = None; - self.version += 1; - - // emit_maintenance_finished(region_id, operator, version); - } - - /// Adds a (coordinator) node. - /// - /// Requires "Operator" signature. - fn add_node(&mut self, region_id: u8, operator: Address, node_addr: SocketAddrV4) { - let region = &mut self.regions[region_id as usize]; - let operator = region - .operators - .get_mut(&operator) - .expect("unknown operator"); - - assert!(!operator.nodes.contains_key(&node_addr), "already exists"); - operator.nodes.insert(node_addr, Node {}); - // emit_node_added(region_id, operator, node_addr, node); - } - - /// Removes a (coordinator) node. - /// - /// Requires "Operator" signature. - fn remove_node(&mut self, region_id: u8, operator: Address, node_addr: SocketAddrV4) { - let region = &mut self.regions[region_id as usize]; - let operator = region - .operators - .get_mut(&operator) - .expect("unknown operator"); - - assert!(operator.nodes.contains_key(&node_addr), "not found"); - operator.nodes.remove(&node_addr); - // emit_node_removed(region_id, operator, node_addr); - } -} diff --git a/crates/contract/src/network.sol b/crates/contract/src/network.sol deleted file mode 100644 index 8b137891..00000000 --- a/crates/contract/src/network.sol +++ /dev/null @@ -1 +0,0 @@ - From 8cfd9351e1e344e3e86833752546109bd1a6a5c2 Mon Sep 17 00:00:00 2001 From: Github Bot Date: Thu, 8 May 2025 09:56:20 +0000 Subject: [PATCH 07/79] Bump VERSION to 250508.0 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index dc2f8a38..83bc0c2c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -250507.0 +250508.0 From bf8f6f94638d186f1fa770a3f2f4280d9c791e9f Mon Sep 17 00:00:00 2001 From: Darksome Date: Thu, 8 May 2025 22:39:55 +0000 Subject: [PATCH 08/79] more tests / bug fixes --- Cargo.lock | 4 - contracts/src/Cluster/Cluster.sol | 31 ++- contracts/src/Cluster/Maintenance.sol | 11 +- contracts/src/Cluster/Migration.sol | 5 +- contracts/test/Suite.sol | 355 +++++++++++++++++++++++--- 5 files changed, 342 insertions(+), 64 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b3fa18d9..42e0ade5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6857,10 +6857,6 @@ dependencies = [ "wcn_rpc", ] -[[package]] -name = "wcn_contract" -version = "0.1.0" - [[package]] name = "wcn_core" version = "0.1.0" diff --git a/contracts/src/Cluster/Cluster.sol b/contracts/src/Cluster/Cluster.sol index caa487c7..7f4aa218 100644 --- a/contracts/src/Cluster/Cluster.sol +++ b/contracts/src/Cluster/Cluster.sol @@ -31,7 +31,8 @@ contract Cluster { event MigrationAborted(uint128 version); event MaintenanceStarted(address operator, uint128 version); - event MaintenanceFinished(address operator, uint128 version); + event MaintenanceCompleted(address operator, uint128 version); + event MaintenanceAborted(uint128 version); event NodeSet(address operator, Node node, uint128 version); event NodeRemoved(address operator, uint256 id, uint128 version); @@ -63,8 +64,8 @@ contract Cluster { _; } - modifier onlyMember() { - require(operators.exists(msg.sender), "not a member"); + modifier onlyOperator() { + require(operators.exists(msg.sender), "not an operator"); _; } @@ -73,7 +74,7 @@ contract Cluster { } function startMigration(address[] calldata operatorsToRemove, NodeOperatorView[] calldata operatorsToAdd) external onlyOwner { - require(!maintenance.inProgress(), "maintenance is in progress"); + require(!maintenance.inProgress(), "maintenance in progress"); for (uint256 i = 0; i < operatorsToRemove.length; i++) { require(operators.exists(operatorsToRemove[i]), "unknown operator"); @@ -91,7 +92,7 @@ contract Cluster { emit MigrationStarted(operatorsToRemove, operatorsToAdd, version); } - function completeMigration() external onlyMember { + function completeMigration() external { migration.completeDataPull(msg.sender); version++; emit MigrationDataPullCompleted(msg.sender, version); @@ -122,27 +123,33 @@ contract Cluster { emit MigrationAborted(version); } - function startMaintenance() external onlyMember { - require(!migration.inProgress(), "migration is in progress"); + function startMaintenance() external onlyOperator { + require(!migration.inProgress(), "migration in progress"); maintenance.start(msg.sender); version++; emit MaintenanceStarted(msg.sender, version); } - function finishMaintenance() external onlyMember { - maintenance.finish(msg.sender); + function completeMaintenance() external onlyOperator { + maintenance.complete(msg.sender); version++; - emit MaintenanceFinished(msg.sender, version); + emit MaintenanceCompleted(msg.sender, version); } - function setNode(Node calldata node) external onlyMember { + function abortMaintenance() external onlyOwner { + maintenance.abort(); + version++; + emit MaintenanceAborted(version); + } + + function setNode(Node calldata node) external onlyOperator { operators.setNode(msg.sender, node); version++; emit NodeSet(msg.sender, node, version); } - function removeNode(uint256 id) external onlyMember { + function removeNode(uint256 id) external onlyOperator { operators.removeNode(msg.sender, id); version++; emit NodeRemoved(msg.sender, id, version); diff --git a/contracts/src/Cluster/Maintenance.sol b/contracts/src/Cluster/Maintenance.sol index 00bd0817..870a9cd4 100644 --- a/contracts/src/Cluster/Maintenance.sol +++ b/contracts/src/Cluster/Maintenance.sol @@ -8,13 +8,18 @@ struct Maintenance { library MaintenanceLib { function start(Maintenance storage self, address operator) public { require(operator != address(0), "invalid address"); - require(self.slot == address(0), "already occupied"); + require(self.slot == address(0), "another maintenance in progress"); self.slot = operator; } - function finish(Maintenance storage self, address operator) public { + function complete(Maintenance storage self, address operator) public { require(operator != address(0), "invalid address"); - require(self.slot == operator, "not occupied"); + require(self.slot == operator, "not under maintenance"); + delete self.slot; + } + + function abort(Maintenance storage self) public { + require(self.slot != address(0), "not under maintenance"); delete self.slot; } diff --git a/contracts/src/Cluster/Migration.sol b/contracts/src/Cluster/Migration.sol index c13d1255..381556e9 100644 --- a/contracts/src/Cluster/Migration.sol +++ b/contracts/src/Cluster/Migration.sol @@ -30,9 +30,6 @@ library MigrationLib { require(!inProgress(self), "migration already in progress"); require(operatorsToRemove.length > 0 || operatorsToAdd.length > 0, "nothing to do"); - self.operatorsToRemove = operatorsToRemove; - self.operatorsToAdd = operatorsToAdd; - for (uint256 i = 0; i < currentOperators.length; i++) { if (currentOperators[i].addr != address(0)) { self.pullingOperators[currentOperators[i].addr] = true; @@ -54,7 +51,7 @@ library MigrationLib { } function completeDataPull(Migration storage self, address operator) public { - require(self.pullingOperators[operator], "already completed"); + require(self.pullingOperators[operator], "not pulling"); self.pullingOperators[operator] = false; self.pullingOperatorsCount--; } diff --git a/contracts/test/Suite.sol b/contracts/test/Suite.sol index 73b651d9..d535bf6a 100644 --- a/contracts/test/Suite.sol +++ b/contracts/test/Suite.sol @@ -1,12 +1,27 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; -import {Test} from "../dependencies/forge-std-1.9.7/src/Test.sol"; +import "../dependencies/forge-std-1.9.7/src/Test.sol"; import {Vm} from "../dependencies/forge-std-1.9.7/src/Vm.sol"; import "../dependencies/forge-std-1.9.7/src/console.sol"; import "../src/Cluster/Cluster.sol"; +uint256 constant OWNER = 12345; +uint256 constant ANYONE = 9000; + +uint256 constant OPERATOR_A = 1; +uint256 constant OPERATOR_B = 2; +uint256 constant OPERATOR_C = 3; + +uint256 constant EXTRA_OPERATOR = 1000; + +uint256 constant MIN_OPERATORS = 5; +uint256 constant MIN_NODES = 1; + +uint256 constant MAX_OPERATORS = 256; +uint256 constant MAX_NODES = 256; + contract ClusterTestSuite is Test { using TestClusterLib for TestCluster; @@ -18,113 +33,315 @@ contract ClusterTestSuite is Test { } } + // contructor + function test_canNotCreateClusterWithTooFewOperators() public { vm.expectRevert("too few operators"); - newTestCluster(vm, Settings({ minOperators: 3, minNodes: 1 }), 2, 1); + newTestCluster(vm, MIN_OPERATORS - 1, MIN_NODES); } function test_canNotCreateClusterWithTooFewNodes() public { vm.expectRevert("too few nodes"); - newTestCluster(vm, Settings({ minOperators: 3, minNodes: 2 }), 3, 1); + newTestCluster(vm, MIN_OPERATORS, MIN_NODES - 1); } function test_canNotCreateClusterWithTooManyOperators() public { vm.expectRevert("too many operators"); - newTestCluster(vm, Settings({ minOperators: 3, minNodes: 1 }), 257, 1); + newTestCluster(vm, MAX_OPERATORS + 1, MIN_NODES); } function test_canNotCreateClusterWithTooManyNodes() public { vm.expectRevert("too many nodes"); - newTestCluster(vm, Settings({ minOperators: 3, minNodes: 2 }), 3, 257); + newTestCluster(vm, MIN_OPERATORS, MAX_NODES + 1); } function test_canCreateClusterWithMinNumberOfOperatorsAndNodes() public { - newTestCluster(vm, Settings({ minOperators: 3, minNodes: 2 }), 3, 2); + newTestCluster(vm, MIN_OPERATORS, MIN_NODES); } function test_canCreateClusterWithMaxNumberOfOperators() public { - newTestCluster(vm, Settings({ minOperators: 3, minNodes: 2 }), 256, 2); + newTestCluster(vm, MAX_OPERATORS, MIN_NODES); } function test_canCreateClusterWithMaxNumberOfNodes() public { - newTestCluster(vm, Settings({ minOperators: 3, minNodes: 2 }), 3, 256); + newTestCluster(vm, MIN_OPERATORS, MAX_NODES); + } + + function test_clusterInitialVersionIs0() public { + newTestCluster(vm).assertVersion(0); } - function test_arbitraryKeypairCanNotStartMigration() public { + function test_clusterInitialKeyspaceVersionIs0() public { + newTestCluster(vm).assertKeyspaceVersion(0); + } + + // startMigration + + function test_anyoneCanNotStartMigration() public { newTestCluster(vm) - .prepareMigration(0, 1) - .addOperator(10) - .setCaller(42) - .startMigration("not the owner"); + .expectRevert("not the owner") + .startMigration(ANYONE, 0, 1); } - function test_memberKeypairCanNotStartMigration() public { + function test_operatorCanNotStartMigration() public { newTestCluster(vm) - .prepareMigration(0, 1) - .addOperator(10) - .setCaller(1) - .startMigration("not the owner"); + .expectRevert("not the owner") + .startMigration(OPERATOR_A, 0, 1); } - function test_ownerKeypairCanStartMigration() public { + function test_ownerCanStartMigration() public { newTestCluster(vm) - .prepareMigration(0, 1) - .addOperator(10) - .startMigration(); + .startMigration(OWNER, 0, 1); } function test_canNotStartMigrationWithTooManyOperators() public { - newTestCluster(vm, Settings({ minOperators: 3, minNodes: 2 })) - .generateMigration(0, 256 - 3 + 1) - .startMigration("too many operators"); + newTestCluster(vm) + .generateMigration(0, MAX_OPERATORS - MIN_OPERATORS + 1) + .expectRevert("too many operators") + .startMigration(OWNER); } function test_canNotStartMigrationWithTooFewOperators() public { - newTestCluster(vm, Settings({ minOperators: 3, minNodes: 2 })) - .generateMigration(2, 1) - .startMigration("too few operators"); + newTestCluster(vm) + .generateMigration(1, 0) + .expectRevert("too few operators") + .startMigration(OWNER); } function test_canStartMigrationWhenAddedOperatorsReplenishRemoved() public { - newTestCluster(vm, Settings({ minOperators: 3, minNodes: 2 })) - .generateMigration(3, 3) - .startMigration(); + newTestCluster(vm) + .generateMigration(MIN_OPERATORS, MIN_OPERATORS) + .startMigration(OWNER); + } + + function test_canNotStartMigrationWithTooManyNodes() public { + newTestCluster(vm) + .prepareMigration(0, 1) + .addOperator(EXTRA_OPERATOR, MAX_NODES + 1) + .expectRevert("too many nodes") + .startMigration(OWNER); + } + + function test_canNotStartMigrationWithTooFewNodes() public { + newTestCluster(vm) + .prepareMigration(0, 1) + .addOperator(EXTRA_OPERATOR, MIN_NODES - 1) + .expectRevert("too few nodes") + .startMigration(OWNER); + } + + function test_canNotStartMigrationWhenMaintenanceInProgress() public { + newTestCluster(vm) + .startMaintenance(OPERATOR_A) + .expectRevert("maintenance in progress") + .startMigration(OWNER, 0, 1); + } + + function test_startMigrationBumpsVersion() public { + newTestCluster(vm) + .startMigration(OWNER, 0, 1) + .assertVersion(1); + } + + function test_startMigrationDoesNotBumpKeyspaceVersion() public { + newTestCluster(vm) + .startMigration(OWNER, 0, 1) + .assertKeyspaceVersion(0); + } + + // completeMigration + + function test_anyoneCanNotCompleteMigration() public { + newTestCluster(vm) + .startMigration(OWNER, 0, 1) + .expectRevert("not pulling") + .completeMigration(ANYONE); + } + + function test_ownerCanNotCompleteMigration() public { + newTestCluster(vm) + .startMigration(OWNER, 0, 1) + .expectRevert("not pulling") + .completeMigration(OWNER); + } + + function test_operatorCanNotCompleteNonExistentMigration() public { + newTestCluster(vm) + .expectRevert("not pulling") + .completeMigration(OPERATOR_A); + } + + function test_operatorCanCompleteMigration() public { + newTestCluster(vm) + .startMigration(OWNER, 0, 1) + .completeMigration(OPERATOR_A); + } + + function test_operatorCanNotCompleteMigrationTwice() public { + newTestCluster(vm) + .startMigration(OWNER, 0, 1) + .completeMigration(OPERATOR_A) + .expectRevert("not pulling") + .completeMigration(OPERATOR_A); + } + + function test_completeMigrationBumpsVersion() public { + newTestCluster(vm) + .startMigration(OWNER, 0, 1) + .completeMigration(OPERATOR_A) + .assertVersion(2); + } + + function test_completeMigrationDoesNotBumpKeyspaceVersionIfNotCompleted() public { + newTestCluster(vm) + .startMigration(OWNER, 0, 1) + .completeMigration(OPERATOR_A) + .assertKeyspaceVersion(0); + } + + function test_completeMigrationBumpKeyspaceVersionIfCompleted() public { + newTestCluster(vm, Settings({ minOperators: 3, minNodes: uint8(MIN_NODES) })) + .startMigration(OWNER, 0, 1) + .completeMigration(OPERATOR_A) + .completeMigration(OPERATOR_B) + .completeMigration(OPERATOR_C) + .completeMigration(EXTRA_OPERATOR) + .assertKeyspaceVersion(1); + } + + // startMaintenance + + function test_anyoneCanNotStartMaintenance() public { + newTestCluster(vm) + .expectRevert("not an operator") + .startMaintenance(ANYONE); + } + + function test_ownerCanNotStartMaintenance() public { + newTestCluster(vm) + .expectRevert("not an operator") + .startMaintenance(OWNER); + } + + function test_operatorCanStartMaintenance() public { + newTestCluster(vm) + .startMaintenance(OPERATOR_A); + } + + function test_operatorCanNotStartMaintenanceWhenMigrationInProgress() public { + newTestCluster(vm) + .startMigration(OWNER, 0, 1) + .expectRevert("migration in progress") + .startMaintenance(OPERATOR_A); + } + + // copleteMaintenance + + function test_anyoneCanNotCompleteMaintenance() public { + newTestCluster(vm) + .expectRevert("not an operator") + .startMaintenance(ANYONE); + } + + function test_anotherOperatorCanNotCompleteMaintenance() public { + newTestCluster(vm) + .startMaintenance(OPERATOR_A) + .expectRevert("not under maintenance") + .completeMaintenance(OPERATOR_B); + } + + function test_ownerCanNotCompleteMaintenance() public { + newTestCluster(vm) + .startMaintenance(OPERATOR_A) + .expectRevert("not an operator") + .completeMaintenance(OWNER); + } + + function test_sameOperatorCanCompleteMaintenance() public { + newTestCluster(vm) + .startMaintenance(OPERATOR_A) + .completeMaintenance(OPERATOR_A); + } + + function test_canNotCompleteNonExistentMaintenance() public { + newTestCluster(vm) + .expectRevert("not under maintenance") + .completeMaintenance(OPERATOR_A); + } + + // abortMaintenance + + function test_anyoneCanNotAbortMaintenance() public { + newTestCluster(vm) + .startMaintenance(OPERATOR_A) + .expectRevert("not the owner") + .abortMaintenance(ANYONE); + } + + function test_operatorCanNotAbortMaintenance() public { + newTestCluster(vm) + .startMaintenance(OPERATOR_A) + .expectRevert("not the owner") + .abortMaintenance(OPERATOR_B); + } + + function test_ownerCanAbortMaintenance() public { + newTestCluster(vm) + .startMaintenance(OPERATOR_A) + .abortMaintenance(OWNER); + } +} + +contract TestTools is Test { + function assertEq(uint128 a, uint128 b) public pure { + super.assertEq(uint256(a), uint256(b)); } } struct TestCluster { Cluster inner; - Vm vm; + Vm vm; + TestTools tools; address[] operatorsToRemove; uint256 operatorsToRemoveLen; NodeOperatorView[] operatorsToAdd; uint256 operatorsToAddLen; + + bytes revertBytes; } function newTestCluster(Vm vm) returns (TestCluster memory) { - return newTestCluster(vm, Settings({ minOperators: 5, minNodes: 2 })); + return newTestCluster(vm, Settings({ minOperators: uint8(MIN_OPERATORS), minNodes: uint8(MIN_NODES) })); } function newTestCluster(Vm vm, Settings memory settings) returns (TestCluster memory) { return newTestCluster(vm, settings, settings.minOperators, settings.minNodes); } +function newTestCluster(Vm vm, uint256 operatorsCount, uint256 nodesCount) returns (TestCluster memory) { + return newTestCluster(vm, Settings({ minOperators: uint8(MIN_OPERATORS), minNodes: uint8(MIN_NODES) }), operatorsCount, nodesCount); +} + function newTestCluster(Vm vm, Settings memory settings, uint256 operatorsCount, uint256 nodesCount) returns (TestCluster memory) { NodeOperatorView[] memory operators = new NodeOperatorView[](operatorsCount); for (uint256 i = 0; i < operatorsCount; i++) { operators[i] = newNodeOperator(vm.addr(i + 1), nodesCount); } + vm.prank(vm.addr(OWNER)); + return TestCluster({ inner: new Cluster(settings, operators), vm: vm, + tools: new TestTools(), operatorsToRemove: new address[](0), operatorsToRemoveLen: 0, operatorsToAdd: new NodeOperatorView[](0), - operatorsToAddLen: 0 + operatorsToAddLen: 0, + revertBytes: new bytes(0) }); } @@ -134,7 +351,24 @@ library TestClusterLib { return self; } - function generateMigration(TestCluster memory self, uint256 operatorsToRemove, uint operatorsToAdd) public view returns (TestCluster memory) { + function expectRevert(TestCluster memory self, bytes memory revertBytes) public pure returns (TestCluster memory) { + self.revertBytes = revertBytes; + return self; + } + + function assertVersion(TestCluster memory self, uint128 expectedVersion) public view returns (TestCluster memory){ + ClusterView memory clusterView = self.inner.getView(); + self.tools.assertEq(clusterView.version, expectedVersion); + return self; + } + + function assertKeyspaceVersion(TestCluster memory self, uint64 expectedVersion) public view returns (TestCluster memory){ + ClusterView memory clusterView = self.inner.getView(); + self.tools.assertEq(clusterView.keyspaceVersion, expectedVersion); + return self; + } + + function generateMigration(TestCluster memory self, uint256 operatorsToRemove, uint256 operatorsToAdd) public view returns (TestCluster memory) { prepareMigration(self, operatorsToRemove, operatorsToAdd); ClusterView memory clusterView = self.inner.getView(); @@ -151,7 +385,7 @@ library TestClusterLib { require(operatorsToRemove == 0); for (uint256 i = 0; i < operatorsToAdd; i++) { - addOperator(self, i + 100); + addOperator(self, EXTRA_OPERATOR + i); } return self; @@ -191,16 +425,55 @@ library TestClusterLib { return self; } - function startMigration(TestCluster memory self, bytes calldata revertBytes) public returns (TestCluster memory) { - self.vm.expectRevert(revertBytes); - startMigration(self); - return self; + function startMigration(TestCluster memory self, uint256 caller, uint256 operatorsToRemove, uint256 operatorsToAdd) public returns (TestCluster memory) { + generateMigration(self, operatorsToRemove, operatorsToAdd); + return startMigration(self, caller); } - function startMigration(TestCluster memory self) public returns (TestCluster memory) { + function startMigration(TestCluster memory self, uint256 caller) public returns (TestCluster memory) { + setCaller(self, caller); + if (self.revertBytes.length != 0) { + self.vm.expectRevert(self.revertBytes); + } self.inner.startMigration(self.operatorsToRemove, self.operatorsToAdd); return self; } + + function completeMigration(TestCluster memory self, uint256 caller) public returns (TestCluster memory) { + setCaller(self, caller); + if (self.revertBytes.length != 0) { + self.vm.expectRevert(self.revertBytes); + } + self.inner.completeMigration(); + return self; + } + + function startMaintenance(TestCluster memory self, uint256 caller) public returns (TestCluster memory) { + setCaller(self, caller); + if (self.revertBytes.length != 0) { + self.vm.expectRevert(self.revertBytes); + } + self.inner.startMaintenance(); + return self; + } + + function completeMaintenance(TestCluster memory self, uint256 caller) public returns (TestCluster memory) { + setCaller(self, caller); + if (self.revertBytes.length != 0) { + self.vm.expectRevert(self.revertBytes); + } + self.inner.completeMaintenance(); + return self; + } + + function abortMaintenance(TestCluster memory self, uint256 caller) public returns (TestCluster memory) { + setCaller(self, caller); + if (self.revertBytes.length != 0) { + self.vm.expectRevert(self.revertBytes); + } + self.inner.abortMaintenance(); + return self; + } } function newNodeOperator(address addr, uint256 nodesCount) pure returns (NodeOperatorView memory) { From eecceee6fcd95535fbbf9e54ddfcfc30da29c7f1 Mon Sep 17 00:00:00 2001 From: Darksome Date: Fri, 9 May 2025 21:15:54 +0000 Subject: [PATCH 09/79] make gas reporter work --- contracts/test/Suite.sol | 464 +++++++++++++++++---------------------- 1 file changed, 205 insertions(+), 259 deletions(-) diff --git a/contracts/test/Suite.sol b/contracts/test/Suite.sol index d535bf6a..dc32b686 100644 --- a/contracts/test/Suite.sol +++ b/contracts/test/Suite.sol @@ -22,12 +22,16 @@ uint256 constant MIN_NODES = 1; uint256 constant MAX_OPERATORS = 256; uint256 constant MAX_NODES = 256; -contract ClusterTestSuite is Test { - using TestClusterLib for TestCluster; +contract ClusterTest is Test { + Cluster cluster; + ClusterView clusterView; mapping(address => uint256) privateKeys; constructor() { + newCluster(vm); + updateClusterView(); + for (uint256 k = 1; k <= 10; k++) { privateKeys[vm.addr(k)] = k; } @@ -36,446 +40,388 @@ contract ClusterTestSuite is Test { // contructor function test_canNotCreateClusterWithTooFewOperators() public { - vm.expectRevert("too few operators"); - newTestCluster(vm, MIN_OPERATORS - 1, MIN_NODES); + expectRevert("too few operators"); + newCluster(vm, MIN_OPERATORS - 1, MIN_NODES); } function test_canNotCreateClusterWithTooFewNodes() public { - vm.expectRevert("too few nodes"); - newTestCluster(vm, MIN_OPERATORS, MIN_NODES - 1); + expectRevert("too few nodes"); + newCluster(vm, MIN_OPERATORS, MIN_NODES - 1); } function test_canNotCreateClusterWithTooManyOperators() public { - vm.expectRevert("too many operators"); - newTestCluster(vm, MAX_OPERATORS + 1, MIN_NODES); + expectRevert("too many operators"); + newCluster(vm, MAX_OPERATORS + 1, MIN_NODES); } function test_canNotCreateClusterWithTooManyNodes() public { - vm.expectRevert("too many nodes"); - newTestCluster(vm, MIN_OPERATORS, MAX_NODES + 1); + expectRevert("too many nodes"); + newCluster(vm, MIN_OPERATORS, MAX_NODES + 1); } function test_canCreateClusterWithMinNumberOfOperatorsAndNodes() public { - newTestCluster(vm, MIN_OPERATORS, MIN_NODES); + newCluster(vm, MIN_OPERATORS, MIN_NODES); } function test_canCreateClusterWithMaxNumberOfOperators() public { - newTestCluster(vm, MAX_OPERATORS, MIN_NODES); + newCluster(vm, MAX_OPERATORS, MIN_NODES); } function test_canCreateClusterWithMaxNumberOfNodes() public { - newTestCluster(vm, MIN_OPERATORS, MAX_NODES); + newCluster(vm, MIN_OPERATORS, MAX_NODES); } function test_clusterInitialVersionIs0() public { - newTestCluster(vm).assertVersion(0); + assertVersion(0); } function test_clusterInitialKeyspaceVersionIs0() public { - newTestCluster(vm).assertKeyspaceVersion(0); + assertKeyspaceVersion(0); } // startMigration function test_anyoneCanNotStartMigration() public { - newTestCluster(vm) - .expectRevert("not the owner") - .startMigration(ANYONE, 0, 1); + expectRevert("not the owner"); + startMigration(ANYONE); } function test_operatorCanNotStartMigration() public { - newTestCluster(vm) - .expectRevert("not the owner") - .startMigration(OPERATOR_A, 0, 1); + expectRevert("not the owner"); + startMigration(OPERATOR_A); } function test_ownerCanStartMigration() public { - newTestCluster(vm) - .startMigration(OWNER, 0, 1); + startMigration(OWNER); } function test_canNotStartMigrationWithTooManyOperators() public { - newTestCluster(vm) - .generateMigration(0, MAX_OPERATORS - MIN_OPERATORS + 1) - .expectRevert("too many operators") - .startMigration(OWNER); + expectRevert("too many operators"); + startMigration(OWNER, 0, MAX_OPERATORS - MIN_OPERATORS + 1); } function test_canNotStartMigrationWithTooFewOperators() public { - newTestCluster(vm) - .generateMigration(1, 0) - .expectRevert("too few operators") - .startMigration(OWNER); + expectRevert("too few operators"); + startMigration(OWNER, 1, 0); } function test_canStartMigrationWhenAddedOperatorsReplenishRemoved() public { - newTestCluster(vm) - .generateMigration(MIN_OPERATORS, MIN_OPERATORS) - .startMigration(OWNER); + startMigration(OWNER, MIN_OPERATORS, MIN_OPERATORS); } function test_canNotStartMigrationWithTooManyNodes() public { - newTestCluster(vm) - .prepareMigration(0, 1) - .addOperator(EXTRA_OPERATOR, MAX_NODES + 1) - .expectRevert("too many nodes") - .startMigration(OWNER); + expectRevert("too many nodes"); + startMigration(OWNER, newMigration().addOperator(EXTRA_OPERATOR, MAX_NODES + 1)); } function test_canNotStartMigrationWithTooFewNodes() public { - newTestCluster(vm) - .prepareMigration(0, 1) - .addOperator(EXTRA_OPERATOR, MIN_NODES - 1) - .expectRevert("too few nodes") - .startMigration(OWNER); + expectRevert("too few nodes"); + startMigration(OWNER, newMigration().addOperator(EXTRA_OPERATOR, MIN_NODES - 1)); } function test_canNotStartMigrationWhenMaintenanceInProgress() public { - newTestCluster(vm) - .startMaintenance(OPERATOR_A) - .expectRevert("maintenance in progress") - .startMigration(OWNER, 0, 1); + startMaintenance(OPERATOR_A); + expectRevert("maintenance in progress"); + startMigration(OWNER, 0, 1); } function test_startMigrationBumpsVersion() public { - newTestCluster(vm) - .startMigration(OWNER, 0, 1) - .assertVersion(1); + startMigration(OWNER, 0, 1); + assertVersion(1); } function test_startMigrationDoesNotBumpKeyspaceVersion() public { - newTestCluster(vm) - .startMigration(OWNER, 0, 1) - .assertKeyspaceVersion(0); + startMigration(OWNER, 0, 1); + assertKeyspaceVersion(0); } // completeMigration function test_anyoneCanNotCompleteMigration() public { - newTestCluster(vm) - .startMigration(OWNER, 0, 1) - .expectRevert("not pulling") - .completeMigration(ANYONE); + startMigration(OWNER, 0, 1); + expectRevert("not pulling"); + completeMigration(ANYONE); } function test_ownerCanNotCompleteMigration() public { - newTestCluster(vm) - .startMigration(OWNER, 0, 1) - .expectRevert("not pulling") - .completeMigration(OWNER); + startMigration(OWNER, 0, 1); + expectRevert("not pulling"); + completeMigration(OWNER); } function test_operatorCanNotCompleteNonExistentMigration() public { - newTestCluster(vm) - .expectRevert("not pulling") - .completeMigration(OPERATOR_A); + expectRevert("not pulling"); + completeMigration(OPERATOR_A); } function test_operatorCanCompleteMigration() public { - newTestCluster(vm) - .startMigration(OWNER, 0, 1) - .completeMigration(OPERATOR_A); + startMigration(OWNER, 0, 1); + completeMigration(OPERATOR_A); } function test_operatorCanNotCompleteMigrationTwice() public { - newTestCluster(vm) - .startMigration(OWNER, 0, 1) - .completeMigration(OPERATOR_A) - .expectRevert("not pulling") - .completeMigration(OPERATOR_A); + startMigration(OWNER, 0, 1); + completeMigration(OPERATOR_A); + expectRevert("not pulling"); + completeMigration(OPERATOR_A); } function test_completeMigrationBumpsVersion() public { - newTestCluster(vm) - .startMigration(OWNER, 0, 1) - .completeMigration(OPERATOR_A) - .assertVersion(2); + startMigration(OWNER, 0, 1); + completeMigration(OPERATOR_A); + assertVersion(2); } function test_completeMigrationDoesNotBumpKeyspaceVersionIfNotCompleted() public { - newTestCluster(vm) - .startMigration(OWNER, 0, 1) - .completeMigration(OPERATOR_A) - .assertKeyspaceVersion(0); + startMigration(OWNER, 0, 1); + completeMigration(OPERATOR_A); + assertKeyspaceVersion(0); } function test_completeMigrationBumpKeyspaceVersionIfCompleted() public { - newTestCluster(vm, Settings({ minOperators: 3, minNodes: uint8(MIN_NODES) })) - .startMigration(OWNER, 0, 1) - .completeMigration(OPERATOR_A) - .completeMigration(OPERATOR_B) - .completeMigration(OPERATOR_C) - .completeMigration(EXTRA_OPERATOR) - .assertKeyspaceVersion(1); + newCluster(vm, Settings({ minOperators: 3, minNodes: uint8(MIN_NODES) })); + startMigration(OWNER, 0, 1); + completeMigration(OPERATOR_A); + completeMigration(OPERATOR_B); + completeMigration(OPERATOR_C); + completeMigration(EXTRA_OPERATOR); + assertKeyspaceVersion(1); } // startMaintenance function test_anyoneCanNotStartMaintenance() public { - newTestCluster(vm) - .expectRevert("not an operator") - .startMaintenance(ANYONE); + expectRevert("not an operator"); + startMaintenance(ANYONE); } function test_ownerCanNotStartMaintenance() public { - newTestCluster(vm) - .expectRevert("not an operator") - .startMaintenance(OWNER); + expectRevert("not an operator"); + startMaintenance(OWNER); } function test_operatorCanStartMaintenance() public { - newTestCluster(vm) - .startMaintenance(OPERATOR_A); + startMaintenance(OPERATOR_A); } function test_operatorCanNotStartMaintenanceWhenMigrationInProgress() public { - newTestCluster(vm) - .startMigration(OWNER, 0, 1) - .expectRevert("migration in progress") - .startMaintenance(OPERATOR_A); + startMigration(OWNER, 0, 1); + expectRevert("migration in progress"); + startMaintenance(OPERATOR_A); } // copleteMaintenance function test_anyoneCanNotCompleteMaintenance() public { - newTestCluster(vm) - .expectRevert("not an operator") - .startMaintenance(ANYONE); + expectRevert("not an operator"); + startMaintenance(ANYONE); } function test_anotherOperatorCanNotCompleteMaintenance() public { - newTestCluster(vm) - .startMaintenance(OPERATOR_A) - .expectRevert("not under maintenance") - .completeMaintenance(OPERATOR_B); + startMaintenance(OPERATOR_A); + expectRevert("not under maintenance"); + completeMaintenance(OPERATOR_B); } function test_ownerCanNotCompleteMaintenance() public { - newTestCluster(vm) - .startMaintenance(OPERATOR_A) - .expectRevert("not an operator") - .completeMaintenance(OWNER); + startMaintenance(OPERATOR_A); + expectRevert("not an operator"); + completeMaintenance(OWNER); } function test_sameOperatorCanCompleteMaintenance() public { - newTestCluster(vm) - .startMaintenance(OPERATOR_A) - .completeMaintenance(OPERATOR_A); + startMaintenance(OPERATOR_A); + completeMaintenance(OPERATOR_A); } function test_canNotCompleteNonExistentMaintenance() public { - newTestCluster(vm) - .expectRevert("not under maintenance") - .completeMaintenance(OPERATOR_A); + expectRevert("not under maintenance"); + completeMaintenance(OPERATOR_A); } // abortMaintenance function test_anyoneCanNotAbortMaintenance() public { - newTestCluster(vm) - .startMaintenance(OPERATOR_A) - .expectRevert("not the owner") - .abortMaintenance(ANYONE); + startMaintenance(OPERATOR_A); + expectRevert("not the owner"); + abortMaintenance(ANYONE); } function test_operatorCanNotAbortMaintenance() public { - newTestCluster(vm) - .startMaintenance(OPERATOR_A) - .expectRevert("not the owner") - .abortMaintenance(OPERATOR_B); + startMaintenance(OPERATOR_A); + expectRevert("not the owner"); + abortMaintenance(OPERATOR_B); } function test_ownerCanAbortMaintenance() public { - newTestCluster(vm) - .startMaintenance(OPERATOR_A) - .abortMaintenance(OWNER); + startMaintenance(OPERATOR_A); + abortMaintenance(OWNER); } -} -contract TestTools is Test { - function assertEq(uint128 a, uint128 b) public pure { - super.assertEq(uint256(a), uint256(b)); + function newCluster(Vm vm) internal { + return newCluster(vm, Settings({ minOperators: uint8(MIN_OPERATORS), minNodes: uint8(MIN_NODES) })); } -} - -struct TestCluster { - Cluster inner; - - Vm vm; - TestTools tools; - - address[] operatorsToRemove; - uint256 operatorsToRemoveLen; - - NodeOperatorView[] operatorsToAdd; - uint256 operatorsToAddLen; - bytes revertBytes; -} - -function newTestCluster(Vm vm) returns (TestCluster memory) { - return newTestCluster(vm, Settings({ minOperators: uint8(MIN_OPERATORS), minNodes: uint8(MIN_NODES) })); -} + function newCluster(Vm vm, Settings memory settings) internal { + return newCluster(vm, settings, settings.minOperators, settings.minNodes); + } -function newTestCluster(Vm vm, Settings memory settings) returns (TestCluster memory) { - return newTestCluster(vm, settings, settings.minOperators, settings.minNodes); -} + function newCluster(Vm vm, uint256 operatorsCount, uint256 nodesCount) internal { + return newCluster(vm, Settings({ minOperators: uint8(MIN_OPERATORS), minNodes: uint8(MIN_NODES) }), operatorsCount, nodesCount); + } -function newTestCluster(Vm vm, uint256 operatorsCount, uint256 nodesCount) returns (TestCluster memory) { - return newTestCluster(vm, Settings({ minOperators: uint8(MIN_OPERATORS), minNodes: uint8(MIN_NODES) }), operatorsCount, nodesCount); -} + function newCluster(Vm vm, Settings memory settings, uint256 operatorsCount, uint256 nodesCount) internal { + setCaller(OWNER); -function newTestCluster(Vm vm, Settings memory settings, uint256 operatorsCount, uint256 nodesCount) returns (TestCluster memory) { - NodeOperatorView[] memory operators = new NodeOperatorView[](operatorsCount); - for (uint256 i = 0; i < operatorsCount; i++) { - operators[i] = newNodeOperator(vm.addr(i + 1), nodesCount); + NodeOperatorView[] memory operators = new NodeOperatorView[](operatorsCount); + for (uint256 i = 0; i < operatorsCount; i++) { + operators[i] = newNodeOperator(vm.addr(i + 1), nodesCount); + } + + cluster = new Cluster(settings, operators); } - vm.prank(vm.addr(OWNER)); - - return TestCluster({ - inner: new Cluster(settings, operators), - vm: vm, - tools: new TestTools(), - operatorsToRemove: new address[](0), - operatorsToRemoveLen: 0, - operatorsToAdd: new NodeOperatorView[](0), - operatorsToAddLen: 0, - revertBytes: new bytes(0) - }); -} + function updateClusterView() internal { + clusterView = cluster.getView(); + } -library TestClusterLib { - function setCaller(TestCluster memory self, uint256 callerPrivateKey) public returns (TestCluster memory) { - self.vm.prank(self.vm.addr(callerPrivateKey)); - return self; + function setCaller(uint256 caller) internal { + vm.prank(vm.addr(caller)); } - function expectRevert(TestCluster memory self, bytes memory revertBytes) public pure returns (TestCluster memory) { - self.revertBytes = revertBytes; - return self; + function expectRevert(bytes memory revertBytes) internal { + vm.expectRevert(revertBytes); } - function assertVersion(TestCluster memory self, uint128 expectedVersion) public view returns (TestCluster memory){ - ClusterView memory clusterView = self.inner.getView(); - self.tools.assertEq(clusterView.version, expectedVersion); - return self; + function assertVersion(uint128 expectedVersion) internal { + assertEq(cluster.getView().version, expectedVersion); } - function assertKeyspaceVersion(TestCluster memory self, uint64 expectedVersion) public view returns (TestCluster memory){ - ClusterView memory clusterView = self.inner.getView(); - self.tools.assertEq(clusterView.keyspaceVersion, expectedVersion); - return self; + function assertKeyspaceVersion(uint64 expectedVersion) internal { + assertEq(cluster.getView().keyspaceVersion, expectedVersion); } - function generateMigration(TestCluster memory self, uint256 operatorsToRemove, uint256 operatorsToAdd) public view returns (TestCluster memory) { - prepareMigration(self, operatorsToRemove, operatorsToAdd); + function newMigration() internal returns (TestMigration memory) { + return TestMigration({ + vm: vm, + operatorsToRemove: new address[](0), + operatorsToAdd: new NodeOperatorView[](0) + }); + } - ClusterView memory clusterView = self.inner.getView(); + function newMigration(uint256 toRemove, uint256 toAdd) internal returns (TestMigration memory) { + TestMigration memory migration = TestMigration({ + vm: vm, + operatorsToRemove: new address[](toRemove), + operatorsToAdd: new NodeOperatorView[](toAdd) + }); + uint256 j; for (uint256 i = 0; i < clusterView.operators.slots.length; i++) { - if (operatorsToRemove == 0) { + if (toRemove == 0) { break; } + if (clusterView.operators.slots[i].addr != address(0)) { - removeOperator(self, clusterView.operators.slots[i].addr); - operatorsToRemove--; + migration.operatorsToRemove[j] = clusterView.operators.slots[i].addr; + j++; + toRemove--; } } - require(operatorsToRemove == 0); - - for (uint256 i = 0; i < operatorsToAdd; i++) { - addOperator(self, EXTRA_OPERATOR + i); + require(toRemove == 0); + + for (uint256 i = 0; i < toAdd; i++) { + migration.operatorsToAdd[i] = newNodeOperator(vm.addr(EXTRA_OPERATOR + i), 2); } - return self; + return migration; } - function prepareMigration(TestCluster memory self, uint256 operatorsToRemove, uint256 operatorsToAdd) public pure returns (TestCluster memory) { - self.operatorsToRemove = new address[](operatorsToRemove); - self.operatorsToRemoveLen = 0; - self.operatorsToAdd = new NodeOperatorView[](operatorsToAdd); - self.operatorsToAddLen = 0; - return self; + function startMigration(uint256 caller) internal { + startMigration(caller, 0, 1); } - function addOperator(TestCluster memory self, uint256 privateKey) public pure returns (TestCluster memory) { - return addOperator(self, privateKey, 2); + function startMigration(uint256 caller, uint256 toRemove, uint256 toAdd) internal { + startMigration(caller, newMigration(toRemove, toAdd)); } - function addOperator(TestCluster memory self, uint256 privateKey, uint256 nodesCount) public pure returns (TestCluster memory) { - Node[] memory nodes = new Node[](nodesCount); - for (uint256 i = 0; i < nodesCount; i++) { - nodes[i] = Node({ id: i + 1 , data: bytes("Some node specific data") }); - } - - self.operatorsToAdd[self.operatorsToAddLen] = NodeOperatorView({ - addr: self.vm.addr(privateKey), - nodes: nodes, - data: bytes("Some operator specific data") - }); - self.operatorsToAddLen++; + function startMigration(uint256 caller, TestMigration memory migration) internal { + setCaller(caller); + cluster.startMigration(migration.operatorsToRemove, migration.operatorsToAdd); + updateClusterView(); + } - return self; + function completeMigration(uint256 caller) internal { + setCaller(caller); + cluster.completeMigration(); + updateClusterView(); } - function removeOperator(TestCluster memory self, address operator) public pure returns (TestCluster memory) { - self.operatorsToRemove[self.operatorsToRemoveLen] = operator; - self.operatorsToRemoveLen++; - return self; + function startMaintenance(uint256 caller) internal { + setCaller(caller); + cluster.startMaintenance(); + updateClusterView(); } - function startMigration(TestCluster memory self, uint256 caller, uint256 operatorsToRemove, uint256 operatorsToAdd) public returns (TestCluster memory) { - generateMigration(self, operatorsToRemove, operatorsToAdd); - return startMigration(self, caller); + function completeMaintenance(uint256 caller) internal { + setCaller(caller); + cluster.completeMaintenance(); + updateClusterView(); } - function startMigration(TestCluster memory self, uint256 caller) public returns (TestCluster memory) { - setCaller(self, caller); - if (self.revertBytes.length != 0) { - self.vm.expectRevert(self.revertBytes); - } - self.inner.startMigration(self.operatorsToRemove, self.operatorsToAdd); - return self; + function abortMaintenance(uint256 caller) internal { + setCaller(caller); + cluster.abortMaintenance(); + updateClusterView(); } +} - function completeMigration(TestCluster memory self, uint256 caller) public returns (TestCluster memory) { - setCaller(self, caller); - if (self.revertBytes.length != 0) { - self.vm.expectRevert(self.revertBytes); - } - self.inner.completeMigration(); - return self; +struct TestMigration { + Vm vm; + + address[] operatorsToRemove; + NodeOperatorView[] operatorsToAdd; +} + +library TestMigrationLib { + function addOperator(TestMigration memory self, uint256 privateKey) internal returns (TestMigration memory) { + return addOperator(self, privateKey, 2); } - function startMaintenance(TestCluster memory self, uint256 caller) public returns (TestCluster memory) { - setCaller(self, caller); - if (self.revertBytes.length != 0) { - self.vm.expectRevert(self.revertBytes); + function addOperator(TestMigration memory self, uint256 privateKey, uint256 nodesCount) internal returns (TestMigration memory) { + Node[] memory nodes = new Node[](nodesCount); + for (uint256 i = 0; i < nodesCount; i++) { + nodes[i] = Node({ id: i + 1 , data: bytes("Some node specific data") }); } - self.inner.startMaintenance(); - return self; - } - function completeMaintenance(TestCluster memory self, uint256 caller) public returns (TestCluster memory) { - setCaller(self, caller); - if (self.revertBytes.length != 0) { - self.vm.expectRevert(self.revertBytes); + NodeOperatorView[] memory operators = new NodeOperatorView[](self.operatorsToAdd.length + 1); + for (uint256 i = 0; i < self.operatorsToAdd.length; i++) { + operators[i] = self.operatorsToAdd[i]; } - self.inner.completeMaintenance(); + operators[operators.length - 1] = NodeOperatorView({ + addr: self.vm.addr(privateKey), + nodes: nodes, + data: bytes("Some operator specific data") + }); + + self.operatorsToAdd = operators; return self; } - function abortMaintenance(TestCluster memory self, uint256 caller) public returns (TestCluster memory) { - setCaller(self, caller); - if (self.revertBytes.length != 0) { - self.vm.expectRevert(self.revertBytes); + function removeOperator(TestMigration memory self, uint256 privateKey) internal returns (TestMigration memory) { + address[] memory operators = new address[](self.operatorsToRemove.length + 1); + for (uint256 i = 0; i < self.operatorsToRemove.length; i++) { + operators[i] = self.operatorsToRemove[i]; } - self.inner.abortMaintenance(); + operators[operators.length - 1] = self.vm.addr(privateKey); + + self.operatorsToRemove = operators; return self; } } +using TestMigrationLib for TestMigration; + function newNodeOperator(address addr, uint256 nodesCount) pure returns (NodeOperatorView memory) { Node[] memory nodes = new Node[](nodesCount); for (uint256 i = 0; i < nodesCount; i++) { From 5bf775b4f4ccab110bc4c57d3841e6db4a569a6d Mon Sep 17 00:00:00 2001 From: Darksome Date: Tue, 13 May 2025 09:41:58 +0000 Subject: [PATCH 10/79] more tests / bug fixes --- contracts/src/Cluster/Cluster.sol | 34 +- contracts/src/Cluster/Migration.sol | 20 +- contracts/src/Cluster/NodeOperators.sol | 10 +- contracts/src/Cluster/Nodes.sol | 16 +- contracts/test/Suite.sol | 665 ++++++++++++++++++++++-- 5 files changed, 677 insertions(+), 68 deletions(-) diff --git a/contracts/src/Cluster/Cluster.sol b/contracts/src/Cluster/Cluster.sol index 7f4aa218..ba380954 100644 --- a/contracts/src/Cluster/Cluster.sol +++ b/contracts/src/Cluster/Cluster.sol @@ -20,23 +20,24 @@ struct ClusterView { uint128 version; } + +event MigrationStarted(address[] operatorsToRemove, NodeOperatorView[] operatorsToAdd, uint128 version); +event MigrationDataPullCompleted(address operator, uint128 version); +event MigrationCompleted(uint128 version); +event MigrationAborted(uint128 version); + +event MaintenanceStarted(address operator, uint128 version); +event MaintenanceCompleted(address operator, uint128 version); +event MaintenanceAborted(uint128 version); + +event NodeSet(address operator, Node node, uint128 version); +event NodeRemoved(address operator, uint256 id, uint128 version); + contract Cluster { using NodeOperatorsLib for NodeOperators; using MigrationLib for Migration; using MaintenanceLib for Maintenance; - event MigrationStarted(address[] operatorsToRemove, NodeOperatorView[] operatorsToAdd, uint128 version); - event MigrationDataPullCompleted(address operator, uint128 version); - event MigrationCompleted(uint128 version); - event MigrationAborted(uint128 version); - - event MaintenanceStarted(address operator, uint128 version); - event MaintenanceCompleted(address operator, uint128 version); - event MaintenanceAborted(uint128 version); - - event NodeSet(address operator, Node node, uint128 version); - event NodeRemoved(address operator, uint256 id, uint128 version); - address owner; Settings settings; @@ -69,10 +70,6 @@ contract Cluster { _; } - function transferOwnership(address newOwner) external onlyOwner { - owner = newOwner; - } - function startMigration(address[] calldata operatorsToRemove, NodeOperatorView[] calldata operatorsToAdd) external onlyOwner { require(!maintenance.inProgress(), "maintenance in progress"); @@ -151,6 +148,7 @@ contract Cluster { function removeNode(uint256 id) external onlyOperator { operators.removeNode(msg.sender, id); + require(operators.nodesCount(msg.sender) >= settings.minNodes, "too few nodes"); version++; emit NodeRemoved(msg.sender, id, version); } @@ -159,6 +157,10 @@ contract Cluster { settings = newSettings; } + function transferOwnership(address newOwner) external onlyOwner { + owner = newOwner; + } + function validateOperatorsCount(uint256 value) view internal { require(value >= settings.minOperators, "too few operators"); require(value <= 256, "too many operators"); diff --git a/contracts/src/Cluster/Migration.sol b/contracts/src/Cluster/Migration.sol index 381556e9..14177a59 100644 --- a/contracts/src/Cluster/Migration.sol +++ b/contracts/src/Cluster/Migration.sol @@ -89,13 +89,21 @@ library MigrationLib { } address[] memory pulling = new address[](self.pullingOperatorsCount); - uint256 j; - for (uint256 i = 0; i < currentOperators.length; i++) { - if (currentOperators[i].addr != address(0) && self.pullingOperators[currentOperators[i].addr]) { - pulling[j] = currentOperators[i].addr; - j++; + if (self.pullingOperatorsCount > 0) { + uint256 j; + for (uint256 i = 0; i < currentOperators.length; i++) { + if (currentOperators[i].addr != address(0) && self.pullingOperators[currentOperators[i].addr]) { + pulling[j] = currentOperators[i].addr; + j++; + } } - } + for (uint256 i = 0; i < self.operatorsToAdd.length; i++) { + if (self.pullingOperators[self.operatorsToAdd[i].addr]) { + pulling[j] = self.operatorsToAdd[i].addr; + j++; + } + } + } return MigrationView({ operatorsToRemove: toRemove, diff --git a/contracts/src/Cluster/NodeOperators.sol b/contracts/src/Cluster/NodeOperators.sol index 7c0d21eb..9714c67f 100644 --- a/contracts/src/Cluster/NodeOperators.sol +++ b/contracts/src/Cluster/NodeOperators.sol @@ -73,8 +73,8 @@ library NodeOperatorsLib { return false; } - function length(NodeOperators storage self) public view returns (uint8) { - return uint8(self.slots.length - self.freeSlotIndexes.length); + function length(NodeOperators storage self) public view returns (uint256) { + return self.slots.length - self.freeSlotIndexes.length; } function setNode(NodeOperators storage self, address operator, Node calldata node) public { @@ -85,8 +85,12 @@ library NodeOperatorsLib { self.slots[self.indexes[operator]].nodes.remove(id); } + function nodesCount(NodeOperators storage self, address operator) public view returns (uint256) { + return self.slots[self.indexes[operator]].nodes.length(); + } + function getView(NodeOperators storage self) public view returns (NodeOperatorsView memory) { - NodeOperatorView[] memory slots = new NodeOperatorView[](length(self)); + NodeOperatorView[] memory slots = new NodeOperatorView[](self.slots.length); for (uint256 i = 0; i < self.slots.length; i++) { slots[i] = NodeOperatorView({ addr: self.slots[i].addr, diff --git a/contracts/src/Cluster/Nodes.sol b/contracts/src/Cluster/Nodes.sol index ce7295fb..1317aa99 100644 --- a/contracts/src/Cluster/Nodes.sol +++ b/contracts/src/Cluster/Nodes.sol @@ -17,7 +17,15 @@ library NodesLib { require(node.id != 0, "invalid id"); uint8 idx; - + + if (self.slots.length > 0) { + idx = self.indexes[node.id]; + if (idx != 0 || self.slots[0].id == node.id) { + self.slots[idx] = node; + return; + } + } + if (self.freeSlotIndexes.length > 0) { idx = self.freeSlotIndexes[self.freeSlotIndexes.length - 1]; self.freeSlotIndexes.pop(); @@ -41,12 +49,12 @@ library NodesLib { self.freeSlotIndexes.push(idx); } - function length(Nodes storage self) public view returns (uint8) { - return uint8(self.slots.length - self.freeSlotIndexes.length); + function length(Nodes storage self) public view returns (uint256) { + return self.slots.length - self.freeSlotIndexes.length; } function getView(Nodes storage self) public view returns (Node[] memory) { - Node[] memory nodes = new Node[](length(self)); + Node[] memory nodes = new Node[](length(self)); uint256 j; for (uint256 i = 0; i < self.slots.length; i++) { if (self.slots[i].id != 0) { diff --git a/contracts/test/Suite.sol b/contracts/test/Suite.sol index dc32b686..35aaa85a 100644 --- a/contracts/test/Suite.sol +++ b/contracts/test/Suite.sol @@ -8,15 +8,23 @@ import "../dependencies/forge-std-1.9.7/src/console.sol"; import "../src/Cluster/Cluster.sol"; uint256 constant OWNER = 12345; +uint256 constant NEW_OWNER = 56789; uint256 constant ANYONE = 9000; uint256 constant OPERATOR_A = 1; uint256 constant OPERATOR_B = 2; uint256 constant OPERATOR_C = 3; - uint256 constant EXTRA_OPERATOR = 1000; -uint256 constant MIN_OPERATORS = 5; +bytes constant DEFAULT_OPERATOR_DATA = "Some operator specific data"; + +uint256 constant NODE_A = 1; +uint256 constant NODE_B = 2; +uint256 constant EXTRA_NODE = 1000; + +bytes constant DEFAULT_NODE_DATA = "Some node specific data"; + +uint256 constant MIN_OPERATORS = 3; uint256 constant MIN_NODES = 1; uint256 constant MAX_OPERATORS = 256; @@ -26,15 +34,8 @@ contract ClusterTest is Test { Cluster cluster; ClusterView clusterView; - mapping(address => uint256) privateKeys; - constructor() { newCluster(vm); - updateClusterView(); - - for (uint256 k = 1; k <= 10; k++) { - privateKeys[vm.addr(k)] = k; - } } // contructor @@ -71,11 +72,29 @@ contract ClusterTest is Test { newCluster(vm, MIN_OPERATORS, MAX_NODES); } - function test_clusterInitialVersionIs0() public { + function test_clusterContainsInitialOperators() public view { + assertOperatorSlotsCount(MIN_OPERATORS); + assertOperatorSlot(0, OPERATOR_A); + assertOperatorSlot(1, OPERATOR_B); + assertOperatorSlot(2, OPERATOR_C); + } + + function test_clusterContainsInitialNodes() public { + assertNodesCount(OPERATOR_A, MIN_NODES); + assertNode(OPERATOR_A, NODE_A, DEFAULT_NODE_DATA); + + assertNodesCount(OPERATOR_B, MIN_NODES); + assertNode(OPERATOR_B, NODE_A, DEFAULT_NODE_DATA); + + assertNodesCount(OPERATOR_C, MIN_NODES); + assertNode(OPERATOR_C, NODE_A, DEFAULT_NODE_DATA); + } + + function test_clusterInitialVersionIs0() public view { assertVersion(0); } - function test_clusterInitialKeyspaceVersionIs0() public { + function test_clusterInitialKeyspaceVersionIs0() public view { assertKeyspaceVersion(0); } @@ -135,6 +154,33 @@ contract ClusterTest is Test { assertKeyspaceVersion(0); } + function test_startMigrationEmitsMigrationStartedEvent() public { + TestMigration memory migration = newMigration(2, 2); + vm.expectEmit(); + emit MigrationStarted(migration.operatorsToRemove, migration.operatorsToAdd, 1); + startMigration(OWNER, migration); + } + + function test_startMigrationUpdatesMigration() public { + newCluster(vm, 5, MIN_NODES); + TestMigration memory migration = newMigration() + .removeOperator(3) + .removeOperator(2) + .addOperator(6) + .addOperator(7) + .addOperator(8); + + startMigration(OWNER, migration); + assertMigration(migration); + assertMigrationPullingOperatorsCount(5 - 2 + 3); + assertMigrationPullingOperator(0, 1); + assertMigrationPullingOperator(1, 4); + assertMigrationPullingOperator(2, 5); + assertMigrationPullingOperator(3, 6); + assertMigrationPullingOperator(4, 7); + assertMigrationPullingOperator(5, 8); + } + // completeMigration function test_anyoneCanNotCompleteMigration() public { @@ -172,6 +218,65 @@ contract ClusterTest is Test { assertVersion(2); } + function test_completeMigrationBumpsVersionForEachCompletedPullAndForCompletionItself() public { + startMigration(OWNER, 0, 1); + completeMigration(OPERATOR_A); + completeMigration(OPERATOR_B); + completeMigration(OPERATOR_C); + completeMigration(EXTRA_OPERATOR); + assertVersion(6); + } + + function test_completeMigrationDoesNotUpdateOperatorsIfNotCompleted() public { + startMigration(OWNER, 0, 1); + completeMigration(OPERATOR_A); + assertOperatorSlotsCount(MIN_OPERATORS); + assertOperatorSlot(0, OPERATOR_A); + assertOperatorSlot(1, OPERATOR_B); + assertOperatorSlot(2, OPERATOR_C); + } + + function test_completeMigrationUpdatesOperatorsIfCompleted() public { + newCluster(vm, 5, MIN_NODES); + TestMigration memory migration = newMigration() + .removeOperator(3) + .removeOperator(4) + .removeOperator(2) + .addOperator(6) + .addOperator(7); + + startMigration(OWNER, migration); + completeMigration(1); + completeMigration(5); + completeMigration(6); + completeMigration(7); + + assertOperatorSlotsCount(5); + assertOperatorSlot(0, 1); + assertOperatorSlot(1, 6); + assertOperatorSlotEmpty(2); + assertOperatorSlot(3, 7); + assertOperatorSlot(4, 5); + } + + function test_completeMigrationDeletesMigrationIfCompleted() public { + startMigration(OWNER, 0, 1); + completeMigration(OPERATOR_A); + completeMigration(OPERATOR_B); + completeMigration(OPERATOR_C); + completeMigration(EXTRA_OPERATOR); + assertNoMigration(); + } + + function test_completeMigrationUpdatesMigrationIfNotCompleted() public { + startMigration(OWNER, 0, 1); + completeMigration(OPERATOR_A); + assertMigrationPullingOperatorsCount(MIN_OPERATORS + 1 - 1); + assertMigrationPullingOperator(0, OPERATOR_B); + assertMigrationPullingOperator(1, OPERATOR_C); + assertMigrationPullingOperator(2, EXTRA_OPERATOR); + } + function test_completeMigrationDoesNotBumpKeyspaceVersionIfNotCompleted() public { startMigration(OWNER, 0, 1); completeMigration(OPERATOR_A); @@ -179,7 +284,6 @@ contract ClusterTest is Test { } function test_completeMigrationBumpKeyspaceVersionIfCompleted() public { - newCluster(vm, Settings({ minOperators: 3, minNodes: uint8(MIN_NODES) })); startMigration(OWNER, 0, 1); completeMigration(OPERATOR_A); completeMigration(OPERATOR_B); @@ -188,6 +292,82 @@ contract ClusterTest is Test { assertKeyspaceVersion(1); } + function test_completeMigrationEmitsMigrationDataPullCompletedEventIfNotCompleted() public { + startMigration(OWNER, 0, 1); + vm.expectEmit(); + emit MigrationDataPullCompleted(vm.addr(OPERATOR_A), 2); + completeMigration(OPERATOR_A); + } + + function test_completeMigrationEmitsMigrationCompletedEventIfCompleted() public { + startMigration(OWNER, 0, 1); + completeMigration(OPERATOR_A); + completeMigration(OPERATOR_B); + completeMigration(OPERATOR_C); + vm.expectEmit(); + emit MigrationDataPullCompleted(vm.addr(EXTRA_OPERATOR), 5); + emit MigrationCompleted(6); + completeMigration(EXTRA_OPERATOR); + } + + // abortMigration + + function test_anyoneCanNotAbortMigration() public { + startMigration(OWNER, 0, 1); + expectRevert("not the owner"); + abortMigration(ANYONE); + } + + function test_operatorCanNotAbortMigration() public { + startMigration(OWNER, 0, 1); + expectRevert("not the owner"); + abortMigration(OPERATOR_A); + } + + function test_ownerCanAbortMigration() public { + startMigration(OWNER, 0, 1); + abortMigration(OWNER); + } + + function test_canNotAbortNonExistentMigration() public { + expectRevert("not in progress"); + abortMigration(OWNER); + } + + function test_abortMigrationBumpsVersion() public { + startMigration(OWNER, 0, 1); + abortMigration(OWNER); + assertVersion(2); + } + + function test_abortMigrationDoesNotBumpKeyspaceVersion() public { + startMigration(OWNER, 0, 1); + abortMigration(OWNER); + assertKeyspaceVersion(0); + } + + function test_abortMigrationDoesNotUpdateOperators() public { + startMigration(OWNER, 0, 1); + abortMigration(OWNER); + assertOperatorSlotsCount(MIN_OPERATORS); + assertOperatorSlot(0, OPERATOR_A); + assertOperatorSlot(1, OPERATOR_B); + assertOperatorSlot(2, OPERATOR_C); + } + + function test_abortMigrationDeletesMigration() public { + startMigration(OWNER, 0, 1); + abortMigration(OWNER); + assertNoMigration(); + } + + function test_abortMigrationEmitsMigrationAbortedEvent() public { + startMigration(OWNER, 0, 1); + vm.expectEmit(); + emit MigrationAborted(2); + abortMigration(OWNER); + } + // startMaintenance function test_anyoneCanNotStartMaintenance() public { @@ -204,13 +384,46 @@ contract ClusterTest is Test { startMaintenance(OPERATOR_A); } + function test_canNotStartMoreThanOneMaintenance() public { + startMaintenance(OPERATOR_A); + expectRevert("another maintenance in progress"); + startMaintenance(OPERATOR_B); + } + + function test_canNotStartMaintenanceTwice() public { + startMaintenance(OPERATOR_A); + expectRevert("another maintenance in progress"); + startMaintenance(OPERATOR_A); + } + function test_operatorCanNotStartMaintenanceWhenMigrationInProgress() public { startMigration(OWNER, 0, 1); expectRevert("migration in progress"); startMaintenance(OPERATOR_A); } - // copleteMaintenance + function test_startMaintenanceBumpsVersion() public { + startMaintenance(OPERATOR_A); + assertVersion(1); + } + + function test_startMaintenanceDoesNotBumpKeyspaceVersion() public { + startMaintenance(OPERATOR_A); + assertKeyspaceVersion(0); + } + + function test_startMaintenanceUpdatesMaintenance() public { + startMaintenance(OPERATOR_A); + assertMaintenance(OPERATOR_A); + } + + function test_startMaintenanceEmitsMaintenanceStartedEvent() public { + vm.expectEmit(); + emit MaintenanceStarted(vm.addr(OPERATOR_A), 1); + startMaintenance(OPERATOR_A); + } + + // completeMaintenance function test_anyoneCanNotCompleteMaintenance() public { expectRevert("not an operator"); @@ -239,6 +452,31 @@ contract ClusterTest is Test { completeMaintenance(OPERATOR_A); } + function test_completeMaintenanceBumpsVersion() public { + startMaintenance(OPERATOR_A); + completeMaintenance(OPERATOR_A); + assertVersion(2); + } + + function test_completeMaintenanceDoesNotBumpKeyspaceVersion() public { + startMaintenance(OPERATOR_A); + completeMaintenance(OPERATOR_A); + assertKeyspaceVersion(0); + } + + function test_completeMaintenanceDeletesMaintenance() public { + startMaintenance(OPERATOR_A); + completeMaintenance(OPERATOR_A); + assertNoMaintenance(); + } + + function test_completeMaintenanceEmitsMaintenanceCompletedEvent() public { + startMaintenance(OPERATOR_A); + vm.expectEmit(); + emit MaintenanceCompleted(vm.addr(OPERATOR_A), 2); + completeMaintenance(OPERATOR_A); + } + // abortMaintenance function test_anyoneCanNotAbortMaintenance() public { @@ -258,16 +496,246 @@ contract ClusterTest is Test { abortMaintenance(OWNER); } + function test_canNotAbortNonExistentMaintenance() public { + expectRevert("not under maintenance"); + abortMaintenance(OWNER); + } + + function test_abortMaintenanceBumpsVersion() public { + startMaintenance(OPERATOR_A); + abortMaintenance(OWNER); + assertVersion(2); + } + + function test_abortMaintenanceDoesNotBumpKeyspaceVersion() public { + startMaintenance(OPERATOR_A); + abortMaintenance(OWNER); + assertKeyspaceVersion(0); + } + + function test_abortMaintenanceDeletesMaintenance() public { + startMaintenance(OPERATOR_A); + abortMaintenance(OWNER); + assertNoMaintenance(); + } + + function test_abortMaintenanceEmitsMaintenanceAbortedEvent() public { + startMaintenance(OPERATOR_A); + vm.expectEmit(); + emit MaintenanceAborted(2); + abortMaintenance(OWNER); + } + + // setNode + + function test_anyoneCanNotSetNode() public { + expectRevert("not an operator"); + setNode(ANYONE, NODE_A, "data"); + } + + function test_ownerCanNotSetNode() public { + expectRevert("not an operator"); + setNode(OWNER, NODE_A, "data"); + } + + function test_operatorCanSetNode() public { + setNode(OPERATOR_A, NODE_A, "data"); + } + + function test_canSetSameNode() public { + setNode(OPERATOR_A, NODE_A, "data"); + setNode(OPERATOR_A, NODE_A, "data"); + } + + function test_canNotSetNewNodeWhenTooManyNodes() public { + newCluster(vm, MIN_OPERATORS, MAX_NODES); + expectRevert("too many nodes"); + setNode(OPERATOR_A, EXTRA_NODE, "data"); + } + + function test_setNodeWithNewIdDoesNotOverwriteExistingOnes() public { + assertNodesCount(OPERATOR_A, 1); + assertNode(OPERATOR_A, NODE_A, DEFAULT_NODE_DATA); + setNode(OPERATOR_A, EXTRA_NODE, "data"); + assertNodesCount(OPERATOR_A, 2); + assertNode(OPERATOR_A, EXTRA_NODE, "data"); + } + + function test_setNodeWithSameIdOverwritesExistingOne() public { + setNode(OPERATOR_A, NODE_A, "data"); + assertNodesCount(OPERATOR_A, 1); + assertNode(OPERATOR_A, NODE_A, "data"); + } + + function test_setNodeBumpsVersion() public { + setNode(OPERATOR_A, NODE_A, "data"); + assertVersion(1); + } + + function test_setNodeDoesNotBumpKeyspaceVersion() public { + setNode(OPERATOR_A, NODE_A, "data"); + assertKeyspaceVersion(0); + } + + function test_setNodeEmitsNodeSetEvent() public { + vm.expectEmit(); + emit NodeSet(vm.addr(OPERATOR_A), Node({ id: NODE_A, data: "NodeSet data"}), 1); + setNode(OPERATOR_A, NODE_A, "NodeSet data"); + } + + // removeNode + + function test_anyoneCanNotRemoveNode() public { + expectRevert("not an operator"); + removeNode(ANYONE, NODE_A); + } + + function test_ownerCanNotRemoveNode() public { + expectRevert("not an operator"); + removeNode(OWNER, NODE_A); + } + + function test_operatorCanRemoveNode() public { + setNode(OPERATOR_A, EXTRA_NODE, "data"); + removeNode(OPERATOR_A, NODE_A); + } + + function test_canNotRemoveNonExistentNode() public { + expectRevert("node doesn't exist"); + removeNode(OPERATOR_A, EXTRA_NODE); + } + + function test_canNotRemoveNodeWhenTooFewNodes() public { + expectRevert("too few nodes"); + removeNode(OPERATOR_A, NODE_A); + } + + function test_removeNodeBumpsVersion() public { + setNode(OPERATOR_A, EXTRA_NODE, "data"); + removeNode(OPERATOR_A, NODE_A); + assertVersion(2); + } + + function test_removeNodeDoesRemoveTheNode() public { + setNode(OPERATOR_A, EXTRA_NODE, "data"); + removeNode(OPERATOR_A, NODE_A); + assertNodesCount(OPERATOR_A, 1); + assertNode(OPERATOR_A, EXTRA_NODE, "data"); + } + + function test_removeNodeDoesNotBumpKeyspaceVersion() public { + setNode(OPERATOR_A, EXTRA_NODE, "data"); + removeNode(OPERATOR_A, NODE_A); + assertKeyspaceVersion(0); + } + + function test_removeNodeEmitsNodeRemovedEvent() public { + setNode(OPERATOR_A, EXTRA_NODE, "data"); + vm.expectEmit(); + emit NodeRemoved(vm.addr(OPERATOR_A), NODE_A, 2); + removeNode(OPERATOR_A, NODE_A); + } + + // updateSettings + + function test_anyoneCanNotUpdateSettings() public { + expectRevert("not the owner"); + updateSettings(ANYONE, Settings({ minOperators: 5, minNodes: 2 })); + } + + function test_operatorCanNotUpdateSettings() public { + expectRevert("not the owner"); + updateSettings(OPERATOR_A, Settings({ minOperators: 5, minNodes: 2 })); + } + + function test_ownerCanUpdateSettings() public { + updateSettings(OWNER, Settings({ minOperators: 5, minNodes: 2 })); + } + + function test_updateSettingsCorrectlyUpdatesMinOperators() public { + newCluster(vm, 5, MIN_NODES); + updateSettings(OWNER, Settings({ minOperators: 3, minNodes: uint8(MIN_NODES) })); + startMigration(OWNER, 1, 0); + } + + function test_updateSettingsCorrectlyUpdatesMinNodes() public { + newCluster(vm, MIN_OPERATORS, 2); + updateSettings(OWNER, Settings({ minOperators: uint8(MIN_OPERATORS), minNodes: 1 })); + removeNode(OPERATOR_A, NODE_A); + } + + // transferOwnership + + function test_anyoneCanNotTransferOwnership() public { + expectRevert("not the owner"); + transferOwnership(ANYONE, ANYONE); + } + + function test_operatorCanNotTransferOwnership() public { + expectRevert("not the owner"); + transferOwnership(OPERATOR_A, OPERATOR_A); + } + + function test_ownerCanTransferOwnership() public { + transferOwnership(OWNER, NEW_OWNER); + } + + function test_transferOwnershipChangesOwner() public { + transferOwnership(OWNER, NEW_OWNER); + startMigration(NEW_OWNER, 0, 1); + } + + // full lifecycle + + function test_fullClusterLifecycle() public { + newCluster(vm, Settings({ minOperators: 5, minNodes: 1 }), 9, 1); + setNode(OPERATOR_A, EXTRA_NODE, "A"); + startMaintenance(OPERATOR_B); + setNode(OPERATOR_C, EXTRA_NODE, "C"); + completeMaintenance(OPERATOR_B); + startMigration(OWNER, newMigration().addOperator(10).addOperator(11).addOperator(12)); + removeNode(OPERATOR_A, NODE_A); + for (uint256 i = 1; i <= 12; i++) { + completeMigration(i); + } + removeNode(OPERATOR_C, NODE_A); + startMaintenance(11); + setNode(11, NODE_A, "11"); + abortMaintenance(OWNER); + + startMigration(OWNER, newMigration().removeOperator(11)); + for (uint256 i = 1; i <= 12; i++) { + if (i != 11) { + completeMigration(i); + } + } + + startMigration(OWNER, newMigration().addOperator(13)); + for (uint256 i = 1; i <= 12; i++) { + if (i != 11) { + completeMigration(i); + } + } + abortMigration(OWNER); + + transferOwnership(OWNER, NEW_OWNER); + updateSettings(NEW_OWNER, Settings({ minOperators: 7, minNodes: 1 })); + + assertKeyspaceVersion(2); + } + + // internal + function newCluster(Vm vm) internal { - return newCluster(vm, Settings({ minOperators: uint8(MIN_OPERATORS), minNodes: uint8(MIN_NODES) })); + newCluster(vm, Settings({ minOperators: uint8(MIN_OPERATORS), minNodes: uint8(MIN_NODES) })); } function newCluster(Vm vm, Settings memory settings) internal { - return newCluster(vm, settings, settings.minOperators, settings.minNodes); + newCluster(vm, settings, settings.minOperators, settings.minNodes); } function newCluster(Vm vm, uint256 operatorsCount, uint256 nodesCount) internal { - return newCluster(vm, Settings({ minOperators: uint8(MIN_OPERATORS), minNodes: uint8(MIN_NODES) }), operatorsCount, nodesCount); + newCluster(vm, Settings({ minOperators: uint8(MIN_OPERATORS), minNodes: uint8(MIN_NODES) }), operatorsCount, nodesCount); } function newCluster(Vm vm, Settings memory settings, uint256 operatorsCount, uint256 nodesCount) internal { @@ -277,8 +745,14 @@ contract ClusterTest is Test { for (uint256 i = 0; i < operatorsCount; i++) { operators[i] = newNodeOperator(vm.addr(i + 1), nodesCount); } - + cluster = new Cluster(settings, operators); + // ECRecover address. Constructor failed + if (address(cluster) == address(1)) { + return; + } + + updateClusterView(); } function updateClusterView() internal { @@ -293,15 +767,110 @@ contract ClusterTest is Test { vm.expectRevert(revertBytes); } - function assertVersion(uint128 expectedVersion) internal { + function assertVersion(uint128 expectedVersion) internal view { assertEq(cluster.getView().version, expectedVersion); } - function assertKeyspaceVersion(uint64 expectedVersion) internal { + function assertKeyspaceVersion(uint64 expectedVersion) internal view { assertEq(cluster.getView().keyspaceVersion, expectedVersion); } - function newMigration() internal returns (TestMigration memory) { + function assertOperatorSlotsCount(uint256 count) internal view { + assertEq(clusterView.operators.slots.length, count); + } + + function assertOperatorSlot(uint256 index, uint256 privateKey) internal view { + assertEq(clusterView.operators.slots[index].addr, vm.addr(privateKey)); + } + + function assertOperatorSlotEmpty(uint256 index) internal view { + assertEq(clusterView.operators.slots[index].addr, address(0)); + } + + function assertNodesCount(uint256 operator, uint256 count) internal { + address addr = vm.addr(operator); + + for (uint256 i = 0; i < clusterView.operators.slots.length; i++) { + if (clusterView.operators.slots[i].addr == addr) { + assertEq(clusterView.operators.slots[i].nodes.length, count); + return; + } + } + + fail(); + } + + function assertNode(uint256 operator, uint256 id, bytes memory data) internal { + address addr = vm.addr(operator); + + for (uint256 i = 0; i < clusterView.operators.slots.length; i++) { + if (clusterView.operators.slots[i].addr == addr) { + for (uint256 j = 0; j < clusterView.operators.slots[i].nodes.length; j++) { + if (clusterView.operators.slots[i].nodes[j].id == id) { + assertEq(clusterView.operators.slots[i].nodes[j].data, data); + return; + } + } + fail(); + } + } + + fail(); + } + + function assertMigration(TestMigration memory migration) internal view { + assertEq(clusterView.migration.operatorsToRemove.length, migration.operatorsToRemove.length); + for (uint256 i = 0; i < clusterView.migration.operatorsToRemove.length; i++) { + assertEq(clusterView.migration.operatorsToRemove[i], migration.operatorsToRemove[i]); + } + + assertEq(clusterView.migration.operatorsToAdd.length, migration.operatorsToAdd.length); + for (uint256 i = 0; i < clusterView.migration.operatorsToAdd.length; i++) { + assertEq(clusterView.migration.operatorsToAdd[i].addr, migration.operatorsToAdd[i].addr); + assertEq(clusterView.migration.operatorsToAdd[i].data, migration.operatorsToAdd[i].data); + for (uint256 j = 0; j < clusterView.migration.operatorsToAdd[i].nodes.length; j++) { + assertEq(clusterView.migration.operatorsToAdd[i].nodes[j].id, migration.operatorsToAdd[i].nodes[j].id); + assertEq(clusterView.migration.operatorsToAdd[i].nodes[j].data, migration.operatorsToAdd[i].nodes[j].data); + } + } + } + + function assertNoMigration() internal view { + TestMigration memory migration; + assertMigration(migration); + } + + function assertMigrationPullingOperatorsCount(uint256 count) internal view { + assertEq(clusterView.migration.pullingOperators.length, count); + } + + function assertMigrationPullingOperator(uint256 idx, uint256 operator) internal view { + assertEq(clusterView.migration.pullingOperators[idx], vm.addr(operator)); + } + + function assertMaintenance(uint256 operator) internal view { + assertEq(clusterView.maintenance.slot, vm.addr(operator)); + } + + function assertNoMaintenance() internal view { + assertEq(clusterView.maintenance.slot, address(0)); + } + + // function assertMigrationOperatorsToRemoveCount(uint256 count) internal { + // assertEq(clusterView.migration.operatorsToRemove.length, count); + // } + + // function assertMigrationOperatorsToAddCount(uint256 count) internal { + // assertEq(clusterView.migration.operatorsToAdd.length, count); + // } + + // function assertMigrationOperatorToAdd(uint256 idx, uint256 privateKey, bytes: data, uint256 nodesCount) internal { + // assertEq(clusterView.migration.operatorsToAdd[idx].addr, vm.addr(privateKey)); + // assertEq(clusterView.migration.operatorsToAdd[idx].data, data); + // assertEq(clusterView.migration.operatorsToAdd[idx].nodes.length, nodesCount); + // } + + function newMigration() internal pure returns (TestMigration memory) { return TestMigration({ vm: vm, operatorsToRemove: new address[](0), @@ -309,7 +878,7 @@ contract ClusterTest is Test { }); } - function newMigration(uint256 toRemove, uint256 toAdd) internal returns (TestMigration memory) { + function newMigration(uint256 toRemove, uint256 toAdd) internal view returns (TestMigration memory) { TestMigration memory migration = TestMigration({ vm: vm, operatorsToRemove: new address[](toRemove), @@ -331,7 +900,7 @@ contract ClusterTest is Test { require(toRemove == 0); for (uint256 i = 0; i < toAdd; i++) { - migration.operatorsToAdd[i] = newNodeOperator(vm.addr(EXTRA_OPERATOR + i), 2); + migration.operatorsToAdd[i] = newNodeOperator(vm.addr(EXTRA_OPERATOR + i), MIN_NODES); } return migration; @@ -357,6 +926,12 @@ contract ClusterTest is Test { updateClusterView(); } + function abortMigration(uint256 caller) internal { + setCaller(caller); + cluster.abortMigration(); + updateClusterView(); + } + function startMaintenance(uint256 caller) internal { setCaller(caller); cluster.startMaintenance(); @@ -374,6 +949,28 @@ contract ClusterTest is Test { cluster.abortMaintenance(); updateClusterView(); } + + function setNode(uint256 caller, uint256 id, bytes memory data) internal { + setCaller(caller); + cluster.setNode(Node({ id: id, data: data })); + updateClusterView(); + } + + function removeNode(uint256 caller, uint256 id) internal { + setCaller(caller); + cluster.removeNode(id); + updateClusterView(); + } + + function updateSettings(uint256 caller, Settings memory settings) internal { + setCaller(caller); + cluster.updateSettings(settings); + } + + function transferOwnership(uint256 caller, uint256 newOwner) internal { + setCaller(caller); + cluster.transferOwnership(vm.addr(newOwner)); + } } struct TestMigration { @@ -384,31 +981,22 @@ struct TestMigration { } library TestMigrationLib { - function addOperator(TestMigration memory self, uint256 privateKey) internal returns (TestMigration memory) { - return addOperator(self, privateKey, 2); + function addOperator(TestMigration memory self, uint256 privateKey) internal pure returns (TestMigration memory) { + return addOperator(self, privateKey, MIN_NODES); } - function addOperator(TestMigration memory self, uint256 privateKey, uint256 nodesCount) internal returns (TestMigration memory) { - Node[] memory nodes = new Node[](nodesCount); - for (uint256 i = 0; i < nodesCount; i++) { - nodes[i] = Node({ id: i + 1 , data: bytes("Some node specific data") }); - } - + function addOperator(TestMigration memory self, uint256 privateKey, uint256 nodesCount) internal pure returns (TestMigration memory) { NodeOperatorView[] memory operators = new NodeOperatorView[](self.operatorsToAdd.length + 1); for (uint256 i = 0; i < self.operatorsToAdd.length; i++) { operators[i] = self.operatorsToAdd[i]; } - operators[operators.length - 1] = NodeOperatorView({ - addr: self.vm.addr(privateKey), - nodes: nodes, - data: bytes("Some operator specific data") - }); + operators[operators.length - 1] = newNodeOperator(self.vm.addr(privateKey), nodesCount); self.operatorsToAdd = operators; return self; } - function removeOperator(TestMigration memory self, uint256 privateKey) internal returns (TestMigration memory) { + function removeOperator(TestMigration memory self, uint256 privateKey) internal pure returns (TestMigration memory) { address[] memory operators = new address[](self.operatorsToRemove.length + 1); for (uint256 i = 0; i < self.operatorsToRemove.length; i++) { operators[i] = self.operatorsToRemove[i]; @@ -425,13 +1013,12 @@ using TestMigrationLib for TestMigration; function newNodeOperator(address addr, uint256 nodesCount) pure returns (NodeOperatorView memory) { Node[] memory nodes = new Node[](nodesCount); for (uint256 i = 0; i < nodesCount; i++) { - nodes[i] = Node({ id: i + 1 , data: bytes("Some node specific data") }); + nodes[i] = Node({ id: i + 1 , data: DEFAULT_NODE_DATA }); } return NodeOperatorView({ addr: addr, nodes: nodes, - data: bytes("Some operator specific data") + data: DEFAULT_OPERATOR_DATA }); } - From f4b2ed615292934fd39e55853562d6f9136137e0 Mon Sep 17 00:00:00 2001 From: Darksome Date: Tue, 13 May 2025 16:00:25 +0000 Subject: [PATCH 11/79] generate alloy bindings --- Cargo.lock | 1450 ++++--- contracts/src/Cluster/Maintenance.sol | 8 +- contracts/src/Cluster/Migration.sol | 12 +- contracts/src/Cluster/NodeOperators.sol | 16 +- contracts/src/Cluster/Nodes.sol | 8 +- contracts/test/Suite.sol | 14 - crates/cluster/Cargo.toml | 13 + crates/cluster/src/contract/mod.rs | 5306 +++++++++++++++++++++++ crates/cluster/src/lib.rs | 4 + crates/cluster/tests/integration.rs | 6 + crates/core/Cargo.toml | 1 - crates/node/Cargo.toml | 14 +- crates/wcn/Cargo.toml | 12 +- 13 files changed, 6308 insertions(+), 556 deletions(-) create mode 100644 crates/cluster/Cargo.toml create mode 100644 crates/cluster/src/contract/mod.rs create mode 100644 crates/cluster/src/lib.rs create mode 100644 crates/cluster/tests/integration.rs diff --git a/Cargo.lock b/Cargo.lock index 42e0ade5..1c63db72 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -52,7 +52,7 @@ dependencies = [ "dhat", "serde", "serde_json", - "thiserror", + "thiserror 1.0.64", "tikv-jemalloc-ctl", "tikv-jemallocator", "tokio", @@ -88,70 +88,95 @@ checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" [[package]] name = "alloy" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy#83af23f563b9359e6691428ff8235c5fc6153984" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "239e728d663a3bdababa24dfdc697faec987593161c5ff54d72ee01df6721d59" dependencies = [ "alloy-consensus", "alloy-contract", "alloy-core", "alloy-eips", - "alloy-genesis", + "alloy-network", "alloy-provider", "alloy-rpc-client", - "alloy-serde", - "alloy-signer", - "alloy-signer-wallet", "alloy-transport", "alloy-transport-http", - "reqwest", ] [[package]] name = "alloy-chains" -version = "0.1.18" +version = "0.1.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03fd095a9d70f4b1c5c102c84a4c782867a5c6416dbf6dcd42a63e7c7a89d3c8" +checksum = "28e2652684758b0d9b389d248b209ed9fd9989ef489a550265fe4bb8454fe7eb" dependencies = [ + "alloy-primitives", "num_enum", "strum", ] [[package]] name = "alloy-consensus" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy#83af23f563b9359e6691428ff8235c5fc6153984" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27d301f5bcfd37e3aac727c360d8b50c33ddff9169ce0370198dedda36a9927d" dependencies = [ "alloy-eips", "alloy-primitives", "alloy-rlp", "alloy-serde", + "alloy-trie", + "auto_impl", "c-kzg", + "derive_more 2.0.1", + "either", + "k256", + "once_cell", + "rand 0.8.5", + "serde", + "serde_with", + "thiserror 2.0.12", +] + +[[package]] +name = "alloy-consensus-any" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f4f97a85a45965e0e4f9f5b94bbafaa3e4ee6868bdbcf2e4a9acb4b358038fe" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-primitives", + "alloy-rlp", + "alloy-serde", "serde", ] [[package]] name = "alloy-contract" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy#83af23f563b9359e6691428ff8235c5fc6153984" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f39e8b96c9e25dde7222372332489075f7e750e4fd3e81c11eec0939b78b71b8" dependencies = [ + "alloy-consensus", "alloy-dyn-abi", "alloy-json-abi", "alloy-network", + "alloy-network-primitives", "alloy-primitives", "alloy-provider", - "alloy-rpc-types", + "alloy-rpc-types-eth", "alloy-sol-types", "alloy-transport", "futures", "futures-util", - "thiserror", + "thiserror 2.0.12", ] [[package]] name = "alloy-core" -version = "0.7.4" +version = "0.8.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7253846c7bf55147775fd66c334abc1dd0a41e97e6155577b3dc513c6e66ef2" +checksum = "9d8bcce99ad10fe02640cfaec1c6bc809b837c783c1d52906aa5af66e2a196f6" dependencies = [ "alloy-dyn-abi", "alloy-json-abi", @@ -161,9 +186,9 @@ dependencies = [ [[package]] name = "alloy-dyn-abi" -version = "0.7.4" +version = "0.8.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8425a283510106b1a6ad25dd4bb648ecde7da3fd2baeb9400a85ad62f51ec90b" +checksum = "eb8e762aefd39a397ff485bc86df673465c4ad3ec8819cc60833a8a3ba5cdc87" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -173,39 +198,70 @@ dependencies = [ "itoa", "serde", "serde_json", - "winnow 0.6.8", + "winnow 0.7.10", ] [[package]] -name = "alloy-eips" +name = "alloy-eip2124" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy#83af23f563b9359e6691428ff8235c5fc6153984" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "675264c957689f0fd75f5993a73123c2cc3b5c235a38f5b9037fe6c826bfb2c0" dependencies = [ "alloy-primitives", "alloy-rlp", - "alloy-serde", - "c-kzg", - "once_cell", + "crc", "serde", - "sha2", + "thiserror 2.0.12", ] [[package]] -name = "alloy-genesis" +name = "alloy-eip2930" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy#83af23f563b9359e6691428ff8235c5fc6153984" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0069cf0642457f87a01a014f6dc29d5d893cd4fd8fddf0c3cdfad1bb3ebafc41" dependencies = [ "alloy-primitives", + "alloy-rlp", + "serde", +] + +[[package]] +name = "alloy-eip7702" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b15b13d38b366d01e818fe8e710d4d702ef7499eacd44926a06171dd9585d0c" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "serde", + "thiserror 2.0.12", +] + +[[package]] +name = "alloy-eips" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10b11c382ca8075128d1ae6822b60921cf484c911d9a5831797a01218f98125f" +dependencies = [ + "alloy-eip2124", + "alloy-eip2930", + "alloy-eip7702", + "alloy-primitives", + "alloy-rlp", "alloy-serde", + "auto_impl", + "c-kzg", + "derive_more 2.0.1", + "either", "serde", - "serde_json", + "sha2", ] [[package]] name = "alloy-json-abi" -version = "0.7.4" +version = "0.8.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e30946aa6173020259055a44971f5cf40a7d76c931d209caeb51b333263df4f" +checksum = "fe6beff64ad0aa6ad1019a3db26fef565aefeb011736150ab73ed3366c3cfd1b" dependencies = [ "alloy-primitives", "alloy-sol-type-parser", @@ -215,93 +271,125 @@ dependencies = [ [[package]] name = "alloy-json-rpc" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy#83af23f563b9359e6691428ff8235c5fc6153984" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbcf26d02a72e23d5bc245425ea403c93ba17d254f20f9c23556a249c6c7e143" dependencies = [ "alloy-primitives", + "alloy-sol-types", "serde", "serde_json", - "thiserror", + "thiserror 2.0.12", "tracing", ] [[package]] name = "alloy-network" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy#83af23f563b9359e6691428ff8235c5fc6153984" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b44dd4429e190f727358571175ebf323db360a303bf4e1731213f510ced1c2e6" dependencies = [ "alloy-consensus", + "alloy-consensus-any", "alloy-eips", "alloy-json-rpc", + "alloy-network-primitives", "alloy-primitives", - "alloy-rpc-types", + "alloy-rpc-types-any", + "alloy-rpc-types-eth", + "alloy-serde", "alloy-signer", "alloy-sol-types", "async-trait", "auto_impl", + "derive_more 2.0.1", "futures-utils-wasm", - "thiserror", + "serde", + "serde_json", + "thiserror 2.0.12", +] + +[[package]] +name = "alloy-network-primitives" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86f736e1d1eb1b770dbd32919bdf46d4dcd4617f2eed07947dfb32649962baba" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-primitives", + "alloy-serde", + "serde", ] [[package]] name = "alloy-primitives" -version = "0.7.7" +version = "0.8.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccb3ead547f4532bc8af961649942f0b9c16ee9226e26caa3f38420651cc0bf4" +checksum = "8c77490fe91a0ce933a1f219029521f20fc28c2c0ca95d53fa4da9c00b8d9d4e" dependencies = [ "alloy-rlp", "bytes", "cfg-if", "const-hex", - "derive_more 0.99.17", - "hex-literal", + "derive_more 2.0.1", + "foldhash", + "hashbrown 0.15.3", + "indexmap 2.9.0", "itoa", "k256", "keccak-asm", + "paste", "proptest", "rand 0.8.5", "ruint", + "rustc-hash 2.1.1", "serde", + "sha3", "tiny-keccak", ] [[package]] name = "alloy-provider" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy#83af23f563b9359e6691428ff8235c5fc6153984" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a557f9e3ec89437b06db3bfc97d20782b1f7cc55b5b602b6a82bf3f64d7efb0e" dependencies = [ "alloy-chains", "alloy-consensus", "alloy-eips", "alloy-json-rpc", "alloy-network", + "alloy-network-primitives", "alloy-primitives", "alloy-rpc-client", - "alloy-rpc-types", - "alloy-rpc-types-trace", + "alloy-rpc-types-eth", + "alloy-signer", + "alloy-sol-types", "alloy-transport", - "alloy-transport-http", "async-stream", "async-trait", "auto_impl", - "dashmap", + "dashmap 6.1.0", + "either", "futures", "futures-utils-wasm", - "lru", + "lru 0.13.0", + "parking_lot", "pin-project", - "reqwest", "serde", "serde_json", + "thiserror 2.0.12", "tokio", "tracing", - "url", + "wasmtimer", ] [[package]] name = "alloy-rlp" -version = "0.3.5" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b155716bab55763c95ba212806cf43d05bcc70e5f35b02bad20cf5ec7fe11fed" +checksum = "3d6c1d995bff8d011f7cd6c81820d51825e6e06d6db73914c1630ecf544d83d6" dependencies = [ "alloy-rlp-derive", "arrayvec", @@ -310,69 +398,74 @@ dependencies = [ [[package]] name = "alloy-rlp-derive" -version = "0.3.5" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8037e03c7f462a063f28daec9fda285a9a89da003c552f8637a80b9c8fd96241" +checksum = "a40e1ef334153322fd878d07e86af7a529bcb86b2439525920a88eba87bcf943" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.101", ] [[package]] name = "alloy-rpc-client" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy#83af23f563b9359e6691428ff8235c5fc6153984" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cec6dc89c4c3ef166f9fa436d1831f8142c16cf2e637647c936a6aaaabd8d898" dependencies = [ "alloy-json-rpc", + "alloy-primitives", "alloy-transport", "alloy-transport-http", + "async-stream", "futures", "pin-project", - "reqwest", "serde", "serde_json", "tokio", "tokio-stream", - "tower", + "tower 0.5.2", "tracing", - "url", + "tracing-futures", + "wasmtimer", ] [[package]] -name = "alloy-rpc-types" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy#83af23f563b9359e6691428ff8235c5fc6153984" +name = "alloy-rpc-types-any" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecd6d480e4e6e456f30eeeb3aef1512aaecb68df2a35d1f78865dbc4d20dc0fd" dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-genesis", - "alloy-primitives", - "alloy-rlp", + "alloy-consensus-any", + "alloy-rpc-types-eth", "alloy-serde", - "alloy-sol-types", - "itertools 0.12.1", - "serde", - "serde_json", - "thiserror", ] [[package]] -name = "alloy-rpc-types-trace" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy#83af23f563b9359e6691428ff8235c5fc6153984" +name = "alloy-rpc-types-eth" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8b6d55bdaa0c4a08650d4b32f174494cbade56adf6f2fcfa2a4f3490cb5511" dependencies = [ + "alloy-consensus", + "alloy-consensus-any", + "alloy-eips", + "alloy-network-primitives", "alloy-primitives", - "alloy-rpc-types", + "alloy-rlp", "alloy-serde", + "alloy-sol-types", + "itertools 0.14.0", "serde", "serde_json", + "thiserror 2.0.12", ] [[package]] name = "alloy-serde" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy#83af23f563b9359e6691428ff8235c5fc6153984" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1824791912f468a481dedc1db50feef3e85a078f6d743a62db2ee9c2ca674882" dependencies = [ "alloy-primitives", "serde", @@ -381,98 +474,85 @@ dependencies = [ [[package]] name = "alloy-signer" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy#83af23f563b9359e6691428ff8235c5fc6153984" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d087fe5aea96a93fbe71be8aaed5c57c3caac303c09e674bc5b1647990d648b" dependencies = [ "alloy-primitives", "async-trait", "auto_impl", + "either", "elliptic-curve", "k256", - "thiserror", -] - -[[package]] -name = "alloy-signer-wallet" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy#83af23f563b9359e6691428ff8235c5fc6153984" -dependencies = [ - "alloy-consensus", - "alloy-network", - "alloy-primitives", - "alloy-signer", - "async-trait", - "coins-bip32", - "coins-bip39", - "k256", - "rand 0.8.5", - "thiserror", + "thiserror 2.0.12", ] [[package]] name = "alloy-sol-macro" -version = "0.7.4" +version = "0.8.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dbd17d67f3e89478c8a634416358e539e577899666c927bc3d2b1328ee9b6ca" +checksum = "e10ae8e9a91d328ae954c22542415303919aabe976fe7a92eb06db1b68fd59f2" dependencies = [ "alloy-sol-macro-expander", "alloy-sol-macro-input", - "proc-macro-error", + "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.101", ] [[package]] name = "alloy-sol-macro-expander" -version = "0.7.4" +version = "0.8.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c6da95adcf4760bb4b108fefa51d50096c5e5fdd29ee72fed3e86ee414f2e34" +checksum = "83ad5da86c127751bc607c174d6c9fe9b85ef0889a9ca0c641735d77d4f98f26" dependencies = [ "alloy-json-abi", "alloy-sol-macro-input", "const-hex", - "heck 0.4.1", - "indexmap", - "proc-macro-error", + "heck 0.5.0", + "indexmap 2.9.0", + "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.101", "syn-solidity", "tiny-keccak", ] [[package]] name = "alloy-sol-macro-input" -version = "0.7.4" +version = "0.8.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32c8da04c1343871fb6ce5a489218f9c85323c8340a36e9106b5fc98d4dd59d5" +checksum = "ba3d30f0d3f9ba3b7686f3ff1de9ee312647aac705604417a2f40c604f409a9e" dependencies = [ "alloy-json-abi", "const-hex", "dunce", "heck 0.5.0", + "macro-string", "proc-macro2", "quote", "serde_json", - "syn 2.0.55", + "syn 2.0.101", "syn-solidity", ] [[package]] name = "alloy-sol-type-parser" -version = "0.7.4" +version = "0.8.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368cae4dc052cad1d8f72eb2ae0c38027116933eeb49213c200a9e9875f208d7" +checksum = "6d162f8524adfdfb0e4bd0505c734c985f3e2474eb022af32eef0d52a4f3935c" dependencies = [ - "winnow 0.6.8", + "serde", + "winnow 0.7.10", ] [[package]] name = "alloy-sol-types" -version = "0.7.4" +version = "0.8.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40a64d2d2395c1ac636b62419a7b17ec39031d6b2367e66e9acbf566e6055e9c" +checksum = "d43d5e60466a440230c07761aa67671d4719d46f43be8ea6e7ed334d8db4a9ab" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -483,36 +563,52 @@ dependencies = [ [[package]] name = "alloy-transport" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy#83af23f563b9359e6691428ff8235c5fc6153984" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6818b4c82a474cc01ac9e88ccfcd9f9b7bc893b2f8aea7e890a28dcd55c0a7aa" dependencies = [ "alloy-json-rpc", "base64 0.22.1", - "futures-util", + "derive_more 2.0.1", + "futures", "futures-utils-wasm", + "parking_lot", "serde", "serde_json", - "thiserror", + "thiserror 2.0.12", "tokio", - "tower", + "tower 0.5.2", + "tracing", "url", - "wasm-bindgen-futures", + "wasmtimer", ] [[package]] name = "alloy-transport-http" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy#83af23f563b9359e6691428ff8235c5fc6153984" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cc3079a33483afa1b1365a3add3ea3e21c75b10f704870198ba7846627d10f2" dependencies = [ - "alloy-json-rpc", "alloy-transport", - "reqwest", - "serde_json", - "tower", - "tracing", "url", ] +[[package]] +name = "alloy-trie" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d95a94854e420f07e962f7807485856cde359ab99ab6413883e15235ad996e8b" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "arrayvec", + "derive_more 1.0.0", + "nybbles", + "serde", + "smallvec", + "tracing", +] + [[package]] name = "android-tzdata" version = "0.1.1" @@ -738,6 +834,9 @@ name = "arrayvec" version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +dependencies = [ + "serde", +] [[package]] name = "asn1-rs" @@ -751,7 +850,7 @@ dependencies = [ "nom", "num-traits", "rusticata-macros", - "thiserror", + "thiserror 1.0.64", "time", ] @@ -763,7 +862,7 @@ checksum = "965c2d33e53cb6b267e148a4cb0760bc01f4904c1cd4bb4002a085bb016d1490" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.101", "synstructure", ] @@ -775,7 +874,7 @@ checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.101", ] [[package]] @@ -797,7 +896,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.101", ] [[package]] @@ -808,7 +907,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.101", ] [[package]] @@ -849,7 +948,7 @@ checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.101", ] [[package]] @@ -858,20 +957,44 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" +[[package]] +name = "aws-lc-rs" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fcc8f365936c834db5514fc45aee5b1202d677e6b40e48468aaaa8183ca8c7" +dependencies = [ + "aws-lc-sys", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61b1d86e7705efe1be1b569bab41d4fa1e14e220b60a160f78de2db687add079" +dependencies = [ + "bindgen 0.69.5", + "cc", + "cmake", + "dunce", + "fs_extra", +] + [[package]] name = "axum" -version = "0.6.20" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" +checksum = "021e862c184ae977658b36c4500f7feac3221ca5da43e3f25bd04ab6c79a29b5" dependencies = [ - "async-trait", "axum-core", - "bitflags 1.3.2", "bytes", + "form_urlencoded", "futures-util", - "http 0.2.12", - "http-body 0.4.6", - "hyper 0.14.28", + "http 1.1.0", + "http-body 1.0.0", + "http-body-util", + "hyper 1.3.1", + "hyper-util", "itoa", "matchit", "memchr", @@ -883,28 +1006,32 @@ dependencies = [ "serde_json", "serde_path_to_error", "serde_urlencoded", - "sync_wrapper", + "sync_wrapper 1.0.2", "tokio", - "tower", + "tower 0.5.2", "tower-layer", "tower-service", + "tracing", ] [[package]] name = "axum-core" -version = "0.3.4" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" +checksum = "68464cd0412f486726fb3373129ef5d2993f90c34bc2bc1c1e9943b2f4fc7ca6" dependencies = [ - "async-trait", "bytes", - "futures-util", - "http 0.2.12", - "http-body 0.4.6", + "futures-core", + "http 1.1.0", + "http-body 1.0.0", + "http-body-util", "mime", + "pin-project-lite", "rustversion", + "sync_wrapper 1.0.2", "tower-layer", "tower-service", + "tracing", ] [[package]] @@ -972,12 +1099,6 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" -[[package]] -name = "bech32" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" - [[package]] name = "better-panic" version = "0.3.0" @@ -1006,23 +1127,46 @@ dependencies = [ "regex", "rustc-hash 1.1.0", "shlex", - "syn 2.0.55", + "syn 2.0.101", +] + +[[package]] +name = "bindgen" +version = "0.69.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" +dependencies = [ + "bitflags 2.6.0", + "cexpr", + "clang-sys", + "itertools 0.12.1", + "lazy_static", + "lazycell", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash 1.1.0", + "shlex", + "syn 2.0.101", + "which", ] [[package]] name = "bit-set" -version = "0.5.3" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" dependencies = [ "bit-vec", ] [[package]] name = "bit-vec" -version = "0.6.3" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" [[package]] name = "bitflags" @@ -1062,9 +1206,9 @@ dependencies = [ [[package]] name = "blst" -version = "0.3.11" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c94087b935a822949d3291a9989ad2b2051ea141eda0fd4e478a75f6aa3e604b" +checksum = "47c79a94619fade3c0b887670333513a67ac28a6a7e653eb260bf0d4103db38d" dependencies = [ "cc", "glob", @@ -1078,7 +1222,6 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" dependencies = [ - "sha2", "tinyvec", ] @@ -1158,15 +1301,16 @@ dependencies = [ [[package]] name = "c-kzg" -version = "1.0.2" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdf100c4cea8f207e883ff91ca886d621d8a166cb04971dfaa9bb8fd99ed95df" +checksum = "7318cfa722931cb5fe0838b98d3ce5621e75f6a6408abc21721d80de9223f2e4" dependencies = [ "blst", "cc", "glob", "hex", "libc", + "once_cell", "serde", ] @@ -1212,7 +1356,7 @@ dependencies = [ "semver 1.0.22", "serde", "serde_json", - "thiserror", + "thiserror 1.0.64", ] [[package]] @@ -1229,12 +1373,13 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.90" +version = "1.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" +checksum = "32db95edf998450acc7881c932f94cd9b05c87b4b2599e8bab064753da4acfd1" dependencies = [ "jobserver", "libc", + "shlex", ] [[package]] @@ -1347,7 +1492,7 @@ dependencies = [ "anstream", "anstyle", "clap_lex", - "strsim 0.11.0", + "strsim 0.11.1", ] [[package]] @@ -1359,7 +1504,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.101", ] [[package]] @@ -1375,62 +1520,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8191fa7302e03607ff0e237d4246cc043ff5b3cb9409d995172ba3bea16b807" [[package]] -name = "cobs" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" - -[[package]] -name = "coins-bip32" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b6be4a5df2098cd811f3194f64ddb96c267606bffd9689ac7b0160097b01ad3" +name = "cluster" +version = "0.1.0" dependencies = [ - "bs58", - "coins-core", - "digest 0.10.7", - "hmac", - "k256", - "serde", - "sha2", - "thiserror", + "alloy", + "tokio", ] [[package]] -name = "coins-bip39" -version = "0.8.7" +name = "cmake" +version = "0.1.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3db8fba409ce3dc04f7d804074039eb68b960b0829161f8e06c95fea3f122528" +checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0" dependencies = [ - "bitvec", - "coins-bip32", - "hmac", - "once_cell", - "pbkdf2", - "rand 0.8.5", - "sha2", - "thiserror", + "cc", ] [[package]] -name = "coins-core" -version = "0.8.7" +name = "cobs" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5286a0843c21f8367f7be734f89df9b822e0321d8bcce8d6e735aadff7d74979" -dependencies = [ - "base64 0.21.7", - "bech32", - "bs58", - "digest 0.10.7", - "generic-array", - "hex", - "ripemd", - "serde", - "serde_derive", - "sha2", - "sha3", - "thiserror", -] +checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" [[package]] name = "collections" @@ -1480,9 +1590,9 @@ dependencies = [ [[package]] name = "const-hex" -version = "1.11.4" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ff96486ccc291d36a958107caf2c0af8c78c0af7d31ae2f35ce055130de1a6" +checksum = "4b0485bab839b018a8f1723fc5391819fea5f8f0f32288ef8a735fd096b6160c" dependencies = [ "cfg-if", "cpufeatures", @@ -1522,11 +1632,21 @@ dependencies = [ "libc", ] +[[package]] +name = "core-foundation" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "core2" @@ -1546,6 +1666,21 @@ dependencies = [ "libc", ] +[[package]] +name = "crc" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9710d3b3739c2e349eb44fe848ad0b7c8cb1e42bd87ee49371df2f7acaf3e675" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" + [[package]] name = "crc32fast" version = "1.4.2" @@ -1703,7 +1838,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.101", ] [[package]] @@ -1712,8 +1847,18 @@ version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" dependencies = [ - "darling_core", - "darling_macro", + "darling_core 0.14.4", + "darling_macro 0.14.4", +] + +[[package]] +name = "darling" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" +dependencies = [ + "darling_core 0.20.11", + "darling_macro 0.20.11", ] [[package]] @@ -1730,17 +1875,42 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "darling_core" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.11.1", + "syn 2.0.101", +] + [[package]] name = "darling_macro" version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" dependencies = [ - "darling_core", + "darling_core 0.14.4", "quote", "syn 1.0.109", ] +[[package]] +name = "darling_macro" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" +dependencies = [ + "darling_core 0.20.11", + "quote", + "syn 2.0.101", +] + [[package]] name = "dashmap" version = "5.5.3" @@ -1748,7 +1918,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ "cfg-if", - "hashbrown", + "hashbrown 0.14.3", + "lock_api", + "once_cell", + "parking_lot_core", +] + +[[package]] +name = "dashmap" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" +dependencies = [ + "cfg-if", + "crossbeam-utils", + "hashbrown 0.14.3", "lock_api", "once_cell", "parking_lot_core", @@ -1840,7 +2024,7 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4ec317cc3e7ef0928b0ca6e4a634a4d6c001672ae210438cf114a83e56b018d" dependencies = [ - "darling", + "darling 0.14.4", "proc-macro2", "quote", "syn 1.0.109", @@ -1875,7 +2059,16 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" dependencies = [ - "derive_more-impl", + "derive_more-impl 1.0.0", +] + +[[package]] +name = "derive_more" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678" +dependencies = [ + "derive_more-impl 2.0.1", ] [[package]] @@ -1886,7 +2079,19 @@ checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.101", + "unicode-xid", +] + +[[package]] +name = "derive_more-impl" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", "unicode-xid", ] @@ -1944,7 +2149,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.101", ] [[package]] @@ -1969,6 +2174,7 @@ dependencies = [ "digest 0.10.7", "elliptic-curve", "rfc6979", + "serdect", "signature", "spki", ] @@ -2007,14 +2213,17 @@ dependencies = [ "enum-ordinalize", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.101", ] [[package]] name = "either" -version = "1.13.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +dependencies = [ + "serde", +] [[package]] name = "elliptic-curve" @@ -2031,6 +2240,7 @@ dependencies = [ "pkcs8", "rand_core 0.6.4", "sec1", + "serdect", "subtle", "zeroize", ] @@ -2064,7 +2274,7 @@ checksum = "0d28318a75d4aead5c4db25382e8ef717932d0346600cacae6357eb5941bc5ff" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.101", ] [[package]] @@ -2166,6 +2376,17 @@ dependencies = [ "bytes", ] +[[package]] +name = "fastrlp" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce8dba4714ef14b8274c371879b175aa55b16b30f269663f19d576f380018dc4" +dependencies = [ + "arrayvec", + "auto_impl", + "bytes", +] + [[package]] name = "ff" version = "0.13.0" @@ -2223,19 +2444,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" +name = "foldhash" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" [[package]] name = "fork" @@ -2255,6 +2467,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + [[package]] name = "funty" version = "2.0.0" @@ -2267,7 +2485,7 @@ version = "0.1.0" source = "git+https://github.com/WalletConnect/utils-rs.git?tag=v0.14.1#bf8f50a711180afbf79b8c334c65b57886173d4b" dependencies = [ "pin-project", - "thiserror", + "thiserror 1.0.64", "tokio", "tokio-util", ] @@ -2339,7 +2557,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.101", ] [[package]] @@ -2439,6 +2657,18 @@ dependencies = [ "wasi 0.11.0+wasi-snapshot-preview1", ] +[[package]] +name = "getrandom" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", +] + [[package]] name = "gimli" version = "0.28.1" @@ -2484,7 +2714,7 @@ dependencies = [ "parking_lot", "signal-hook", "smallvec", - "thiserror", + "thiserror 1.0.64", "unicode-normalization", ] @@ -2498,7 +2728,7 @@ dependencies = [ "btoi", "gix-date", "itoa", - "thiserror", + "thiserror 1.0.64", "winnow 0.5.40", ] @@ -2508,7 +2738,7 @@ version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a371db66cbd4e13f0ed9dc4c0fea712d7276805fccc877f77e96374d317e87ae" dependencies = [ - "thiserror", + "thiserror 1.0.64", ] [[package]] @@ -2517,7 +2747,7 @@ version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45c8751169961ba7640b513c3b24af61aa962c967aaf04116734975cd5af0c52" dependencies = [ - "thiserror", + "thiserror 1.0.64", ] [[package]] @@ -2531,7 +2761,7 @@ dependencies = [ "gix-features", "gix-hash", "memmap2", - "thiserror", + "thiserror 1.0.64", ] [[package]] @@ -2550,7 +2780,7 @@ dependencies = [ "memchr", "once_cell", "smallvec", - "thiserror", + "thiserror 1.0.64", "unicode-bom", "winnow 0.5.40", ] @@ -2565,7 +2795,7 @@ dependencies = [ "bstr", "gix-path", "libc", - "thiserror", + "thiserror 1.0.64", ] [[package]] @@ -2576,7 +2806,7 @@ checksum = "180b130a4a41870edfbd36ce4169c7090bca70e195da783dea088dd973daa59c" dependencies = [ "bstr", "itoa", - "thiserror", + "thiserror 1.0.64", "time", ] @@ -2589,7 +2819,7 @@ dependencies = [ "bstr", "gix-hash", "gix-object", - "thiserror", + "thiserror 1.0.64", ] [[package]] @@ -2604,7 +2834,7 @@ dependencies = [ "gix-path", "gix-ref", "gix-sec", - "thiserror", + "thiserror 1.0.64", ] [[package]] @@ -2621,7 +2851,7 @@ dependencies = [ "once_cell", "prodash", "sha1_smol", - "thiserror", + "thiserror 1.0.64", "walkdir", ] @@ -2653,7 +2883,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f93d7df7366121b5018f947a04d37f034717e113dcf9ccd85c34b58e57a74d5e" dependencies = [ "faster-hex", - "thiserror", + "thiserror 1.0.64", ] [[package]] @@ -2663,7 +2893,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ddf80e16f3c19ac06ce415a38b8591993d3f73aede049cb561becb5b3a8e242" dependencies = [ "gix-hash", - "hashbrown", + "hashbrown 0.14.3", "parking_lot", ] @@ -2689,7 +2919,7 @@ dependencies = [ "memmap2", "rustix", "smallvec", - "thiserror", + "thiserror 1.0.64", ] [[package]] @@ -2700,7 +2930,7 @@ checksum = "f40a439397f1e230b54cf85d52af87e5ea44cc1e7748379785d3f6d03d802b00" dependencies = [ "gix-tempfile", "gix-utils", - "thiserror", + "thiserror 1.0.64", ] [[package]] @@ -2711,7 +2941,7 @@ checksum = "1dff438f14e67e7713ab9332f5fd18c8f20eb7eb249494f6c2bf170522224032" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.101", ] [[package]] @@ -2729,7 +2959,7 @@ dependencies = [ "gix-validate", "itoa", "smallvec", - "thiserror", + "thiserror 1.0.64", "winnow 0.5.40", ] @@ -2749,7 +2979,7 @@ dependencies = [ "gix-quote", "parking_lot", "tempfile", - "thiserror", + "thiserror 1.0.64", ] [[package]] @@ -2769,7 +2999,7 @@ dependencies = [ "memmap2", "parking_lot", "smallvec", - "thiserror", + "thiserror 1.0.64", ] [[package]] @@ -2782,7 +3012,7 @@ dependencies = [ "gix-trace", "home", "once_cell", - "thiserror", + "thiserror 1.0.64", ] [[package]] @@ -2793,7 +3023,7 @@ checksum = "cbff4f9b9ea3fa7a25a70ee62f545143abef624ac6aa5884344e70c8b0a1d9ff" dependencies = [ "bstr", "gix-utils", - "thiserror", + "thiserror 1.0.64", ] [[package]] @@ -2813,7 +3043,7 @@ dependencies = [ "gix-tempfile", "gix-validate", "memmap2", - "thiserror", + "thiserror 1.0.64", "winnow 0.5.40", ] @@ -2828,7 +3058,7 @@ dependencies = [ "gix-revision", "gix-validate", "smallvec", - "thiserror", + "thiserror 1.0.64", ] [[package]] @@ -2844,7 +3074,7 @@ dependencies = [ "gix-object", "gix-revwalk", "gix-trace", - "thiserror", + "thiserror 1.0.64", ] [[package]] @@ -2859,7 +3089,7 @@ dependencies = [ "gix-hashtable", "gix-object", "smallvec", - "thiserror", + "thiserror 1.0.64", ] [[package]] @@ -2908,7 +3138,7 @@ dependencies = [ "gix-object", "gix-revwalk", "smallvec", - "thiserror", + "thiserror 1.0.64", ] [[package]] @@ -2921,7 +3151,7 @@ dependencies = [ "gix-features", "gix-path", "home", - "thiserror", + "thiserror 1.0.64", "url", ] @@ -2942,7 +3172,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e39fc6e06044985eac19dd34d474909e517307582e462b2eb4c8fa51b6241545" dependencies = [ "bstr", - "thiserror", + "thiserror 1.0.64", ] [[package]] @@ -2992,7 +3222,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap", + "indexmap 2.9.0", "slab", "tokio", "tokio-util", @@ -3011,7 +3241,7 @@ dependencies = [ "futures-core", "futures-sink", "http 1.1.0", - "indexmap", + "indexmap 2.9.0", "slab", "tokio", "tokio-util", @@ -3028,6 +3258,12 @@ dependencies = [ "crunchy", ] +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + [[package]] name = "hashbrown" version = "0.14.3" @@ -3039,19 +3275,25 @@ dependencies = [ ] [[package]] -name = "heck" -version = "0.3.3" +name = "hashbrown" +version = "0.15.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3" dependencies = [ - "unicode-segmentation", + "allocator-api2", + "equivalent", + "foldhash", + "serde", ] [[package]] name = "heck" -version = "0.4.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +dependencies = [ + "unicode-segmentation", +] [[package]] name = "heck" @@ -3083,12 +3325,6 @@ dependencies = [ "serde", ] -[[package]] -name = "hex-literal" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" - [[package]] name = "hex_fmt" version = "0.3.0" @@ -3242,18 +3478,21 @@ dependencies = [ ] [[package]] -name = "hyper-tls" -version = "0.6.0" +name = "hyper-rustls" +version = "0.27.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2" dependencies = [ - "bytes", - "http-body-util", + "futures-util", + "http 1.1.0", "hyper 1.3.1", "hyper-util", - "native-tls", + "log", + "rustls", + "rustls-native-certs 0.8.1", + "rustls-pki-types", "tokio", - "tokio-native-tls", + "tokio-rustls", "tower-service", ] @@ -3272,7 +3511,7 @@ dependencies = [ "pin-project-lite", "socket2", "tokio", - "tower", + "tower 0.4.13", "tower-service", "tracing", ] @@ -3354,12 +3593,24 @@ checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" [[package]] name = "indexmap" -version = "2.2.6" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "indexmap" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.15.3", + "serde", ] [[package]] @@ -3441,6 +3692,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.11" @@ -3457,7 +3717,7 @@ dependencies = [ "combine", "jni-sys", "log", - "thiserror", + "thiserror 1.0.64", "walkdir", ] @@ -3469,9 +3729,9 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] name = "jobserver" -version = "0.1.28" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab46a6e9526ddef3ae7f787c06f0f2600639ba80ea3eade3d8e670a2230f51d6" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" dependencies = [ "libc", ] @@ -3495,8 +3755,8 @@ dependencies = [ "ecdsa", "elliptic-curve", "once_cell", + "serdect", "sha2", - "signature", ] [[package]] @@ -3552,9 +3812,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.161" +version = "0.2.172" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" +checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" [[package]] name = "libloading" @@ -3593,7 +3853,7 @@ dependencies = [ "multiaddr", "pin-project", "rw-stream-sink", - "thiserror", + "thiserror 1.0.64", ] [[package]] @@ -3642,7 +3902,7 @@ dependencies = [ "rw-stream-sink", "serde", "smallvec", - "thiserror", + "thiserror 1.0.64", "tracing", "unsigned-varint 0.8.0", "void", @@ -3695,7 +3955,7 @@ dependencies = [ "rand 0.8.5", "serde", "sha2", - "thiserror", + "thiserror 1.0.64", "tracing", "zeroize", ] @@ -3723,7 +3983,7 @@ dependencies = [ "serde", "sha2", "smallvec", - "thiserror", + "thiserror 1.0.64", "tracing", "uint", "void", @@ -3742,7 +4002,7 @@ dependencies = [ "futures-timer", "libp2p-core", "libp2p-identity", - "lru", + "lru 0.12.3", "multistream-select", "once_cell", "rand 0.8.5", @@ -3766,7 +4026,7 @@ dependencies = [ "ring 0.17.8", "rustls", "rustls-webpki 0.101.7", - "thiserror", + "thiserror 1.0.64", "x509-parser", "yasna", ] @@ -3777,7 +4037,7 @@ version = "0.11.0+8.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3386f101bcb4bd252d8e9d2fb41ec3b0862a15a62b478c355b2982efa469e3e" dependencies = [ - "bindgen", + "bindgen 0.65.1", "bzip2-sys", "cc", "glob", @@ -3837,7 +4097,16 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" dependencies = [ - "hashbrown", + "hashbrown 0.14.3", +] + +[[package]] +name = "lru" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "227748d55f2f0ab4735d87fd623798cb6b664512fe979705f829c9f81c934465" +dependencies = [ + "hashbrown 0.15.3", ] [[package]] @@ -3850,6 +4119,17 @@ dependencies = [ "libc", ] +[[package]] +name = "macro-string" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b27834086c65ec3f9387b096d66e99f221cf081c2b738042aa252bcd41204e3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + [[package]] name = "macros" version = "0.9.0" @@ -3872,9 +4152,9 @@ dependencies = [ [[package]] name = "matchit" -version = "0.7.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" +checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" [[package]] name = "memchr" @@ -3912,21 +4192,21 @@ dependencies = [ [[package]] name = "metrics-exporter-prometheus" -version = "0.15.0" +version = "0.15.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26eb45aff37b45cff885538e1dcbd6c2b462c04fe84ce0155ea469f325672c98" +checksum = "b4f0c8427b39666bf970460908b213ec09b3b350f20c0c2eabcbba51704a08e6" dependencies = [ "base64 0.22.1", "http-body-util", "hyper 1.3.1", - "hyper-tls", + "hyper-rustls", "hyper-util", - "indexmap", + "indexmap 2.9.0", "ipnet", "metrics", "metrics-util", "quanta", - "thiserror", + "thiserror 1.0.64", "tokio", "tracing", ] @@ -3939,7 +4219,7 @@ checksum = "4259040465c955f9f2f1a4a8a16dc46726169bca0f88e8fb2dbeced487c3e828" dependencies = [ "crossbeam-epoch", "crossbeam-utils", - "hashbrown", + "hashbrown 0.14.3", "metrics", "num_cpus", "quanta", @@ -3960,7 +4240,7 @@ checksum = "c325dfab65f261f386debee8b0969da215b3fa0037e74c8a1234db7ba986d803" dependencies = [ "crossbeam-channel", "crossbeam-utils", - "dashmap", + "dashmap 5.5.3", "skeptic", "smallvec", "tagptr", @@ -4076,24 +4356,6 @@ dependencies = [ "unsigned-varint 0.7.2", ] -[[package]] -name = "native-tls" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" -dependencies = [ - "lazy_static", - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - [[package]] name = "nix" version = "0.28.0" @@ -4227,7 +4489,7 @@ checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.101", ] [[package]] @@ -4239,6 +4501,19 @@ dependencies = [ "libc", ] +[[package]] +name = "nybbles" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8983bb634df7248924ee0c4c3a749609b5abcb082c28fffe3254b3eb3602b307" +dependencies = [ + "alloy-rlp", + "const-hex", + "proptest", + "serde", + "smallvec", +] + [[package]] name = "object" version = "0.32.2" @@ -4259,9 +4534,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.19.0" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "oorandom" @@ -4284,57 +4559,19 @@ dependencies = [ "maplit", "rand 0.8.5", "serde", - "thiserror", + "thiserror 1.0.64", "tokio", "tracing", "tracing-futures", "validit", ] -[[package]] -name = "openssl" -version = "0.10.66" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" -dependencies = [ - "bitflags 2.6.0", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.55", -] - [[package]] name = "openssl-probe" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" -[[package]] -name = "openssl-sys" -version = "0.9.103" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "overload" version = "0.1.1" @@ -4396,7 +4633,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fa925f9becb532d758b0014b472c576869910929cf4c3f8054b386f19ab9e21" dependencies = [ - "thiserror", + "thiserror 1.0.64", ] [[package]] @@ -4411,16 +4648,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" -[[package]] -name = "pbkdf2" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" -dependencies = [ - "digest 0.10.7", - "hmac", -] - [[package]] name = "peeking_take_while" version = "0.1.2" @@ -4450,7 +4677,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "560131c633294438da9f7c4b08189194b20946c8274c6b9e38881a7874dc8ee8" dependencies = [ "memchr", - "thiserror", + "thiserror 1.0.64", "ucd-trie", ] @@ -4459,7 +4686,7 @@ name = "phi-accrual-failure-detector" version = "0.1.0" source = "git+https://github.com/heilhead/phi-accrual-failure-detector.git?rev=30fb190#30fb190da0127fa2fa14b833d44c4e39872f81b7" dependencies = [ - "thiserror", + "thiserror 1.0.64", ] [[package]] @@ -4490,7 +4717,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.101", ] [[package]] @@ -4591,7 +4818,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d3928fb5db768cb86f891ff014f0144589297e3c6a1aba6ed7cecfdace270c7" dependencies = [ "proc-macro2", - "syn 2.0.55", + "syn 2.0.101", ] [[package]] @@ -4638,11 +4865,33 @@ dependencies = [ "version_check", ] +[[package]] +name = "proc-macro-error-attr2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "proc-macro-error2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" +dependencies = [ + "proc-macro-error-attr2", + "proc-macro2", + "quote", + "syn 2.0.101", +] + [[package]] name = "proc-macro2" -version = "1.0.79" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" dependencies = [ "unicode-ident", ] @@ -4682,14 +4931,14 @@ checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.101", ] [[package]] name = "proptest" -version = "1.4.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31b476131c3c86cb68032fdc5cb6d5a1045e3e42d96b69fa599fd77701e1f5bf" +checksum = "14cae93065090804185d3b75f0bf93b8eeda30c7a9b4a33d3bdb3988d6229e50" dependencies = [ "bit-set", "bit-vec", @@ -4723,7 +4972,7 @@ dependencies = [ "arc-swap", "futures", "phi-accrual-failure-detector", - "thiserror", + "thiserror 1.0.64", "tokio", "tokio-stream", "tokio-util", @@ -4774,7 +5023,7 @@ dependencies = [ "asynchronous-codec", "bytes", "quick-protobuf", - "thiserror", + "thiserror 1.0.64", "unsigned-varint 0.8.0", ] @@ -4788,10 +5037,10 @@ dependencies = [ "pin-project-lite", "quinn-proto", "quinn-udp", - "rustc-hash 2.0.0", + "rustc-hash 2.1.1", "rustls", "socket2", - "thiserror", + "thiserror 1.0.64", "tokio", "tracing", ] @@ -4805,11 +5054,11 @@ dependencies = [ "bytes", "rand 0.8.5", "ring 0.17.8", - "rustc-hash 2.0.0", + "rustc-hash 2.1.1", "rustls", "rustls-platform-verifier", "slab", - "thiserror", + "thiserror 1.0.64", "tinyvec", "tracing", ] @@ -4836,6 +5085,12 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" + [[package]] name = "radium" version = "0.7.0" @@ -4852,7 +5107,7 @@ dependencies = [ "openraft", "postcard", "serde", - "thiserror", + "thiserror 1.0.64", "tokio", "tokio-stream", "tracing", @@ -4882,6 +5137,17 @@ dependencies = [ "libc", "rand_chacha 0.3.1", "rand_core 0.6.4", + "serde", +] + +[[package]] +name = "rand" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.3", ] [[package]] @@ -4904,6 +5170,16 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.3", +] + [[package]] name = "rand_core" version = "0.5.1" @@ -4922,6 +5198,15 @@ dependencies = [ "getrandom 0.2.15", ] +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom 0.3.3", +] + [[package]] name = "rand_hc" version = "0.2.0" @@ -5067,7 +5352,7 @@ dependencies = [ "tempfile", "test-context", "test-log", - "thiserror", + "thiserror 1.0.64", "tokio", "tokio-util", "tracing", @@ -5088,23 +5373,19 @@ dependencies = [ "http-body 1.0.0", "http-body-util", "hyper 1.3.1", - "hyper-tls", "hyper-util", "ipnet", "js-sys", "log", "mime", - "native-tls", "once_cell", "percent-encoding", "pin-project-lite", - "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", - "sync_wrapper", + "sync_wrapper 0.1.2", "tokio", - "tokio-native-tls", "tower-service", "url", "wasm-bindgen", @@ -5153,15 +5434,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "ripemd" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" -dependencies = [ - "digest 0.10.7", -] - [[package]] name = "rlp" version = "0.5.2" @@ -5229,27 +5501,30 @@ dependencies = [ "regex", "relative-path", "rustc_version 0.4.0", - "syn 2.0.55", + "syn 2.0.101", "unicode-ident", ] [[package]] name = "ruint" -version = "1.12.3" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c3cc4c2511671f327125da14133d0c5c5d137f006a1017a16f557bc85b16286" +checksum = "78a46eb779843b2c4f21fac5773e25d6d5b7c8f0922876c91541790d2ca27eef" dependencies = [ "alloy-rlp", "ark-ff 0.3.0", "ark-ff 0.4.2", "bytes", - "fastrlp", + "fastrlp 0.3.1", + "fastrlp 0.4.0", "num-bigint", + "num-integer", "num-traits", "parity-scale-codec", "primitive-types", "proptest", "rand 0.8.5", + "rand 0.9.1", "rlp", "ruint-macro", "serde", @@ -5277,9 +5552,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc-hash" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" [[package]] name = "rustc-hex" @@ -5329,10 +5604,12 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.16" +version = "0.23.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eee87ff5d9b36712a58574e12e9f0ea80f915a5b0ac518d322b24a465617925e" +checksum = "47796c98c480fce5406ef69d1c76378375492c3b0a0de587be0c1d9feb12f395" dependencies = [ + "aws-lc-rs", + "log", "once_cell", "ring 0.17.8", "rustls-pki-types", @@ -5351,7 +5628,19 @@ dependencies = [ "rustls-pemfile", "rustls-pki-types", "schannel", - "security-framework", + "security-framework 2.11.1", +] + +[[package]] +name = "rustls-native-certs" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" +dependencies = [ + "openssl-probe", + "rustls-pki-types", + "schannel", + "security-framework 3.2.0", ] [[package]] @@ -5376,16 +5665,16 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "afbb878bdfdf63a336a5e63561b1835e7a8c91524f51621db870169eac84b490" dependencies = [ - "core-foundation", + "core-foundation 0.9.4", "core-foundation-sys", "jni", "log", "once_cell", "rustls", - "rustls-native-certs", + "rustls-native-certs 0.7.3", "rustls-platform-verifier-android", "rustls-webpki 0.102.8", - "security-framework", + "security-framework 2.11.1", "security-framework-sys", "webpki-roots", "winapi", @@ -5413,6 +5702,7 @@ version = "0.102.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" dependencies = [ + "aws-lc-rs", "ring 0.17.8", "rustls-pki-types", "untrusted 0.9.0", @@ -5487,6 +5777,7 @@ dependencies = [ "der", "generic-array", "pkcs8", + "serdect", "subtle", "zeroize", ] @@ -5498,18 +5789,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ "bitflags 2.6.0", - "core-foundation", + "core-foundation 0.9.4", "core-foundation-sys", "libc", "num-bigint", "security-framework-sys", ] +[[package]] +name = "security-framework" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271720403f46ca04f7ba6f55d438f8bd878d6b8ca0a1046e8228c4145bcbb316" +dependencies = [ + "bitflags 2.6.0", + "core-foundation 0.10.0", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + [[package]] name = "security-framework-sys" -version = "2.12.0" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" +checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" dependencies = [ "core-foundation-sys", "libc", @@ -5568,7 +5872,7 @@ checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.101", ] [[package]] @@ -5614,6 +5918,46 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_with" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6b6f7f2fcb69f747921f79f3926bd1e203fce4fef62c268dd3abfb6d86029aa" +dependencies = [ + "base64 0.22.1", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.9.0", + "serde", + "serde_derive", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d00caa5193a3c8362ac2b73be6b9e768aa5a4b2f721d8f4b339600c3cb51f8e" +dependencies = [ + "darling 0.20.11", + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "serdect" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a84f14a19e9a014bb9f4512488d9829a68e04ecabffb0f9904cd1ace94598177" +dependencies = [ + "base16ct", + "serde", +] + [[package]] name = "sha1_smol" version = "1.0.0" @@ -5664,9 +6008,9 @@ dependencies = [ name = "sharding" version = "0.1.0" dependencies = [ - "indexmap", + "indexmap 2.9.0", "rand 0.8.5", - "thiserror", + "thiserror 1.0.64", ] [[package]] @@ -5815,9 +6159,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "strsim" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "structopt" @@ -5845,24 +6189,24 @@ dependencies = [ [[package]] name = "strum" -version = "0.26.2" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29" +checksum = "f64def088c51c9510a8579e3c5d67c65349dcf755e5479ad3d010aa6454e2c32" dependencies = [ "strum_macros", ] [[package]] name = "strum_macros" -version = "0.26.2" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6cf59daf282c0a494ba14fd21610a0325f9f90ec9d1231dea26bcb1d696c946" +checksum = "c77a8c5abcaf0f9ce05d62342b7d298c346515365c36b673df4ebe3ced01fde8" dependencies = [ - "heck 0.4.1", + "heck 0.5.0", "proc-macro2", "quote", "rustversion", - "syn 2.0.55", + "syn 2.0.101", ] [[package]] @@ -5884,9 +6228,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.55" +version = "2.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "002a1b3dbf967edfafc32655d0f377ab0bb7b994aa1d32c8cc7e9b8bf3ebb8f0" +checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" dependencies = [ "proc-macro2", "quote", @@ -5895,14 +6239,14 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "0.7.4" +version = "0.8.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8db114c44cf843a8bacd37a146e37987a0b823a0e8bc4fdc610c9c72ab397a5" +checksum = "4560533fbd6914b94a8fb5cc803ed6801c3455668db3b810702c57612bac9412" dependencies = [ "paste", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.101", ] [[package]] @@ -5911,6 +6255,12 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" + [[package]] name = "synstructure" version = "0.13.1" @@ -5919,7 +6269,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.101", ] [[package]] @@ -5988,7 +6338,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d506c7664333e246f564949bee4ed39062aa0f11918e6f5a95f553cdad65c274" dependencies = [ "quote", - "syn 2.0.55", + "syn 2.0.101", ] [[package]] @@ -6009,7 +6359,7 @@ checksum = "c8f546451eaa38373f549093fe9fd05e7d2bade739e2ddf834b9968621d60107" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.101", ] [[package]] @@ -6027,7 +6377,16 @@ version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.64", +] + +[[package]] +name = "thiserror" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +dependencies = [ + "thiserror-impl 2.0.12", ] [[package]] @@ -6038,7 +6397,18 @@ checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.101", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", ] [[package]] @@ -6166,9 +6536,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.41.0" +version = "1.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "145f3413504347a2be84393cc8a7d2fb4d863b375909ea59f2158261aa258bbb" +checksum = "2513ca694ef9ede0fb23fe71a4ee4107cb102b9dc1930f6d0fd77aae068ae165" dependencies = [ "backtrace", "bytes", @@ -6184,22 +6554,22 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.101", ] [[package]] -name = "tokio-native-tls" -version = "0.3.1" +name = "tokio-rustls" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" dependencies = [ - "native-tls", + "rustls", "tokio", ] @@ -6282,7 +6652,7 @@ version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" dependencies = [ - "indexmap", + "indexmap 2.9.0", "toml_datetime", "winnow 0.5.40", ] @@ -6293,7 +6663,7 @@ version = "0.22.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c127785850e8c20836d49732ae6abfa47616e60bf9d9f57c43c250361a9db96c" dependencies = [ - "indexmap", + "indexmap 2.9.0", "serde", "serde_spanned", "toml_datetime", @@ -6316,17 +6686,33 @@ dependencies = [ "tracing", ] +[[package]] +name = "tower" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper 1.0.2", + "tokio", + "tower-layer", + "tower-service", + "tracing", +] + [[package]] name = "tower-layer" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" @@ -6347,7 +6733,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3566e8ce28cc0a3fe42519fc80e6b4c943cc4c8cef275620eb8dac2d3d4e06cf" dependencies = [ "crossbeam-channel", - "thiserror", + "thiserror 1.0.64", "time", "tracing-subscriber", ] @@ -6360,7 +6746,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.101", ] [[package]] @@ -6379,6 +6765,8 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" dependencies = [ + "futures", + "futures-task", "pin-project", "tracing", ] @@ -6681,6 +7069,15 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + [[package]] name = "wasm-bindgen" version = "0.2.92" @@ -6702,7 +7099,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.101", "wasm-bindgen-shared", ] @@ -6736,7 +7133,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.101", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -6747,6 +7144,20 @@ version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +[[package]] +name = "wasmtimer" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0048ad49a55b9deb3953841fa1fc5858f0efbcb7a18868c899a360269fac1b23" +dependencies = [ + "futures", + "js-sys", + "parking_lot", + "pin-utils", + "slab", + "wasm-bindgen", +] + [[package]] name = "wc" version = "0.1.0" @@ -6776,7 +7187,6 @@ dependencies = [ name = "wcn" version = "0.1.0" dependencies = [ - "alloy", "anyhow", "chrono", "clap 4.5.4", @@ -6794,7 +7204,7 @@ dependencies = [ "serde", "serde_json", "tap", - "thiserror", + "thiserror 1.0.64", "tokio", "tracing", "vergen-pretty", @@ -6814,7 +7224,7 @@ dependencies = [ "postcard", "serde", "snap", - "thiserror", + "thiserror 1.0.64", "tracing", "wcn_rpc", ] @@ -6832,7 +7242,7 @@ dependencies = [ "serde", "serde-big-array", "serde_json", - "thiserror", + "thiserror 1.0.64", "wcn_rpc", ] @@ -6847,7 +7257,7 @@ dependencies = [ "rand 0.8.5", "serde", "serde_json", - "thiserror", + "thiserror 1.0.64", "tokio", "tokio-stream", "tracing", @@ -6864,14 +7274,13 @@ dependencies = [ "alloc_counter", "anyhow", "arc-swap", - "async-trait", "backoff", "better-panic", "bitflags 2.6.0", "bytes", "chrono", "criterion", - "dashmap", + "dashmap 5.5.3", "derivative", "derive_more 1.0.0", "difference", @@ -6895,7 +7304,7 @@ dependencies = [ "structopt", "tap", "test-log", - "thiserror", + "thiserror 1.0.64", "tokio", "tokio-stream", "tokio-util", @@ -6913,7 +7322,7 @@ version = "0.1.0" dependencies = [ "serde", "sharding", - "thiserror", + "thiserror 1.0.64", "wcn_core", "wcn_rpc", "xxhash-rust", @@ -6928,7 +7337,7 @@ dependencies = [ "governor", "serde", "tap", - "thiserror", + "thiserror 1.0.64", "time", "tokio", "tokio-serde", @@ -6946,7 +7355,7 @@ dependencies = [ "futures", "relay_rocks", "serde", - "thiserror", + "thiserror 1.0.64", "time", "tracing", "wc", @@ -6957,7 +7366,6 @@ dependencies = [ name = "wcn_node" version = "0.0.0" dependencies = [ - "alloy", "anyerror", "anyhow", "async-trait", @@ -6998,7 +7406,7 @@ dependencies = [ "tap", "tempfile", "test-log", - "thiserror", + "thiserror 1.0.64", "time", "tokio", "tokio-stream", @@ -7031,7 +7439,7 @@ dependencies = [ "futures", "postcard", "serde", - "thiserror", + "thiserror 1.0.64", "tracing", "wcn_rpc", ] @@ -7043,7 +7451,7 @@ dependencies = [ "futures", "raft", "serde", - "thiserror", + "thiserror 1.0.64", "tracing", "wc", "wcn_rpc", @@ -7057,7 +7465,7 @@ dependencies = [ "futures", "smallvec", "tap", - "thiserror", + "thiserror 1.0.64", "tokio", "tracing", "wc", @@ -7076,7 +7484,7 @@ dependencies = [ "derive_more 1.0.0", "futures", "governor", - "indexmap", + "indexmap 2.9.0", "libp2p", "libp2p-tls", "metrics", @@ -7090,7 +7498,7 @@ dependencies = [ "serde_json", "socket2", "tap", - "thiserror", + "thiserror 1.0.64", "tokio", "tokio-serde", "tokio-serde-postcard", @@ -7108,7 +7516,7 @@ dependencies = [ "arc-swap", "futures", "serde", - "thiserror", + "thiserror 1.0.64", "time", "tracing", "wc", @@ -7145,6 +7553,18 @@ dependencies = [ "rustls-pki-types", ] +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix", +] + [[package]] name = "winapi" version = "0.3.9" @@ -7401,6 +7821,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "winnow" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06928c8748d81b05c9be96aad92e1b6ff01833332f281e8cfca3be4b35fc9ec" +dependencies = [ + "memchr", +] + [[package]] name = "winreg" version = "0.52.0" @@ -7411,6 +7840,15 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags 2.6.0", +] + [[package]] name = "wyz" version = "0.5.1" @@ -7433,7 +7871,7 @@ dependencies = [ "nom", "oid-registry", "rusticata-macros", - "thiserror", + "thiserror 1.0.64", "time", ] @@ -7469,7 +7907,7 @@ checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.101", ] [[package]] @@ -7489,5 +7927,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.101", ] diff --git a/contracts/src/Cluster/Maintenance.sol b/contracts/src/Cluster/Maintenance.sol index 870a9cd4..11c2edea 100644 --- a/contracts/src/Cluster/Maintenance.sol +++ b/contracts/src/Cluster/Maintenance.sol @@ -6,24 +6,24 @@ struct Maintenance { } library MaintenanceLib { - function start(Maintenance storage self, address operator) public { + function start(Maintenance storage self, address operator) internal { require(operator != address(0), "invalid address"); require(self.slot == address(0), "another maintenance in progress"); self.slot = operator; } - function complete(Maintenance storage self, address operator) public { + function complete(Maintenance storage self, address operator) internal { require(operator != address(0), "invalid address"); require(self.slot == operator, "not under maintenance"); delete self.slot; } - function abort(Maintenance storage self) public { + function abort(Maintenance storage self) internal { require(self.slot != address(0), "not under maintenance"); delete self.slot; } - function inProgress(Maintenance calldata self) public pure returns (bool) { + function inProgress(Maintenance storage self) internal view returns (bool) { return (self.slot != address(0)); } } diff --git a/contracts/src/Cluster/Migration.sol b/contracts/src/Cluster/Migration.sol index 14177a59..11abd403 100644 --- a/contracts/src/Cluster/Migration.sol +++ b/contracts/src/Cluster/Migration.sol @@ -26,7 +26,7 @@ library MigrationLib { NodeOperator[] storage currentOperators, address[] calldata operatorsToRemove, NodeOperatorView[] calldata operatorsToAdd - ) public { + ) internal { require(!inProgress(self), "migration already in progress"); require(operatorsToRemove.length > 0 || operatorsToAdd.length > 0, "nothing to do"); @@ -50,19 +50,19 @@ library MigrationLib { } } - function completeDataPull(Migration storage self, address operator) public { + function completeDataPull(Migration storage self, address operator) internal { require(self.pullingOperators[operator], "not pulling"); self.pullingOperators[operator] = false; self.pullingOperatorsCount--; } - function complete(Migration storage self) public { + function complete(Migration storage self) internal { require(inProgress(self), "not in progress"); require(self.pullingOperatorsCount == 0, "data pull in progress"); self.cleanup(); } - function abort(Migration storage self) public { + function abort(Migration storage self) internal { require(inProgress(self), "not in progress"); self.cleanup(); } @@ -73,11 +73,11 @@ library MigrationLib { delete self.pullingOperatorsCount; } - function inProgress(Migration storage self) public view returns (bool) { + function inProgress(Migration storage self) internal view returns (bool) { return (self.operatorsToRemove.length != 0 || self.operatorsToAdd.length != 0); } - function getView(Migration storage self, NodeOperator[] storage currentOperators) public view returns (MigrationView memory) { + function getView(Migration storage self, NodeOperator[] storage currentOperators) internal view returns (MigrationView memory) { address[] memory toRemove = new address[](self.operatorsToRemove.length); for (uint256 i = 0; i < self.operatorsToRemove.length; i++) { toRemove[i] = self.operatorsToRemove[i]; diff --git a/contracts/src/Cluster/NodeOperators.sol b/contracts/src/Cluster/NodeOperators.sol index 9714c67f..207a92e4 100644 --- a/contracts/src/Cluster/NodeOperators.sol +++ b/contracts/src/Cluster/NodeOperators.sol @@ -29,7 +29,7 @@ library NodeOperatorsLib { using NodesLib for Nodes; using NodeOperatorsLib for NodeOperators; - function add(NodeOperators storage self, NodeOperatorView calldata operator) public { + function add(NodeOperators storage self, NodeOperatorView memory operator) internal { require(!exists(self, operator.addr), "operator already exists"); uint8 idx; @@ -52,7 +52,7 @@ library NodeOperatorsLib { } } - function remove(NodeOperators storage self, address addr) public { + function remove(NodeOperators storage self, address addr) internal { require(addr != address(0), "invalid address"); uint8 idx = self.indexes[addr]; @@ -63,7 +63,7 @@ library NodeOperatorsLib { self.freeSlotIndexes.push(idx); } - function exists(NodeOperators storage self, address addr) public view returns (bool) { + function exists(NodeOperators storage self, address addr) internal view returns (bool) { require(addr != address(0), "invalid address"); if (self.slots.length > 0) { @@ -73,23 +73,23 @@ library NodeOperatorsLib { return false; } - function length(NodeOperators storage self) public view returns (uint256) { + function length(NodeOperators storage self) internal view returns (uint256) { return self.slots.length - self.freeSlotIndexes.length; } - function setNode(NodeOperators storage self, address operator, Node calldata node) public { + function setNode(NodeOperators storage self, address operator, Node calldata node) internal { self.slots[self.indexes[operator]].nodes.set(node); } - function removeNode(NodeOperators storage self, address operator, uint256 id) public { + function removeNode(NodeOperators storage self, address operator, uint256 id) internal { self.slots[self.indexes[operator]].nodes.remove(id); } - function nodesCount(NodeOperators storage self, address operator) public view returns (uint256) { + function nodesCount(NodeOperators storage self, address operator) internal view returns (uint256) { return self.slots[self.indexes[operator]].nodes.length(); } - function getView(NodeOperators storage self) public view returns (NodeOperatorsView memory) { + function getView(NodeOperators storage self) internal view returns (NodeOperatorsView memory) { NodeOperatorView[] memory slots = new NodeOperatorView[](self.slots.length); for (uint256 i = 0; i < self.slots.length; i++) { slots[i] = NodeOperatorView({ diff --git a/contracts/src/Cluster/Nodes.sol b/contracts/src/Cluster/Nodes.sol index 1317aa99..939db40e 100644 --- a/contracts/src/Cluster/Nodes.sol +++ b/contracts/src/Cluster/Nodes.sol @@ -13,7 +13,7 @@ struct Nodes { } library NodesLib { - function set(Nodes storage self, Node calldata node) public { + function set(Nodes storage self, Node memory node) internal { require(node.id != 0, "invalid id"); uint8 idx; @@ -39,7 +39,7 @@ library NodesLib { self.slots[idx] = node; } - function remove(Nodes storage self, uint256 id) public { + function remove(Nodes storage self, uint256 id) internal { require(id != 0, "invalid id"); uint8 idx = self.indexes[id]; @@ -49,11 +49,11 @@ library NodesLib { self.freeSlotIndexes.push(idx); } - function length(Nodes storage self) public view returns (uint256) { + function length(Nodes storage self) internal view returns (uint256) { return self.slots.length - self.freeSlotIndexes.length; } - function getView(Nodes storage self) public view returns (Node[] memory) { + function getView(Nodes storage self) internal view returns (Node[] memory) { Node[] memory nodes = new Node[](length(self)); uint256 j; for (uint256 i = 0; i < self.slots.length; i++) { diff --git a/contracts/test/Suite.sol b/contracts/test/Suite.sol index 35aaa85a..9b279f2b 100644 --- a/contracts/test/Suite.sol +++ b/contracts/test/Suite.sol @@ -856,20 +856,6 @@ contract ClusterTest is Test { assertEq(clusterView.maintenance.slot, address(0)); } - // function assertMigrationOperatorsToRemoveCount(uint256 count) internal { - // assertEq(clusterView.migration.operatorsToRemove.length, count); - // } - - // function assertMigrationOperatorsToAddCount(uint256 count) internal { - // assertEq(clusterView.migration.operatorsToAdd.length, count); - // } - - // function assertMigrationOperatorToAdd(uint256 idx, uint256 privateKey, bytes: data, uint256 nodesCount) internal { - // assertEq(clusterView.migration.operatorsToAdd[idx].addr, vm.addr(privateKey)); - // assertEq(clusterView.migration.operatorsToAdd[idx].data, data); - // assertEq(clusterView.migration.operatorsToAdd[idx].nodes.length, nodesCount); - // } - function newMigration() internal pure returns (TestMigration memory) { return TestMigration({ vm: vm, diff --git a/crates/cluster/Cargo.toml b/crates/cluster/Cargo.toml new file mode 100644 index 00000000..5e1d723e --- /dev/null +++ b/crates/cluster/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "cluster" +version = "0.1.0" +edition = "2021" + +[lints] +workspace = true + +[dependencies] +alloy = { version = "0.13", default-features = false, features = ["sol-types", "contract"] } + +[dev-dependencies] +tokio = { version = "1", default-features = false } diff --git a/crates/cluster/src/contract/mod.rs b/crates/cluster/src/contract/mod.rs new file mode 100644 index 00000000..da5ccddd --- /dev/null +++ b/crates/cluster/src/contract/mod.rs @@ -0,0 +1,5306 @@ +#![allow(unused_imports, clippy::all, rustdoc::all)] +//! This module contains the sol! generated bindings for solidity contracts. +//! This is autogenerated code. +//! Do not manually edit these files. +//! These files may be overwritten by the codegen system at any time. +/// Generated by the following Solidity interface... +/// ```solidity + +/// interface Cluster { +/// struct ClusterView { +/// NodeOperatorsView operators; +/// MigrationView migration; +/// Maintenance maintenance; +/// uint64 keyspaceVersion; +/// uint128 version; +/// } +/// struct Maintenance { +/// address slot; +/// } +/// struct MigrationView { +/// address[] operatorsToRemove; +/// NodeOperatorView[] operatorsToAdd; +/// address[] pullingOperators; +/// } +/// struct Node { +/// uint256 id; +/// bytes data; +/// } +/// struct NodeOperatorView { +/// address addr; +/// Node[] nodes; +/// bytes data; +/// } +/// struct NodeOperatorsView { +/// NodeOperatorView[] slots; +/// } +/// struct Settings { +/// uint8 minOperators; +/// uint8 minNodes; +/// } +/// +/// event MaintenanceAborted(uint128 version); +/// event MaintenanceCompleted(address operator, uint128 version); +/// event MaintenanceStarted(address operator, uint128 version); +/// event MigrationAborted(uint128 version); +/// event MigrationCompleted(uint128 version); +/// event MigrationDataPullCompleted(address operator, uint128 version); +/// event MigrationStarted(address[] operatorsToRemove, NodeOperatorView[] +/// operatorsToAdd, uint128 version); event NodeRemoved(address operator, +/// uint256 id, uint128 version); event NodeSet(address operator, Node node, +/// uint128 version); +/// +/// constructor(Settings initialSettings, NodeOperatorView[] initialOperators); +/// +/// function abortMaintenance() external; +/// function abortMigration() external; +/// function completeMaintenance() external; +/// function completeMigration() external; +/// function getView() external view returns (ClusterView memory); +/// function removeNode(uint256 id) external; +/// function setNode(Node memory node) external; +/// function startMaintenance() external; +/// function startMigration(address[] memory operatorsToRemove, +/// NodeOperatorView[] memory operatorsToAdd) external; +/// function transferOwnership(address newOwner) external; +/// function updateSettings(Settings memory newSettings) external; +/// } +/// ``` +/// +/// ...which was generated by the following JSON ABI: +/// ```json +/// [ +/// { +/// "type": "constructor", +/// "inputs": [ +/// { +/// "name": "initialSettings", +/// "type": "tuple", +/// "internalType": "struct Settings", +/// "components": [ +/// { +/// "name": "minOperators", +/// "type": "uint8", +/// "internalType": "uint8" +/// }, +/// { +/// "name": "minNodes", +/// "type": "uint8", +/// "internalType": "uint8" +/// } +/// ] +/// }, +/// { +/// "name": "initialOperators", +/// "type": "tuple[]", +/// "internalType": "struct NodeOperatorView[]", +/// "components": [ +/// { +/// "name": "addr", +/// "type": "address", +/// "internalType": "address" +/// }, +/// { +/// "name": "nodes", +/// "type": "tuple[]", +/// "internalType": "struct Node[]", +/// "components": [ +/// { +/// "name": "id", +/// "type": "uint256", +/// "internalType": "uint256" +/// }, +/// { +/// "name": "data", +/// "type": "bytes", +/// "internalType": "bytes" +/// } +/// ] +/// }, +/// { +/// "name": "data", +/// "type": "bytes", +/// "internalType": "bytes" +/// } +/// ] +/// } +/// ], +/// "stateMutability": "nonpayable" +/// }, +/// { +/// "type": "function", +/// "name": "abortMaintenance", +/// "inputs": [], +/// "outputs": [], +/// "stateMutability": "nonpayable" +/// }, +/// { +/// "type": "function", +/// "name": "abortMigration", +/// "inputs": [], +/// "outputs": [], +/// "stateMutability": "nonpayable" +/// }, +/// { +/// "type": "function", +/// "name": "completeMaintenance", +/// "inputs": [], +/// "outputs": [], +/// "stateMutability": "nonpayable" +/// }, +/// { +/// "type": "function", +/// "name": "completeMigration", +/// "inputs": [], +/// "outputs": [], +/// "stateMutability": "nonpayable" +/// }, +/// { +/// "type": "function", +/// "name": "getView", +/// "inputs": [], +/// "outputs": [ +/// { +/// "name": "", +/// "type": "tuple", +/// "internalType": "struct ClusterView", +/// "components": [ +/// { +/// "name": "operators", +/// "type": "tuple", +/// "internalType": "struct NodeOperatorsView", +/// "components": [ +/// { +/// "name": "slots", +/// "type": "tuple[]", +/// "internalType": "struct NodeOperatorView[]", +/// "components": [ +/// { +/// "name": "addr", +/// "type": "address", +/// "internalType": "address" +/// }, +/// { +/// "name": "nodes", +/// "type": "tuple[]", +/// "internalType": "struct Node[]", +/// "components": [ +/// { +/// "name": "id", +/// "type": "uint256", +/// "internalType": "uint256" +/// }, +/// { +/// "name": "data", +/// "type": "bytes", +/// "internalType": "bytes" +/// } +/// ] +/// }, +/// { +/// "name": "data", +/// "type": "bytes", +/// "internalType": "bytes" +/// } +/// ] +/// } +/// ] +/// }, +/// { +/// "name": "migration", +/// "type": "tuple", +/// "internalType": "struct MigrationView", +/// "components": [ +/// { +/// "name": "operatorsToRemove", +/// "type": "address[]", +/// "internalType": "address[]" +/// }, +/// { +/// "name": "operatorsToAdd", +/// "type": "tuple[]", +/// "internalType": "struct NodeOperatorView[]", +/// "components": [ +/// { +/// "name": "addr", +/// "type": "address", +/// "internalType": "address" +/// }, +/// { +/// "name": "nodes", +/// "type": "tuple[]", +/// "internalType": "struct Node[]", +/// "components": [ +/// { +/// "name": "id", +/// "type": "uint256", +/// "internalType": "uint256" +/// }, +/// { +/// "name": "data", +/// "type": "bytes", +/// "internalType": "bytes" +/// } +/// ] +/// }, +/// { +/// "name": "data", +/// "type": "bytes", +/// "internalType": "bytes" +/// } +/// ] +/// }, +/// { +/// "name": "pullingOperators", +/// "type": "address[]", +/// "internalType": "address[]" +/// } +/// ] +/// }, +/// { +/// "name": "maintenance", +/// "type": "tuple", +/// "internalType": "struct Maintenance", +/// "components": [ +/// { +/// "name": "slot", +/// "type": "address", +/// "internalType": "address" +/// } +/// ] +/// }, +/// { +/// "name": "keyspaceVersion", +/// "type": "uint64", +/// "internalType": "uint64" +/// }, +/// { +/// "name": "version", +/// "type": "uint128", +/// "internalType": "uint128" +/// } +/// ] +/// } +/// ], +/// "stateMutability": "view" +/// }, +/// { +/// "type": "function", +/// "name": "removeNode", +/// "inputs": [ +/// { +/// "name": "id", +/// "type": "uint256", +/// "internalType": "uint256" +/// } +/// ], +/// "outputs": [], +/// "stateMutability": "nonpayable" +/// }, +/// { +/// "type": "function", +/// "name": "setNode", +/// "inputs": [ +/// { +/// "name": "node", +/// "type": "tuple", +/// "internalType": "struct Node", +/// "components": [ +/// { +/// "name": "id", +/// "type": "uint256", +/// "internalType": "uint256" +/// }, +/// { +/// "name": "data", +/// "type": "bytes", +/// "internalType": "bytes" +/// } +/// ] +/// } +/// ], +/// "outputs": [], +/// "stateMutability": "nonpayable" +/// }, +/// { +/// "type": "function", +/// "name": "startMaintenance", +/// "inputs": [], +/// "outputs": [], +/// "stateMutability": "nonpayable" +/// }, +/// { +/// "type": "function", +/// "name": "startMigration", +/// "inputs": [ +/// { +/// "name": "operatorsToRemove", +/// "type": "address[]", +/// "internalType": "address[]" +/// }, +/// { +/// "name": "operatorsToAdd", +/// "type": "tuple[]", +/// "internalType": "struct NodeOperatorView[]", +/// "components": [ +/// { +/// "name": "addr", +/// "type": "address", +/// "internalType": "address" +/// }, +/// { +/// "name": "nodes", +/// "type": "tuple[]", +/// "internalType": "struct Node[]", +/// "components": [ +/// { +/// "name": "id", +/// "type": "uint256", +/// "internalType": "uint256" +/// }, +/// { +/// "name": "data", +/// "type": "bytes", +/// "internalType": "bytes" +/// } +/// ] +/// }, +/// { +/// "name": "data", +/// "type": "bytes", +/// "internalType": "bytes" +/// } +/// ] +/// } +/// ], +/// "outputs": [], +/// "stateMutability": "nonpayable" +/// }, +/// { +/// "type": "function", +/// "name": "transferOwnership", +/// "inputs": [ +/// { +/// "name": "newOwner", +/// "type": "address", +/// "internalType": "address" +/// } +/// ], +/// "outputs": [], +/// "stateMutability": "nonpayable" +/// }, +/// { +/// "type": "function", +/// "name": "updateSettings", +/// "inputs": [ +/// { +/// "name": "newSettings", +/// "type": "tuple", +/// "internalType": "struct Settings", +/// "components": [ +/// { +/// "name": "minOperators", +/// "type": "uint8", +/// "internalType": "uint8" +/// }, +/// { +/// "name": "minNodes", +/// "type": "uint8", +/// "internalType": "uint8" +/// } +/// ] +/// } +/// ], +/// "outputs": [], +/// "stateMutability": "nonpayable" +/// }, +/// { +/// "type": "event", +/// "name": "MaintenanceAborted", +/// "inputs": [ +/// { +/// "name": "version", +/// "type": "uint128", +/// "indexed": false, +/// "internalType": "uint128" +/// } +/// ], +/// "anonymous": false +/// }, +/// { +/// "type": "event", +/// "name": "MaintenanceCompleted", +/// "inputs": [ +/// { +/// "name": "operator", +/// "type": "address", +/// "indexed": false, +/// "internalType": "address" +/// }, +/// { +/// "name": "version", +/// "type": "uint128", +/// "indexed": false, +/// "internalType": "uint128" +/// } +/// ], +/// "anonymous": false +/// }, +/// { +/// "type": "event", +/// "name": "MaintenanceStarted", +/// "inputs": [ +/// { +/// "name": "operator", +/// "type": "address", +/// "indexed": false, +/// "internalType": "address" +/// }, +/// { +/// "name": "version", +/// "type": "uint128", +/// "indexed": false, +/// "internalType": "uint128" +/// } +/// ], +/// "anonymous": false +/// }, +/// { +/// "type": "event", +/// "name": "MigrationAborted", +/// "inputs": [ +/// { +/// "name": "version", +/// "type": "uint128", +/// "indexed": false, +/// "internalType": "uint128" +/// } +/// ], +/// "anonymous": false +/// }, +/// { +/// "type": "event", +/// "name": "MigrationCompleted", +/// "inputs": [ +/// { +/// "name": "version", +/// "type": "uint128", +/// "indexed": false, +/// "internalType": "uint128" +/// } +/// ], +/// "anonymous": false +/// }, +/// { +/// "type": "event", +/// "name": "MigrationDataPullCompleted", +/// "inputs": [ +/// { +/// "name": "operator", +/// "type": "address", +/// "indexed": false, +/// "internalType": "address" +/// }, +/// { +/// "name": "version", +/// "type": "uint128", +/// "indexed": false, +/// "internalType": "uint128" +/// } +/// ], +/// "anonymous": false +/// }, +/// { +/// "type": "event", +/// "name": "MigrationStarted", +/// "inputs": [ +/// { +/// "name": "operatorsToRemove", +/// "type": "address[]", +/// "indexed": false, +/// "internalType": "address[]" +/// }, +/// { +/// "name": "operatorsToAdd", +/// "type": "tuple[]", +/// "indexed": false, +/// "internalType": "struct NodeOperatorView[]", +/// "components": [ +/// { +/// "name": "addr", +/// "type": "address", +/// "internalType": "address" +/// }, +/// { +/// "name": "nodes", +/// "type": "tuple[]", +/// "internalType": "struct Node[]", +/// "components": [ +/// { +/// "name": "id", +/// "type": "uint256", +/// "internalType": "uint256" +/// }, +/// { +/// "name": "data", +/// "type": "bytes", +/// "internalType": "bytes" +/// } +/// ] +/// }, +/// { +/// "name": "data", +/// "type": "bytes", +/// "internalType": "bytes" +/// } +/// ] +/// }, +/// { +/// "name": "version", +/// "type": "uint128", +/// "indexed": false, +/// "internalType": "uint128" +/// } +/// ], +/// "anonymous": false +/// }, +/// { +/// "type": "event", +/// "name": "NodeRemoved", +/// "inputs": [ +/// { +/// "name": "operator", +/// "type": "address", +/// "indexed": false, +/// "internalType": "address" +/// }, +/// { +/// "name": "id", +/// "type": "uint256", +/// "indexed": false, +/// "internalType": "uint256" +/// }, +/// { +/// "name": "version", +/// "type": "uint128", +/// "indexed": false, +/// "internalType": "uint128" +/// } +/// ], +/// "anonymous": false +/// }, +/// { +/// "type": "event", +/// "name": "NodeSet", +/// "inputs": [ +/// { +/// "name": "operator", +/// "type": "address", +/// "indexed": false, +/// "internalType": "address" +/// }, +/// { +/// "name": "node", +/// "type": "tuple", +/// "indexed": false, +/// "internalType": "struct Node", +/// "components": [ +/// { +/// "name": "id", +/// "type": "uint256", +/// "internalType": "uint256" +/// }, +/// { +/// "name": "data", +/// "type": "bytes", +/// "internalType": "bytes" +/// } +/// ] +/// }, +/// { +/// "name": "version", +/// "type": "uint128", +/// "indexed": false, +/// "internalType": "uint128" +/// } +/// ], +/// "anonymous": false +/// } +/// ] +/// ``` +#[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style, + clippy::empty_structs_with_brackets +)] +pub mod Cluster { + use {super::*, alloy::sol_types as alloy_sol_types}; + /// The creation / init bytecode of the contract. + /// + /// ```text + ///0x608060405234801561000f575f5ffd5b5060405161741138038061741183398181016040528101906100319190610e18565b335f5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508160015f820151815f015f6101000a81548160ff021916908360ff1602179055506020820151815f0160016101000a81548160ff021916908360ff1602179055509050506100c4815161014360201b60201c565b5f5f90505b815181101561013b576101008282815181106100e8576100e7610e72565b5b602002602001015160200151516101e160201b60201c565b61012e82828151811061011657610115610e72565b5b6020026020010151600261028060201b90919060201c565b80806001019150506100c9565b5050506114ea565b60015f015f9054906101000a900460ff1660ff16811015610199576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161019090610ef9565b60405180910390fd5b6101008111156101de576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101d590610f61565b60405180910390fd5b50565b60015f0160019054906101000a900460ff1660ff16811015610238576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161022f90610fc9565b60405180910390fd5b61010081111561027d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161027490611031565b60405180910390fd5b50565b61029382825f015161051360201b60201c565b156102d3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102ca90611099565b60405180910390fd5b5f5f8360020180549050111561036d5782600201600184600201805490506102fb91906110e4565b8154811061030c5761030b610e72565b5b905f5260205f2090602091828204019190069054906101000a900460ff169050826002018054806103405761033f611117565b5b600190038181905f5260205f2090602091828204019190066101000a81549060ff021916905590556103de565b610100835f0180549050106103b7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103ae90610f61565b60405180910390fd5b825f01805490509050825f0160018160018154018082558091505003905f5260205f209050505b80836001015f845f015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908360ff1602179055505f835f018260ff168154811061045157610450610e72565b5b905f5260205f2090600502019050825f0151815f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555082604001518160040190816104b8919061134b565b505f5f90505b83602001515181101561050c576104ff846020015182815181106104e5576104e4610e72565b5b60200260200101518360010161066b60201b90919060201c565b80806001019150506104be565b5050505050565b5f5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610582576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161057990611464565b60405180910390fd5b5f835f01805490501115610661575f836001015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1660ff1614158061065a57508173ffffffffffffffffffffffffffffffffffffffff16835f015f8154811061061457610613610e72565b5b905f5260205f2090600502015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b9050610665565b5f90505b92915050565b5f815f0151036106b0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106a7906114cc565b60405180910390fd5b5f5f835f0180549050111561076d57826001015f835f015181526020019081526020015f205f9054906101000a900460ff1690505f8160ff1614158061071b5750815f0151835f015f8154811061070a57610709610e72565b5b905f5260205f2090600202015f0154145b1561076c5781835f018260ff168154811061073957610738610e72565b5b905f5260205f2090600202015f820151815f01556020820151816001019081610762919061134b565b50905050506108ed565b5b5f8360020180549050111561080657826002016001846002018054905061079491906110e4565b815481106107a5576107a4610e72565b5b905f5260205f2090602091828204019190069054906101000a900460ff169050826002018054806107d9576107d8611117565b5b600190038181905f5260205f2090602091828204019190066101000a81549060ff02191690559055610877565b610100835f018054905010610850576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161084790611031565b60405180910390fd5b825f01805490509050825f0160018160018154018082558091505003905f5260205f209050505b80836001015f845f015181526020019081526020015f205f6101000a81548160ff021916908360ff16021790555081835f018260ff16815481106108be576108bd610e72565b5b905f5260205f2090600202015f820151815f015560208201518160010190816108e7919061134b565b50905050505b5050565b5f604051905090565b5f5ffd5b5f5ffd5b5f5ffd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b61094c82610906565b810181811067ffffffffffffffff8211171561096b5761096a610916565b5b80604052505050565b5f61097d6108f1565b90506109898282610943565b919050565b5f5ffd5b5f60ff82169050919050565b6109a781610992565b81146109b1575f5ffd5b50565b5f815190506109c28161099e565b92915050565b5f604082840312156109dd576109dc610902565b5b6109e76040610974565b90505f6109f6848285016109b4565b5f830152506020610a09848285016109b4565b60208301525092915050565b5f5ffd5b5f67ffffffffffffffff821115610a3357610a32610916565b5b602082029050602081019050919050565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f610a7182610a48565b9050919050565b610a8181610a67565b8114610a8b575f5ffd5b50565b5f81519050610a9c81610a78565b92915050565b5f67ffffffffffffffff821115610abc57610abb610916565b5b602082029050602081019050919050565b5f819050919050565b610adf81610acd565b8114610ae9575f5ffd5b50565b5f81519050610afa81610ad6565b92915050565b5f5ffd5b5f67ffffffffffffffff821115610b1e57610b1d610916565b5b610b2782610906565b9050602081019050919050565b8281835e5f83830152505050565b5f610b54610b4f84610b04565b610974565b905082815260208101848484011115610b7057610b6f610b00565b5b610b7b848285610b34565b509392505050565b5f82601f830112610b9757610b96610a15565b5b8151610ba7848260208601610b42565b91505092915050565b5f60408284031215610bc557610bc4610902565b5b610bcf6040610974565b90505f610bde84828501610aec565b5f83015250602082015167ffffffffffffffff811115610c0157610c0061098e565b5b610c0d84828501610b83565b60208301525092915050565b5f610c2b610c2684610aa2565b610974565b90508083825260208201905060208402830185811115610c4e57610c4d610a44565b5b835b81811015610c9557805167ffffffffffffffff811115610c7357610c72610a15565b5b808601610c808982610bb0565b85526020850194505050602081019050610c50565b5050509392505050565b5f82601f830112610cb357610cb2610a15565b5b8151610cc3848260208601610c19565b91505092915050565b5f60608284031215610ce157610ce0610902565b5b610ceb6060610974565b90505f610cfa84828501610a8e565b5f83015250602082015167ffffffffffffffff811115610d1d57610d1c61098e565b5b610d2984828501610c9f565b602083015250604082015167ffffffffffffffff811115610d4d57610d4c61098e565b5b610d5984828501610b83565b60408301525092915050565b5f610d77610d7284610a19565b610974565b90508083825260208201905060208402830185811115610d9a57610d99610a44565b5b835b81811015610de157805167ffffffffffffffff811115610dbf57610dbe610a15565b5b808601610dcc8982610ccc565b85526020850194505050602081019050610d9c565b5050509392505050565b5f82601f830112610dff57610dfe610a15565b5b8151610e0f848260208601610d65565b91505092915050565b5f5f60608385031215610e2e57610e2d6108fa565b5b5f610e3b858286016109c8565b925050604083015167ffffffffffffffff811115610e5c57610e5b6108fe565b5b610e6885828601610deb565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f82825260208201905092915050565b7f746f6f20666577206f70657261746f72730000000000000000000000000000005f82015250565b5f610ee3601183610e9f565b9150610eee82610eaf565b602082019050919050565b5f6020820190508181035f830152610f1081610ed7565b9050919050565b7f746f6f206d616e79206f70657261746f727300000000000000000000000000005f82015250565b5f610f4b601283610e9f565b9150610f5682610f17565b602082019050919050565b5f6020820190508181035f830152610f7881610f3f565b9050919050565b7f746f6f20666577206e6f646573000000000000000000000000000000000000005f82015250565b5f610fb3600d83610e9f565b9150610fbe82610f7f565b602082019050919050565b5f6020820190508181035f830152610fe081610fa7565b9050919050565b7f746f6f206d616e79206e6f6465730000000000000000000000000000000000005f82015250565b5f61101b600e83610e9f565b915061102682610fe7565b602082019050919050565b5f6020820190508181035f8301526110488161100f565b9050919050565b7f6f70657261746f7220616c7265616479206578697374730000000000000000005f82015250565b5f611083601783610e9f565b915061108e8261104f565b602082019050919050565b5f6020820190508181035f8301526110b081611077565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6110ee82610acd565b91506110f983610acd565b9250828203905081811115611111576111106110b7565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffd5b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061119257607f821691505b6020821081036111a5576111a461114e565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026112077fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826111cc565b61121186836111cc565b95508019841693508086168417925050509392505050565b5f819050919050565b5f61124c61124761124284610acd565b611229565b610acd565b9050919050565b5f819050919050565b61126583611232565b61127961127182611253565b8484546111d8565b825550505050565b5f5f905090565b611290611281565b61129b81848461125c565b505050565b5b818110156112be576112b35f82611288565b6001810190506112a1565b5050565b601f821115611303576112d4816111ab565b6112dd846111bd565b810160208510156112ec578190505b6113006112f8856111bd565b8301826112a0565b50505b505050565b5f82821c905092915050565b5f6113235f1984600802611308565b1980831691505092915050565b5f61133b8383611314565b9150826002028217905092915050565b61135482611144565b67ffffffffffffffff81111561136d5761136c610916565b5b611377825461117b565b6113828282856112c2565b5f60209050601f8311600181146113b3575f84156113a1578287015190505b6113ab8582611330565b865550611412565b601f1984166113c1866111ab565b5f5b828110156113e8578489015182556001820191506020850194506020810190506113c3565b868310156114055784890151611401601f891682611314565b8355505b6001600288020188555050505b505050505050565b7f696e76616c6964206164647265737300000000000000000000000000000000005f82015250565b5f61144e600f83610e9f565b91506114598261141a565b602082019050919050565b5f6020820190508181035f83015261147b81611442565b9050919050565b7f696e76616c6964206964000000000000000000000000000000000000000000005f82015250565b5f6114b6600a83610e9f565b91506114c182611482565b602082019050919050565b5f6020820190508181035f8301526114e3816114aa565b9050919050565b615f1a806114f75f395ff3fe608060405234801561000f575f5ffd5b50600436106100a7575f3560e01c8063ad36e6d01161006f578063ad36e6d014610115578063c130809a1461011f578063cc45662a14610129578063f2fde38b14610145578063f5f2d9f114610161578063ffd740df1461016b576100a7565b80633048bfba146100ab578063409900e8146100b55780634886f62c146100d15780636c0b61b9146100db57806375418b9d146100f7575b5f5ffd5b6100b3610187565b005b6100cf60048036038101906100ca91906139e2565b6102db565b005b6100d961037e565b005b6100f560048036038101906100f09190613a2b565b61082c565b005b6100ff610956565b60405161010c9190613f47565b60405180910390f35b61011d610a58565b005b610127610b7d565b005b610143600480360381019061013e919061401d565b610cd1565b005b61015f600480360381019061015a91906140c5565b61103b565b005b61016961110b565b005b6101856004803603810190610180919061411a565b61127a565b005b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610215576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161020c9061419f565b60405180910390fd5b61021f600961140e565b600a600881819054906101000a90046fffffffffffffffffffffffffffffffff168092919061024d906141ea565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507f8fb9cd054d0a022110cced239e908b834e4cd219511856d4eaae3051d932d604600a60089054906101000a90046fffffffffffffffffffffffffffffffff166040516102d19190614230565b60405180910390a1565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610369576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103609061419f565b60405180910390fd5b806001818161037891906143c4565b90505050565b6103923360056114c690919063ffffffff16565b600a600881819054906101000a90046fffffffffffffffffffffffffffffffff16809291906103c0906141ea565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507fa76a8fc1a90266ddee8937a18e12f01eade946b3b66197fff289af9277c2bd2533600a60089054906101000a90046fffffffffffffffffffffffffffffffff166040516104469291906143e1565b60405180910390a15f60056003015f9054906101000a900460ff1660ff161161082a575f5f90505b60055f01805490508110156104db576104ce60055f01828154811061049657610495614408565b5b905f5260205f20015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660026115e490919063ffffffff16565b808060010191505061046e565b505f5f90505b6005600101805490508110156107185761070b6005600101828154811061050b5761050a614408565b5b905f5260205f2090600302016040518060600160405290815f82015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160018201805480602002602001604051908101604052809291908181526020015f905b82821015610663578382905f5260205f2090600202016040518060400160405290815f82015481526020016001820180546105d490614462565b80601f016020809104026020016040519081016040528092919081815260200182805461060090614462565b801561064b5780601f106106225761010080835404028352916020019161064b565b820191905f5260205f20905b81548152906001019060200180831161062e57829003601f168201915b5050505050815250508152602001906001019061059a565b50505050815260200160028201805461067b90614462565b80601f01602080910402602001604051908101604052809291908181526020018280546106a790614462565b80156106f25780601f106106c9576101008083540402835291602001916106f2565b820191905f5260205f20905b8154815290600101906020018083116106d557829003601f168201915b505050505081525050600261187690919063ffffffff16565b80806001019150506104e1565b50600a5f81819054906101000a900467ffffffffffffffff168092919061073e90614492565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055505061076f6005611b03565b600a600881819054906101000a90046fffffffffffffffffffffffffffffffff168092919061079d906141ea565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507f11ce50160e66100537fd4b0ae26de66d51dab713ad92313353a18c24e8f6daab600a60089054906101000a90046fffffffffffffffffffffffffffffffff166040516108219190614230565b60405180910390a15b565b610840336002611bac90919063ffffffff16565b61087f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108769061450b565b60405180910390fd5b61089533826002611d049092919063ffffffff16565b600a600881819054906101000a90046fffffffffffffffffffffffffffffffff16809291906108c3906141ea565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507f6adfb896d3407681d05fb874d4dfb7068e6e2a36f09acd38a3b7d04c01745fee3382600a60089054906101000a90046fffffffffffffffffffffffffffffffff1660405161094b93929190614633565b60405180910390a150565b61095e613746565b6040518060a001604052806109736002611d96565b815260200161098f60025f016005611f9990919063ffffffff16565b815260200160096040518060200160405290815f82015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815250508152602001600a5f9054906101000a900467ffffffffffffffff1667ffffffffffffffff168152602001600a60089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff16815250905090565b610a6c336002611bac90919063ffffffff16565b610aab576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610aa29061450b565b60405180910390fd5b610abf33600961270090919063ffffffff16565b600a600881819054906101000a90046fffffffffffffffffffffffffffffffff1680929190610aed906141ea565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507ff91067eb420c28d3124865fc996e6aa9d541b9b4fef9188cb965a6cc6491638e33600a60089054906101000a90046fffffffffffffffffffffffffffffffff16604051610b739291906143e1565b60405180910390a1565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610c0b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c029061419f565b60405180910390fd5b610c156005612827565b600a600881819054906101000a90046fffffffffffffffffffffffffffffffff1680929190610c43906141ea565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507f9ce192aea5faf2151bbc246cd8918d2eba702fa26951f67f2bf7b3817e689d98600a60089054906101000a90046fffffffffffffffffffffffffffffffff16604051610cc79190614230565b60405180910390a1565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610d5f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d569061419f565b60405180910390fd5b610d69600961287b565b15610da9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610da0906146b9565b60405180910390fd5b5f5f90505b84849050811015610e4057610df4858583818110610dcf57610dce614408565b5b9050602002016020810190610de491906140c5565b6002611bac90919063ffffffff16565b610e33576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e2a90614721565b60405180910390fd5b8080600101915050610dae565b505f5f90505b82829050811015610f2557610e8f838383818110610e6757610e66614408565b5b9050602002810190610e79919061474b565b8060200190610e889190614772565b90506128d5565b610ed8838383818110610ea557610ea4614408565b5b9050602002810190610eb7919061474b565b5f016020810190610ec891906140c5565b6002611bac90919063ffffffff16565b15610f18576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f0f9061481e565b60405180910390fd5b8080600101915050610e46565b50610f548282905085859050610f3b6002612974565b610f45919061483c565b610f4f919061486f565b612995565b610f7360025f01858585856005612a339095949392919063ffffffff16565b600a600881819054906101000a90046fffffffffffffffffffffffffffffffff1680929190610fa1906141ea565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507f7e05e40117b6e18ab284c04a3508c3826422dc84a65e9c236a8248774416f8ac84848484600a60089054906101000a90046fffffffffffffffffffffffffffffffff1660405161102d959493929190614be8565b60405180910390a150505050565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146110c9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110c09061419f565b60405180910390fd5b805f5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b61111f336002611bac90919063ffffffff16565b61115e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111559061450b565b60405180910390fd5b6111686005612ed5565b156111a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161119f90614c79565b60405180910390fd5b6111bc336009612ef990919063ffffffff16565b600a600881819054906101000a90046fffffffffffffffffffffffffffffffff16809291906111ea906141ea565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507fbc2748cf02f7a1291525e866efc76ab3b96d32d7afcbb26c53daec617b38b47933600a60089054906101000a90046fffffffffffffffffffffffffffffffff166040516112709291906143e1565b60405180910390a1565b61128e336002611bac90919063ffffffff16565b6112cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112c49061450b565b60405180910390fd5b6112e33382600261303c9092919063ffffffff16565b60015f0160019054906101000a900460ff1660ff1661130c3360026130c590919063ffffffff16565b101561134d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161134490614ce1565b60405180910390fd5b600a600881819054906101000a90046fffffffffffffffffffffffffffffffff168092919061137b906141ea565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507fbd184de79f134b0f3da466d278f5417cbcb1450d72f1bd1a1b84f18b1bcd03ca3382600a60089054906101000a90046fffffffffffffffffffffffffffffffff1660405161140393929190614d0e565b60405180910390a150565b5f73ffffffffffffffffffffffffffffffffffffffff16815f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff160361149e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161149590614d8d565b60405180910390fd5b805f015f6101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905550565b816002015f8273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16611551576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161154890614df5565b60405180910390fd5b5f826002015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908315150217905550816003015f81819054906101000a900460ff16809291906115c790614e13565b91906101000a81548160ff021916908360ff160217905550505050565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611652576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161164990614e84565b60405180910390fd5b5f826001015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1690505f8160ff1614158061172057508173ffffffffffffffffffffffffffffffffffffffff16835f015f815481106116da576116d9614408565b5b905f5260205f2090600502015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b61175f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161175690614eec565b60405180910390fd5b826001015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81549060ff0219169055825f018160ff16815481106117c5576117c4614408565b5b905f5260205f2090600502015f5f82015f6101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600182015f5f82015f61180a91906137a1565b600282015f61181991906137c2565b5050600482015f61182a91906137e7565b50508260020181908060018154018082558091505060019003905f5260205f2090602091828204019190069091909190916101000a81548160ff021916908360ff160217905550505050565b61188382825f0151611bac565b156118c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118ba9061481e565b60405180910390fd5b5f5f8360020180549050111561195d5782600201600184600201805490506118eb919061483c565b815481106118fc576118fb614408565b5b905f5260205f2090602091828204019190069054906101000a900460ff169050826002018054806119305761192f614f0a565b5b600190038181905f5260205f2090602091828204019190066101000a81549060ff021916905590556119ce565b610100835f0180549050106119a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161199e90614f81565b60405180910390fd5b825f01805490509050825f0160018160018154018082558091505003905f5260205f209050505b80836001015f845f015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908360ff1602179055505f835f018260ff1681548110611a4157611a40614408565b5b905f5260205f2090600502019050825f0151815f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508260400151816004019081611aa89190615163565b505f5f90505b836020015151811015611afc57611aef84602001518281518110611ad557611ad4614408565b5b60200260200101518360010161314890919063ffffffff16565b8080600101915050611aae565b5050505050565b611b0c81612ed5565b611b4b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b429061527c565b60405180910390fd5b5f816003015f9054906101000a900460ff1660ff1614611ba0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b97906152e4565b60405180910390fd5b611ba9816133ce565b50565b5f5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611c1b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c1290614e84565b60405180910390fd5b5f835f01805490501115611cfa575f836001015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1660ff16141580611cf357508173ffffffffffffffffffffffffffffffffffffffff16835f015f81548110611cad57611cac614408565b5b905f5260205f2090600502015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b9050611cfe565b5f90505b92915050565b611d9181611d1190615460565b845f01856001015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1660ff1681548110611d7457611d73614408565b5b905f5260205f20906005020160010161314890919063ffffffff16565b505050565b611d9e613824565b5f825f018054905067ffffffffffffffff811115611dbf57611dbe614f9f565b5b604051908082528060200260200182016040528015611df857816020015b611de5613837565b815260200190600190039081611ddd5790505b5090505f5f90505b835f0180549050811015611f81576040518060600160405280855f018381548110611e2e57611e2d614408565b5b905f5260205f2090600502015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001611ea3865f018481548110611e8f57611e8e614408565b5b905f5260205f209060050201600101613401565b8152602001855f018381548110611ebd57611ebc614408565b5b905f5260205f2090600502016004018054611ed790614462565b80601f0160208091040260200160405190810160405280929190818152602001828054611f0390614462565b8015611f4e5780601f10611f2557610100808354040283529160200191611f4e565b820191905f5260205f20905b815481529060010190602001808311611f3157829003601f168201915b5050505050815250828281518110611f6957611f68614408565b5b60200260200101819052508080600101915050611e00565b50604051806020016040528082815250915050919050565b611fa161386d565b5f835f018054905067ffffffffffffffff811115611fc257611fc1614f9f565b5b604051908082528060200260200182016040528015611ff05781602001602082028036833780820191505090505b5090505f5f90505b845f018054905081101561209d57845f01818154811061201b5761201a614408565b5b905f5260205f20015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682828151811061205657612055614408565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508080600101915050611ff8565b505f846001018054905067ffffffffffffffff8111156120c0576120bf614f9f565b5b6040519080825280602002602001820160405280156120f957816020015b6120e6613837565b8152602001906001900390816120de5790505b5090505f5f90505b85600101805490508110156123415785600101818154811061212657612125614408565b5b905f5260205f2090600302016040518060600160405290815f82015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160018201805480602002602001604051908101604052809291908181526020015f905b8282101561227e578382905f5260205f2090600202016040518060400160405290815f82015481526020016001820180546121ef90614462565b80601f016020809104026020016040519081016040528092919081815260200182805461221b90614462565b80156122665780601f1061223d57610100808354040283529160200191612266565b820191905f5260205f20905b81548152906001019060200180831161224957829003601f168201915b505050505081525050815260200190600101906121b5565b50505050815260200160028201805461229690614462565b80601f01602080910402602001604051908101604052809291908181526020018280546122c290614462565b801561230d5780601f106122e45761010080835404028352916020019161230d565b820191905f5260205f20905b8154815290600101906020018083116122f057829003601f168201915b50505050508152505082828151811061232957612328614408565b5b60200260200101819052508080600101915050612101565b505f856003015f9054906101000a900460ff1660ff1667ffffffffffffffff8111156123705761236f614f9f565b5b60405190808252806020026020018201604052801561239e5781602001602082028036833780820191505090505b5090505f866003015f9054906101000a900460ff1660ff1611156126da575f5f5f90505b8680549050811015612581575f73ffffffffffffffffffffffffffffffffffffffff168782815481106123f8576123f7614408565b5b905f5260205f2090600502015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141580156124d25750876002015f88838154811061245d5761245c614408565b5b905f5260205f2090600502015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff165b15612574578681815481106124ea576124e9614408565b5b905f5260205f2090600502015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683838151811061252b5761252a614408565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050818061257090615472565b9250505b80806001019150506123c2565b505f5f90505b87600101805490508110156126d757876002015f8960010183815481106125b1576125b0614408565b5b905f5260205f2090600302015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16156126ca578760010181815481106126405761263f614408565b5b905f5260205f2090600302015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683838151811061268157612680614408565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505081806126c690615472565b9250505b8080600101915050612587565b50505b604051806060016040528084815260200183815260200182815250935050505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361276e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161276590614e84565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16825f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146127fe576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127f590614d8d565b60405180910390fd5b815f015f6101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690555050565b61283081612ed5565b61286f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016128669061527c565b60405180910390fd5b612878816133ce565b50565b5f5f73ffffffffffffffffffffffffffffffffffffffff16825f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614159050919050565b60015f0160019054906101000a900460ff1660ff1681101561292c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161292390614ce1565b60405180910390fd5b610100811115612971576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161296890615503565b60405180910390fd5b50565b5f8160020180549050825f018054905061298e919061483c565b9050919050565b60015f015f9054906101000a900460ff1660ff168110156129eb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129e29061556b565b60405180910390fd5b610100811115612a30576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a2790614f81565b60405180910390fd5b50565b612a3c86612ed5565b15612a7c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a73906155d3565b60405180910390fd5b5f848490501180612a8f57505f82829050115b612ace576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612ac59061563b565b60405180910390fd5b5f5f90505b8580549050811015612c30575f73ffffffffffffffffffffffffffffffffffffffff16868281548110612b0957612b08614408565b5b905f5260205f2090600502015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612c23576001876002015f888481548110612b6c57612b6b614408565b5b905f5260205f2090600502015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908315150217905550866003015f81819054906101000a900460ff1680929190612c0990615659565b91906101000a81548160ff021916908360ff160217905550505b8080600101915050612ad3565b505f5f90505b84849050811015612d8c57865f01858583818110612c5757612c56614408565b5b9050602002016020810190612c6c91906140c5565b908060018154018082558091505060019003905f5260205f20015f9091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505f876002015f878785818110612ce257612ce1614408565b5b9050602002016020810190612cf791906140c5565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908315150217905550866003015f81819054906101000a900460ff1680929190612d6690614e13565b91906101000a81548160ff021916908360ff160217905550508080600101915050612c36565b505f5f90505b82829050811015612ecc5786600101838383818110612db457612db3614408565b5b9050602002810190612dc6919061474b565b908060018154018082558091505060019003905f5260205f2090600302015f909190919091508181612df89190615d9e565b50506001876002015f858585818110612e1457612e13614408565b5b9050602002810190612e26919061474b565b5f016020810190612e3791906140c5565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908315150217905550866003015f81819054906101000a900460ff1680929190612ea690615659565b91906101000a81548160ff021916908360ff160217905550508080600101915050612d92565b50505050505050565b5f5f825f0180549050141580612ef257505f826001018054905014155b9050919050565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612f67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612f5e90614e84565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff16825f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612ff7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612fee90615df6565b60405180910390fd5b80825f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b6130c081845f01856001015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1660ff16815481106130a3576130a2614408565b5b905f5260205f2090600502016001016135c790919063ffffffff16565b505050565b5f613140835f01846001015f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1660ff168154811061312c5761312b614408565b5b905f5260205f209060050201600101613725565b905092915050565b5f815f01510361318d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161318490615e5e565b60405180910390fd5b5f5f835f0180549050111561324a57826001015f835f015181526020019081526020015f205f9054906101000a900460ff1690505f8160ff161415806131f85750815f0151835f015f815481106131e7576131e6614408565b5b905f5260205f2090600202015f0154145b156132495781835f018260ff168154811061321657613215614408565b5b905f5260205f2090600202015f820151815f0155602082015181600101908161323f9190615163565b50905050506133ca565b5b5f836002018054905011156132e3578260020160018460020180549050613271919061483c565b8154811061328257613281614408565b5b905f5260205f2090602091828204019190069054906101000a900460ff169050826002018054806132b6576132b5614f0a565b5b600190038181905f5260205f2090602091828204019190066101000a81549060ff02191690559055613354565b610100835f01805490501061332d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161332490615503565b60405180910390fd5b825f01805490509050825f0160018160018154018082558091505003905f5260205f209050505b80836001015f845f015181526020019081526020015f205f6101000a81548160ff021916908360ff16021790555081835f018260ff168154811061339b5761339a614408565b5b905f5260205f2090600202015f820151815f015560208201518160010190816133c49190615163565b50905050505b5050565b805f015f6133dc919061388e565b806001015f6133eb91906138ac565b806003015f6101000a81549060ff021916905550565b60605f61340d83613725565b67ffffffffffffffff81111561342657613425614f9f565b5b60405190808252806020026020018201604052801561345f57816020015b61344c6138cd565b8152602001906001900390816134445790505b5090505f5f5f90505b845f01805490508110156135bc575f855f01828154811061348c5761348b614408565b5b905f5260205f2090600202015f0154146135af576040518060400160405280865f0183815481106134c0576134bf614408565b5b905f5260205f2090600202015f01548152602001865f0183815481106134e9576134e8614408565b5b905f5260205f209060020201600101805461350390614462565b80601f016020809104026020016040519081016040528092919081815260200182805461352f90614462565b801561357a5780601f106135515761010080835404028352916020019161357a565b820191905f5260205f20905b81548152906001019060200180831161355d57829003601f168201915b505050505081525083838151811061359557613594614408565b5b602002602001018190525081806135ab90615472565b9250505b8080600101915050613468565b508192505050919050565b5f8103613609576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161360090615e5e565b60405180910390fd5b5f826001015f8381526020019081526020015f205f9054906101000a900460ff1690505f8160ff16141580613660575081835f015f8154811061364f5761364e614408565b5b905f5260205f2090600202015f0154145b61369f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161369690615ec6565b60405180910390fd5b825f018160ff16815481106136b7576136b6614408565b5b905f5260205f2090600202015f5f82015f9055600182015f6136d991906137e7565b50508260020181908060018154018082558091505060019003905f5260205f2090602091828204019190069091909190916101000a81548160ff021916908360ff160217905550505050565b5f8160020180549050825f018054905061373f919061483c565b9050919050565b6040518060a00160405280613759613824565b815260200161376661386d565b81526020016137736138e6565b81526020015f67ffffffffffffffff1681526020015f6fffffffffffffffffffffffffffffffff1681525090565b5080545f8255600202905f5260205f20908101906137bf919061390e565b50565b5080545f8255601f0160209004905f5260205f20908101906137e4919061393a565b50565b5080546137f390614462565b5f825580601f106138045750613821565b601f0160209004905f5260205f2090810190613820919061393a565b5b50565b6040518060200160405280606081525090565b60405180606001604052805f73ffffffffffffffffffffffffffffffffffffffff16815260200160608152602001606081525090565b60405180606001604052806060815260200160608152602001606081525090565b5080545f8255905f5260205f20908101906138a9919061393a565b50565b5080545f8255600302905f5260205f20908101906138ca9190613955565b50565b60405180604001604052805f8152602001606081525090565b60405180602001604052805f73ffffffffffffffffffffffffffffffffffffffff1681525090565b5b80821115613936575f5f82015f9055600182015f61392d91906137e7565b5060020161390f565b5090565b5b80821115613951575f815f90555060010161393b565b5090565b5b808211156139ab575f5f82015f6101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600182015f61399391906137a1565b600282015f6139a291906137e7565b50600301613956565b5090565b5f604051905090565b5f5ffd5b5f5ffd5b5f5ffd5b5f604082840312156139d9576139d86139c0565b5b81905092915050565b5f604082840312156139f7576139f66139b8565b5b5f613a04848285016139c4565b91505092915050565b5f60408284031215613a2257613a216139c0565b5b81905092915050565b5f60208284031215613a4057613a3f6139b8565b5b5f82013567ffffffffffffffff811115613a5d57613a5c6139bc565b5b613a6984828501613a0d565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f613ac482613a9b565b9050919050565b613ad481613aba565b82525050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f819050919050565b613b1581613b03565b82525050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f613b5d82613b1b565b613b678185613b25565b9350613b77818560208601613b35565b613b8081613b43565b840191505092915050565b5f604083015f830151613ba05f860182613b0c565b5060208301518482036020860152613bb88282613b53565b9150508091505092915050565b5f613bd08383613b8b565b905092915050565b5f602082019050919050565b5f613bee82613ada565b613bf88185613ae4565b935083602082028501613c0a85613af4565b805f5b85811015613c455784840389528151613c268582613bc5565b9450613c3183613bd8565b925060208a01995050600181019050613c0d565b50829750879550505050505092915050565b5f606083015f830151613c6c5f860182613acb565b5060208301518482036020860152613c848282613be4565b91505060408301518482036040860152613c9e8282613b53565b9150508091505092915050565b5f613cb68383613c57565b905092915050565b5f602082019050919050565b5f613cd482613a72565b613cde8185613a7c565b935083602082028501613cf085613a8c565b805f5b85811015613d2b5784840389528151613d0c8582613cab565b9450613d1783613cbe565b925060208a01995050600181019050613cf3565b50829750879550505050505092915050565b5f602083015f8301518482035f860152613d578282613cca565b9150508091505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f613d988383613acb565b60208301905092915050565b5f602082019050919050565b5f613dba82613d64565b613dc48185613d6e565b9350613dcf83613d7e565b805f5b83811015613dff578151613de68882613d8d565b9750613df183613da4565b925050600181019050613dd2565b5085935050505092915050565b5f606083015f8301518482035f860152613e268282613db0565b91505060208301518482036020860152613e408282613cca565b91505060408301518482036040860152613e5a8282613db0565b9150508091505092915050565b602082015f820151613e7b5f850182613acb565b50505050565b5f67ffffffffffffffff82169050919050565b613e9d81613e81565b82525050565b5f6fffffffffffffffffffffffffffffffff82169050919050565b613ec781613ea3565b82525050565b5f60a083015f8301518482035f860152613ee78282613d3d565b91505060208301518482036020860152613f018282613e0c565b9150506040830151613f166040860182613e67565b506060830151613f296060860182613e94565b506080830151613f3c6080860182613ebe565b508091505092915050565b5f6020820190508181035f830152613f5f8184613ecd565b905092915050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f83601f840112613f8857613f87613f67565b5b8235905067ffffffffffffffff811115613fa557613fa4613f6b565b5b602083019150836020820283011115613fc157613fc0613f6f565b5b9250929050565b5f5f83601f840112613fdd57613fdc613f67565b5b8235905067ffffffffffffffff811115613ffa57613ff9613f6b565b5b60208301915083602082028301111561401657614015613f6f565b5b9250929050565b5f5f5f5f60408587031215614035576140346139b8565b5b5f85013567ffffffffffffffff811115614052576140516139bc565b5b61405e87828801613f73565b9450945050602085013567ffffffffffffffff811115614081576140806139bc565b5b61408d87828801613fc8565b925092505092959194509250565b6140a481613aba565b81146140ae575f5ffd5b50565b5f813590506140bf8161409b565b92915050565b5f602082840312156140da576140d96139b8565b5b5f6140e7848285016140b1565b91505092915050565b6140f981613b03565b8114614103575f5ffd5b50565b5f81359050614114816140f0565b92915050565b5f6020828403121561412f5761412e6139b8565b5b5f61413c84828501614106565b91505092915050565b5f82825260208201905092915050565b7f6e6f7420746865206f776e6572000000000000000000000000000000000000005f82015250565b5f614189600d83614145565b915061419482614155565b602082019050919050565b5f6020820190508181035f8301526141b68161417d565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6141f482613ea3565b91506fffffffffffffffffffffffffffffffff8203614216576142156141bd565b5b600182019050919050565b61422a81613ea3565b82525050565b5f6020820190506142435f830184614221565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b5f60ff82169050919050565b61428a81614275565b8114614294575f5ffd5b50565b5f81356142a381614281565b80915050919050565b5f815f1b9050919050565b5f60ff6142c3846142ac565b9350801983169250808416831791505092915050565b5f819050919050565b5f6142fc6142f76142f284614275565b6142d9565b614275565b9050919050565b5f819050919050565b614315826142e2565b61432861432182614303565b83546142b7565b8255505050565b5f8160081b9050919050565b5f61ff006143488461432f565b9350801983169250808416831791505092915050565b614367826142e2565b61437a61437382614303565b835461433b565b8255505050565b5f81015f83018061439181614297565b905061439d818461430c565b5050505f810160208301806143b181614297565b90506143bd818461435e565b5050505050565b6143ce8282614381565b5050565b6143db81613aba565b82525050565b5f6040820190506143f45f8301856143d2565b6144016020830184614221565b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061447957607f821691505b60208210810361448c5761448b614435565b5b50919050565b5f61449c82613e81565b915067ffffffffffffffff82036144b6576144b56141bd565b5b600182019050919050565b7f6e6f7420616e206f70657261746f7200000000000000000000000000000000005f82015250565b5f6144f5600f83614145565b9150614500826144c1565b602082019050919050565b5f6020820190508181035f830152614522816144e9565b9050919050565b5f6145376020840184614106565b905092915050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f8335600160200384360303811261456757614566614547565b5b83810192508235915060208301925067ffffffffffffffff82111561458f5761458e61453f565b5b6001820236038313156145a5576145a4614543565b5b509250929050565b828183375f83830152505050565b5f6145c68385613b25565b93506145d38385846145ad565b6145dc83613b43565b840190509392505050565b5f604083016145f85f840184614529565b6146045f860182613b0c565b50614612602084018461454b565b85830360208701526146258382846145bb565b925050508091505092915050565b5f6060820190506146465f8301866143d2565b818103602083015261465881856145e7565b90506146676040830184614221565b949350505050565b7f6d61696e74656e616e636520696e2070726f67726573730000000000000000005f82015250565b5f6146a3601783614145565b91506146ae8261466f565b602082019050919050565b5f6020820190508181035f8301526146d081614697565b9050919050565b7f756e6b6e6f776e206f70657261746f72000000000000000000000000000000005f82015250565b5f61470b601083614145565b9150614716826146d7565b602082019050919050565b5f6020820190508181035f830152614738816146ff565b9050919050565b5f5ffd5b5f5ffd5b5f5ffd5b5f823560016060038336030381126147665761476561473f565b5b80830191505092915050565b5f5f8335600160200384360303811261478e5761478d61473f565b5b80840192508235915067ffffffffffffffff8211156147b0576147af614743565b5b6020830192506020820236038313156147cc576147cb614747565b5b509250929050565b7f6f70657261746f7220616c7265616479206578697374730000000000000000005f82015250565b5f614808601783614145565b9150614813826147d4565b602082019050919050565b5f6020820190508181035f830152614835816147fc565b9050919050565b5f61484682613b03565b915061485183613b03565b9250828203905081811115614869576148686141bd565b5b92915050565b5f61487982613b03565b915061488483613b03565b925082820190508082111561489c5761489b6141bd565b5b92915050565b5f82825260208201905092915050565b5f819050919050565b5f6148c960208401846140b1565b905092915050565b5f602082019050919050565b5f6148e883856148a2565b93506148f3826148b2565b805f5b8581101561492b5761490882846148bb565b6149128882613d8d565b975061491d836148d1565b9250506001810190506148f6565b5085925050509392505050565b5f82825260208201905092915050565b5f819050919050565b5f5f8335600160200384360303811261496d5761496c614547565b5b83810192508235915060208301925067ffffffffffffffff8211156149955761499461453f565b5b6020820236038313156149ab576149aa614543565b5b509250929050565b5f819050919050565b5f604083016149cd5f840184614529565b6149d95f860182613b0c565b506149e7602084018461454b565b85830360208701526149fa8382846145bb565b925050508091505092915050565b5f614a1383836149bc565b905092915050565b5f82356001604003833603038112614a3657614a35614547565b5b82810191505092915050565b5f602082019050919050565b5f614a598385613ae4565b935083602084028501614a6b846149b3565b805f5b87811015614aae578484038952614a858284614a1b565b614a8f8582614a08565b9450614a9a83614a42565b925060208a01995050600181019050614a6e565b50829750879450505050509392505050565b5f60608301614ad15f8401846148bb565b614add5f860182613acb565b50614aeb6020840184614951565b8583036020870152614afe838284614a4e565b92505050614b0f604084018461454b565b8583036040870152614b228382846145bb565b925050508091505092915050565b5f614b3b8383614ac0565b905092915050565b5f82356001606003833603038112614b5e57614b5d614547565b5b82810191505092915050565b5f602082019050919050565b5f614b818385614938565b935083602084028501614b9384614948565b805f5b87811015614bd6578484038952614bad8284614b43565b614bb78582614b30565b9450614bc283614b6a565b925060208a01995050600181019050614b96565b50829750879450505050509392505050565b5f6060820190508181035f830152614c018187896148dd565b90508181036020830152614c16818587614b76565b9050614c256040830184614221565b9695505050505050565b7f6d6967726174696f6e20696e2070726f677265737300000000000000000000005f82015250565b5f614c63601583614145565b9150614c6e82614c2f565b602082019050919050565b5f6020820190508181035f830152614c9081614c57565b9050919050565b7f746f6f20666577206e6f646573000000000000000000000000000000000000005f82015250565b5f614ccb600d83614145565b9150614cd682614c97565b602082019050919050565b5f6020820190508181035f830152614cf881614cbf565b9050919050565b614d0881613b03565b82525050565b5f606082019050614d215f8301866143d2565b614d2e6020830185614cff565b614d3b6040830184614221565b949350505050565b7f6e6f7420756e646572206d61696e74656e616e636500000000000000000000005f82015250565b5f614d77601583614145565b9150614d8282614d43565b602082019050919050565b5f6020820190508181035f830152614da481614d6b565b9050919050565b7f6e6f742070756c6c696e670000000000000000000000000000000000000000005f82015250565b5f614ddf600b83614145565b9150614dea82614dab565b602082019050919050565b5f6020820190508181035f830152614e0c81614dd3565b9050919050565b5f614e1d82614275565b91505f8203614e2f57614e2e6141bd565b5b600182039050919050565b7f696e76616c6964206164647265737300000000000000000000000000000000005f82015250565b5f614e6e600f83614145565b9150614e7982614e3a565b602082019050919050565b5f6020820190508181035f830152614e9b81614e62565b9050919050565b7f6f70657261746f7220646f65736e2774206578697374000000000000000000005f82015250565b5f614ed6601683614145565b9150614ee182614ea2565b602082019050919050565b5f6020820190508181035f830152614f0381614eca565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffd5b7f746f6f206d616e79206f70657261746f727300000000000000000000000000005f82015250565b5f614f6b601283614145565b9150614f7682614f37565b602082019050919050565b5f6020820190508181035f830152614f9881614f5f565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026150287fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82614fed565b6150328683614fed565b95508019841693508086168417925050509392505050565b5f61506461505f61505a84613b03565b6142d9565b613b03565b9050919050565b5f819050919050565b61507d8361504a565b6150916150898261506b565b848454614ff9565b825550505050565b5f5f905090565b6150a8615099565b6150b3818484615074565b505050565b5b818110156150d6576150cb5f826150a0565b6001810190506150b9565b5050565b601f82111561511b576150ec81614fcc565b6150f584614fde565b81016020851015615104578190505b61511861511085614fde565b8301826150b8565b50505b505050565b5f82821c905092915050565b5f61513b5f1984600802615120565b1980831691505092915050565b5f615153838361512c565b9150826002028217905092915050565b61516c82613b1b565b67ffffffffffffffff81111561518557615184614f9f565b5b61518f8254614462565b61519a8282856150da565b5f60209050601f8311600181146151cb575f84156151b9578287015190505b6151c38582615148565b86555061522a565b601f1984166151d986614fcc565b5f5b82811015615200578489015182556001820191506020850194506020810190506151db565b8683101561521d5784890151615219601f89168261512c565b8355505b6001600288020188555050505b505050505050565b7f6e6f7420696e2070726f677265737300000000000000000000000000000000005f82015250565b5f615266600f83614145565b915061527182615232565b602082019050919050565b5f6020820190508181035f8301526152938161525a565b9050919050565b7f646174612070756c6c20696e2070726f677265737300000000000000000000005f82015250565b5f6152ce601583614145565b91506152d98261529a565b602082019050919050565b5f6020820190508181035f8301526152fb816152c2565b9050919050565b5f5ffd5b61530f82613b43565b810181811067ffffffffffffffff8211171561532e5761532d614f9f565b5b80604052505050565b5f6153406139af565b905061534c8282615306565b919050565b5f5ffd5b5f5ffd5b5f67ffffffffffffffff82111561537357615372614f9f565b5b61537c82613b43565b9050602081019050919050565b5f61539b61539684615359565b615337565b9050828152602081018484840111156153b7576153b6615355565b5b6153c28482856145ad565b509392505050565b5f82601f8301126153de576153dd613f67565b5b81356153ee848260208601615389565b91505092915050565b5f6040828403121561540c5761540b615302565b5b6154166040615337565b90505f61542584828501614106565b5f83015250602082013567ffffffffffffffff81111561544857615447615351565b5b615454848285016153ca565b60208301525092915050565b5f61546b36836153f7565b9050919050565b5f61547c82613b03565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036154ae576154ad6141bd565b5b600182019050919050565b7f746f6f206d616e79206e6f6465730000000000000000000000000000000000005f82015250565b5f6154ed600e83614145565b91506154f8826154b9565b602082019050919050565b5f6020820190508181035f83015261551a816154e1565b9050919050565b7f746f6f20666577206f70657261746f72730000000000000000000000000000005f82015250565b5f615555601183614145565b915061556082615521565b602082019050919050565b5f6020820190508181035f83015261558281615549565b9050919050565b7f6d6967726174696f6e20616c726561647920696e2070726f67726573730000005f82015250565b5f6155bd601d83614145565b91506155c882615589565b602082019050919050565b5f6020820190508181035f8301526155ea816155b1565b9050919050565b7f6e6f7468696e6720746f20646f000000000000000000000000000000000000005f82015250565b5f615625600d83614145565b9150615630826155f1565b602082019050919050565b5f6020820190508181035f83015261565281615619565b9050919050565b5f61566382614275565b915060ff8203615676576156756141bd565b5b600182019050919050565b5f813561568d8161409b565b80915050919050565b5f73ffffffffffffffffffffffffffffffffffffffff6156b5846142ac565b9350801983169250808416831791505092915050565b5f6156e56156e06156db84613a9b565b6142d9565b613a9b565b9050919050565b5f6156f6826156cb565b9050919050565b5f615707826156ec565b9050919050565b5f819050919050565b615720826156fd565b61573361572c8261570e565b8354615696565b8255505050565b5f823560016040038336030381126157555761575461473f565b5b80830191505092915050565b5f81549050919050565b5f61577582613b03565b915061578083613b03565b925082820261578e81613b03565b915082820484148315176157a5576157a46141bd565b5b5092915050565b5f8190506157bb82600261576b565b9050919050565b5f819050815f5260205f209050919050565b6158047fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83602003600802615120565b815481168255505050565b61581881614fcc565b615823838254615148565b8083555f825550505050565b602084105f811461588957601f841160018114615857576158508685615148565b8355615883565b61586083614fcc565b61587761586c87614fde565b8201600183016150b8565b615881878561580f565b505b506158d6565b61589282614fcc565b61589b86614fde565b8101601f871680156158b5576158b481600184036157d4565b5b6158c96158c188614fde565b8401836150b8565b6001886002021785555050505b5050505050565b680100000000000000008411156158f7576158f6614f9f565b5b602083105f811461594057602085105f811461591e576159178685615148565b835561593a565b8360ff191693508361592f84614fcc565b556001866002020183555b5061594a565b6001856002020182555b5050505050565b805461595c81614462565b8084111561597157615970848284866158dd565b5b80841015615986576159858482848661582f565b5b50505050565b818110156159a95761599e5f826150a0565b60018101905061598c565b5050565b6159b75f82615951565b50565b5f82146159ca576159c9614249565b5b6159d3816159ad565b5050565b6159e35f5f83016150a0565b6159f05f600183016159ba565b50565b5f8214615a0357615a02614249565b5b615a0c816159d7565b5050565b5b81811015615a2e57615a235f826159f3565b600281019050615a11565b5050565b81831015615a6b57615a43826157ac565b615a4c846157ac565b615a55836157c2565b818101838201615a658183615a10565b50505050505b505050565b68010000000000000000821115615a8a57615a89614f9f565b5b615a9381615761565b828255615aa1838284615a32565b505050565b5f82905092915050565b5f8135615abc816140f0565b80915050919050565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff615af0846142ac565b9350801983169250808416831791505092915050565b615b0f8261504a565b615b22615b1b8261506b565b8354615ac5565b8255505050565b5f5f83356001602003843603038112615b4557615b4461473f565b5b80840192508235915067ffffffffffffffff821115615b6757615b66614743565b5b602083019250600182023603831315615b8357615b82614747565b5b509250929050565b5f82905092915050565b615b9f8383615b8b565b67ffffffffffffffff811115615bb857615bb7614f9f565b5b615bc28254614462565b615bcd8282856150da565b5f601f831160018114615bfa575f8415615be8578287013590505b615bf28582615148565b865550615c59565b601f198416615c0886614fcc565b5f5b82811015615c2f57848901358255600182019150602085019450602081019050615c0a565b86831015615c4c5784890135615c48601f89168261512c565b8355505b6001600288020188555050505b50505050505050565b615c6d838383615b95565b505050565b5f81015f830180615c8281615ab0565b9050615c8e8184615b06565b5050506001810160208301615ca38185615b29565b615cae818386615c62565b505050505050565b615cc08282615c72565b5050565b615cce8383615aa6565b615cd88183615a70565b615ce1836149b3565b615cea836157c2565b5f5b83811015615d2057615cfe838761573a565b615d088184615cb6565b60208401935060028301925050600181019050615cec565b50505050505050565b615d34838383615cc4565b505050565b5f81015f830180615d4981615681565b9050615d558184615717565b5050506001810160208301615d6a8185614772565b615d75818386615d29565b505050506002810160408301615d8b8185615b29565b615d96818386615c62565b505050505050565b615da88282615d39565b5050565b7f616e6f74686572206d61696e74656e616e636520696e2070726f6772657373005f82015250565b5f615de0601f83614145565b9150615deb82615dac565b602082019050919050565b5f6020820190508181035f830152615e0d81615dd4565b9050919050565b7f696e76616c6964206964000000000000000000000000000000000000000000005f82015250565b5f615e48600a83614145565b9150615e5382615e14565b602082019050919050565b5f6020820190508181035f830152615e7581615e3c565b9050919050565b7f6e6f646520646f65736e277420657869737400000000000000000000000000005f82015250565b5f615eb0601283614145565b9150615ebb82615e7c565b602082019050919050565b5f6020820190508181035f830152615edd81615ea4565b905091905056fea26469706673582212205ec0504f700c355842dfb4a4d399a8e48b0ca02d4766027c3ae5b1d4f339375864736f6c634300081c0033 + /// ``` + #[rustfmt::skip] + #[allow(clippy::all)] + pub static BYTECODE: alloy_sol_types::private::Bytes = alloy_sol_types::private::Bytes::from_static( + b"`\x80`@R4\x80\x15a\0\x0FW__\xFD[P`@Qat\x118\x03\x80at\x11\x839\x81\x81\x01`@R\x81\x01\x90a\x001\x91\x90a\x0E\x18V[3__a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UP\x81`\x01_\x82\x01Q\x81_\x01_a\x01\0\n\x81T\x81`\xFF\x02\x19\x16\x90\x83`\xFF\x16\x02\x17\x90UP` \x82\x01Q\x81_\x01`\x01a\x01\0\n\x81T\x81`\xFF\x02\x19\x16\x90\x83`\xFF\x16\x02\x17\x90UP\x90PPa\0\xC4\x81Qa\x01C` \x1B` \x1CV[__\x90P[\x81Q\x81\x10\x15a\x01;Wa\x01\0\x82\x82\x81Q\x81\x10a\0\xE8Wa\0\xE7a\x0ErV[[` \x02` \x01\x01Q` \x01QQa\x01\xE1` \x1B` \x1CV[a\x01.\x82\x82\x81Q\x81\x10a\x01\x16Wa\x01\x15a\x0ErV[[` \x02` \x01\x01Q`\x02a\x02\x80` \x1B\x90\x91\x90` \x1CV[\x80\x80`\x01\x01\x91PPa\0\xC9V[PPPa\x14\xEAV[`\x01_\x01_\x90T\x90a\x01\0\n\x90\x04`\xFF\x16`\xFF\x16\x81\x10\x15a\x01\x99W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x01\x90\x90a\x0E\xF9V[`@Q\x80\x91\x03\x90\xFD[a\x01\0\x81\x11\x15a\x01\xDEW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x01\xD5\x90a\x0FaV[`@Q\x80\x91\x03\x90\xFD[PV[`\x01_\x01`\x01\x90T\x90a\x01\0\n\x90\x04`\xFF\x16`\xFF\x16\x81\x10\x15a\x028W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x02/\x90a\x0F\xC9V[`@Q\x80\x91\x03\x90\xFD[a\x01\0\x81\x11\x15a\x02}W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x02t\x90a\x101V[`@Q\x80\x91\x03\x90\xFD[PV[a\x02\x93\x82\x82_\x01Qa\x05\x13` \x1B` \x1CV[\x15a\x02\xD3W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x02\xCA\x90a\x10\x99V[`@Q\x80\x91\x03\x90\xFD[__\x83`\x02\x01\x80T\x90P\x11\x15a\x03mW\x82`\x02\x01`\x01\x84`\x02\x01\x80T\x90Pa\x02\xFB\x91\x90a\x10\xE4V[\x81T\x81\x10a\x03\x0CWa\x03\x0Ba\x0ErV[[\x90_R` _ \x90` \x91\x82\x82\x04\x01\x91\x90\x06\x90T\x90a\x01\0\n\x90\x04`\xFF\x16\x90P\x82`\x02\x01\x80T\x80a\x03@Wa\x03?a\x11\x17V[[`\x01\x90\x03\x81\x81\x90_R` _ \x90` \x91\x82\x82\x04\x01\x91\x90\x06a\x01\0\n\x81T\x90`\xFF\x02\x19\x16\x90U\x90Ua\x03\xDEV[a\x01\0\x83_\x01\x80T\x90P\x10a\x03\xB7W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x03\xAE\x90a\x0FaV[`@Q\x80\x91\x03\x90\xFD[\x82_\x01\x80T\x90P\x90P\x82_\x01`\x01\x81`\x01\x81T\x01\x80\x82U\x80\x91PP\x03\x90_R` _ \x90PP[\x80\x83`\x01\x01_\x84_\x01Qs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ _a\x01\0\n\x81T\x81`\xFF\x02\x19\x16\x90\x83`\xFF\x16\x02\x17\x90UP_\x83_\x01\x82`\xFF\x16\x81T\x81\x10a\x04QWa\x04Pa\x0ErV[[\x90_R` _ \x90`\x05\x02\x01\x90P\x82_\x01Q\x81_\x01_a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UP\x82`@\x01Q\x81`\x04\x01\x90\x81a\x04\xB8\x91\x90a\x13KV[P__\x90P[\x83` \x01QQ\x81\x10\x15a\x05\x0CWa\x04\xFF\x84` \x01Q\x82\x81Q\x81\x10a\x04\xE5Wa\x04\xE4a\x0ErV[[` \x02` \x01\x01Q\x83`\x01\x01a\x06k` \x1B\x90\x91\x90` \x1CV[\x80\x80`\x01\x01\x91PPa\x04\xBEV[PPPPPV[__s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x82s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x03a\x05\x82W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x05y\x90a\x14dV[`@Q\x80\x91\x03\x90\xFD[_\x83_\x01\x80T\x90P\x11\x15a\x06aW_\x83`\x01\x01_\x84s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ _\x90T\x90a\x01\0\n\x90\x04`\xFF\x16`\xFF\x16\x14\x15\x80a\x06ZWP\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x83_\x01_\x81T\x81\x10a\x06\x14Wa\x06\x13a\x0ErV[[\x90_R` _ \x90`\x05\x02\x01_\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14[\x90Pa\x06eV[_\x90P[\x92\x91PPV[_\x81_\x01Q\x03a\x06\xB0W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x06\xA7\x90a\x14\xCCV[`@Q\x80\x91\x03\x90\xFD[__\x83_\x01\x80T\x90P\x11\x15a\x07mW\x82`\x01\x01_\x83_\x01Q\x81R` \x01\x90\x81R` \x01_ _\x90T\x90a\x01\0\n\x90\x04`\xFF\x16\x90P_\x81`\xFF\x16\x14\x15\x80a\x07\x1BWP\x81_\x01Q\x83_\x01_\x81T\x81\x10a\x07\nWa\x07\ta\x0ErV[[\x90_R` _ \x90`\x02\x02\x01_\x01T\x14[\x15a\x07lW\x81\x83_\x01\x82`\xFF\x16\x81T\x81\x10a\x079Wa\x078a\x0ErV[[\x90_R` _ \x90`\x02\x02\x01_\x82\x01Q\x81_\x01U` \x82\x01Q\x81`\x01\x01\x90\x81a\x07b\x91\x90a\x13KV[P\x90PPPa\x08\xEDV[[_\x83`\x02\x01\x80T\x90P\x11\x15a\x08\x06W\x82`\x02\x01`\x01\x84`\x02\x01\x80T\x90Pa\x07\x94\x91\x90a\x10\xE4V[\x81T\x81\x10a\x07\xA5Wa\x07\xA4a\x0ErV[[\x90_R` _ \x90` \x91\x82\x82\x04\x01\x91\x90\x06\x90T\x90a\x01\0\n\x90\x04`\xFF\x16\x90P\x82`\x02\x01\x80T\x80a\x07\xD9Wa\x07\xD8a\x11\x17V[[`\x01\x90\x03\x81\x81\x90_R` _ \x90` \x91\x82\x82\x04\x01\x91\x90\x06a\x01\0\n\x81T\x90`\xFF\x02\x19\x16\x90U\x90Ua\x08wV[a\x01\0\x83_\x01\x80T\x90P\x10a\x08PW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x08G\x90a\x101V[`@Q\x80\x91\x03\x90\xFD[\x82_\x01\x80T\x90P\x90P\x82_\x01`\x01\x81`\x01\x81T\x01\x80\x82U\x80\x91PP\x03\x90_R` _ \x90PP[\x80\x83`\x01\x01_\x84_\x01Q\x81R` \x01\x90\x81R` \x01_ _a\x01\0\n\x81T\x81`\xFF\x02\x19\x16\x90\x83`\xFF\x16\x02\x17\x90UP\x81\x83_\x01\x82`\xFF\x16\x81T\x81\x10a\x08\xBEWa\x08\xBDa\x0ErV[[\x90_R` _ \x90`\x02\x02\x01_\x82\x01Q\x81_\x01U` \x82\x01Q\x81`\x01\x01\x90\x81a\x08\xE7\x91\x90a\x13KV[P\x90PPP[PPV[_`@Q\x90P\x90V[__\xFD[__\xFD[__\xFD[_`\x1F\x19`\x1F\x83\x01\x16\x90P\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`A`\x04R`$_\xFD[a\tL\x82a\t\x06V[\x81\x01\x81\x81\x10g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x17\x15a\tkWa\tja\t\x16V[[\x80`@RPPPV[_a\t}a\x08\xF1V[\x90Pa\t\x89\x82\x82a\tCV[\x91\x90PV[__\xFD[_`\xFF\x82\x16\x90P\x91\x90PV[a\t\xA7\x81a\t\x92V[\x81\x14a\t\xB1W__\xFD[PV[_\x81Q\x90Pa\t\xC2\x81a\t\x9EV[\x92\x91PPV[_`@\x82\x84\x03\x12\x15a\t\xDDWa\t\xDCa\t\x02V[[a\t\xE7`@a\ttV[\x90P_a\t\xF6\x84\x82\x85\x01a\t\xB4V[_\x83\x01RP` a\n\t\x84\x82\x85\x01a\t\xB4V[` \x83\x01RP\x92\x91PPV[__\xFD[_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15a\n3Wa\n2a\t\x16V[[` \x82\x02\x90P` \x81\x01\x90P\x91\x90PV[__\xFD[_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[_a\nq\x82a\nHV[\x90P\x91\x90PV[a\n\x81\x81a\ngV[\x81\x14a\n\x8BW__\xFD[PV[_\x81Q\x90Pa\n\x9C\x81a\nxV[\x92\x91PPV[_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15a\n\xBCWa\n\xBBa\t\x16V[[` \x82\x02\x90P` \x81\x01\x90P\x91\x90PV[_\x81\x90P\x91\x90PV[a\n\xDF\x81a\n\xCDV[\x81\x14a\n\xE9W__\xFD[PV[_\x81Q\x90Pa\n\xFA\x81a\n\xD6V[\x92\x91PPV[__\xFD[_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15a\x0B\x1EWa\x0B\x1Da\t\x16V[[a\x0B'\x82a\t\x06V[\x90P` \x81\x01\x90P\x91\x90PV[\x82\x81\x83^_\x83\x83\x01RPPPV[_a\x0BTa\x0BO\x84a\x0B\x04V[a\ttV[\x90P\x82\x81R` \x81\x01\x84\x84\x84\x01\x11\x15a\x0BpWa\x0Boa\x0B\0V[[a\x0B{\x84\x82\x85a\x0B4V[P\x93\x92PPPV[_\x82`\x1F\x83\x01\x12a\x0B\x97Wa\x0B\x96a\n\x15V[[\x81Qa\x0B\xA7\x84\x82` \x86\x01a\x0BBV[\x91PP\x92\x91PPV[_`@\x82\x84\x03\x12\x15a\x0B\xC5Wa\x0B\xC4a\t\x02V[[a\x0B\xCF`@a\ttV[\x90P_a\x0B\xDE\x84\x82\x85\x01a\n\xECV[_\x83\x01RP` \x82\x01Qg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x0C\x01Wa\x0C\0a\t\x8EV[[a\x0C\r\x84\x82\x85\x01a\x0B\x83V[` \x83\x01RP\x92\x91PPV[_a\x0C+a\x0C&\x84a\n\xA2V[a\ttV[\x90P\x80\x83\x82R` \x82\x01\x90P` \x84\x02\x83\x01\x85\x81\x11\x15a\x0CNWa\x0CMa\nDV[[\x83[\x81\x81\x10\x15a\x0C\x95W\x80Qg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x0CsWa\x0Cra\n\x15V[[\x80\x86\x01a\x0C\x80\x89\x82a\x0B\xB0V[\x85R` \x85\x01\x94PPP` \x81\x01\x90Pa\x0CPV[PPP\x93\x92PPPV[_\x82`\x1F\x83\x01\x12a\x0C\xB3Wa\x0C\xB2a\n\x15V[[\x81Qa\x0C\xC3\x84\x82` \x86\x01a\x0C\x19V[\x91PP\x92\x91PPV[_``\x82\x84\x03\x12\x15a\x0C\xE1Wa\x0C\xE0a\t\x02V[[a\x0C\xEB``a\ttV[\x90P_a\x0C\xFA\x84\x82\x85\x01a\n\x8EV[_\x83\x01RP` \x82\x01Qg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\r\x1DWa\r\x1Ca\t\x8EV[[a\r)\x84\x82\x85\x01a\x0C\x9FV[` \x83\x01RP`@\x82\x01Qg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\rMWa\rLa\t\x8EV[[a\rY\x84\x82\x85\x01a\x0B\x83V[`@\x83\x01RP\x92\x91PPV[_a\rwa\rr\x84a\n\x19V[a\ttV[\x90P\x80\x83\x82R` \x82\x01\x90P` \x84\x02\x83\x01\x85\x81\x11\x15a\r\x9AWa\r\x99a\nDV[[\x83[\x81\x81\x10\x15a\r\xE1W\x80Qg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\r\xBFWa\r\xBEa\n\x15V[[\x80\x86\x01a\r\xCC\x89\x82a\x0C\xCCV[\x85R` \x85\x01\x94PPP` \x81\x01\x90Pa\r\x9CV[PPP\x93\x92PPPV[_\x82`\x1F\x83\x01\x12a\r\xFFWa\r\xFEa\n\x15V[[\x81Qa\x0E\x0F\x84\x82` \x86\x01a\reV[\x91PP\x92\x91PPV[__``\x83\x85\x03\x12\x15a\x0E.Wa\x0E-a\x08\xFAV[[_a\x0E;\x85\x82\x86\x01a\t\xC8V[\x92PP`@\x83\x01Qg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x0E\\Wa\x0E[a\x08\xFEV[[a\x0Eh\x85\x82\x86\x01a\r\xEBV[\x91PP\x92P\x92\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`2`\x04R`$_\xFD[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[\x7Ftoo few operators\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a\x0E\xE3`\x11\x83a\x0E\x9FV[\x91Pa\x0E\xEE\x82a\x0E\xAFV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra\x0F\x10\x81a\x0E\xD7V[\x90P\x91\x90PV[\x7Ftoo many operators\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a\x0FK`\x12\x83a\x0E\x9FV[\x91Pa\x0FV\x82a\x0F\x17V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra\x0Fx\x81a\x0F?V[\x90P\x91\x90PV[\x7Ftoo few nodes\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a\x0F\xB3`\r\x83a\x0E\x9FV[\x91Pa\x0F\xBE\x82a\x0F\x7FV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra\x0F\xE0\x81a\x0F\xA7V[\x90P\x91\x90PV[\x7Ftoo many nodes\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a\x10\x1B`\x0E\x83a\x0E\x9FV[\x91Pa\x10&\x82a\x0F\xE7V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra\x10H\x81a\x10\x0FV[\x90P\x91\x90PV[\x7Foperator already exists\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a\x10\x83`\x17\x83a\x0E\x9FV[\x91Pa\x10\x8E\x82a\x10OV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra\x10\xB0\x81a\x10wV[\x90P\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`\x11`\x04R`$_\xFD[_a\x10\xEE\x82a\n\xCDV[\x91Pa\x10\xF9\x83a\n\xCDV[\x92P\x82\x82\x03\x90P\x81\x81\x11\x15a\x11\x11Wa\x11\x10a\x10\xB7V[[\x92\x91PPV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`1`\x04R`$_\xFD[_\x81Q\x90P\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`\"`\x04R`$_\xFD[_`\x02\x82\x04\x90P`\x01\x82\x16\x80a\x11\x92W`\x7F\x82\x16\x91P[` \x82\x10\x81\x03a\x11\xA5Wa\x11\xA4a\x11NV[[P\x91\x90PV[_\x81\x90P\x81_R` _ \x90P\x91\x90PV[_` `\x1F\x83\x01\x04\x90P\x91\x90PV[_\x82\x82\x1B\x90P\x92\x91PPV[_`\x08\x83\x02a\x12\x07\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82a\x11\xCCV[a\x12\x11\x86\x83a\x11\xCCV[\x95P\x80\x19\x84\x16\x93P\x80\x86\x16\x84\x17\x92PPP\x93\x92PPPV[_\x81\x90P\x91\x90PV[_a\x12La\x12Ga\x12B\x84a\n\xCDV[a\x12)V[a\n\xCDV[\x90P\x91\x90PV[_\x81\x90P\x91\x90PV[a\x12e\x83a\x122V[a\x12ya\x12q\x82a\x12SV[\x84\x84Ta\x11\xD8V[\x82UPPPPV[__\x90P\x90V[a\x12\x90a\x12\x81V[a\x12\x9B\x81\x84\x84a\x12\\V[PPPV[[\x81\x81\x10\x15a\x12\xBEWa\x12\xB3_\x82a\x12\x88V[`\x01\x81\x01\x90Pa\x12\xA1V[PPV[`\x1F\x82\x11\x15a\x13\x03Wa\x12\xD4\x81a\x11\xABV[a\x12\xDD\x84a\x11\xBDV[\x81\x01` \x85\x10\x15a\x12\xECW\x81\x90P[a\x13\0a\x12\xF8\x85a\x11\xBDV[\x83\x01\x82a\x12\xA0V[PP[PPPV[_\x82\x82\x1C\x90P\x92\x91PPV[_a\x13#_\x19\x84`\x08\x02a\x13\x08V[\x19\x80\x83\x16\x91PP\x92\x91PPV[_a\x13;\x83\x83a\x13\x14V[\x91P\x82`\x02\x02\x82\x17\x90P\x92\x91PPV[a\x13T\x82a\x11DV[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x13mWa\x13la\t\x16V[[a\x13w\x82Ta\x11{V[a\x13\x82\x82\x82\x85a\x12\xC2V[_` \x90P`\x1F\x83\x11`\x01\x81\x14a\x13\xB3W_\x84\x15a\x13\xA1W\x82\x87\x01Q\x90P[a\x13\xAB\x85\x82a\x130V[\x86UPa\x14\x12V[`\x1F\x19\x84\x16a\x13\xC1\x86a\x11\xABV[_[\x82\x81\x10\x15a\x13\xE8W\x84\x89\x01Q\x82U`\x01\x82\x01\x91P` \x85\x01\x94P` \x81\x01\x90Pa\x13\xC3V[\x86\x83\x10\x15a\x14\x05W\x84\x89\x01Qa\x14\x01`\x1F\x89\x16\x82a\x13\x14V[\x83UP[`\x01`\x02\x88\x02\x01\x88UPPP[PPPPPPV[\x7Finvalid address\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a\x14N`\x0F\x83a\x0E\x9FV[\x91Pa\x14Y\x82a\x14\x1AV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra\x14{\x81a\x14BV[\x90P\x91\x90PV[\x7Finvalid id\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a\x14\xB6`\n\x83a\x0E\x9FV[\x91Pa\x14\xC1\x82a\x14\x82V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra\x14\xE3\x81a\x14\xAAV[\x90P\x91\x90PV[a_\x1A\x80a\x14\xF7_9_\xF3\xFE`\x80`@R4\x80\x15a\0\x0FW__\xFD[P`\x046\x10a\0\xA7W_5`\xE0\x1C\x80c\xAD6\xE6\xD0\x11a\0oW\x80c\xAD6\xE6\xD0\x14a\x01\x15W\x80c\xC10\x80\x9A\x14a\x01\x1FW\x80c\xCCEf*\x14a\x01)W\x80c\xF2\xFD\xE3\x8B\x14a\x01EW\x80c\xF5\xF2\xD9\xF1\x14a\x01aW\x80c\xFF\xD7@\xDF\x14a\x01kWa\0\xA7V[\x80c0H\xBF\xBA\x14a\0\xABW\x80c@\x99\0\xE8\x14a\0\xB5W\x80cH\x86\xF6,\x14a\0\xD1W\x80cl\x0Ba\xB9\x14a\0\xDBW\x80cuA\x8B\x9D\x14a\0\xF7W[__\xFD[a\0\xB3a\x01\x87V[\0[a\0\xCF`\x04\x806\x03\x81\x01\x90a\0\xCA\x91\x90a9\xE2V[a\x02\xDBV[\0[a\0\xD9a\x03~V[\0[a\0\xF5`\x04\x806\x03\x81\x01\x90a\0\xF0\x91\x90a:+V[a\x08,V[\0[a\0\xFFa\tVV[`@Qa\x01\x0C\x91\x90a?GV[`@Q\x80\x91\x03\x90\xF3[a\x01\x1Da\nXV[\0[a\x01'a\x0B}V[\0[a\x01C`\x04\x806\x03\x81\x01\x90a\x01>\x91\x90a@\x1DV[a\x0C\xD1V[\0[a\x01_`\x04\x806\x03\x81\x01\x90a\x01Z\x91\x90a@\xC5V[a\x10;V[\0[a\x01ia\x11\x0BV[\0[a\x01\x85`\x04\x806\x03\x81\x01\x90a\x01\x80\x91\x90aA\x1AV[a\x12zV[\0[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x02\x15W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x02\x0C\x90aA\x9FV[`@Q\x80\x91\x03\x90\xFD[a\x02\x1F`\ta\x14\x0EV[`\n`\x08\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x02M\x90aA\xEAV[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\x8F\xB9\xCD\x05M\n\x02!\x10\xCC\xED#\x9E\x90\x8B\x83NL\xD2\x19Q\x18V\xD4\xEA\xAE0Q\xD92\xD6\x04`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x02\xD1\x91\x90aB0V[`@Q\x80\x91\x03\x90\xA1V[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x03iW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x03`\x90aA\x9FV[`@Q\x80\x91\x03\x90\xFD[\x80`\x01\x81\x81a\x03x\x91\x90aC\xC4V[\x90PPPV[a\x03\x923`\x05a\x14\xC6\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[`\n`\x08\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x03\xC0\x90aA\xEAV[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\xA7j\x8F\xC1\xA9\x02f\xDD\xEE\x897\xA1\x8E\x12\xF0\x1E\xAD\xE9F\xB3\xB6a\x97\xFF\xF2\x89\xAF\x92w\xC2\xBD%3`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x04F\x92\x91\x90aC\xE1V[`@Q\x80\x91\x03\x90\xA1_`\x05`\x03\x01_\x90T\x90a\x01\0\n\x90\x04`\xFF\x16`\xFF\x16\x11a\x08*W__\x90P[`\x05_\x01\x80T\x90P\x81\x10\x15a\x04\xDBWa\x04\xCE`\x05_\x01\x82\x81T\x81\x10a\x04\x96Wa\x04\x95aD\x08V[[\x90_R` _ \x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02a\x15\xE4\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x80\x80`\x01\x01\x91PPa\x04nV[P__\x90P[`\x05`\x01\x01\x80T\x90P\x81\x10\x15a\x07\x18Wa\x07\x0B`\x05`\x01\x01\x82\x81T\x81\x10a\x05\x0BWa\x05\naD\x08V[[\x90_R` _ \x90`\x03\x02\x01`@Q\x80``\x01`@R\x90\x81_\x82\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01`\x01\x82\x01\x80T\x80` \x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01_\x90[\x82\x82\x10\x15a\x06cW\x83\x82\x90_R` _ \x90`\x02\x02\x01`@Q\x80`@\x01`@R\x90\x81_\x82\x01T\x81R` \x01`\x01\x82\x01\x80Ta\x05\xD4\x90aDbV[\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01\x82\x80Ta\x06\0\x90aDbV[\x80\x15a\x06KW\x80`\x1F\x10a\x06\"Wa\x01\0\x80\x83T\x04\x02\x83R\x91` \x01\x91a\x06KV[\x82\x01\x91\x90_R` _ \x90[\x81T\x81R\x90`\x01\x01\x90` \x01\x80\x83\x11a\x06.W\x82\x90\x03`\x1F\x16\x82\x01\x91[PPPPP\x81RPP\x81R` \x01\x90`\x01\x01\x90a\x05\x9AV[PPPP\x81R` \x01`\x02\x82\x01\x80Ta\x06{\x90aDbV[\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01\x82\x80Ta\x06\xA7\x90aDbV[\x80\x15a\x06\xF2W\x80`\x1F\x10a\x06\xC9Wa\x01\0\x80\x83T\x04\x02\x83R\x91` \x01\x91a\x06\xF2V[\x82\x01\x91\x90_R` _ \x90[\x81T\x81R\x90`\x01\x01\x90` \x01\x80\x83\x11a\x06\xD5W\x82\x90\x03`\x1F\x16\x82\x01\x91[PPPPP\x81RPP`\x02a\x18v\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x80\x80`\x01\x01\x91PPa\x04\xE1V[P`\n_\x81\x81\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x07>\x90aD\x92V[\x91\x90a\x01\0\n\x81T\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPPa\x07o`\x05a\x1B\x03V[`\n`\x08\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x07\x9D\x90aA\xEAV[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\x11\xCEP\x16\x0Ef\x10\x057\xFDK\n\xE2m\xE6mQ\xDA\xB7\x13\xAD\x9213S\xA1\x8C$\xE8\xF6\xDA\xAB`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x08!\x91\x90aB0V[`@Q\x80\x91\x03\x90\xA1[V[a\x08@3`\x02a\x1B\xAC\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x08\x7FW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x08v\x90aE\x0BV[`@Q\x80\x91\x03\x90\xFD[a\x08\x953\x82`\x02a\x1D\x04\x90\x92\x91\x90c\xFF\xFF\xFF\xFF\x16V[`\n`\x08\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x08\xC3\x90aA\xEAV[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7Fj\xDF\xB8\x96\xD3@v\x81\xD0_\xB8t\xD4\xDF\xB7\x06\x8En*6\xF0\x9A\xCD8\xA3\xB7\xD0L\x01t_\xEE3\x82`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\tK\x93\x92\x91\x90aF3V[`@Q\x80\x91\x03\x90\xA1PV[a\t^a7FV[`@Q\x80`\xA0\x01`@R\x80a\ts`\x02a\x1D\x96V[\x81R` \x01a\t\x8F`\x02_\x01`\x05a\x1F\x99\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x81R` \x01`\t`@Q\x80` \x01`@R\x90\x81_\x82\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RPP\x81R` \x01`\n_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RP\x90P\x90V[a\nl3`\x02a\x1B\xAC\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\n\xABW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\n\xA2\x90aE\x0BV[`@Q\x80\x91\x03\x90\xFD[a\n\xBF3`\ta'\0\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[`\n`\x08\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\n\xED\x90aA\xEAV[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\xF9\x10g\xEBB\x0C(\xD3\x12He\xFC\x99nj\xA9\xD5A\xB9\xB4\xFE\xF9\x18\x8C\xB9e\xA6\xCCd\x91c\x8E3`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x0Bs\x92\x91\x90aC\xE1V[`@Q\x80\x91\x03\x90\xA1V[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x0C\x0BW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x0C\x02\x90aA\x9FV[`@Q\x80\x91\x03\x90\xFD[a\x0C\x15`\x05a('V[`\n`\x08\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x0CC\x90aA\xEAV[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\x9C\xE1\x92\xAE\xA5\xFA\xF2\x15\x1B\xBC$l\xD8\x91\x8D.\xBAp/\xA2iQ\xF6\x7F+\xF7\xB3\x81~h\x9D\x98`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x0C\xC7\x91\x90aB0V[`@Q\x80\x91\x03\x90\xA1V[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\r_W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\rV\x90aA\x9FV[`@Q\x80\x91\x03\x90\xFD[a\ri`\ta({V[\x15a\r\xA9W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\r\xA0\x90aF\xB9V[`@Q\x80\x91\x03\x90\xFD[__\x90P[\x84\x84\x90P\x81\x10\x15a\x0E@Wa\r\xF4\x85\x85\x83\x81\x81\x10a\r\xCFWa\r\xCEaD\x08V[[\x90P` \x02\x01` \x81\x01\x90a\r\xE4\x91\x90a@\xC5V[`\x02a\x1B\xAC\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x0E3W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x0E*\x90aG!V[`@Q\x80\x91\x03\x90\xFD[\x80\x80`\x01\x01\x91PPa\r\xAEV[P__\x90P[\x82\x82\x90P\x81\x10\x15a\x0F%Wa\x0E\x8F\x83\x83\x83\x81\x81\x10a\x0EgWa\x0EfaD\x08V[[\x90P` \x02\x81\x01\x90a\x0Ey\x91\x90aGKV[\x80` \x01\x90a\x0E\x88\x91\x90aGrV[\x90Pa(\xD5V[a\x0E\xD8\x83\x83\x83\x81\x81\x10a\x0E\xA5Wa\x0E\xA4aD\x08V[[\x90P` \x02\x81\x01\x90a\x0E\xB7\x91\x90aGKV[_\x01` \x81\x01\x90a\x0E\xC8\x91\x90a@\xC5V[`\x02a\x1B\xAC\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x15a\x0F\x18W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x0F\x0F\x90aH\x1EV[`@Q\x80\x91\x03\x90\xFD[\x80\x80`\x01\x01\x91PPa\x0EFV[Pa\x0FT\x82\x82\x90P\x85\x85\x90Pa\x0F;`\x02a)tV[a\x0FE\x91\x90aH&\x82\x82a=\xB0V[\x91PP` \x83\x01Q\x84\x82\x03` \x86\x01Ra>@\x82\x82a<\xCAV[\x91PP`@\x83\x01Q\x84\x82\x03`@\x86\x01Ra>Z\x82\x82a=\xB0V[\x91PP\x80\x91PP\x92\x91PPV[` \x82\x01_\x82\x01Qa>{_\x85\x01\x82a:\xCBV[PPPPV[_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[a>\x9D\x81a>\x81V[\x82RPPV[_o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[a>\xC7\x81a>\xA3V[\x82RPPV[_`\xA0\x83\x01_\x83\x01Q\x84\x82\x03_\x86\x01Ra>\xE7\x82\x82a==V[\x91PP` \x83\x01Q\x84\x82\x03` \x86\x01Ra?\x01\x82\x82a>\x0CV[\x91PP`@\x83\x01Qa?\x16`@\x86\x01\x82a>gV[P``\x83\x01Qa?)``\x86\x01\x82a>\x94V[P`\x80\x83\x01Qa?<`\x80\x86\x01\x82a>\xBEV[P\x80\x91PP\x92\x91PPV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra?_\x81\x84a>\xCDV[\x90P\x92\x91PPV[__\xFD[__\xFD[__\xFD[__\x83`\x1F\x84\x01\x12a?\x88Wa?\x87a?gV[[\x825\x90Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a?\xA5Wa?\xA4a?kV[[` \x83\x01\x91P\x83` \x82\x02\x83\x01\x11\x15a?\xC1Wa?\xC0a?oV[[\x92P\x92\x90PV[__\x83`\x1F\x84\x01\x12a?\xDDWa?\xDCa?gV[[\x825\x90Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a?\xFAWa?\xF9a?kV[[` \x83\x01\x91P\x83` \x82\x02\x83\x01\x11\x15a@\x16Wa@\x15a?oV[[\x92P\x92\x90PV[____`@\x85\x87\x03\x12\x15a@5Wa@4a9\xB8V[[_\x85\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a@RWa@Qa9\xBCV[[a@^\x87\x82\x88\x01a?sV[\x94P\x94PP` \x85\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a@\x81Wa@\x80a9\xBCV[[a@\x8D\x87\x82\x88\x01a?\xC8V[\x92P\x92PP\x92\x95\x91\x94P\x92PV[a@\xA4\x81a:\xBAV[\x81\x14a@\xAEW__\xFD[PV[_\x815\x90Pa@\xBF\x81a@\x9BV[\x92\x91PPV[_` \x82\x84\x03\x12\x15a@\xDAWa@\xD9a9\xB8V[[_a@\xE7\x84\x82\x85\x01a@\xB1V[\x91PP\x92\x91PPV[a@\xF9\x81a;\x03V[\x81\x14aA\x03W__\xFD[PV[_\x815\x90PaA\x14\x81a@\xF0V[\x92\x91PPV[_` \x82\x84\x03\x12\x15aA/WaA.a9\xB8V[[_aA<\x84\x82\x85\x01aA\x06V[\x91PP\x92\x91PPV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[\x7Fnot the owner\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aA\x89`\r\x83aAEV[\x91PaA\x94\x82aAUV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaA\xB6\x81aA}V[\x90P\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`\x11`\x04R`$_\xFD[_aA\xF4\x82a>\xA3V[\x91Po\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x03aB\x16WaB\x15aA\xBDV[[`\x01\x82\x01\x90P\x91\x90PV[aB*\x81a>\xA3V[\x82RPPV[_` \x82\x01\x90PaBC_\x83\x01\x84aB!V[\x92\x91PPV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R_`\x04R`$_\xFD[_`\xFF\x82\x16\x90P\x91\x90PV[aB\x8A\x81aBuV[\x81\x14aB\x94W__\xFD[PV[_\x815aB\xA3\x81aB\x81V[\x80\x91PP\x91\x90PV[_\x81_\x1B\x90P\x91\x90PV[_`\xFFaB\xC3\x84aB\xACV[\x93P\x80\x19\x83\x16\x92P\x80\x84\x16\x83\x17\x91PP\x92\x91PPV[_\x81\x90P\x91\x90PV[_aB\xFCaB\xF7aB\xF2\x84aBuV[aB\xD9V[aBuV[\x90P\x91\x90PV[_\x81\x90P\x91\x90PV[aC\x15\x82aB\xE2V[aC(aC!\x82aC\x03V[\x83TaB\xB7V[\x82UPPPV[_\x81`\x08\x1B\x90P\x91\x90PV[_a\xFF\0aCH\x84aC/V[\x93P\x80\x19\x83\x16\x92P\x80\x84\x16\x83\x17\x91PP\x92\x91PPV[aCg\x82aB\xE2V[aCzaCs\x82aC\x03V[\x83TaC;V[\x82UPPPV[_\x81\x01_\x83\x01\x80aC\x91\x81aB\x97V[\x90PaC\x9D\x81\x84aC\x0CV[PPP_\x81\x01` \x83\x01\x80aC\xB1\x81aB\x97V[\x90PaC\xBD\x81\x84aC^V[PPPPPV[aC\xCE\x82\x82aC\x81V[PPV[aC\xDB\x81a:\xBAV[\x82RPPV[_`@\x82\x01\x90PaC\xF4_\x83\x01\x85aC\xD2V[aD\x01` \x83\x01\x84aB!V[\x93\x92PPPV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`2`\x04R`$_\xFD[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`\"`\x04R`$_\xFD[_`\x02\x82\x04\x90P`\x01\x82\x16\x80aDyW`\x7F\x82\x16\x91P[` \x82\x10\x81\x03aD\x8CWaD\x8BaD5V[[P\x91\x90PV[_aD\x9C\x82a>\x81V[\x91Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x03aD\xB6WaD\xB5aA\xBDV[[`\x01\x82\x01\x90P\x91\x90PV[\x7Fnot an operator\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aD\xF5`\x0F\x83aAEV[\x91PaE\0\x82aD\xC1V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaE\"\x81aD\xE9V[\x90P\x91\x90PV[_aE7` \x84\x01\x84aA\x06V[\x90P\x92\x91PPV[__\xFD[__\xFD[__\xFD[__\x835`\x01` \x03\x846\x03\x03\x81\x12aEgWaEfaEGV[[\x83\x81\x01\x92P\x825\x91P` \x83\x01\x92Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15aE\x8FWaE\x8EaE?V[[`\x01\x82\x026\x03\x83\x13\x15aE\xA5WaE\xA4aECV[[P\x92P\x92\x90PV[\x82\x81\x837_\x83\x83\x01RPPPV[_aE\xC6\x83\x85a;%V[\x93PaE\xD3\x83\x85\x84aE\xADV[aE\xDC\x83a;CV[\x84\x01\x90P\x93\x92PPPV[_`@\x83\x01aE\xF8_\x84\x01\x84aE)V[aF\x04_\x86\x01\x82a;\x0CV[PaF\x12` \x84\x01\x84aEKV[\x85\x83\x03` \x87\x01RaF%\x83\x82\x84aE\xBBV[\x92PPP\x80\x91PP\x92\x91PPV[_``\x82\x01\x90PaFF_\x83\x01\x86aC\xD2V[\x81\x81\x03` \x83\x01RaFX\x81\x85aE\xE7V[\x90PaFg`@\x83\x01\x84aB!V[\x94\x93PPPPV[\x7Fmaintenance in progress\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aF\xA3`\x17\x83aAEV[\x91PaF\xAE\x82aFoV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaF\xD0\x81aF\x97V[\x90P\x91\x90PV[\x7Funknown operator\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aG\x0B`\x10\x83aAEV[\x91PaG\x16\x82aF\xD7V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaG8\x81aF\xFFV[\x90P\x91\x90PV[__\xFD[__\xFD[__\xFD[_\x825`\x01``\x03\x836\x03\x03\x81\x12aGfWaGeaG?V[[\x80\x83\x01\x91PP\x92\x91PPV[__\x835`\x01` \x03\x846\x03\x03\x81\x12aG\x8EWaG\x8DaG?V[[\x80\x84\x01\x92P\x825\x91Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15aG\xB0WaG\xAFaGCV[[` \x83\x01\x92P` \x82\x026\x03\x83\x13\x15aG\xCCWaG\xCBaGGV[[P\x92P\x92\x90PV[\x7Foperator already exists\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aH\x08`\x17\x83aAEV[\x91PaH\x13\x82aG\xD4V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaH5\x81aG\xFCV[\x90P\x91\x90PV[_aHF\x82a;\x03V[\x91PaHQ\x83a;\x03V[\x92P\x82\x82\x03\x90P\x81\x81\x11\x15aHiWaHhaA\xBDV[[\x92\x91PPV[_aHy\x82a;\x03V[\x91PaH\x84\x83a;\x03V[\x92P\x82\x82\x01\x90P\x80\x82\x11\x15aH\x9CWaH\x9BaA\xBDV[[\x92\x91PPV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[_\x81\x90P\x91\x90PV[_aH\xC9` \x84\x01\x84a@\xB1V[\x90P\x92\x91PPV[_` \x82\x01\x90P\x91\x90PV[_aH\xE8\x83\x85aH\xA2V[\x93PaH\xF3\x82aH\xB2V[\x80_[\x85\x81\x10\x15aI+WaI\x08\x82\x84aH\xBBV[aI\x12\x88\x82a=\x8DV[\x97PaI\x1D\x83aH\xD1V[\x92PP`\x01\x81\x01\x90PaH\xF6V[P\x85\x92PPP\x93\x92PPPV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[_\x81\x90P\x91\x90PV[__\x835`\x01` \x03\x846\x03\x03\x81\x12aImWaIlaEGV[[\x83\x81\x01\x92P\x825\x91P` \x83\x01\x92Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15aI\x95WaI\x94aE?V[[` \x82\x026\x03\x83\x13\x15aI\xABWaI\xAAaECV[[P\x92P\x92\x90PV[_\x81\x90P\x91\x90PV[_`@\x83\x01aI\xCD_\x84\x01\x84aE)V[aI\xD9_\x86\x01\x82a;\x0CV[PaI\xE7` \x84\x01\x84aEKV[\x85\x83\x03` \x87\x01RaI\xFA\x83\x82\x84aE\xBBV[\x92PPP\x80\x91PP\x92\x91PPV[_aJ\x13\x83\x83aI\xBCV[\x90P\x92\x91PPV[_\x825`\x01`@\x03\x836\x03\x03\x81\x12aJ6WaJ5aEGV[[\x82\x81\x01\x91PP\x92\x91PPV[_` \x82\x01\x90P\x91\x90PV[_aJY\x83\x85a:\xE4V[\x93P\x83` \x84\x02\x85\x01aJk\x84aI\xB3V[\x80_[\x87\x81\x10\x15aJ\xAEW\x84\x84\x03\x89RaJ\x85\x82\x84aJ\x1BV[aJ\x8F\x85\x82aJ\x08V[\x94PaJ\x9A\x83aJBV[\x92P` \x8A\x01\x99PP`\x01\x81\x01\x90PaJnV[P\x82\x97P\x87\x94PPPPP\x93\x92PPPV[_``\x83\x01aJ\xD1_\x84\x01\x84aH\xBBV[aJ\xDD_\x86\x01\x82a:\xCBV[PaJ\xEB` \x84\x01\x84aIQV[\x85\x83\x03` \x87\x01RaJ\xFE\x83\x82\x84aJNV[\x92PPPaK\x0F`@\x84\x01\x84aEKV[\x85\x83\x03`@\x87\x01RaK\"\x83\x82\x84aE\xBBV[\x92PPP\x80\x91PP\x92\x91PPV[_aK;\x83\x83aJ\xC0V[\x90P\x92\x91PPV[_\x825`\x01``\x03\x836\x03\x03\x81\x12aK^WaK]aEGV[[\x82\x81\x01\x91PP\x92\x91PPV[_` \x82\x01\x90P\x91\x90PV[_aK\x81\x83\x85aI8V[\x93P\x83` \x84\x02\x85\x01aK\x93\x84aIHV[\x80_[\x87\x81\x10\x15aK\xD6W\x84\x84\x03\x89RaK\xAD\x82\x84aKCV[aK\xB7\x85\x82aK0V[\x94PaK\xC2\x83aKjV[\x92P` \x8A\x01\x99PP`\x01\x81\x01\x90PaK\x96V[P\x82\x97P\x87\x94PPPPP\x93\x92PPPV[_``\x82\x01\x90P\x81\x81\x03_\x83\x01RaL\x01\x81\x87\x89aH\xDDV[\x90P\x81\x81\x03` \x83\x01RaL\x16\x81\x85\x87aKvV[\x90PaL%`@\x83\x01\x84aB!V[\x96\x95PPPPPPV[\x7Fmigration in progress\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aLc`\x15\x83aAEV[\x91PaLn\x82aL/V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaL\x90\x81aLWV[\x90P\x91\x90PV[\x7Ftoo few nodes\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aL\xCB`\r\x83aAEV[\x91PaL\xD6\x82aL\x97V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaL\xF8\x81aL\xBFV[\x90P\x91\x90PV[aM\x08\x81a;\x03V[\x82RPPV[_``\x82\x01\x90PaM!_\x83\x01\x86aC\xD2V[aM.` \x83\x01\x85aL\xFFV[aM;`@\x83\x01\x84aB!V[\x94\x93PPPPV[\x7Fnot under maintenance\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aMw`\x15\x83aAEV[\x91PaM\x82\x82aMCV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaM\xA4\x81aMkV[\x90P\x91\x90PV[\x7Fnot pulling\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aM\xDF`\x0B\x83aAEV[\x91PaM\xEA\x82aM\xABV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaN\x0C\x81aM\xD3V[\x90P\x91\x90PV[_aN\x1D\x82aBuV[\x91P_\x82\x03aN/WaN.aA\xBDV[[`\x01\x82\x03\x90P\x91\x90PV[\x7Finvalid address\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aNn`\x0F\x83aAEV[\x91PaNy\x82aN:V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaN\x9B\x81aNbV[\x90P\x91\x90PV[\x7Foperator doesn't exist\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aN\xD6`\x16\x83aAEV[\x91PaN\xE1\x82aN\xA2V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaO\x03\x81aN\xCAV[\x90P\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`1`\x04R`$_\xFD[\x7Ftoo many operators\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aOk`\x12\x83aAEV[\x91PaOv\x82aO7V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaO\x98\x81aO_V[\x90P\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`A`\x04R`$_\xFD[_\x81\x90P\x81_R` _ \x90P\x91\x90PV[_` `\x1F\x83\x01\x04\x90P\x91\x90PV[_\x82\x82\x1B\x90P\x92\x91PPV[_`\x08\x83\x02aP(\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82aO\xEDV[aP2\x86\x83aO\xEDV[\x95P\x80\x19\x84\x16\x93P\x80\x86\x16\x84\x17\x92PPP\x93\x92PPPV[_aPdaP_aPZ\x84a;\x03V[aB\xD9V[a;\x03V[\x90P\x91\x90PV[_\x81\x90P\x91\x90PV[aP}\x83aPJV[aP\x91aP\x89\x82aPkV[\x84\x84TaO\xF9V[\x82UPPPPV[__\x90P\x90V[aP\xA8aP\x99V[aP\xB3\x81\x84\x84aPtV[PPPV[[\x81\x81\x10\x15aP\xD6WaP\xCB_\x82aP\xA0V[`\x01\x81\x01\x90PaP\xB9V[PPV[`\x1F\x82\x11\x15aQ\x1BWaP\xEC\x81aO\xCCV[aP\xF5\x84aO\xDEV[\x81\x01` \x85\x10\x15aQ\x04W\x81\x90P[aQ\x18aQ\x10\x85aO\xDEV[\x83\x01\x82aP\xB8V[PP[PPPV[_\x82\x82\x1C\x90P\x92\x91PPV[_aQ;_\x19\x84`\x08\x02aQ V[\x19\x80\x83\x16\x91PP\x92\x91PPV[_aQS\x83\x83aQ,V[\x91P\x82`\x02\x02\x82\x17\x90P\x92\x91PPV[aQl\x82a;\x1BV[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15aQ\x85WaQ\x84aO\x9FV[[aQ\x8F\x82TaDbV[aQ\x9A\x82\x82\x85aP\xDAV[_` \x90P`\x1F\x83\x11`\x01\x81\x14aQ\xCBW_\x84\x15aQ\xB9W\x82\x87\x01Q\x90P[aQ\xC3\x85\x82aQHV[\x86UPaR*V[`\x1F\x19\x84\x16aQ\xD9\x86aO\xCCV[_[\x82\x81\x10\x15aR\0W\x84\x89\x01Q\x82U`\x01\x82\x01\x91P` \x85\x01\x94P` \x81\x01\x90PaQ\xDBV[\x86\x83\x10\x15aR\x1DW\x84\x89\x01QaR\x19`\x1F\x89\x16\x82aQ,V[\x83UP[`\x01`\x02\x88\x02\x01\x88UPPP[PPPPPPV[\x7Fnot in progress\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aRf`\x0F\x83aAEV[\x91PaRq\x82aR2V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaR\x93\x81aRZV[\x90P\x91\x90PV[\x7Fdata pull in progress\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aR\xCE`\x15\x83aAEV[\x91PaR\xD9\x82aR\x9AV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaR\xFB\x81aR\xC2V[\x90P\x91\x90PV[__\xFD[aS\x0F\x82a;CV[\x81\x01\x81\x81\x10g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x17\x15aS.WaS-aO\x9FV[[\x80`@RPPPV[_aS@a9\xAFV[\x90PaSL\x82\x82aS\x06V[\x91\x90PV[__\xFD[__\xFD[_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15aSsWaSraO\x9FV[[aS|\x82a;CV[\x90P` \x81\x01\x90P\x91\x90PV[_aS\x9BaS\x96\x84aSYV[aS7V[\x90P\x82\x81R` \x81\x01\x84\x84\x84\x01\x11\x15aS\xB7WaS\xB6aSUV[[aS\xC2\x84\x82\x85aE\xADV[P\x93\x92PPPV[_\x82`\x1F\x83\x01\x12aS\xDEWaS\xDDa?gV[[\x815aS\xEE\x84\x82` \x86\x01aS\x89V[\x91PP\x92\x91PPV[_`@\x82\x84\x03\x12\x15aT\x0CWaT\x0BaS\x02V[[aT\x16`@aS7V[\x90P_aT%\x84\x82\x85\x01aA\x06V[_\x83\x01RP` \x82\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15aTHWaTGaSQV[[aTT\x84\x82\x85\x01aS\xCAV[` \x83\x01RP\x92\x91PPV[_aTk6\x83aS\xF7V[\x90P\x91\x90PV[_aT|\x82a;\x03V[\x91P\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x03aT\xAEWaT\xADaA\xBDV[[`\x01\x82\x01\x90P\x91\x90PV[\x7Ftoo many nodes\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aT\xED`\x0E\x83aAEV[\x91PaT\xF8\x82aT\xB9V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaU\x1A\x81aT\xE1V[\x90P\x91\x90PV[\x7Ftoo few operators\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aUU`\x11\x83aAEV[\x91PaU`\x82aU!V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaU\x82\x81aUIV[\x90P\x91\x90PV[\x7Fmigration already in progress\0\0\0_\x82\x01RPV[_aU\xBD`\x1D\x83aAEV[\x91PaU\xC8\x82aU\x89V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaU\xEA\x81aU\xB1V[\x90P\x91\x90PV[\x7Fnothing to do\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aV%`\r\x83aAEV[\x91PaV0\x82aU\xF1V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaVR\x81aV\x19V[\x90P\x91\x90PV[_aVc\x82aBuV[\x91P`\xFF\x82\x03aVvWaVuaA\xBDV[[`\x01\x82\x01\x90P\x91\x90PV[_\x815aV\x8D\x81a@\x9BV[\x80\x91PP\x91\x90PV[_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFFaV\xB5\x84aB\xACV[\x93P\x80\x19\x83\x16\x92P\x80\x84\x16\x83\x17\x91PP\x92\x91PPV[_aV\xE5aV\xE0aV\xDB\x84a:\x9BV[aB\xD9V[a:\x9BV[\x90P\x91\x90PV[_aV\xF6\x82aV\xCBV[\x90P\x91\x90PV[_aW\x07\x82aV\xECV[\x90P\x91\x90PV[_\x81\x90P\x91\x90PV[aW \x82aV\xFDV[aW3aW,\x82aW\x0EV[\x83TaV\x96V[\x82UPPPV[_\x825`\x01`@\x03\x836\x03\x03\x81\x12aWUWaWTaG?V[[\x80\x83\x01\x91PP\x92\x91PPV[_\x81T\x90P\x91\x90PV[_aWu\x82a;\x03V[\x91PaW\x80\x83a;\x03V[\x92P\x82\x82\x02aW\x8E\x81a;\x03V[\x91P\x82\x82\x04\x84\x14\x83\x15\x17aW\xA5WaW\xA4aA\xBDV[[P\x92\x91PPV[_\x81\x90PaW\xBB\x82`\x02aWkV[\x90P\x91\x90PV[_\x81\x90P\x81_R` _ \x90P\x91\x90PV[aX\x04\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x83` \x03`\x08\x02aQ V[\x81T\x81\x16\x82UPPPV[aX\x18\x81aO\xCCV[aX#\x83\x82TaQHV[\x80\x83U_\x82UPPPPV[` \x84\x10_\x81\x14aX\x89W`\x1F\x84\x11`\x01\x81\x14aXWWaXP\x86\x85aQHV[\x83UaX\x83V[aX`\x83aO\xCCV[aXwaXl\x87aO\xDEV[\x82\x01`\x01\x83\x01aP\xB8V[aX\x81\x87\x85aX\x0FV[P[PaX\xD6V[aX\x92\x82aO\xCCV[aX\x9B\x86aO\xDEV[\x81\x01`\x1F\x87\x16\x80\x15aX\xB5WaX\xB4\x81`\x01\x84\x03aW\xD4V[[aX\xC9aX\xC1\x88aO\xDEV[\x84\x01\x83aP\xB8V[`\x01\x88`\x02\x02\x17\x85UPPP[PPPPPV[h\x01\0\0\0\0\0\0\0\0\x84\x11\x15aX\xF7WaX\xF6aO\x9FV[[` \x83\x10_\x81\x14aY@W` \x85\x10_\x81\x14aY\x1EWaY\x17\x86\x85aQHV[\x83UaY:V[\x83`\xFF\x19\x16\x93P\x83aY/\x84aO\xCCV[U`\x01\x86`\x02\x02\x01\x83U[PaYJV[`\x01\x85`\x02\x02\x01\x82U[PPPPPV[\x80TaY\\\x81aDbV[\x80\x84\x11\x15aYqWaYp\x84\x82\x84\x86aX\xDDV[[\x80\x84\x10\x15aY\x86WaY\x85\x84\x82\x84\x86aX/V[[PPPPV[\x81\x81\x10\x15aY\xA9WaY\x9E_\x82aP\xA0V[`\x01\x81\x01\x90PaY\x8CV[PPV[aY\xB7_\x82aYQV[PV[_\x82\x14aY\xCAWaY\xC9aBIV[[aY\xD3\x81aY\xADV[PPV[aY\xE3__\x83\x01aP\xA0V[aY\xF0_`\x01\x83\x01aY\xBAV[PV[_\x82\x14aZ\x03WaZ\x02aBIV[[aZ\x0C\x81aY\xD7V[PPV[[\x81\x81\x10\x15aZ.WaZ#_\x82aY\xF3V[`\x02\x81\x01\x90PaZ\x11V[PPV[\x81\x83\x10\x15aZkWaZC\x82aW\xACV[aZL\x84aW\xACV[aZU\x83aW\xC2V[\x81\x81\x01\x83\x82\x01aZe\x81\x83aZ\x10V[PPPPP[PPPV[h\x01\0\0\0\0\0\0\0\0\x82\x11\x15aZ\x8AWaZ\x89aO\x9FV[[aZ\x93\x81aWaV[\x82\x82UaZ\xA1\x83\x82\x84aZ2V[PPPV[_\x82\x90P\x92\x91PPV[_\x815aZ\xBC\x81a@\xF0V[\x80\x91PP\x91\x90PV[_\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFFaZ\xF0\x84aB\xACV[\x93P\x80\x19\x83\x16\x92P\x80\x84\x16\x83\x17\x91PP\x92\x91PPV[a[\x0F\x82aPJV[a[\"a[\x1B\x82aPkV[\x83TaZ\xC5V[\x82UPPPV[__\x835`\x01` \x03\x846\x03\x03\x81\x12a[EWa[DaG?V[[\x80\x84\x01\x92P\x825\x91Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15a[gWa[faGCV[[` \x83\x01\x92P`\x01\x82\x026\x03\x83\x13\x15a[\x83Wa[\x82aGGV[[P\x92P\x92\x90PV[_\x82\x90P\x92\x91PPV[a[\x9F\x83\x83a[\x8BV[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a[\xB8Wa[\xB7aO\x9FV[[a[\xC2\x82TaDbV[a[\xCD\x82\x82\x85aP\xDAV[_`\x1F\x83\x11`\x01\x81\x14a[\xFAW_\x84\x15a[\xE8W\x82\x87\x015\x90P[a[\xF2\x85\x82aQHV[\x86UPa\\YV[`\x1F\x19\x84\x16a\\\x08\x86aO\xCCV[_[\x82\x81\x10\x15a\\/W\x84\x89\x015\x82U`\x01\x82\x01\x91P` \x85\x01\x94P` \x81\x01\x90Pa\\\nV[\x86\x83\x10\x15a\\LW\x84\x89\x015a\\H`\x1F\x89\x16\x82aQ,V[\x83UP[`\x01`\x02\x88\x02\x01\x88UPPP[PPPPPPPV[a\\m\x83\x83\x83a[\x95V[PPPV[_\x81\x01_\x83\x01\x80a\\\x82\x81aZ\xB0V[\x90Pa\\\x8E\x81\x84a[\x06V[PPP`\x01\x81\x01` \x83\x01a\\\xA3\x81\x85a[)V[a\\\xAE\x81\x83\x86a\\bV[PPPPPPV[a\\\xC0\x82\x82a\\rV[PPV[a\\\xCE\x83\x83aZ\xA6V[a\\\xD8\x81\x83aZpV[a\\\xE1\x83aI\xB3V[a\\\xEA\x83aW\xC2V[_[\x83\x81\x10\x15a] Wa\\\xFE\x83\x87aW:V[a]\x08\x81\x84a\\\xB6V[` \x84\x01\x93P`\x02\x83\x01\x92PP`\x01\x81\x01\x90Pa\\\xECV[PPPPPPPV[a]4\x83\x83\x83a\\\xC4V[PPPV[_\x81\x01_\x83\x01\x80a]I\x81aV\x81V[\x90Pa]U\x81\x84aW\x17V[PPP`\x01\x81\x01` \x83\x01a]j\x81\x85aGrV[a]u\x81\x83\x86a])V[PPPP`\x02\x81\x01`@\x83\x01a]\x8B\x81\x85a[)V[a]\x96\x81\x83\x86a\\bV[PPPPPPV[a]\xA8\x82\x82a]9V[PPV[\x7Fanother maintenance in progress\0_\x82\x01RPV[_a]\xE0`\x1F\x83aAEV[\x91Pa]\xEB\x82a]\xACV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra^\r\x81a]\xD4V[\x90P\x91\x90PV[\x7Finvalid id\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a^H`\n\x83aAEV[\x91Pa^S\x82a^\x14V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra^u\x81a^\x91\x90a@\x1DV[a\x0C\xD1V[\0[a\x01_`\x04\x806\x03\x81\x01\x90a\x01Z\x91\x90a@\xC5V[a\x10;V[\0[a\x01ia\x11\x0BV[\0[a\x01\x85`\x04\x806\x03\x81\x01\x90a\x01\x80\x91\x90aA\x1AV[a\x12zV[\0[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x02\x15W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x02\x0C\x90aA\x9FV[`@Q\x80\x91\x03\x90\xFD[a\x02\x1F`\ta\x14\x0EV[`\n`\x08\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x02M\x90aA\xEAV[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\x8F\xB9\xCD\x05M\n\x02!\x10\xCC\xED#\x9E\x90\x8B\x83NL\xD2\x19Q\x18V\xD4\xEA\xAE0Q\xD92\xD6\x04`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x02\xD1\x91\x90aB0V[`@Q\x80\x91\x03\x90\xA1V[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x03iW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x03`\x90aA\x9FV[`@Q\x80\x91\x03\x90\xFD[\x80`\x01\x81\x81a\x03x\x91\x90aC\xC4V[\x90PPPV[a\x03\x923`\x05a\x14\xC6\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[`\n`\x08\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x03\xC0\x90aA\xEAV[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\xA7j\x8F\xC1\xA9\x02f\xDD\xEE\x897\xA1\x8E\x12\xF0\x1E\xAD\xE9F\xB3\xB6a\x97\xFF\xF2\x89\xAF\x92w\xC2\xBD%3`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x04F\x92\x91\x90aC\xE1V[`@Q\x80\x91\x03\x90\xA1_`\x05`\x03\x01_\x90T\x90a\x01\0\n\x90\x04`\xFF\x16`\xFF\x16\x11a\x08*W__\x90P[`\x05_\x01\x80T\x90P\x81\x10\x15a\x04\xDBWa\x04\xCE`\x05_\x01\x82\x81T\x81\x10a\x04\x96Wa\x04\x95aD\x08V[[\x90_R` _ \x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02a\x15\xE4\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x80\x80`\x01\x01\x91PPa\x04nV[P__\x90P[`\x05`\x01\x01\x80T\x90P\x81\x10\x15a\x07\x18Wa\x07\x0B`\x05`\x01\x01\x82\x81T\x81\x10a\x05\x0BWa\x05\naD\x08V[[\x90_R` _ \x90`\x03\x02\x01`@Q\x80``\x01`@R\x90\x81_\x82\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01`\x01\x82\x01\x80T\x80` \x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01_\x90[\x82\x82\x10\x15a\x06cW\x83\x82\x90_R` _ \x90`\x02\x02\x01`@Q\x80`@\x01`@R\x90\x81_\x82\x01T\x81R` \x01`\x01\x82\x01\x80Ta\x05\xD4\x90aDbV[\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01\x82\x80Ta\x06\0\x90aDbV[\x80\x15a\x06KW\x80`\x1F\x10a\x06\"Wa\x01\0\x80\x83T\x04\x02\x83R\x91` \x01\x91a\x06KV[\x82\x01\x91\x90_R` _ \x90[\x81T\x81R\x90`\x01\x01\x90` \x01\x80\x83\x11a\x06.W\x82\x90\x03`\x1F\x16\x82\x01\x91[PPPPP\x81RPP\x81R` \x01\x90`\x01\x01\x90a\x05\x9AV[PPPP\x81R` \x01`\x02\x82\x01\x80Ta\x06{\x90aDbV[\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01\x82\x80Ta\x06\xA7\x90aDbV[\x80\x15a\x06\xF2W\x80`\x1F\x10a\x06\xC9Wa\x01\0\x80\x83T\x04\x02\x83R\x91` \x01\x91a\x06\xF2V[\x82\x01\x91\x90_R` _ \x90[\x81T\x81R\x90`\x01\x01\x90` \x01\x80\x83\x11a\x06\xD5W\x82\x90\x03`\x1F\x16\x82\x01\x91[PPPPP\x81RPP`\x02a\x18v\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x80\x80`\x01\x01\x91PPa\x04\xE1V[P`\n_\x81\x81\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x07>\x90aD\x92V[\x91\x90a\x01\0\n\x81T\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPPa\x07o`\x05a\x1B\x03V[`\n`\x08\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x07\x9D\x90aA\xEAV[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\x11\xCEP\x16\x0Ef\x10\x057\xFDK\n\xE2m\xE6mQ\xDA\xB7\x13\xAD\x9213S\xA1\x8C$\xE8\xF6\xDA\xAB`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x08!\x91\x90aB0V[`@Q\x80\x91\x03\x90\xA1[V[a\x08@3`\x02a\x1B\xAC\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x08\x7FW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x08v\x90aE\x0BV[`@Q\x80\x91\x03\x90\xFD[a\x08\x953\x82`\x02a\x1D\x04\x90\x92\x91\x90c\xFF\xFF\xFF\xFF\x16V[`\n`\x08\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x08\xC3\x90aA\xEAV[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7Fj\xDF\xB8\x96\xD3@v\x81\xD0_\xB8t\xD4\xDF\xB7\x06\x8En*6\xF0\x9A\xCD8\xA3\xB7\xD0L\x01t_\xEE3\x82`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\tK\x93\x92\x91\x90aF3V[`@Q\x80\x91\x03\x90\xA1PV[a\t^a7FV[`@Q\x80`\xA0\x01`@R\x80a\ts`\x02a\x1D\x96V[\x81R` \x01a\t\x8F`\x02_\x01`\x05a\x1F\x99\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x81R` \x01`\t`@Q\x80` \x01`@R\x90\x81_\x82\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RPP\x81R` \x01`\n_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RP\x90P\x90V[a\nl3`\x02a\x1B\xAC\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\n\xABW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\n\xA2\x90aE\x0BV[`@Q\x80\x91\x03\x90\xFD[a\n\xBF3`\ta'\0\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[`\n`\x08\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\n\xED\x90aA\xEAV[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\xF9\x10g\xEBB\x0C(\xD3\x12He\xFC\x99nj\xA9\xD5A\xB9\xB4\xFE\xF9\x18\x8C\xB9e\xA6\xCCd\x91c\x8E3`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x0Bs\x92\x91\x90aC\xE1V[`@Q\x80\x91\x03\x90\xA1V[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x0C\x0BW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x0C\x02\x90aA\x9FV[`@Q\x80\x91\x03\x90\xFD[a\x0C\x15`\x05a('V[`\n`\x08\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x0CC\x90aA\xEAV[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\x9C\xE1\x92\xAE\xA5\xFA\xF2\x15\x1B\xBC$l\xD8\x91\x8D.\xBAp/\xA2iQ\xF6\x7F+\xF7\xB3\x81~h\x9D\x98`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x0C\xC7\x91\x90aB0V[`@Q\x80\x91\x03\x90\xA1V[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\r_W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\rV\x90aA\x9FV[`@Q\x80\x91\x03\x90\xFD[a\ri`\ta({V[\x15a\r\xA9W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\r\xA0\x90aF\xB9V[`@Q\x80\x91\x03\x90\xFD[__\x90P[\x84\x84\x90P\x81\x10\x15a\x0E@Wa\r\xF4\x85\x85\x83\x81\x81\x10a\r\xCFWa\r\xCEaD\x08V[[\x90P` \x02\x01` \x81\x01\x90a\r\xE4\x91\x90a@\xC5V[`\x02a\x1B\xAC\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x0E3W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x0E*\x90aG!V[`@Q\x80\x91\x03\x90\xFD[\x80\x80`\x01\x01\x91PPa\r\xAEV[P__\x90P[\x82\x82\x90P\x81\x10\x15a\x0F%Wa\x0E\x8F\x83\x83\x83\x81\x81\x10a\x0EgWa\x0EfaD\x08V[[\x90P` \x02\x81\x01\x90a\x0Ey\x91\x90aGKV[\x80` \x01\x90a\x0E\x88\x91\x90aGrV[\x90Pa(\xD5V[a\x0E\xD8\x83\x83\x83\x81\x81\x10a\x0E\xA5Wa\x0E\xA4aD\x08V[[\x90P` \x02\x81\x01\x90a\x0E\xB7\x91\x90aGKV[_\x01` \x81\x01\x90a\x0E\xC8\x91\x90a@\xC5V[`\x02a\x1B\xAC\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x15a\x0F\x18W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x0F\x0F\x90aH\x1EV[`@Q\x80\x91\x03\x90\xFD[\x80\x80`\x01\x01\x91PPa\x0EFV[Pa\x0FT\x82\x82\x90P\x85\x85\x90Pa\x0F;`\x02a)tV[a\x0FE\x91\x90aH&\x82\x82a=\xB0V[\x91PP` \x83\x01Q\x84\x82\x03` \x86\x01Ra>@\x82\x82a<\xCAV[\x91PP`@\x83\x01Q\x84\x82\x03`@\x86\x01Ra>Z\x82\x82a=\xB0V[\x91PP\x80\x91PP\x92\x91PPV[` \x82\x01_\x82\x01Qa>{_\x85\x01\x82a:\xCBV[PPPPV[_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[a>\x9D\x81a>\x81V[\x82RPPV[_o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[a>\xC7\x81a>\xA3V[\x82RPPV[_`\xA0\x83\x01_\x83\x01Q\x84\x82\x03_\x86\x01Ra>\xE7\x82\x82a==V[\x91PP` \x83\x01Q\x84\x82\x03` \x86\x01Ra?\x01\x82\x82a>\x0CV[\x91PP`@\x83\x01Qa?\x16`@\x86\x01\x82a>gV[P``\x83\x01Qa?)``\x86\x01\x82a>\x94V[P`\x80\x83\x01Qa?<`\x80\x86\x01\x82a>\xBEV[P\x80\x91PP\x92\x91PPV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra?_\x81\x84a>\xCDV[\x90P\x92\x91PPV[__\xFD[__\xFD[__\xFD[__\x83`\x1F\x84\x01\x12a?\x88Wa?\x87a?gV[[\x825\x90Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a?\xA5Wa?\xA4a?kV[[` \x83\x01\x91P\x83` \x82\x02\x83\x01\x11\x15a?\xC1Wa?\xC0a?oV[[\x92P\x92\x90PV[__\x83`\x1F\x84\x01\x12a?\xDDWa?\xDCa?gV[[\x825\x90Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a?\xFAWa?\xF9a?kV[[` \x83\x01\x91P\x83` \x82\x02\x83\x01\x11\x15a@\x16Wa@\x15a?oV[[\x92P\x92\x90PV[____`@\x85\x87\x03\x12\x15a@5Wa@4a9\xB8V[[_\x85\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a@RWa@Qa9\xBCV[[a@^\x87\x82\x88\x01a?sV[\x94P\x94PP` \x85\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a@\x81Wa@\x80a9\xBCV[[a@\x8D\x87\x82\x88\x01a?\xC8V[\x92P\x92PP\x92\x95\x91\x94P\x92PV[a@\xA4\x81a:\xBAV[\x81\x14a@\xAEW__\xFD[PV[_\x815\x90Pa@\xBF\x81a@\x9BV[\x92\x91PPV[_` \x82\x84\x03\x12\x15a@\xDAWa@\xD9a9\xB8V[[_a@\xE7\x84\x82\x85\x01a@\xB1V[\x91PP\x92\x91PPV[a@\xF9\x81a;\x03V[\x81\x14aA\x03W__\xFD[PV[_\x815\x90PaA\x14\x81a@\xF0V[\x92\x91PPV[_` \x82\x84\x03\x12\x15aA/WaA.a9\xB8V[[_aA<\x84\x82\x85\x01aA\x06V[\x91PP\x92\x91PPV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[\x7Fnot the owner\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aA\x89`\r\x83aAEV[\x91PaA\x94\x82aAUV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaA\xB6\x81aA}V[\x90P\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`\x11`\x04R`$_\xFD[_aA\xF4\x82a>\xA3V[\x91Po\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x03aB\x16WaB\x15aA\xBDV[[`\x01\x82\x01\x90P\x91\x90PV[aB*\x81a>\xA3V[\x82RPPV[_` \x82\x01\x90PaBC_\x83\x01\x84aB!V[\x92\x91PPV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R_`\x04R`$_\xFD[_`\xFF\x82\x16\x90P\x91\x90PV[aB\x8A\x81aBuV[\x81\x14aB\x94W__\xFD[PV[_\x815aB\xA3\x81aB\x81V[\x80\x91PP\x91\x90PV[_\x81_\x1B\x90P\x91\x90PV[_`\xFFaB\xC3\x84aB\xACV[\x93P\x80\x19\x83\x16\x92P\x80\x84\x16\x83\x17\x91PP\x92\x91PPV[_\x81\x90P\x91\x90PV[_aB\xFCaB\xF7aB\xF2\x84aBuV[aB\xD9V[aBuV[\x90P\x91\x90PV[_\x81\x90P\x91\x90PV[aC\x15\x82aB\xE2V[aC(aC!\x82aC\x03V[\x83TaB\xB7V[\x82UPPPV[_\x81`\x08\x1B\x90P\x91\x90PV[_a\xFF\0aCH\x84aC/V[\x93P\x80\x19\x83\x16\x92P\x80\x84\x16\x83\x17\x91PP\x92\x91PPV[aCg\x82aB\xE2V[aCzaCs\x82aC\x03V[\x83TaC;V[\x82UPPPV[_\x81\x01_\x83\x01\x80aC\x91\x81aB\x97V[\x90PaC\x9D\x81\x84aC\x0CV[PPP_\x81\x01` \x83\x01\x80aC\xB1\x81aB\x97V[\x90PaC\xBD\x81\x84aC^V[PPPPPV[aC\xCE\x82\x82aC\x81V[PPV[aC\xDB\x81a:\xBAV[\x82RPPV[_`@\x82\x01\x90PaC\xF4_\x83\x01\x85aC\xD2V[aD\x01` \x83\x01\x84aB!V[\x93\x92PPPV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`2`\x04R`$_\xFD[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`\"`\x04R`$_\xFD[_`\x02\x82\x04\x90P`\x01\x82\x16\x80aDyW`\x7F\x82\x16\x91P[` \x82\x10\x81\x03aD\x8CWaD\x8BaD5V[[P\x91\x90PV[_aD\x9C\x82a>\x81V[\x91Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x03aD\xB6WaD\xB5aA\xBDV[[`\x01\x82\x01\x90P\x91\x90PV[\x7Fnot an operator\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aD\xF5`\x0F\x83aAEV[\x91PaE\0\x82aD\xC1V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaE\"\x81aD\xE9V[\x90P\x91\x90PV[_aE7` \x84\x01\x84aA\x06V[\x90P\x92\x91PPV[__\xFD[__\xFD[__\xFD[__\x835`\x01` \x03\x846\x03\x03\x81\x12aEgWaEfaEGV[[\x83\x81\x01\x92P\x825\x91P` \x83\x01\x92Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15aE\x8FWaE\x8EaE?V[[`\x01\x82\x026\x03\x83\x13\x15aE\xA5WaE\xA4aECV[[P\x92P\x92\x90PV[\x82\x81\x837_\x83\x83\x01RPPPV[_aE\xC6\x83\x85a;%V[\x93PaE\xD3\x83\x85\x84aE\xADV[aE\xDC\x83a;CV[\x84\x01\x90P\x93\x92PPPV[_`@\x83\x01aE\xF8_\x84\x01\x84aE)V[aF\x04_\x86\x01\x82a;\x0CV[PaF\x12` \x84\x01\x84aEKV[\x85\x83\x03` \x87\x01RaF%\x83\x82\x84aE\xBBV[\x92PPP\x80\x91PP\x92\x91PPV[_``\x82\x01\x90PaFF_\x83\x01\x86aC\xD2V[\x81\x81\x03` \x83\x01RaFX\x81\x85aE\xE7V[\x90PaFg`@\x83\x01\x84aB!V[\x94\x93PPPPV[\x7Fmaintenance in progress\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aF\xA3`\x17\x83aAEV[\x91PaF\xAE\x82aFoV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaF\xD0\x81aF\x97V[\x90P\x91\x90PV[\x7Funknown operator\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aG\x0B`\x10\x83aAEV[\x91PaG\x16\x82aF\xD7V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaG8\x81aF\xFFV[\x90P\x91\x90PV[__\xFD[__\xFD[__\xFD[_\x825`\x01``\x03\x836\x03\x03\x81\x12aGfWaGeaG?V[[\x80\x83\x01\x91PP\x92\x91PPV[__\x835`\x01` \x03\x846\x03\x03\x81\x12aG\x8EWaG\x8DaG?V[[\x80\x84\x01\x92P\x825\x91Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15aG\xB0WaG\xAFaGCV[[` \x83\x01\x92P` \x82\x026\x03\x83\x13\x15aG\xCCWaG\xCBaGGV[[P\x92P\x92\x90PV[\x7Foperator already exists\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aH\x08`\x17\x83aAEV[\x91PaH\x13\x82aG\xD4V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaH5\x81aG\xFCV[\x90P\x91\x90PV[_aHF\x82a;\x03V[\x91PaHQ\x83a;\x03V[\x92P\x82\x82\x03\x90P\x81\x81\x11\x15aHiWaHhaA\xBDV[[\x92\x91PPV[_aHy\x82a;\x03V[\x91PaH\x84\x83a;\x03V[\x92P\x82\x82\x01\x90P\x80\x82\x11\x15aH\x9CWaH\x9BaA\xBDV[[\x92\x91PPV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[_\x81\x90P\x91\x90PV[_aH\xC9` \x84\x01\x84a@\xB1V[\x90P\x92\x91PPV[_` \x82\x01\x90P\x91\x90PV[_aH\xE8\x83\x85aH\xA2V[\x93PaH\xF3\x82aH\xB2V[\x80_[\x85\x81\x10\x15aI+WaI\x08\x82\x84aH\xBBV[aI\x12\x88\x82a=\x8DV[\x97PaI\x1D\x83aH\xD1V[\x92PP`\x01\x81\x01\x90PaH\xF6V[P\x85\x92PPP\x93\x92PPPV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[_\x81\x90P\x91\x90PV[__\x835`\x01` \x03\x846\x03\x03\x81\x12aImWaIlaEGV[[\x83\x81\x01\x92P\x825\x91P` \x83\x01\x92Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15aI\x95WaI\x94aE?V[[` \x82\x026\x03\x83\x13\x15aI\xABWaI\xAAaECV[[P\x92P\x92\x90PV[_\x81\x90P\x91\x90PV[_`@\x83\x01aI\xCD_\x84\x01\x84aE)V[aI\xD9_\x86\x01\x82a;\x0CV[PaI\xE7` \x84\x01\x84aEKV[\x85\x83\x03` \x87\x01RaI\xFA\x83\x82\x84aE\xBBV[\x92PPP\x80\x91PP\x92\x91PPV[_aJ\x13\x83\x83aI\xBCV[\x90P\x92\x91PPV[_\x825`\x01`@\x03\x836\x03\x03\x81\x12aJ6WaJ5aEGV[[\x82\x81\x01\x91PP\x92\x91PPV[_` \x82\x01\x90P\x91\x90PV[_aJY\x83\x85a:\xE4V[\x93P\x83` \x84\x02\x85\x01aJk\x84aI\xB3V[\x80_[\x87\x81\x10\x15aJ\xAEW\x84\x84\x03\x89RaJ\x85\x82\x84aJ\x1BV[aJ\x8F\x85\x82aJ\x08V[\x94PaJ\x9A\x83aJBV[\x92P` \x8A\x01\x99PP`\x01\x81\x01\x90PaJnV[P\x82\x97P\x87\x94PPPPP\x93\x92PPPV[_``\x83\x01aJ\xD1_\x84\x01\x84aH\xBBV[aJ\xDD_\x86\x01\x82a:\xCBV[PaJ\xEB` \x84\x01\x84aIQV[\x85\x83\x03` \x87\x01RaJ\xFE\x83\x82\x84aJNV[\x92PPPaK\x0F`@\x84\x01\x84aEKV[\x85\x83\x03`@\x87\x01RaK\"\x83\x82\x84aE\xBBV[\x92PPP\x80\x91PP\x92\x91PPV[_aK;\x83\x83aJ\xC0V[\x90P\x92\x91PPV[_\x825`\x01``\x03\x836\x03\x03\x81\x12aK^WaK]aEGV[[\x82\x81\x01\x91PP\x92\x91PPV[_` \x82\x01\x90P\x91\x90PV[_aK\x81\x83\x85aI8V[\x93P\x83` \x84\x02\x85\x01aK\x93\x84aIHV[\x80_[\x87\x81\x10\x15aK\xD6W\x84\x84\x03\x89RaK\xAD\x82\x84aKCV[aK\xB7\x85\x82aK0V[\x94PaK\xC2\x83aKjV[\x92P` \x8A\x01\x99PP`\x01\x81\x01\x90PaK\x96V[P\x82\x97P\x87\x94PPPPP\x93\x92PPPV[_``\x82\x01\x90P\x81\x81\x03_\x83\x01RaL\x01\x81\x87\x89aH\xDDV[\x90P\x81\x81\x03` \x83\x01RaL\x16\x81\x85\x87aKvV[\x90PaL%`@\x83\x01\x84aB!V[\x96\x95PPPPPPV[\x7Fmigration in progress\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aLc`\x15\x83aAEV[\x91PaLn\x82aL/V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaL\x90\x81aLWV[\x90P\x91\x90PV[\x7Ftoo few nodes\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aL\xCB`\r\x83aAEV[\x91PaL\xD6\x82aL\x97V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaL\xF8\x81aL\xBFV[\x90P\x91\x90PV[aM\x08\x81a;\x03V[\x82RPPV[_``\x82\x01\x90PaM!_\x83\x01\x86aC\xD2V[aM.` \x83\x01\x85aL\xFFV[aM;`@\x83\x01\x84aB!V[\x94\x93PPPPV[\x7Fnot under maintenance\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aMw`\x15\x83aAEV[\x91PaM\x82\x82aMCV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaM\xA4\x81aMkV[\x90P\x91\x90PV[\x7Fnot pulling\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aM\xDF`\x0B\x83aAEV[\x91PaM\xEA\x82aM\xABV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaN\x0C\x81aM\xD3V[\x90P\x91\x90PV[_aN\x1D\x82aBuV[\x91P_\x82\x03aN/WaN.aA\xBDV[[`\x01\x82\x03\x90P\x91\x90PV[\x7Finvalid address\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aNn`\x0F\x83aAEV[\x91PaNy\x82aN:V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaN\x9B\x81aNbV[\x90P\x91\x90PV[\x7Foperator doesn't exist\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aN\xD6`\x16\x83aAEV[\x91PaN\xE1\x82aN\xA2V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaO\x03\x81aN\xCAV[\x90P\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`1`\x04R`$_\xFD[\x7Ftoo many operators\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aOk`\x12\x83aAEV[\x91PaOv\x82aO7V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaO\x98\x81aO_V[\x90P\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`A`\x04R`$_\xFD[_\x81\x90P\x81_R` _ \x90P\x91\x90PV[_` `\x1F\x83\x01\x04\x90P\x91\x90PV[_\x82\x82\x1B\x90P\x92\x91PPV[_`\x08\x83\x02aP(\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82aO\xEDV[aP2\x86\x83aO\xEDV[\x95P\x80\x19\x84\x16\x93P\x80\x86\x16\x84\x17\x92PPP\x93\x92PPPV[_aPdaP_aPZ\x84a;\x03V[aB\xD9V[a;\x03V[\x90P\x91\x90PV[_\x81\x90P\x91\x90PV[aP}\x83aPJV[aP\x91aP\x89\x82aPkV[\x84\x84TaO\xF9V[\x82UPPPPV[__\x90P\x90V[aP\xA8aP\x99V[aP\xB3\x81\x84\x84aPtV[PPPV[[\x81\x81\x10\x15aP\xD6WaP\xCB_\x82aP\xA0V[`\x01\x81\x01\x90PaP\xB9V[PPV[`\x1F\x82\x11\x15aQ\x1BWaP\xEC\x81aO\xCCV[aP\xF5\x84aO\xDEV[\x81\x01` \x85\x10\x15aQ\x04W\x81\x90P[aQ\x18aQ\x10\x85aO\xDEV[\x83\x01\x82aP\xB8V[PP[PPPV[_\x82\x82\x1C\x90P\x92\x91PPV[_aQ;_\x19\x84`\x08\x02aQ V[\x19\x80\x83\x16\x91PP\x92\x91PPV[_aQS\x83\x83aQ,V[\x91P\x82`\x02\x02\x82\x17\x90P\x92\x91PPV[aQl\x82a;\x1BV[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15aQ\x85WaQ\x84aO\x9FV[[aQ\x8F\x82TaDbV[aQ\x9A\x82\x82\x85aP\xDAV[_` \x90P`\x1F\x83\x11`\x01\x81\x14aQ\xCBW_\x84\x15aQ\xB9W\x82\x87\x01Q\x90P[aQ\xC3\x85\x82aQHV[\x86UPaR*V[`\x1F\x19\x84\x16aQ\xD9\x86aO\xCCV[_[\x82\x81\x10\x15aR\0W\x84\x89\x01Q\x82U`\x01\x82\x01\x91P` \x85\x01\x94P` \x81\x01\x90PaQ\xDBV[\x86\x83\x10\x15aR\x1DW\x84\x89\x01QaR\x19`\x1F\x89\x16\x82aQ,V[\x83UP[`\x01`\x02\x88\x02\x01\x88UPPP[PPPPPPV[\x7Fnot in progress\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aRf`\x0F\x83aAEV[\x91PaRq\x82aR2V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaR\x93\x81aRZV[\x90P\x91\x90PV[\x7Fdata pull in progress\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aR\xCE`\x15\x83aAEV[\x91PaR\xD9\x82aR\x9AV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaR\xFB\x81aR\xC2V[\x90P\x91\x90PV[__\xFD[aS\x0F\x82a;CV[\x81\x01\x81\x81\x10g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x17\x15aS.WaS-aO\x9FV[[\x80`@RPPPV[_aS@a9\xAFV[\x90PaSL\x82\x82aS\x06V[\x91\x90PV[__\xFD[__\xFD[_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15aSsWaSraO\x9FV[[aS|\x82a;CV[\x90P` \x81\x01\x90P\x91\x90PV[_aS\x9BaS\x96\x84aSYV[aS7V[\x90P\x82\x81R` \x81\x01\x84\x84\x84\x01\x11\x15aS\xB7WaS\xB6aSUV[[aS\xC2\x84\x82\x85aE\xADV[P\x93\x92PPPV[_\x82`\x1F\x83\x01\x12aS\xDEWaS\xDDa?gV[[\x815aS\xEE\x84\x82` \x86\x01aS\x89V[\x91PP\x92\x91PPV[_`@\x82\x84\x03\x12\x15aT\x0CWaT\x0BaS\x02V[[aT\x16`@aS7V[\x90P_aT%\x84\x82\x85\x01aA\x06V[_\x83\x01RP` \x82\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15aTHWaTGaSQV[[aTT\x84\x82\x85\x01aS\xCAV[` \x83\x01RP\x92\x91PPV[_aTk6\x83aS\xF7V[\x90P\x91\x90PV[_aT|\x82a;\x03V[\x91P\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x03aT\xAEWaT\xADaA\xBDV[[`\x01\x82\x01\x90P\x91\x90PV[\x7Ftoo many nodes\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aT\xED`\x0E\x83aAEV[\x91PaT\xF8\x82aT\xB9V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaU\x1A\x81aT\xE1V[\x90P\x91\x90PV[\x7Ftoo few operators\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aUU`\x11\x83aAEV[\x91PaU`\x82aU!V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaU\x82\x81aUIV[\x90P\x91\x90PV[\x7Fmigration already in progress\0\0\0_\x82\x01RPV[_aU\xBD`\x1D\x83aAEV[\x91PaU\xC8\x82aU\x89V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaU\xEA\x81aU\xB1V[\x90P\x91\x90PV[\x7Fnothing to do\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aV%`\r\x83aAEV[\x91PaV0\x82aU\xF1V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaVR\x81aV\x19V[\x90P\x91\x90PV[_aVc\x82aBuV[\x91P`\xFF\x82\x03aVvWaVuaA\xBDV[[`\x01\x82\x01\x90P\x91\x90PV[_\x815aV\x8D\x81a@\x9BV[\x80\x91PP\x91\x90PV[_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFFaV\xB5\x84aB\xACV[\x93P\x80\x19\x83\x16\x92P\x80\x84\x16\x83\x17\x91PP\x92\x91PPV[_aV\xE5aV\xE0aV\xDB\x84a:\x9BV[aB\xD9V[a:\x9BV[\x90P\x91\x90PV[_aV\xF6\x82aV\xCBV[\x90P\x91\x90PV[_aW\x07\x82aV\xECV[\x90P\x91\x90PV[_\x81\x90P\x91\x90PV[aW \x82aV\xFDV[aW3aW,\x82aW\x0EV[\x83TaV\x96V[\x82UPPPV[_\x825`\x01`@\x03\x836\x03\x03\x81\x12aWUWaWTaG?V[[\x80\x83\x01\x91PP\x92\x91PPV[_\x81T\x90P\x91\x90PV[_aWu\x82a;\x03V[\x91PaW\x80\x83a;\x03V[\x92P\x82\x82\x02aW\x8E\x81a;\x03V[\x91P\x82\x82\x04\x84\x14\x83\x15\x17aW\xA5WaW\xA4aA\xBDV[[P\x92\x91PPV[_\x81\x90PaW\xBB\x82`\x02aWkV[\x90P\x91\x90PV[_\x81\x90P\x81_R` _ \x90P\x91\x90PV[aX\x04\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x83` \x03`\x08\x02aQ V[\x81T\x81\x16\x82UPPPV[aX\x18\x81aO\xCCV[aX#\x83\x82TaQHV[\x80\x83U_\x82UPPPPV[` \x84\x10_\x81\x14aX\x89W`\x1F\x84\x11`\x01\x81\x14aXWWaXP\x86\x85aQHV[\x83UaX\x83V[aX`\x83aO\xCCV[aXwaXl\x87aO\xDEV[\x82\x01`\x01\x83\x01aP\xB8V[aX\x81\x87\x85aX\x0FV[P[PaX\xD6V[aX\x92\x82aO\xCCV[aX\x9B\x86aO\xDEV[\x81\x01`\x1F\x87\x16\x80\x15aX\xB5WaX\xB4\x81`\x01\x84\x03aW\xD4V[[aX\xC9aX\xC1\x88aO\xDEV[\x84\x01\x83aP\xB8V[`\x01\x88`\x02\x02\x17\x85UPPP[PPPPPV[h\x01\0\0\0\0\0\0\0\0\x84\x11\x15aX\xF7WaX\xF6aO\x9FV[[` \x83\x10_\x81\x14aY@W` \x85\x10_\x81\x14aY\x1EWaY\x17\x86\x85aQHV[\x83UaY:V[\x83`\xFF\x19\x16\x93P\x83aY/\x84aO\xCCV[U`\x01\x86`\x02\x02\x01\x83U[PaYJV[`\x01\x85`\x02\x02\x01\x82U[PPPPPV[\x80TaY\\\x81aDbV[\x80\x84\x11\x15aYqWaYp\x84\x82\x84\x86aX\xDDV[[\x80\x84\x10\x15aY\x86WaY\x85\x84\x82\x84\x86aX/V[[PPPPV[\x81\x81\x10\x15aY\xA9WaY\x9E_\x82aP\xA0V[`\x01\x81\x01\x90PaY\x8CV[PPV[aY\xB7_\x82aYQV[PV[_\x82\x14aY\xCAWaY\xC9aBIV[[aY\xD3\x81aY\xADV[PPV[aY\xE3__\x83\x01aP\xA0V[aY\xF0_`\x01\x83\x01aY\xBAV[PV[_\x82\x14aZ\x03WaZ\x02aBIV[[aZ\x0C\x81aY\xD7V[PPV[[\x81\x81\x10\x15aZ.WaZ#_\x82aY\xF3V[`\x02\x81\x01\x90PaZ\x11V[PPV[\x81\x83\x10\x15aZkWaZC\x82aW\xACV[aZL\x84aW\xACV[aZU\x83aW\xC2V[\x81\x81\x01\x83\x82\x01aZe\x81\x83aZ\x10V[PPPPP[PPPV[h\x01\0\0\0\0\0\0\0\0\x82\x11\x15aZ\x8AWaZ\x89aO\x9FV[[aZ\x93\x81aWaV[\x82\x82UaZ\xA1\x83\x82\x84aZ2V[PPPV[_\x82\x90P\x92\x91PPV[_\x815aZ\xBC\x81a@\xF0V[\x80\x91PP\x91\x90PV[_\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFFaZ\xF0\x84aB\xACV[\x93P\x80\x19\x83\x16\x92P\x80\x84\x16\x83\x17\x91PP\x92\x91PPV[a[\x0F\x82aPJV[a[\"a[\x1B\x82aPkV[\x83TaZ\xC5V[\x82UPPPV[__\x835`\x01` \x03\x846\x03\x03\x81\x12a[EWa[DaG?V[[\x80\x84\x01\x92P\x825\x91Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15a[gWa[faGCV[[` \x83\x01\x92P`\x01\x82\x026\x03\x83\x13\x15a[\x83Wa[\x82aGGV[[P\x92P\x92\x90PV[_\x82\x90P\x92\x91PPV[a[\x9F\x83\x83a[\x8BV[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a[\xB8Wa[\xB7aO\x9FV[[a[\xC2\x82TaDbV[a[\xCD\x82\x82\x85aP\xDAV[_`\x1F\x83\x11`\x01\x81\x14a[\xFAW_\x84\x15a[\xE8W\x82\x87\x015\x90P[a[\xF2\x85\x82aQHV[\x86UPa\\YV[`\x1F\x19\x84\x16a\\\x08\x86aO\xCCV[_[\x82\x81\x10\x15a\\/W\x84\x89\x015\x82U`\x01\x82\x01\x91P` \x85\x01\x94P` \x81\x01\x90Pa\\\nV[\x86\x83\x10\x15a\\LW\x84\x89\x015a\\H`\x1F\x89\x16\x82aQ,V[\x83UP[`\x01`\x02\x88\x02\x01\x88UPPP[PPPPPPPV[a\\m\x83\x83\x83a[\x95V[PPPV[_\x81\x01_\x83\x01\x80a\\\x82\x81aZ\xB0V[\x90Pa\\\x8E\x81\x84a[\x06V[PPP`\x01\x81\x01` \x83\x01a\\\xA3\x81\x85a[)V[a\\\xAE\x81\x83\x86a\\bV[PPPPPPV[a\\\xC0\x82\x82a\\rV[PPV[a\\\xCE\x83\x83aZ\xA6V[a\\\xD8\x81\x83aZpV[a\\\xE1\x83aI\xB3V[a\\\xEA\x83aW\xC2V[_[\x83\x81\x10\x15a] Wa\\\xFE\x83\x87aW:V[a]\x08\x81\x84a\\\xB6V[` \x84\x01\x93P`\x02\x83\x01\x92PP`\x01\x81\x01\x90Pa\\\xECV[PPPPPPPV[a]4\x83\x83\x83a\\\xC4V[PPPV[_\x81\x01_\x83\x01\x80a]I\x81aV\x81V[\x90Pa]U\x81\x84aW\x17V[PPP`\x01\x81\x01` \x83\x01a]j\x81\x85aGrV[a]u\x81\x83\x86a])V[PPPP`\x02\x81\x01`@\x83\x01a]\x8B\x81\x85a[)V[a]\x96\x81\x83\x86a\\bV[PPPPPPV[a]\xA8\x82\x82a]9V[PPV[\x7Fanother maintenance in progress\0_\x82\x01RPV[_a]\xE0`\x1F\x83aAEV[\x91Pa]\xEB\x82a]\xACV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra^\r\x81a]\xD4V[\x90P\x91\x90PV[\x7Finvalid id\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a^H`\n\x83aAEV[\x91Pa^S\x82a^\x14V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra^u\x81a^::RustType, + #[allow(missing_docs)] + pub migration: ::RustType, + #[allow(missing_docs)] + pub maintenance: ::RustType, + #[allow(missing_docs)] + pub keyspaceVersion: u64, + #[allow(missing_docs)] + pub version: u128, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + NodeOperatorsView, + MigrationView, + Maintenance, + alloy::sol_types::sol_data::Uint<64>, + alloy::sol_types::sol_data::Uint<128>, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + ::RustType, + ::RustType, + ::RustType, + u64, + u128, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: ClusterView) -> Self { + ( + value.operators, + value.migration, + value.maintenance, + value.keyspaceVersion, + value.version, + ) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for ClusterView { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + operators: tuple.0, + migration: tuple.1, + maintenance: tuple.2, + keyspaceVersion: tuple.3, + version: tuple.4, + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolValue for ClusterView { + type SolType = Self; + } + #[automatically_derived] + impl alloy_sol_types::private::SolTypeValue for ClusterView { + #[inline] + fn stv_to_tokens(&self) -> ::Token<'_> { + ( + ::tokenize(&self.operators), + ::tokenize(&self.migration), + ::tokenize(&self.maintenance), + as alloy_sol_types::SolType>::tokenize( + &self.keyspaceVersion, + ), + as alloy_sol_types::SolType>::tokenize( + &self.version, + ), + ) + } + #[inline] + fn stv_abi_encoded_size(&self) -> usize { + if let Some(size) = ::ENCODED_SIZE { + return size; + } + let tuple = + as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encoded_size(&tuple) + } + #[inline] + fn stv_eip712_data_word(&self) -> alloy_sol_types::Word { + ::eip712_hash_struct(self) + } + #[inline] + fn stv_abi_encode_packed_to(&self, out: &mut alloy_sol_types::private::Vec) { + let tuple = + as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encode_packed_to( + &tuple, out, + ) + } + #[inline] + fn stv_abi_packed_encoded_size(&self) -> usize { + if let Some(size) = ::PACKED_ENCODED_SIZE { + return size; + } + let tuple = + as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_packed_encoded_size( + &tuple, + ) + } + } + #[automatically_derived] + impl alloy_sol_types::SolType for ClusterView { + type RustType = Self; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SOL_NAME: &'static str = ::NAME; + const ENCODED_SIZE: Option = + as alloy_sol_types::SolType>::ENCODED_SIZE; + const PACKED_ENCODED_SIZE: Option = + as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; + #[inline] + fn valid_token(token: &Self::Token<'_>) -> bool { + as alloy_sol_types::SolType>::valid_token(token) + } + #[inline] + fn detokenize(token: Self::Token<'_>) -> Self::RustType { + let tuple = as alloy_sol_types::SolType>::detokenize(token); + >>::from(tuple) + } + } + #[automatically_derived] + impl alloy_sol_types::SolStruct for ClusterView { + const NAME: &'static str = "ClusterView"; + #[inline] + fn eip712_root_type() -> alloy_sol_types::private::Cow<'static, str> { + alloy_sol_types::private::Cow::Borrowed( + "ClusterView(NodeOperatorsView operators,MigrationView migration,Maintenance \ + maintenance,uint64 keyspaceVersion,uint128 version)", + ) + } + #[inline] + fn eip712_components( + ) -> alloy_sol_types::private::Vec> + { + let mut components = alloy_sol_types::private::Vec::with_capacity(3); + components + .push(::eip712_root_type()); + components + .extend(::eip712_components()); + components.push(::eip712_root_type()); + components + .extend(::eip712_components()); + components.push(::eip712_root_type()); + components.extend(::eip712_components()); + components + } + #[inline] + fn eip712_encode_data(&self) -> alloy_sol_types::private::Vec { + [ + ::eip712_data_word( + &self.operators, + ) + .0, + ::eip712_data_word( + &self.migration, + ) + .0, + ::eip712_data_word( + &self.maintenance, + ) + .0, + as alloy_sol_types::SolType>::eip712_data_word( + &self.keyspaceVersion, + ) + .0, + as alloy_sol_types::SolType>::eip712_data_word(&self.version) + .0, + ] + .concat() + } + } + #[automatically_derived] + impl alloy_sol_types::EventTopic for ClusterView { + #[inline] + fn topic_preimage_length(rust: &Self::RustType) -> usize { + 0usize + + ::topic_preimage_length( + &rust.operators, + ) + + ::topic_preimage_length( + &rust.migration, + ) + + ::topic_preimage_length( + &rust.maintenance, + ) + + as alloy_sol_types::EventTopic>::topic_preimage_length( + &rust.keyspaceVersion, + ) + + as alloy_sol_types::EventTopic>::topic_preimage_length( + &rust.version, + ) + } + #[inline] + fn encode_topic_preimage( + rust: &Self::RustType, + out: &mut alloy_sol_types::private::Vec, + ) { + out.reserve(::topic_preimage_length(rust)); + ::encode_topic_preimage( + &rust.operators, + out, + ); + ::encode_topic_preimage( + &rust.migration, + out, + ); + ::encode_topic_preimage( + &rust.maintenance, + out, + ); + as alloy_sol_types::EventTopic>::encode_topic_preimage( + &rust.keyspaceVersion, + out, + ); + as alloy_sol_types::EventTopic>::encode_topic_preimage( + &rust.version, + out, + ); + } + #[inline] + fn encode_topic(rust: &Self::RustType) -> alloy_sol_types::abi::token::WordToken { + let mut out = alloy_sol_types::private::Vec::new(); + ::encode_topic_preimage(rust, &mut out); + alloy_sol_types::abi::token::WordToken(alloy_sol_types::private::keccak256(out)) + } + } + }; + /// ```solidity + /// struct Maintenance { address slot; } + /// ``` + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct Maintenance { + #[allow(missing_docs)] + pub slot: alloy::sol_types::private::Address, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Address,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::Address,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: Maintenance) -> Self { + (value.slot,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for Maintenance { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { slot: tuple.0 } + } + } + #[automatically_derived] + impl alloy_sol_types::SolValue for Maintenance { + type SolType = Self; + } + #[automatically_derived] + impl alloy_sol_types::private::SolTypeValue for Maintenance { + #[inline] + fn stv_to_tokens(&self) -> ::Token<'_> { + ( + ::tokenize( + &self.slot, + ), + ) + } + #[inline] + fn stv_abi_encoded_size(&self) -> usize { + if let Some(size) = ::ENCODED_SIZE { + return size; + } + let tuple = + as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encoded_size(&tuple) + } + #[inline] + fn stv_eip712_data_word(&self) -> alloy_sol_types::Word { + ::eip712_hash_struct(self) + } + #[inline] + fn stv_abi_encode_packed_to(&self, out: &mut alloy_sol_types::private::Vec) { + let tuple = + as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encode_packed_to( + &tuple, out, + ) + } + #[inline] + fn stv_abi_packed_encoded_size(&self) -> usize { + if let Some(size) = ::PACKED_ENCODED_SIZE { + return size; + } + let tuple = + as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_packed_encoded_size( + &tuple, + ) + } + } + #[automatically_derived] + impl alloy_sol_types::SolType for Maintenance { + type RustType = Self; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SOL_NAME: &'static str = ::NAME; + const ENCODED_SIZE: Option = + as alloy_sol_types::SolType>::ENCODED_SIZE; + const PACKED_ENCODED_SIZE: Option = + as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; + #[inline] + fn valid_token(token: &Self::Token<'_>) -> bool { + as alloy_sol_types::SolType>::valid_token(token) + } + #[inline] + fn detokenize(token: Self::Token<'_>) -> Self::RustType { + let tuple = as alloy_sol_types::SolType>::detokenize(token); + >>::from(tuple) + } + } + #[automatically_derived] + impl alloy_sol_types::SolStruct for Maintenance { + const NAME: &'static str = "Maintenance"; + #[inline] + fn eip712_root_type() -> alloy_sol_types::private::Cow<'static, str> { + alloy_sol_types::private::Cow::Borrowed("Maintenance(address slot)") + } + #[inline] + fn eip712_components( + ) -> alloy_sol_types::private::Vec> + { + alloy_sol_types::private::Vec::new() + } + #[inline] + fn eip712_encode_type() -> alloy_sol_types::private::Cow<'static, str> { + ::eip712_root_type() + } + #[inline] + fn eip712_encode_data(&self) -> alloy_sol_types::private::Vec { + ::eip712_data_word( + &self.slot, + ) + .0 + .to_vec() + } + } + #[automatically_derived] + impl alloy_sol_types::EventTopic for Maintenance { + #[inline] + fn topic_preimage_length(rust: &Self::RustType) -> usize { + 0usize + + ::topic_preimage_length( + &rust.slot, + ) + } + #[inline] + fn encode_topic_preimage( + rust: &Self::RustType, + out: &mut alloy_sol_types::private::Vec, + ) { + out.reserve(::topic_preimage_length(rust)); + ::encode_topic_preimage( + &rust.slot, + out, + ); + } + #[inline] + fn encode_topic(rust: &Self::RustType) -> alloy_sol_types::abi::token::WordToken { + let mut out = alloy_sol_types::private::Vec::new(); + ::encode_topic_preimage(rust, &mut out); + alloy_sol_types::abi::token::WordToken(alloy_sol_types::private::keccak256(out)) + } + } + }; + /// ```solidity + /// struct MigrationView { address[] operatorsToRemove; NodeOperatorView[] operatorsToAdd; address[] pullingOperators; } + /// ``` + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct MigrationView { + #[allow(missing_docs)] + pub operatorsToRemove: alloy::sol_types::private::Vec, + #[allow(missing_docs)] + pub operatorsToAdd: alloy::sol_types::private::Vec< + ::RustType, + >, + #[allow(missing_docs)] + pub pullingOperators: alloy::sol_types::private::Vec, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::Array, + alloy::sol_types::sol_data::Array, + alloy::sol_types::sol_data::Array, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::Vec, + alloy::sol_types::private::Vec< + ::RustType, + >, + alloy::sol_types::private::Vec, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: MigrationView) -> Self { + ( + value.operatorsToRemove, + value.operatorsToAdd, + value.pullingOperators, + ) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for MigrationView { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + operatorsToRemove: tuple.0, + operatorsToAdd: tuple.1, + pullingOperators: tuple.2, + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolValue for MigrationView { + type SolType = Self; + } + #[automatically_derived] + impl alloy_sol_types::private::SolTypeValue for MigrationView { + #[inline] + fn stv_to_tokens(&self) -> ::Token<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.operatorsToRemove), + as alloy_sol_types::SolType>::tokenize(&self.operatorsToAdd), + as alloy_sol_types::SolType>::tokenize(&self.pullingOperators), + ) + } + #[inline] + fn stv_abi_encoded_size(&self) -> usize { + if let Some(size) = ::ENCODED_SIZE { + return size; + } + let tuple = + as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encoded_size(&tuple) + } + #[inline] + fn stv_eip712_data_word(&self) -> alloy_sol_types::Word { + ::eip712_hash_struct(self) + } + #[inline] + fn stv_abi_encode_packed_to(&self, out: &mut alloy_sol_types::private::Vec) { + let tuple = + as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encode_packed_to( + &tuple, out, + ) + } + #[inline] + fn stv_abi_packed_encoded_size(&self) -> usize { + if let Some(size) = ::PACKED_ENCODED_SIZE { + return size; + } + let tuple = + as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_packed_encoded_size( + &tuple, + ) + } + } + #[automatically_derived] + impl alloy_sol_types::SolType for MigrationView { + type RustType = Self; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SOL_NAME: &'static str = ::NAME; + const ENCODED_SIZE: Option = + as alloy_sol_types::SolType>::ENCODED_SIZE; + const PACKED_ENCODED_SIZE: Option = + as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; + #[inline] + fn valid_token(token: &Self::Token<'_>) -> bool { + as alloy_sol_types::SolType>::valid_token(token) + } + #[inline] + fn detokenize(token: Self::Token<'_>) -> Self::RustType { + let tuple = as alloy_sol_types::SolType>::detokenize(token); + >>::from(tuple) + } + } + #[automatically_derived] + impl alloy_sol_types::SolStruct for MigrationView { + const NAME: &'static str = "MigrationView"; + #[inline] + fn eip712_root_type() -> alloy_sol_types::private::Cow<'static, str> { + alloy_sol_types::private::Cow::Borrowed( + "MigrationView(address[] operatorsToRemove,NodeOperatorView[] \ + operatorsToAdd,address[] pullingOperators)", + ) + } + #[inline] + fn eip712_components( + ) -> alloy_sol_types::private::Vec> + { + let mut components = alloy_sol_types::private::Vec::with_capacity(1); + components + .push(::eip712_root_type()); + components + .extend(::eip712_components()); + components + } + #[inline] + fn eip712_encode_data(&self) -> alloy_sol_types::private::Vec { + [ + as alloy_sol_types::SolType>::eip712_data_word( + &self.operatorsToRemove, + ) + .0, + as alloy_sol_types::SolType>::eip712_data_word( + &self.operatorsToAdd, + ) + .0, + as alloy_sol_types::SolType>::eip712_data_word( + &self.pullingOperators, + ) + .0, + ] + .concat() + } + } + #[automatically_derived] + impl alloy_sol_types::EventTopic for MigrationView { + #[inline] + fn topic_preimage_length(rust: &Self::RustType) -> usize { + 0usize + + as alloy_sol_types::EventTopic>::topic_preimage_length( + &rust.operatorsToRemove, + ) + + as alloy_sol_types::EventTopic>::topic_preimage_length( + &rust.operatorsToAdd, + ) + + as alloy_sol_types::EventTopic>::topic_preimage_length( + &rust.pullingOperators, + ) + } + #[inline] + fn encode_topic_preimage( + rust: &Self::RustType, + out: &mut alloy_sol_types::private::Vec, + ) { + out.reserve(::topic_preimage_length(rust)); + as alloy_sol_types::EventTopic>::encode_topic_preimage( + &rust.operatorsToRemove, + out, + ); + as alloy_sol_types::EventTopic>::encode_topic_preimage( + &rust.operatorsToAdd, + out, + ); + as alloy_sol_types::EventTopic>::encode_topic_preimage( + &rust.pullingOperators, + out, + ); + } + #[inline] + fn encode_topic(rust: &Self::RustType) -> alloy_sol_types::abi::token::WordToken { + let mut out = alloy_sol_types::private::Vec::new(); + ::encode_topic_preimage(rust, &mut out); + alloy_sol_types::abi::token::WordToken(alloy_sol_types::private::keccak256(out)) + } + } + }; + /// ```solidity + /// struct Node { uint256 id; bytes data; } + /// ``` + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct Node { + #[allow(missing_docs)] + pub id: alloy::sol_types::private::primitives::aliases::U256, + #[allow(missing_docs)] + pub data: alloy::sol_types::private::Bytes, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::Uint<256>, + alloy::sol_types::sol_data::Bytes, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::primitives::aliases::U256, + alloy::sol_types::private::Bytes, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: Node) -> Self { + (value.id, value.data) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for Node { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + id: tuple.0, + data: tuple.1, + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolValue for Node { + type SolType = Self; + } + #[automatically_derived] + impl alloy_sol_types::private::SolTypeValue for Node { + #[inline] + fn stv_to_tokens(&self) -> ::Token<'_> { + ( + as alloy_sol_types::SolType>::tokenize( + &self.id, + ), + ::tokenize( + &self.data, + ), + ) + } + #[inline] + fn stv_abi_encoded_size(&self) -> usize { + if let Some(size) = ::ENCODED_SIZE { + return size; + } + let tuple = + as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encoded_size(&tuple) + } + #[inline] + fn stv_eip712_data_word(&self) -> alloy_sol_types::Word { + ::eip712_hash_struct(self) + } + #[inline] + fn stv_abi_encode_packed_to(&self, out: &mut alloy_sol_types::private::Vec) { + let tuple = + as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encode_packed_to( + &tuple, out, + ) + } + #[inline] + fn stv_abi_packed_encoded_size(&self) -> usize { + if let Some(size) = ::PACKED_ENCODED_SIZE { + return size; + } + let tuple = + as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_packed_encoded_size( + &tuple, + ) + } + } + #[automatically_derived] + impl alloy_sol_types::SolType for Node { + type RustType = Self; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SOL_NAME: &'static str = ::NAME; + const ENCODED_SIZE: Option = + as alloy_sol_types::SolType>::ENCODED_SIZE; + const PACKED_ENCODED_SIZE: Option = + as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; + #[inline] + fn valid_token(token: &Self::Token<'_>) -> bool { + as alloy_sol_types::SolType>::valid_token(token) + } + #[inline] + fn detokenize(token: Self::Token<'_>) -> Self::RustType { + let tuple = as alloy_sol_types::SolType>::detokenize(token); + >>::from(tuple) + } + } + #[automatically_derived] + impl alloy_sol_types::SolStruct for Node { + const NAME: &'static str = "Node"; + #[inline] + fn eip712_root_type() -> alloy_sol_types::private::Cow<'static, str> { + alloy_sol_types::private::Cow::Borrowed("Node(uint256 id,bytes data)") + } + #[inline] + fn eip712_components( + ) -> alloy_sol_types::private::Vec> + { + alloy_sol_types::private::Vec::new() + } + #[inline] + fn eip712_encode_type() -> alloy_sol_types::private::Cow<'static, str> { + ::eip712_root_type() + } + #[inline] + fn eip712_encode_data(&self) -> alloy_sol_types::private::Vec { + [ + as alloy_sol_types::SolType>::eip712_data_word(&self.id) + .0, + ::eip712_data_word( + &self.data, + ) + .0, + ] + .concat() + } + } + #[automatically_derived] + impl alloy_sol_types::EventTopic for Node { + #[inline] + fn topic_preimage_length(rust: &Self::RustType) -> usize { + 0usize + + as alloy_sol_types::EventTopic>::topic_preimage_length(&rust.id) + + ::topic_preimage_length( + &rust.data, + ) + } + #[inline] + fn encode_topic_preimage( + rust: &Self::RustType, + out: &mut alloy_sol_types::private::Vec, + ) { + out.reserve(::topic_preimage_length(rust)); + as alloy_sol_types::EventTopic>::encode_topic_preimage(&rust.id, out); + ::encode_topic_preimage( + &rust.data, + out, + ); + } + #[inline] + fn encode_topic(rust: &Self::RustType) -> alloy_sol_types::abi::token::WordToken { + let mut out = alloy_sol_types::private::Vec::new(); + ::encode_topic_preimage(rust, &mut out); + alloy_sol_types::abi::token::WordToken(alloy_sol_types::private::keccak256(out)) + } + } + }; + /// ```solidity + /// struct NodeOperatorView { address addr; Node[] nodes; bytes data; } + /// ``` + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct NodeOperatorView { + #[allow(missing_docs)] + pub addr: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub nodes: alloy::sol_types::private::Vec<::RustType>, + #[allow(missing_docs)] + pub data: alloy::sol_types::private::Bytes, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Array, + alloy::sol_types::sol_data::Bytes, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::Address, + alloy::sol_types::private::Vec<::RustType>, + alloy::sol_types::private::Bytes, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: NodeOperatorView) -> Self { + (value.addr, value.nodes, value.data) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for NodeOperatorView { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + addr: tuple.0, + nodes: tuple.1, + data: tuple.2, + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolValue for NodeOperatorView { + type SolType = Self; + } + #[automatically_derived] + impl alloy_sol_types::private::SolTypeValue for NodeOperatorView { + #[inline] + fn stv_to_tokens(&self) -> ::Token<'_> { + ( + ::tokenize( + &self.addr, + ), + as alloy_sol_types::SolType>::tokenize( + &self.nodes, + ), + ::tokenize( + &self.data, + ), + ) + } + #[inline] + fn stv_abi_encoded_size(&self) -> usize { + if let Some(size) = ::ENCODED_SIZE { + return size; + } + let tuple = + as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encoded_size(&tuple) + } + #[inline] + fn stv_eip712_data_word(&self) -> alloy_sol_types::Word { + ::eip712_hash_struct(self) + } + #[inline] + fn stv_abi_encode_packed_to(&self, out: &mut alloy_sol_types::private::Vec) { + let tuple = + as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encode_packed_to( + &tuple, out, + ) + } + #[inline] + fn stv_abi_packed_encoded_size(&self) -> usize { + if let Some(size) = ::PACKED_ENCODED_SIZE { + return size; + } + let tuple = + as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_packed_encoded_size( + &tuple, + ) + } + } + #[automatically_derived] + impl alloy_sol_types::SolType for NodeOperatorView { + type RustType = Self; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SOL_NAME: &'static str = ::NAME; + const ENCODED_SIZE: Option = + as alloy_sol_types::SolType>::ENCODED_SIZE; + const PACKED_ENCODED_SIZE: Option = + as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; + #[inline] + fn valid_token(token: &Self::Token<'_>) -> bool { + as alloy_sol_types::SolType>::valid_token(token) + } + #[inline] + fn detokenize(token: Self::Token<'_>) -> Self::RustType { + let tuple = as alloy_sol_types::SolType>::detokenize(token); + >>::from(tuple) + } + } + #[automatically_derived] + impl alloy_sol_types::SolStruct for NodeOperatorView { + const NAME: &'static str = "NodeOperatorView"; + #[inline] + fn eip712_root_type() -> alloy_sol_types::private::Cow<'static, str> { + alloy_sol_types::private::Cow::Borrowed( + "NodeOperatorView(address addr,Node[] nodes,bytes data)", + ) + } + #[inline] + fn eip712_components( + ) -> alloy_sol_types::private::Vec> + { + let mut components = alloy_sol_types::private::Vec::with_capacity(1); + components.push(::eip712_root_type()); + components.extend(::eip712_components()); + components + } + #[inline] + fn eip712_encode_data(&self) -> alloy_sol_types::private::Vec { + [ + ::eip712_data_word( + &self.addr, + ) + .0, + as alloy_sol_types::SolType>::eip712_data_word(&self.nodes) + .0, + ::eip712_data_word( + &self.data, + ) + .0, + ] + .concat() + } + } + #[automatically_derived] + impl alloy_sol_types::EventTopic for NodeOperatorView { + #[inline] + fn topic_preimage_length(rust: &Self::RustType) -> usize { + 0usize + + ::topic_preimage_length( + &rust.addr, + ) + + as alloy_sol_types::EventTopic>::topic_preimage_length(&rust.nodes) + + ::topic_preimage_length( + &rust.data, + ) + } + #[inline] + fn encode_topic_preimage( + rust: &Self::RustType, + out: &mut alloy_sol_types::private::Vec, + ) { + out.reserve(::topic_preimage_length(rust)); + ::encode_topic_preimage( + &rust.addr, + out, + ); + as alloy_sol_types::EventTopic>::encode_topic_preimage( + &rust.nodes, + out, + ); + ::encode_topic_preimage( + &rust.data, + out, + ); + } + #[inline] + fn encode_topic(rust: &Self::RustType) -> alloy_sol_types::abi::token::WordToken { + let mut out = alloy_sol_types::private::Vec::new(); + ::encode_topic_preimage(rust, &mut out); + alloy_sol_types::abi::token::WordToken(alloy_sol_types::private::keccak256(out)) + } + } + }; + /// ```solidity + /// struct NodeOperatorsView { NodeOperatorView[] slots; } + /// ``` + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct NodeOperatorsView { + #[allow(missing_docs)] + pub slots: alloy::sol_types::private::Vec< + ::RustType, + >, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Array,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::Vec< + ::RustType, + >, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: NodeOperatorsView) -> Self { + (value.slots,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for NodeOperatorsView { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { slots: tuple.0 } + } + } + #[automatically_derived] + impl alloy_sol_types::SolValue for NodeOperatorsView { + type SolType = Self; + } + #[automatically_derived] + impl alloy_sol_types::private::SolTypeValue for NodeOperatorsView { + #[inline] + fn stv_to_tokens(&self) -> ::Token<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.slots), + ) + } + #[inline] + fn stv_abi_encoded_size(&self) -> usize { + if let Some(size) = ::ENCODED_SIZE { + return size; + } + let tuple = + as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encoded_size(&tuple) + } + #[inline] + fn stv_eip712_data_word(&self) -> alloy_sol_types::Word { + ::eip712_hash_struct(self) + } + #[inline] + fn stv_abi_encode_packed_to(&self, out: &mut alloy_sol_types::private::Vec) { + let tuple = + as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encode_packed_to( + &tuple, out, + ) + } + #[inline] + fn stv_abi_packed_encoded_size(&self) -> usize { + if let Some(size) = ::PACKED_ENCODED_SIZE { + return size; + } + let tuple = + as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_packed_encoded_size( + &tuple, + ) + } + } + #[automatically_derived] + impl alloy_sol_types::SolType for NodeOperatorsView { + type RustType = Self; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SOL_NAME: &'static str = ::NAME; + const ENCODED_SIZE: Option = + as alloy_sol_types::SolType>::ENCODED_SIZE; + const PACKED_ENCODED_SIZE: Option = + as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; + #[inline] + fn valid_token(token: &Self::Token<'_>) -> bool { + as alloy_sol_types::SolType>::valid_token(token) + } + #[inline] + fn detokenize(token: Self::Token<'_>) -> Self::RustType { + let tuple = as alloy_sol_types::SolType>::detokenize(token); + >>::from(tuple) + } + } + #[automatically_derived] + impl alloy_sol_types::SolStruct for NodeOperatorsView { + const NAME: &'static str = "NodeOperatorsView"; + #[inline] + fn eip712_root_type() -> alloy_sol_types::private::Cow<'static, str> { + alloy_sol_types::private::Cow::Borrowed( + "NodeOperatorsView(NodeOperatorView[] slots)", + ) + } + #[inline] + fn eip712_components( + ) -> alloy_sol_types::private::Vec> + { + let mut components = alloy_sol_types::private::Vec::with_capacity(1); + components + .push(::eip712_root_type()); + components + .extend(::eip712_components()); + components + } + #[inline] + fn eip712_encode_data(&self) -> alloy_sol_types::private::Vec { + as alloy_sol_types::SolType>::eip712_data_word(&self.slots) + .0 + .to_vec() + } + } + #[automatically_derived] + impl alloy_sol_types::EventTopic for NodeOperatorsView { + #[inline] + fn topic_preimage_length(rust: &Self::RustType) -> usize { + 0usize + + as alloy_sol_types::EventTopic>::topic_preimage_length(&rust.slots) + } + #[inline] + fn encode_topic_preimage( + rust: &Self::RustType, + out: &mut alloy_sol_types::private::Vec, + ) { + out.reserve(::topic_preimage_length(rust)); + as alloy_sol_types::EventTopic>::encode_topic_preimage( + &rust.slots, + out, + ); + } + #[inline] + fn encode_topic(rust: &Self::RustType) -> alloy_sol_types::abi::token::WordToken { + let mut out = alloy_sol_types::private::Vec::new(); + ::encode_topic_preimage(rust, &mut out); + alloy_sol_types::abi::token::WordToken(alloy_sol_types::private::keccak256(out)) + } + } + }; + /// ```solidity + /// struct Settings { uint8 minOperators; uint8 minNodes; } + /// ``` + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct Settings { + #[allow(missing_docs)] + pub minOperators: u8, + #[allow(missing_docs)] + pub minNodes: u8, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::Uint<8>, + alloy::sol_types::sol_data::Uint<8>, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (u8, u8); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: Settings) -> Self { + (value.minOperators, value.minNodes) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for Settings { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + minOperators: tuple.0, + minNodes: tuple.1, + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolValue for Settings { + type SolType = Self; + } + #[automatically_derived] + impl alloy_sol_types::private::SolTypeValue for Settings { + #[inline] + fn stv_to_tokens(&self) -> ::Token<'_> { + ( + as alloy_sol_types::SolType>::tokenize( + &self.minOperators, + ), + as alloy_sol_types::SolType>::tokenize( + &self.minNodes, + ), + ) + } + #[inline] + fn stv_abi_encoded_size(&self) -> usize { + if let Some(size) = ::ENCODED_SIZE { + return size; + } + let tuple = + as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encoded_size(&tuple) + } + #[inline] + fn stv_eip712_data_word(&self) -> alloy_sol_types::Word { + ::eip712_hash_struct(self) + } + #[inline] + fn stv_abi_encode_packed_to(&self, out: &mut alloy_sol_types::private::Vec) { + let tuple = + as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encode_packed_to( + &tuple, out, + ) + } + #[inline] + fn stv_abi_packed_encoded_size(&self) -> usize { + if let Some(size) = ::PACKED_ENCODED_SIZE { + return size; + } + let tuple = + as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_packed_encoded_size( + &tuple, + ) + } + } + #[automatically_derived] + impl alloy_sol_types::SolType for Settings { + type RustType = Self; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SOL_NAME: &'static str = ::NAME; + const ENCODED_SIZE: Option = + as alloy_sol_types::SolType>::ENCODED_SIZE; + const PACKED_ENCODED_SIZE: Option = + as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; + #[inline] + fn valid_token(token: &Self::Token<'_>) -> bool { + as alloy_sol_types::SolType>::valid_token(token) + } + #[inline] + fn detokenize(token: Self::Token<'_>) -> Self::RustType { + let tuple = as alloy_sol_types::SolType>::detokenize(token); + >>::from(tuple) + } + } + #[automatically_derived] + impl alloy_sol_types::SolStruct for Settings { + const NAME: &'static str = "Settings"; + #[inline] + fn eip712_root_type() -> alloy_sol_types::private::Cow<'static, str> { + alloy_sol_types::private::Cow::Borrowed( + "Settings(uint8 minOperators,uint8 minNodes)", + ) + } + #[inline] + fn eip712_components( + ) -> alloy_sol_types::private::Vec> + { + alloy_sol_types::private::Vec::new() + } + #[inline] + fn eip712_encode_type() -> alloy_sol_types::private::Cow<'static, str> { + ::eip712_root_type() + } + #[inline] + fn eip712_encode_data(&self) -> alloy_sol_types::private::Vec { + [ + as alloy_sol_types::SolType>::eip712_data_word(&self.minOperators) + .0, + as alloy_sol_types::SolType>::eip712_data_word(&self.minNodes) + .0, + ] + .concat() + } + } + #[automatically_derived] + impl alloy_sol_types::EventTopic for Settings { + #[inline] + fn topic_preimage_length(rust: &Self::RustType) -> usize { + 0usize + + as alloy_sol_types::EventTopic>::topic_preimage_length( + &rust.minOperators, + ) + + as alloy_sol_types::EventTopic>::topic_preimage_length( + &rust.minNodes, + ) + } + #[inline] + fn encode_topic_preimage( + rust: &Self::RustType, + out: &mut alloy_sol_types::private::Vec, + ) { + out.reserve(::topic_preimage_length(rust)); + as alloy_sol_types::EventTopic>::encode_topic_preimage( + &rust.minOperators, + out, + ); + as alloy_sol_types::EventTopic>::encode_topic_preimage( + &rust.minNodes, + out, + ); + } + #[inline] + fn encode_topic(rust: &Self::RustType) -> alloy_sol_types::abi::token::WordToken { + let mut out = alloy_sol_types::private::Vec::new(); + ::encode_topic_preimage(rust, &mut out); + alloy_sol_types::abi::token::WordToken(alloy_sol_types::private::keccak256(out)) + } + } + }; + /// Event with signature `MaintenanceAborted(uint128)` and selector + /// `0x8fb9cd054d0a022110cced239e908b834e4cd219511856d4eaae3051d932d604`. + /// ```solidity + /// event MaintenanceAborted(uint128 version); + /// ``` + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + #[derive(Clone)] + pub struct MaintenanceAborted { + #[allow(missing_docs)] + pub version: u128, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[automatically_derived] + impl alloy_sol_types::SolEvent for MaintenanceAborted { + type DataTuple<'a> = (alloy::sol_types::sol_data::Uint<128>,); + type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); + const SIGNATURE: &'static str = "MaintenanceAborted(uint128)"; + const SIGNATURE_HASH: alloy_sol_types::private::B256 = + alloy_sol_types::private::B256::new([ + 143u8, 185u8, 205u8, 5u8, 77u8, 10u8, 2u8, 33u8, 16u8, 204u8, 237u8, 35u8, + 158u8, 144u8, 139u8, 131u8, 78u8, 76u8, 210u8, 25u8, 81u8, 24u8, 86u8, 212u8, + 234u8, 174u8, 48u8, 81u8, 217u8, 50u8, 214u8, 4u8, + ]); + const ANONYMOUS: bool = false; + #[allow(unused_variables)] + #[inline] + fn new( + topics: ::RustType, + data: as alloy_sol_types::SolType>::RustType, + ) -> Self { + Self { version: data.0 } + } + #[inline] + fn check_signature( + topics: &::RustType, + ) -> alloy_sol_types::Result<()> { + if topics.0 != Self::SIGNATURE_HASH { + return Err(alloy_sol_types::Error::invalid_event_signature_hash( + Self::SIGNATURE, + topics.0, + Self::SIGNATURE_HASH, + )); + } + Ok(()) + } + #[inline] + fn tokenize_body(&self) -> Self::DataToken<'_> { + ( + as alloy_sol_types::SolType>::tokenize( + &self.version, + ), + ) + } + #[inline] + fn topics(&self) -> ::RustType { + (Self::SIGNATURE_HASH.into(),) + } + #[inline] + fn encode_topics_raw( + &self, + out: &mut [alloy_sol_types::abi::token::WordToken], + ) -> alloy_sol_types::Result<()> { + if out.len() < ::COUNT { + return Err(alloy_sol_types::Error::Overrun); + } + out[0usize] = alloy_sol_types::abi::token::WordToken(Self::SIGNATURE_HASH); + Ok(()) + } + } + #[automatically_derived] + impl alloy_sol_types::private::IntoLogData for MaintenanceAborted { + fn to_log_data(&self) -> alloy_sol_types::private::LogData { + From::from(self) + } + fn into_log_data(self) -> alloy_sol_types::private::LogData { + From::from(&self) + } + } + #[automatically_derived] + impl From<&MaintenanceAborted> for alloy_sol_types::private::LogData { + #[inline] + fn from(this: &MaintenanceAborted) -> alloy_sol_types::private::LogData { + alloy_sol_types::SolEvent::encode_log_data(this) + } + } + }; + /// Event with signature `MaintenanceCompleted(address,uint128)` and + /// selector `0xf91067eb420c28d3124865fc996e6aa9d541b9b4fef9188cb965a6cc6491638e`. + /// ```solidity + /// event MaintenanceCompleted(address operator, uint128 version); + /// ``` + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + #[derive(Clone)] + pub struct MaintenanceCompleted { + #[allow(missing_docs)] + pub operator: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub version: u128, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[automatically_derived] + impl alloy_sol_types::SolEvent for MaintenanceCompleted { + type DataTuple<'a> = ( + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Uint<128>, + ); + type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); + const SIGNATURE: &'static str = "MaintenanceCompleted(address,uint128)"; + const SIGNATURE_HASH: alloy_sol_types::private::B256 = + alloy_sol_types::private::B256::new([ + 249u8, 16u8, 103u8, 235u8, 66u8, 12u8, 40u8, 211u8, 18u8, 72u8, 101u8, 252u8, + 153u8, 110u8, 106u8, 169u8, 213u8, 65u8, 185u8, 180u8, 254u8, 249u8, 24u8, + 140u8, 185u8, 101u8, 166u8, 204u8, 100u8, 145u8, 99u8, 142u8, + ]); + const ANONYMOUS: bool = false; + #[allow(unused_variables)] + #[inline] + fn new( + topics: ::RustType, + data: as alloy_sol_types::SolType>::RustType, + ) -> Self { + Self { + operator: data.0, + version: data.1, + } + } + #[inline] + fn check_signature( + topics: &::RustType, + ) -> alloy_sol_types::Result<()> { + if topics.0 != Self::SIGNATURE_HASH { + return Err(alloy_sol_types::Error::invalid_event_signature_hash( + Self::SIGNATURE, + topics.0, + Self::SIGNATURE_HASH, + )); + } + Ok(()) + } + #[inline] + fn tokenize_body(&self) -> Self::DataToken<'_> { + ( + ::tokenize( + &self.operator, + ), + as alloy_sol_types::SolType>::tokenize( + &self.version, + ), + ) + } + #[inline] + fn topics(&self) -> ::RustType { + (Self::SIGNATURE_HASH.into(),) + } + #[inline] + fn encode_topics_raw( + &self, + out: &mut [alloy_sol_types::abi::token::WordToken], + ) -> alloy_sol_types::Result<()> { + if out.len() < ::COUNT { + return Err(alloy_sol_types::Error::Overrun); + } + out[0usize] = alloy_sol_types::abi::token::WordToken(Self::SIGNATURE_HASH); + Ok(()) + } + } + #[automatically_derived] + impl alloy_sol_types::private::IntoLogData for MaintenanceCompleted { + fn to_log_data(&self) -> alloy_sol_types::private::LogData { + From::from(self) + } + fn into_log_data(self) -> alloy_sol_types::private::LogData { + From::from(&self) + } + } + #[automatically_derived] + impl From<&MaintenanceCompleted> for alloy_sol_types::private::LogData { + #[inline] + fn from(this: &MaintenanceCompleted) -> alloy_sol_types::private::LogData { + alloy_sol_types::SolEvent::encode_log_data(this) + } + } + }; + /// Event with signature `MaintenanceStarted(address,uint128)` and selector + /// `0xbc2748cf02f7a1291525e866efc76ab3b96d32d7afcbb26c53daec617b38b479`. + /// ```solidity + /// event MaintenanceStarted(address operator, uint128 version); + /// ``` + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + #[derive(Clone)] + pub struct MaintenanceStarted { + #[allow(missing_docs)] + pub operator: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub version: u128, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[automatically_derived] + impl alloy_sol_types::SolEvent for MaintenanceStarted { + type DataTuple<'a> = ( + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Uint<128>, + ); + type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); + const SIGNATURE: &'static str = "MaintenanceStarted(address,uint128)"; + const SIGNATURE_HASH: alloy_sol_types::private::B256 = + alloy_sol_types::private::B256::new([ + 188u8, 39u8, 72u8, 207u8, 2u8, 247u8, 161u8, 41u8, 21u8, 37u8, 232u8, 102u8, + 239u8, 199u8, 106u8, 179u8, 185u8, 109u8, 50u8, 215u8, 175u8, 203u8, 178u8, + 108u8, 83u8, 218u8, 236u8, 97u8, 123u8, 56u8, 180u8, 121u8, + ]); + const ANONYMOUS: bool = false; + #[allow(unused_variables)] + #[inline] + fn new( + topics: ::RustType, + data: as alloy_sol_types::SolType>::RustType, + ) -> Self { + Self { + operator: data.0, + version: data.1, + } + } + #[inline] + fn check_signature( + topics: &::RustType, + ) -> alloy_sol_types::Result<()> { + if topics.0 != Self::SIGNATURE_HASH { + return Err(alloy_sol_types::Error::invalid_event_signature_hash( + Self::SIGNATURE, + topics.0, + Self::SIGNATURE_HASH, + )); + } + Ok(()) + } + #[inline] + fn tokenize_body(&self) -> Self::DataToken<'_> { + ( + ::tokenize( + &self.operator, + ), + as alloy_sol_types::SolType>::tokenize( + &self.version, + ), + ) + } + #[inline] + fn topics(&self) -> ::RustType { + (Self::SIGNATURE_HASH.into(),) + } + #[inline] + fn encode_topics_raw( + &self, + out: &mut [alloy_sol_types::abi::token::WordToken], + ) -> alloy_sol_types::Result<()> { + if out.len() < ::COUNT { + return Err(alloy_sol_types::Error::Overrun); + } + out[0usize] = alloy_sol_types::abi::token::WordToken(Self::SIGNATURE_HASH); + Ok(()) + } + } + #[automatically_derived] + impl alloy_sol_types::private::IntoLogData for MaintenanceStarted { + fn to_log_data(&self) -> alloy_sol_types::private::LogData { + From::from(self) + } + fn into_log_data(self) -> alloy_sol_types::private::LogData { + From::from(&self) + } + } + #[automatically_derived] + impl From<&MaintenanceStarted> for alloy_sol_types::private::LogData { + #[inline] + fn from(this: &MaintenanceStarted) -> alloy_sol_types::private::LogData { + alloy_sol_types::SolEvent::encode_log_data(this) + } + } + }; + /// Event with signature `MigrationAborted(uint128)` and selector + /// `0x9ce192aea5faf2151bbc246cd8918d2eba702fa26951f67f2bf7b3817e689d98`. + /// ```solidity + /// event MigrationAborted(uint128 version); + /// ``` + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + #[derive(Clone)] + pub struct MigrationAborted { + #[allow(missing_docs)] + pub version: u128, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[automatically_derived] + impl alloy_sol_types::SolEvent for MigrationAborted { + type DataTuple<'a> = (alloy::sol_types::sol_data::Uint<128>,); + type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); + const SIGNATURE: &'static str = "MigrationAborted(uint128)"; + const SIGNATURE_HASH: alloy_sol_types::private::B256 = + alloy_sol_types::private::B256::new([ + 156u8, 225u8, 146u8, 174u8, 165u8, 250u8, 242u8, 21u8, 27u8, 188u8, 36u8, + 108u8, 216u8, 145u8, 141u8, 46u8, 186u8, 112u8, 47u8, 162u8, 105u8, 81u8, + 246u8, 127u8, 43u8, 247u8, 179u8, 129u8, 126u8, 104u8, 157u8, 152u8, + ]); + const ANONYMOUS: bool = false; + #[allow(unused_variables)] + #[inline] + fn new( + topics: ::RustType, + data: as alloy_sol_types::SolType>::RustType, + ) -> Self { + Self { version: data.0 } + } + #[inline] + fn check_signature( + topics: &::RustType, + ) -> alloy_sol_types::Result<()> { + if topics.0 != Self::SIGNATURE_HASH { + return Err(alloy_sol_types::Error::invalid_event_signature_hash( + Self::SIGNATURE, + topics.0, + Self::SIGNATURE_HASH, + )); + } + Ok(()) + } + #[inline] + fn tokenize_body(&self) -> Self::DataToken<'_> { + ( + as alloy_sol_types::SolType>::tokenize( + &self.version, + ), + ) + } + #[inline] + fn topics(&self) -> ::RustType { + (Self::SIGNATURE_HASH.into(),) + } + #[inline] + fn encode_topics_raw( + &self, + out: &mut [alloy_sol_types::abi::token::WordToken], + ) -> alloy_sol_types::Result<()> { + if out.len() < ::COUNT { + return Err(alloy_sol_types::Error::Overrun); + } + out[0usize] = alloy_sol_types::abi::token::WordToken(Self::SIGNATURE_HASH); + Ok(()) + } + } + #[automatically_derived] + impl alloy_sol_types::private::IntoLogData for MigrationAborted { + fn to_log_data(&self) -> alloy_sol_types::private::LogData { + From::from(self) + } + fn into_log_data(self) -> alloy_sol_types::private::LogData { + From::from(&self) + } + } + #[automatically_derived] + impl From<&MigrationAborted> for alloy_sol_types::private::LogData { + #[inline] + fn from(this: &MigrationAborted) -> alloy_sol_types::private::LogData { + alloy_sol_types::SolEvent::encode_log_data(this) + } + } + }; + /// Event with signature `MigrationCompleted(uint128)` and selector + /// `0x11ce50160e66100537fd4b0ae26de66d51dab713ad92313353a18c24e8f6daab`. + /// ```solidity + /// event MigrationCompleted(uint128 version); + /// ``` + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + #[derive(Clone)] + pub struct MigrationCompleted { + #[allow(missing_docs)] + pub version: u128, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[automatically_derived] + impl alloy_sol_types::SolEvent for MigrationCompleted { + type DataTuple<'a> = (alloy::sol_types::sol_data::Uint<128>,); + type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); + const SIGNATURE: &'static str = "MigrationCompleted(uint128)"; + const SIGNATURE_HASH: alloy_sol_types::private::B256 = + alloy_sol_types::private::B256::new([ + 17u8, 206u8, 80u8, 22u8, 14u8, 102u8, 16u8, 5u8, 55u8, 253u8, 75u8, 10u8, + 226u8, 109u8, 230u8, 109u8, 81u8, 218u8, 183u8, 19u8, 173u8, 146u8, 49u8, 51u8, + 83u8, 161u8, 140u8, 36u8, 232u8, 246u8, 218u8, 171u8, + ]); + const ANONYMOUS: bool = false; + #[allow(unused_variables)] + #[inline] + fn new( + topics: ::RustType, + data: as alloy_sol_types::SolType>::RustType, + ) -> Self { + Self { version: data.0 } + } + #[inline] + fn check_signature( + topics: &::RustType, + ) -> alloy_sol_types::Result<()> { + if topics.0 != Self::SIGNATURE_HASH { + return Err(alloy_sol_types::Error::invalid_event_signature_hash( + Self::SIGNATURE, + topics.0, + Self::SIGNATURE_HASH, + )); + } + Ok(()) + } + #[inline] + fn tokenize_body(&self) -> Self::DataToken<'_> { + ( + as alloy_sol_types::SolType>::tokenize( + &self.version, + ), + ) + } + #[inline] + fn topics(&self) -> ::RustType { + (Self::SIGNATURE_HASH.into(),) + } + #[inline] + fn encode_topics_raw( + &self, + out: &mut [alloy_sol_types::abi::token::WordToken], + ) -> alloy_sol_types::Result<()> { + if out.len() < ::COUNT { + return Err(alloy_sol_types::Error::Overrun); + } + out[0usize] = alloy_sol_types::abi::token::WordToken(Self::SIGNATURE_HASH); + Ok(()) + } + } + #[automatically_derived] + impl alloy_sol_types::private::IntoLogData for MigrationCompleted { + fn to_log_data(&self) -> alloy_sol_types::private::LogData { + From::from(self) + } + fn into_log_data(self) -> alloy_sol_types::private::LogData { + From::from(&self) + } + } + #[automatically_derived] + impl From<&MigrationCompleted> for alloy_sol_types::private::LogData { + #[inline] + fn from(this: &MigrationCompleted) -> alloy_sol_types::private::LogData { + alloy_sol_types::SolEvent::encode_log_data(this) + } + } + }; + /// Event with signature `MigrationDataPullCompleted(address,uint128)` and + /// selector `0xa76a8fc1a90266ddee8937a18e12f01eade946b3b66197fff289af9277c2bd25`. + /// ```solidity + /// event MigrationDataPullCompleted(address operator, uint128 version); + /// ``` + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + #[derive(Clone)] + pub struct MigrationDataPullCompleted { + #[allow(missing_docs)] + pub operator: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub version: u128, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[automatically_derived] + impl alloy_sol_types::SolEvent for MigrationDataPullCompleted { + type DataTuple<'a> = ( + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Uint<128>, + ); + type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); + const SIGNATURE: &'static str = "MigrationDataPullCompleted(address,uint128)"; + const SIGNATURE_HASH: alloy_sol_types::private::B256 = + alloy_sol_types::private::B256::new([ + 167u8, 106u8, 143u8, 193u8, 169u8, 2u8, 102u8, 221u8, 238u8, 137u8, 55u8, + 161u8, 142u8, 18u8, 240u8, 30u8, 173u8, 233u8, 70u8, 179u8, 182u8, 97u8, 151u8, + 255u8, 242u8, 137u8, 175u8, 146u8, 119u8, 194u8, 189u8, 37u8, + ]); + const ANONYMOUS: bool = false; + #[allow(unused_variables)] + #[inline] + fn new( + topics: ::RustType, + data: as alloy_sol_types::SolType>::RustType, + ) -> Self { + Self { + operator: data.0, + version: data.1, + } + } + #[inline] + fn check_signature( + topics: &::RustType, + ) -> alloy_sol_types::Result<()> { + if topics.0 != Self::SIGNATURE_HASH { + return Err(alloy_sol_types::Error::invalid_event_signature_hash( + Self::SIGNATURE, + topics.0, + Self::SIGNATURE_HASH, + )); + } + Ok(()) + } + #[inline] + fn tokenize_body(&self) -> Self::DataToken<'_> { + ( + ::tokenize( + &self.operator, + ), + as alloy_sol_types::SolType>::tokenize( + &self.version, + ), + ) + } + #[inline] + fn topics(&self) -> ::RustType { + (Self::SIGNATURE_HASH.into(),) + } + #[inline] + fn encode_topics_raw( + &self, + out: &mut [alloy_sol_types::abi::token::WordToken], + ) -> alloy_sol_types::Result<()> { + if out.len() < ::COUNT { + return Err(alloy_sol_types::Error::Overrun); + } + out[0usize] = alloy_sol_types::abi::token::WordToken(Self::SIGNATURE_HASH); + Ok(()) + } + } + #[automatically_derived] + impl alloy_sol_types::private::IntoLogData for MigrationDataPullCompleted { + fn to_log_data(&self) -> alloy_sol_types::private::LogData { + From::from(self) + } + fn into_log_data(self) -> alloy_sol_types::private::LogData { + From::from(&self) + } + } + #[automatically_derived] + impl From<&MigrationDataPullCompleted> for alloy_sol_types::private::LogData { + #[inline] + fn from(this: &MigrationDataPullCompleted) -> alloy_sol_types::private::LogData { + alloy_sol_types::SolEvent::encode_log_data(this) + } + } + }; + /// Event with signature + /// `MigrationStarted(address[],(address,(uint256,bytes)[],bytes)[], + /// uint128)` and selector + /// `0x7e05e40117b6e18ab284c04a3508c3826422dc84a65e9c236a8248774416f8ac`. + /// ```solidity + /// event MigrationStarted(address[] operatorsToRemove, NodeOperatorView[] operatorsToAdd, uint128 version); + /// ``` + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + #[derive(Clone)] + pub struct MigrationStarted { + #[allow(missing_docs)] + pub operatorsToRemove: alloy::sol_types::private::Vec, + #[allow(missing_docs)] + pub operatorsToAdd: alloy::sol_types::private::Vec< + ::RustType, + >, + #[allow(missing_docs)] + pub version: u128, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[automatically_derived] + impl alloy_sol_types::SolEvent for MigrationStarted { + type DataTuple<'a> = ( + alloy::sol_types::sol_data::Array, + alloy::sol_types::sol_data::Array, + alloy::sol_types::sol_data::Uint<128>, + ); + type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); + const SIGNATURE: &'static str = + "MigrationStarted(address[],(address,(uint256,bytes)[],bytes)[],uint128)"; + const SIGNATURE_HASH: alloy_sol_types::private::B256 = + alloy_sol_types::private::B256::new([ + 126u8, 5u8, 228u8, 1u8, 23u8, 182u8, 225u8, 138u8, 178u8, 132u8, 192u8, 74u8, + 53u8, 8u8, 195u8, 130u8, 100u8, 34u8, 220u8, 132u8, 166u8, 94u8, 156u8, 35u8, + 106u8, 130u8, 72u8, 119u8, 68u8, 22u8, 248u8, 172u8, + ]); + const ANONYMOUS: bool = false; + #[allow(unused_variables)] + #[inline] + fn new( + topics: ::RustType, + data: as alloy_sol_types::SolType>::RustType, + ) -> Self { + Self { + operatorsToRemove: data.0, + operatorsToAdd: data.1, + version: data.2, + } + } + #[inline] + fn check_signature( + topics: &::RustType, + ) -> alloy_sol_types::Result<()> { + if topics.0 != Self::SIGNATURE_HASH { + return Err(alloy_sol_types::Error::invalid_event_signature_hash( + Self::SIGNATURE, + topics.0, + Self::SIGNATURE_HASH, + )); + } + Ok(()) + } + #[inline] + fn tokenize_body(&self) -> Self::DataToken<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.operatorsToRemove), + as alloy_sol_types::SolType>::tokenize(&self.operatorsToAdd), + as alloy_sol_types::SolType>::tokenize(&self.version), + ) + } + #[inline] + fn topics(&self) -> ::RustType { + (Self::SIGNATURE_HASH.into(),) + } + #[inline] + fn encode_topics_raw( + &self, + out: &mut [alloy_sol_types::abi::token::WordToken], + ) -> alloy_sol_types::Result<()> { + if out.len() < ::COUNT { + return Err(alloy_sol_types::Error::Overrun); + } + out[0usize] = alloy_sol_types::abi::token::WordToken(Self::SIGNATURE_HASH); + Ok(()) + } + } + #[automatically_derived] + impl alloy_sol_types::private::IntoLogData for MigrationStarted { + fn to_log_data(&self) -> alloy_sol_types::private::LogData { + From::from(self) + } + fn into_log_data(self) -> alloy_sol_types::private::LogData { + From::from(&self) + } + } + #[automatically_derived] + impl From<&MigrationStarted> for alloy_sol_types::private::LogData { + #[inline] + fn from(this: &MigrationStarted) -> alloy_sol_types::private::LogData { + alloy_sol_types::SolEvent::encode_log_data(this) + } + } + }; + /// Event with signature `NodeRemoved(address,uint256,uint128)` and selector + /// `0xbd184de79f134b0f3da466d278f5417cbcb1450d72f1bd1a1b84f18b1bcd03ca`. + /// ```solidity + /// event NodeRemoved(address operator, uint256 id, uint128 version); + /// ``` + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + #[derive(Clone)] + pub struct NodeRemoved { + #[allow(missing_docs)] + pub operator: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub id: alloy::sol_types::private::primitives::aliases::U256, + #[allow(missing_docs)] + pub version: u128, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[automatically_derived] + impl alloy_sol_types::SolEvent for NodeRemoved { + type DataTuple<'a> = ( + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Uint<256>, + alloy::sol_types::sol_data::Uint<128>, + ); + type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); + const SIGNATURE: &'static str = "NodeRemoved(address,uint256,uint128)"; + const SIGNATURE_HASH: alloy_sol_types::private::B256 = + alloy_sol_types::private::B256::new([ + 189u8, 24u8, 77u8, 231u8, 159u8, 19u8, 75u8, 15u8, 61u8, 164u8, 102u8, 210u8, + 120u8, 245u8, 65u8, 124u8, 188u8, 177u8, 69u8, 13u8, 114u8, 241u8, 189u8, 26u8, + 27u8, 132u8, 241u8, 139u8, 27u8, 205u8, 3u8, 202u8, + ]); + const ANONYMOUS: bool = false; + #[allow(unused_variables)] + #[inline] + fn new( + topics: ::RustType, + data: as alloy_sol_types::SolType>::RustType, + ) -> Self { + Self { + operator: data.0, + id: data.1, + version: data.2, + } + } + #[inline] + fn check_signature( + topics: &::RustType, + ) -> alloy_sol_types::Result<()> { + if topics.0 != Self::SIGNATURE_HASH { + return Err(alloy_sol_types::Error::invalid_event_signature_hash( + Self::SIGNATURE, + topics.0, + Self::SIGNATURE_HASH, + )); + } + Ok(()) + } + #[inline] + fn tokenize_body(&self) -> Self::DataToken<'_> { + ( + ::tokenize( + &self.operator, + ), + as alloy_sol_types::SolType>::tokenize( + &self.id, + ), + as alloy_sol_types::SolType>::tokenize( + &self.version, + ), + ) + } + #[inline] + fn topics(&self) -> ::RustType { + (Self::SIGNATURE_HASH.into(),) + } + #[inline] + fn encode_topics_raw( + &self, + out: &mut [alloy_sol_types::abi::token::WordToken], + ) -> alloy_sol_types::Result<()> { + if out.len() < ::COUNT { + return Err(alloy_sol_types::Error::Overrun); + } + out[0usize] = alloy_sol_types::abi::token::WordToken(Self::SIGNATURE_HASH); + Ok(()) + } + } + #[automatically_derived] + impl alloy_sol_types::private::IntoLogData for NodeRemoved { + fn to_log_data(&self) -> alloy_sol_types::private::LogData { + From::from(self) + } + fn into_log_data(self) -> alloy_sol_types::private::LogData { + From::from(&self) + } + } + #[automatically_derived] + impl From<&NodeRemoved> for alloy_sol_types::private::LogData { + #[inline] + fn from(this: &NodeRemoved) -> alloy_sol_types::private::LogData { + alloy_sol_types::SolEvent::encode_log_data(this) + } + } + }; + /// Event with signature `NodeSet(address,(uint256,bytes),uint128)` and + /// selector `0x6adfb896d3407681d05fb874d4dfb7068e6e2a36f09acd38a3b7d04c01745fee`. + /// ```solidity + /// event NodeSet(address operator, Node node, uint128 version); + /// ``` + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + #[derive(Clone)] + pub struct NodeSet { + #[allow(missing_docs)] + pub operator: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub node: ::RustType, + #[allow(missing_docs)] + pub version: u128, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[automatically_derived] + impl alloy_sol_types::SolEvent for NodeSet { + type DataTuple<'a> = ( + alloy::sol_types::sol_data::Address, + Node, + alloy::sol_types::sol_data::Uint<128>, + ); + type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); + const SIGNATURE: &'static str = "NodeSet(address,(uint256,bytes),uint128)"; + const SIGNATURE_HASH: alloy_sol_types::private::B256 = + alloy_sol_types::private::B256::new([ + 106u8, 223u8, 184u8, 150u8, 211u8, 64u8, 118u8, 129u8, 208u8, 95u8, 184u8, + 116u8, 212u8, 223u8, 183u8, 6u8, 142u8, 110u8, 42u8, 54u8, 240u8, 154u8, 205u8, + 56u8, 163u8, 183u8, 208u8, 76u8, 1u8, 116u8, 95u8, 238u8, + ]); + const ANONYMOUS: bool = false; + #[allow(unused_variables)] + #[inline] + fn new( + topics: ::RustType, + data: as alloy_sol_types::SolType>::RustType, + ) -> Self { + Self { + operator: data.0, + node: data.1, + version: data.2, + } + } + #[inline] + fn check_signature( + topics: &::RustType, + ) -> alloy_sol_types::Result<()> { + if topics.0 != Self::SIGNATURE_HASH { + return Err(alloy_sol_types::Error::invalid_event_signature_hash( + Self::SIGNATURE, + topics.0, + Self::SIGNATURE_HASH, + )); + } + Ok(()) + } + #[inline] + fn tokenize_body(&self) -> Self::DataToken<'_> { + ( + ::tokenize( + &self.operator, + ), + ::tokenize(&self.node), + as alloy_sol_types::SolType>::tokenize( + &self.version, + ), + ) + } + #[inline] + fn topics(&self) -> ::RustType { + (Self::SIGNATURE_HASH.into(),) + } + #[inline] + fn encode_topics_raw( + &self, + out: &mut [alloy_sol_types::abi::token::WordToken], + ) -> alloy_sol_types::Result<()> { + if out.len() < ::COUNT { + return Err(alloy_sol_types::Error::Overrun); + } + out[0usize] = alloy_sol_types::abi::token::WordToken(Self::SIGNATURE_HASH); + Ok(()) + } + } + #[automatically_derived] + impl alloy_sol_types::private::IntoLogData for NodeSet { + fn to_log_data(&self) -> alloy_sol_types::private::LogData { + From::from(self) + } + fn into_log_data(self) -> alloy_sol_types::private::LogData { + From::from(&self) + } + } + #[automatically_derived] + impl From<&NodeSet> for alloy_sol_types::private::LogData { + #[inline] + fn from(this: &NodeSet) -> alloy_sol_types::private::LogData { + alloy_sol_types::SolEvent::encode_log_data(this) + } + } + }; + /// Constructor`. + /// ```solidity + /// constructor(Settings initialSettings, NodeOperatorView[] initialOperators); + /// ``` + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct constructorCall { + #[allow(missing_docs)] + pub initialSettings: ::RustType, + #[allow(missing_docs)] + pub initialOperators: alloy::sol_types::private::Vec< + ::RustType, + >, + } + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + Settings, + alloy::sol_types::sol_data::Array, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + ::RustType, + alloy::sol_types::private::Vec< + ::RustType, + >, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: constructorCall) -> Self { + (value.initialSettings, value.initialOperators) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for constructorCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + initialSettings: tuple.0, + initialOperators: tuple.1, + } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolConstructor for constructorCall { + type Parameters<'a> = ( + Settings, + alloy::sol_types::sol_data::Array, + ); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + ::tokenize( + &self.initialSettings, + ), + as alloy_sol_types::SolType>::tokenize(&self.initialOperators), + ) + } + } + }; + /// Function with signature `abortMaintenance()` and selector `0x3048bfba`. + /// ```solidity + /// function abortMaintenance() external; + /// ``` + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct abortMaintenanceCall {} + /// Container type for the return parameters of the + /// [`abortMaintenance()`](abortMaintenanceCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct abortMaintenanceReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: abortMaintenanceCall) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for abortMaintenanceCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: abortMaintenanceReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for abortMaintenanceReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for abortMaintenanceCall { + type Parameters<'a> = (); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = abortMaintenanceReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "abortMaintenance()"; + const SELECTOR: [u8; 4] = [48u8, 72u8, 191u8, 186u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn abi_decode_returns( + data: &[u8], + validate: bool, + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence( + data, validate, + ) + .map(Into::into) + } + } + }; + /// Function with signature `abortMigration()` and selector `0xc130809a`. + /// ```solidity + /// function abortMigration() external; + /// ``` + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct abortMigrationCall {} + /// Container type for the return parameters of the + /// [`abortMigration()`](abortMigrationCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct abortMigrationReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: abortMigrationCall) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for abortMigrationCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: abortMigrationReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for abortMigrationReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for abortMigrationCall { + type Parameters<'a> = (); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = abortMigrationReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "abortMigration()"; + const SELECTOR: [u8; 4] = [193u8, 48u8, 128u8, 154u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn abi_decode_returns( + data: &[u8], + validate: bool, + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence( + data, validate, + ) + .map(Into::into) + } + } + }; + /// Function with signature `completeMaintenance()` and selector + /// `0xad36e6d0`. ```solidity + /// function completeMaintenance() external; + /// ``` + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct completeMaintenanceCall {} + /// Container type for the return parameters of the + /// [`completeMaintenance()`](completeMaintenanceCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct completeMaintenanceReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: completeMaintenanceCall) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for completeMaintenanceCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: completeMaintenanceReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for completeMaintenanceReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for completeMaintenanceCall { + type Parameters<'a> = (); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = completeMaintenanceReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "completeMaintenance()"; + const SELECTOR: [u8; 4] = [173u8, 54u8, 230u8, 208u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn abi_decode_returns( + data: &[u8], + validate: bool, + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence( + data, validate, + ) + .map(Into::into) + } + } + }; + /// Function with signature `completeMigration()` and selector `0x4886f62c`. + /// ```solidity + /// function completeMigration() external; + /// ``` + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct completeMigrationCall {} + /// Container type for the return parameters of the + /// [`completeMigration()`](completeMigrationCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct completeMigrationReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: completeMigrationCall) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for completeMigrationCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: completeMigrationReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for completeMigrationReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for completeMigrationCall { + type Parameters<'a> = (); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = completeMigrationReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "completeMigration()"; + const SELECTOR: [u8; 4] = [72u8, 134u8, 246u8, 44u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn abi_decode_returns( + data: &[u8], + validate: bool, + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence( + data, validate, + ) + .map(Into::into) + } + } + }; + /// Function with signature `getView()` and selector `0x75418b9d`. + /// ```solidity + /// function getView() external view returns (ClusterView memory); + /// ``` + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct getViewCall {} + /// Container type for the return parameters of the + /// [`getView()`](getViewCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct getViewReturn { + #[allow(missing_docs)] + pub _0: ::RustType, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: getViewCall) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for getViewCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (ClusterView,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (::RustType,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: getViewReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for getViewReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for getViewCall { + type Parameters<'a> = (); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = getViewReturn; + type ReturnTuple<'a> = (ClusterView,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "getView()"; + const SELECTOR: [u8; 4] = [117u8, 65u8, 139u8, 157u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn abi_decode_returns( + data: &[u8], + validate: bool, + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence( + data, validate, + ) + .map(Into::into) + } + } + }; + /// Function with signature `removeNode(uint256)` and selector `0xffd740df`. + /// ```solidity + /// function removeNode(uint256 id) external; + /// ``` + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct removeNodeCall { + #[allow(missing_docs)] + pub id: alloy::sol_types::private::primitives::aliases::U256, + } + /// Container type for the return parameters of the + /// [`removeNode(uint256)`](removeNodeCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct removeNodeReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Uint<256>,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::primitives::aliases::U256,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: removeNodeCall) -> Self { + (value.id,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for removeNodeCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { id: tuple.0 } + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: removeNodeReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for removeNodeReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for removeNodeCall { + type Parameters<'a> = (alloy::sol_types::sol_data::Uint<256>,); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = removeNodeReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "removeNode(uint256)"; + const SELECTOR: [u8; 4] = [255u8, 215u8, 64u8, 223u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + as alloy_sol_types::SolType>::tokenize( + &self.id, + ), + ) + } + #[inline] + fn abi_decode_returns( + data: &[u8], + validate: bool, + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence( + data, validate, + ) + .map(Into::into) + } + } + }; + /// Function with signature `setNode((uint256,bytes))` and selector + /// `0x6c0b61b9`. ```solidity + /// function setNode(Node memory node) external; + /// ``` + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct setNodeCall { + #[allow(missing_docs)] + pub node: ::RustType, + } + /// Container type for the return parameters of the + /// [`setNode((uint256,bytes))`](setNodeCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct setNodeReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (Node,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (::RustType,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: setNodeCall) -> Self { + (value.node,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for setNodeCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { node: tuple.0 } + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: setNodeReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for setNodeReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for setNodeCall { + type Parameters<'a> = (Node,); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = setNodeReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "setNode((uint256,bytes))"; + const SELECTOR: [u8; 4] = [108u8, 11u8, 97u8, 185u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + (::tokenize(&self.node),) + } + #[inline] + fn abi_decode_returns( + data: &[u8], + validate: bool, + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence( + data, validate, + ) + .map(Into::into) + } + } + }; + /// Function with signature `startMaintenance()` and selector `0xf5f2d9f1`. + /// ```solidity + /// function startMaintenance() external; + /// ``` + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct startMaintenanceCall {} + /// Container type for the return parameters of the + /// [`startMaintenance()`](startMaintenanceCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct startMaintenanceReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: startMaintenanceCall) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for startMaintenanceCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: startMaintenanceReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for startMaintenanceReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for startMaintenanceCall { + type Parameters<'a> = (); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = startMaintenanceReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "startMaintenance()"; + const SELECTOR: [u8; 4] = [245u8, 242u8, 217u8, 241u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn abi_decode_returns( + data: &[u8], + validate: bool, + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence( + data, validate, + ) + .map(Into::into) + } + } + }; + /// Function with signature + /// `startMigration(address[],(address,(uint256,bytes)[],bytes)[])` and + /// selector `0xcc45662a`. ```solidity + /// function startMigration(address[] memory operatorsToRemove, + /// NodeOperatorView[] memory operatorsToAdd) external; ``` + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct startMigrationCall { + #[allow(missing_docs)] + pub operatorsToRemove: alloy::sol_types::private::Vec, + #[allow(missing_docs)] + pub operatorsToAdd: alloy::sol_types::private::Vec< + ::RustType, + >, + } + /// Container type for the return parameters of the + /// [`startMigration(address[],(address,(uint256,bytes)[], + /// bytes)[])`](startMigrationCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct startMigrationReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::Array, + alloy::sol_types::sol_data::Array, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::Vec, + alloy::sol_types::private::Vec< + ::RustType, + >, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: startMigrationCall) -> Self { + (value.operatorsToRemove, value.operatorsToAdd) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for startMigrationCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + operatorsToRemove: tuple.0, + operatorsToAdd: tuple.1, + } + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: startMigrationReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for startMigrationReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for startMigrationCall { + type Parameters<'a> = ( + alloy::sol_types::sol_data::Array, + alloy::sol_types::sol_data::Array, + ); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = startMigrationReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = + "startMigration(address[],(address,(uint256,bytes)[],bytes)[])"; + const SELECTOR: [u8; 4] = [204u8, 69u8, 102u8, 42u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.operatorsToRemove), + as alloy_sol_types::SolType>::tokenize(&self.operatorsToAdd), + ) + } + #[inline] + fn abi_decode_returns( + data: &[u8], + validate: bool, + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence( + data, validate, + ) + .map(Into::into) + } + } + }; + /// Function with signature `transferOwnership(address)` and selector + /// `0xf2fde38b`. ```solidity + /// function transferOwnership(address newOwner) external; + /// ``` + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct transferOwnershipCall { + #[allow(missing_docs)] + pub newOwner: alloy::sol_types::private::Address, + } + /// Container type for the return parameters of the + /// [`transferOwnership(address)`](transferOwnershipCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct transferOwnershipReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Address,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::Address,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: transferOwnershipCall) -> Self { + (value.newOwner,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for transferOwnershipCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { newOwner: tuple.0 } + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: transferOwnershipReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for transferOwnershipReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for transferOwnershipCall { + type Parameters<'a> = (alloy::sol_types::sol_data::Address,); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = transferOwnershipReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "transferOwnership(address)"; + const SELECTOR: [u8; 4] = [242u8, 253u8, 227u8, 139u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + ::tokenize( + &self.newOwner, + ), + ) + } + #[inline] + fn abi_decode_returns( + data: &[u8], + validate: bool, + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence( + data, validate, + ) + .map(Into::into) + } + } + }; + /// Function with signature `updateSettings((uint8,uint8))` and selector + /// `0x409900e8`. ```solidity + /// function updateSettings(Settings memory newSettings) external; + /// ``` + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct updateSettingsCall { + #[allow(missing_docs)] + pub newSettings: ::RustType, + } + /// Container type for the return parameters of the + /// [`updateSettings((uint8,uint8))`](updateSettingsCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct updateSettingsReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (Settings,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (::RustType,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: updateSettingsCall) -> Self { + (value.newSettings,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for updateSettingsCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + newSettings: tuple.0, + } + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: updateSettingsReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for updateSettingsReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for updateSettingsCall { + type Parameters<'a> = (Settings,); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = updateSettingsReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "updateSettings((uint8,uint8))"; + const SELECTOR: [u8; 4] = [64u8, 153u8, 0u8, 232u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + (::tokenize( + &self.newSettings, + ),) + } + #[inline] + fn abi_decode_returns( + data: &[u8], + validate: bool, + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence( + data, validate, + ) + .map(Into::into) + } + } + }; + /// Container for all the [`Cluster`](self) function calls. + pub enum ClusterCalls { + #[allow(missing_docs)] + abortMaintenance(abortMaintenanceCall), + #[allow(missing_docs)] + abortMigration(abortMigrationCall), + #[allow(missing_docs)] + completeMaintenance(completeMaintenanceCall), + #[allow(missing_docs)] + completeMigration(completeMigrationCall), + #[allow(missing_docs)] + getView(getViewCall), + #[allow(missing_docs)] + removeNode(removeNodeCall), + #[allow(missing_docs)] + setNode(setNodeCall), + #[allow(missing_docs)] + startMaintenance(startMaintenanceCall), + #[allow(missing_docs)] + startMigration(startMigrationCall), + #[allow(missing_docs)] + transferOwnership(transferOwnershipCall), + #[allow(missing_docs)] + updateSettings(updateSettingsCall), + } + #[automatically_derived] + impl ClusterCalls { + /// All the selectors of this enum. + /// + /// Note that the selectors might not be in the same order as the + /// variants. No guarantees are made about the order of the + /// selectors. + /// + /// Prefer using `SolInterface` methods instead. + pub const SELECTORS: &'static [[u8; 4usize]] = &[ + [48u8, 72u8, 191u8, 186u8], + [64u8, 153u8, 0u8, 232u8], + [72u8, 134u8, 246u8, 44u8], + [108u8, 11u8, 97u8, 185u8], + [117u8, 65u8, 139u8, 157u8], + [173u8, 54u8, 230u8, 208u8], + [193u8, 48u8, 128u8, 154u8], + [204u8, 69u8, 102u8, 42u8], + [242u8, 253u8, 227u8, 139u8], + [245u8, 242u8, 217u8, 241u8], + [255u8, 215u8, 64u8, 223u8], + ]; + } + #[automatically_derived] + impl alloy_sol_types::SolInterface for ClusterCalls { + const NAME: &'static str = "ClusterCalls"; + const MIN_DATA_LENGTH: usize = 0usize; + const COUNT: usize = 11usize; + #[inline] + fn selector(&self) -> [u8; 4] { + match self { + Self::abortMaintenance(_) => { + ::SELECTOR + } + Self::abortMigration(_) => { + ::SELECTOR + } + Self::completeMaintenance(_) => { + ::SELECTOR + } + Self::completeMigration(_) => { + ::SELECTOR + } + Self::getView(_) => ::SELECTOR, + Self::removeNode(_) => ::SELECTOR, + Self::setNode(_) => ::SELECTOR, + Self::startMaintenance(_) => { + ::SELECTOR + } + Self::startMigration(_) => { + ::SELECTOR + } + Self::transferOwnership(_) => { + ::SELECTOR + } + Self::updateSettings(_) => { + ::SELECTOR + } + } + } + #[inline] + fn selector_at(i: usize) -> ::core::option::Option<[u8; 4]> { + Self::SELECTORS.get(i).copied() + } + #[inline] + fn valid_selector(selector: [u8; 4]) -> bool { + Self::SELECTORS.binary_search(&selector).is_ok() + } + #[inline] + #[allow(non_snake_case)] + fn abi_decode_raw( + selector: [u8; 4], + data: &[u8], + validate: bool, + ) -> alloy_sol_types::Result { + static DECODE_SHIMS: &[fn(&[u8], bool) -> alloy_sol_types::Result] = &[ + { + fn abortMaintenance( + data: &[u8], + validate: bool, + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, validate, + ) + .map(ClusterCalls::abortMaintenance) + } + abortMaintenance + }, + { + fn updateSettings( + data: &[u8], + validate: bool, + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, validate, + ) + .map(ClusterCalls::updateSettings) + } + updateSettings + }, + { + fn completeMigration( + data: &[u8], + validate: bool, + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, validate, + ) + .map(ClusterCalls::completeMigration) + } + completeMigration + }, + { + fn setNode( + data: &[u8], + validate: bool, + ) -> alloy_sol_types::Result { + ::abi_decode_raw(data, validate) + .map(ClusterCalls::setNode) + } + setNode + }, + { + fn getView( + data: &[u8], + validate: bool, + ) -> alloy_sol_types::Result { + ::abi_decode_raw(data, validate) + .map(ClusterCalls::getView) + } + getView + }, + { + fn completeMaintenance( + data: &[u8], + validate: bool, + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, validate, + ) + .map(ClusterCalls::completeMaintenance) + } + completeMaintenance + }, + { + fn abortMigration( + data: &[u8], + validate: bool, + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, validate, + ) + .map(ClusterCalls::abortMigration) + } + abortMigration + }, + { + fn startMigration( + data: &[u8], + validate: bool, + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, validate, + ) + .map(ClusterCalls::startMigration) + } + startMigration + }, + { + fn transferOwnership( + data: &[u8], + validate: bool, + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, validate, + ) + .map(ClusterCalls::transferOwnership) + } + transferOwnership + }, + { + fn startMaintenance( + data: &[u8], + validate: bool, + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, validate, + ) + .map(ClusterCalls::startMaintenance) + } + startMaintenance + }, + { + fn removeNode( + data: &[u8], + validate: bool, + ) -> alloy_sol_types::Result { + ::abi_decode_raw(data, validate) + .map(ClusterCalls::removeNode) + } + removeNode + }, + ]; + let Ok(idx) = Self::SELECTORS.binary_search(&selector) else { + return Err(alloy_sol_types::Error::unknown_selector( + ::NAME, + selector, + )); + }; + DECODE_SHIMS[idx](data, validate) + } + #[inline] + fn abi_encoded_size(&self) -> usize { + match self { + Self::abortMaintenance(inner) => { + ::abi_encoded_size(inner) + } + Self::abortMigration(inner) => { + ::abi_encoded_size(inner) + } + Self::completeMaintenance(inner) => { + ::abi_encoded_size(inner) + } + Self::completeMigration(inner) => { + ::abi_encoded_size(inner) + } + Self::getView(inner) => { + ::abi_encoded_size(inner) + } + Self::removeNode(inner) => { + ::abi_encoded_size(inner) + } + Self::setNode(inner) => { + ::abi_encoded_size(inner) + } + Self::startMaintenance(inner) => { + ::abi_encoded_size(inner) + } + Self::startMigration(inner) => { + ::abi_encoded_size(inner) + } + Self::transferOwnership(inner) => { + ::abi_encoded_size(inner) + } + Self::updateSettings(inner) => { + ::abi_encoded_size(inner) + } + } + } + #[inline] + fn abi_encode_raw(&self, out: &mut alloy_sol_types::private::Vec) { + match self { + Self::abortMaintenance(inner) => { + ::abi_encode_raw(inner, out) + } + Self::abortMigration(inner) => { + ::abi_encode_raw(inner, out) + } + Self::completeMaintenance(inner) => { + ::abi_encode_raw( + inner, out, + ) + } + Self::completeMigration(inner) => { + ::abi_encode_raw(inner, out) + } + Self::getView(inner) => { + ::abi_encode_raw(inner, out) + } + Self::removeNode(inner) => { + ::abi_encode_raw(inner, out) + } + Self::setNode(inner) => { + ::abi_encode_raw(inner, out) + } + Self::startMaintenance(inner) => { + ::abi_encode_raw(inner, out) + } + Self::startMigration(inner) => { + ::abi_encode_raw(inner, out) + } + Self::transferOwnership(inner) => { + ::abi_encode_raw(inner, out) + } + Self::updateSettings(inner) => { + ::abi_encode_raw(inner, out) + } + } + } + } + /// Container for all the [`Cluster`](self) events. + pub enum ClusterEvents { + #[allow(missing_docs)] + MaintenanceAborted(MaintenanceAborted), + #[allow(missing_docs)] + MaintenanceCompleted(MaintenanceCompleted), + #[allow(missing_docs)] + MaintenanceStarted(MaintenanceStarted), + #[allow(missing_docs)] + MigrationAborted(MigrationAborted), + #[allow(missing_docs)] + MigrationCompleted(MigrationCompleted), + #[allow(missing_docs)] + MigrationDataPullCompleted(MigrationDataPullCompleted), + #[allow(missing_docs)] + MigrationStarted(MigrationStarted), + #[allow(missing_docs)] + NodeRemoved(NodeRemoved), + #[allow(missing_docs)] + NodeSet(NodeSet), + } + #[automatically_derived] + impl ClusterEvents { + /// All the selectors of this enum. + /// + /// Note that the selectors might not be in the same order as the + /// variants. No guarantees are made about the order of the + /// selectors. + /// + /// Prefer using `SolInterface` methods instead. + pub const SELECTORS: &'static [[u8; 32usize]] = &[ + [ + 17u8, 206u8, 80u8, 22u8, 14u8, 102u8, 16u8, 5u8, 55u8, 253u8, 75u8, 10u8, 226u8, + 109u8, 230u8, 109u8, 81u8, 218u8, 183u8, 19u8, 173u8, 146u8, 49u8, 51u8, 83u8, + 161u8, 140u8, 36u8, 232u8, 246u8, 218u8, 171u8, + ], + [ + 106u8, 223u8, 184u8, 150u8, 211u8, 64u8, 118u8, 129u8, 208u8, 95u8, 184u8, 116u8, + 212u8, 223u8, 183u8, 6u8, 142u8, 110u8, 42u8, 54u8, 240u8, 154u8, 205u8, 56u8, + 163u8, 183u8, 208u8, 76u8, 1u8, 116u8, 95u8, 238u8, + ], + [ + 126u8, 5u8, 228u8, 1u8, 23u8, 182u8, 225u8, 138u8, 178u8, 132u8, 192u8, 74u8, 53u8, + 8u8, 195u8, 130u8, 100u8, 34u8, 220u8, 132u8, 166u8, 94u8, 156u8, 35u8, 106u8, + 130u8, 72u8, 119u8, 68u8, 22u8, 248u8, 172u8, + ], + [ + 143u8, 185u8, 205u8, 5u8, 77u8, 10u8, 2u8, 33u8, 16u8, 204u8, 237u8, 35u8, 158u8, + 144u8, 139u8, 131u8, 78u8, 76u8, 210u8, 25u8, 81u8, 24u8, 86u8, 212u8, 234u8, + 174u8, 48u8, 81u8, 217u8, 50u8, 214u8, 4u8, + ], + [ + 156u8, 225u8, 146u8, 174u8, 165u8, 250u8, 242u8, 21u8, 27u8, 188u8, 36u8, 108u8, + 216u8, 145u8, 141u8, 46u8, 186u8, 112u8, 47u8, 162u8, 105u8, 81u8, 246u8, 127u8, + 43u8, 247u8, 179u8, 129u8, 126u8, 104u8, 157u8, 152u8, + ], + [ + 167u8, 106u8, 143u8, 193u8, 169u8, 2u8, 102u8, 221u8, 238u8, 137u8, 55u8, 161u8, + 142u8, 18u8, 240u8, 30u8, 173u8, 233u8, 70u8, 179u8, 182u8, 97u8, 151u8, 255u8, + 242u8, 137u8, 175u8, 146u8, 119u8, 194u8, 189u8, 37u8, + ], + [ + 188u8, 39u8, 72u8, 207u8, 2u8, 247u8, 161u8, 41u8, 21u8, 37u8, 232u8, 102u8, 239u8, + 199u8, 106u8, 179u8, 185u8, 109u8, 50u8, 215u8, 175u8, 203u8, 178u8, 108u8, 83u8, + 218u8, 236u8, 97u8, 123u8, 56u8, 180u8, 121u8, + ], + [ + 189u8, 24u8, 77u8, 231u8, 159u8, 19u8, 75u8, 15u8, 61u8, 164u8, 102u8, 210u8, + 120u8, 245u8, 65u8, 124u8, 188u8, 177u8, 69u8, 13u8, 114u8, 241u8, 189u8, 26u8, + 27u8, 132u8, 241u8, 139u8, 27u8, 205u8, 3u8, 202u8, + ], + [ + 249u8, 16u8, 103u8, 235u8, 66u8, 12u8, 40u8, 211u8, 18u8, 72u8, 101u8, 252u8, + 153u8, 110u8, 106u8, 169u8, 213u8, 65u8, 185u8, 180u8, 254u8, 249u8, 24u8, 140u8, + 185u8, 101u8, 166u8, 204u8, 100u8, 145u8, 99u8, 142u8, + ], + ]; + } + #[automatically_derived] + impl alloy_sol_types::SolEventInterface for ClusterEvents { + const NAME: &'static str = "ClusterEvents"; + const COUNT: usize = 9usize; + fn decode_raw_log( + topics: &[alloy_sol_types::Word], + data: &[u8], + validate: bool, + ) -> alloy_sol_types::Result { + match topics.first().copied() { + Some(::SIGNATURE_HASH) => { + ::decode_raw_log( + topics, data, validate, + ) + .map(Self::MaintenanceAborted) + } + Some(::SIGNATURE_HASH) => { + ::decode_raw_log( + topics, data, validate, + ) + .map(Self::MaintenanceCompleted) + } + Some(::SIGNATURE_HASH) => { + ::decode_raw_log( + topics, data, validate, + ) + .map(Self::MaintenanceStarted) + } + Some(::SIGNATURE_HASH) => { + ::decode_raw_log( + topics, data, validate, + ) + .map(Self::MigrationAborted) + } + Some(::SIGNATURE_HASH) => { + ::decode_raw_log( + topics, data, validate, + ) + .map(Self::MigrationCompleted) + } + Some(::SIGNATURE_HASH) => { + ::decode_raw_log( + topics, data, validate, + ) + .map(Self::MigrationDataPullCompleted) + } + Some(::SIGNATURE_HASH) => { + ::decode_raw_log( + topics, data, validate, + ) + .map(Self::MigrationStarted) + } + Some(::SIGNATURE_HASH) => { + ::decode_raw_log( + topics, data, validate, + ) + .map(Self::NodeRemoved) + } + Some(::SIGNATURE_HASH) => { + ::decode_raw_log(topics, data, validate) + .map(Self::NodeSet) + } + _ => alloy_sol_types::private::Err(alloy_sol_types::Error::InvalidLog { + name: ::NAME, + log: alloy_sol_types::private::Box::new( + alloy_sol_types::private::LogData::new_unchecked( + topics.to_vec(), + data.to_vec().into(), + ), + ), + }), + } + } + } + #[automatically_derived] + impl alloy_sol_types::private::IntoLogData for ClusterEvents { + fn to_log_data(&self) -> alloy_sol_types::private::LogData { + match self { + Self::MaintenanceAborted(inner) => { + alloy_sol_types::private::IntoLogData::to_log_data(inner) + } + Self::MaintenanceCompleted(inner) => { + alloy_sol_types::private::IntoLogData::to_log_data(inner) + } + Self::MaintenanceStarted(inner) => { + alloy_sol_types::private::IntoLogData::to_log_data(inner) + } + Self::MigrationAborted(inner) => { + alloy_sol_types::private::IntoLogData::to_log_data(inner) + } + Self::MigrationCompleted(inner) => { + alloy_sol_types::private::IntoLogData::to_log_data(inner) + } + Self::MigrationDataPullCompleted(inner) => { + alloy_sol_types::private::IntoLogData::to_log_data(inner) + } + Self::MigrationStarted(inner) => { + alloy_sol_types::private::IntoLogData::to_log_data(inner) + } + Self::NodeRemoved(inner) => { + alloy_sol_types::private::IntoLogData::to_log_data(inner) + } + Self::NodeSet(inner) => alloy_sol_types::private::IntoLogData::to_log_data(inner), + } + } + fn into_log_data(self) -> alloy_sol_types::private::LogData { + match self { + Self::MaintenanceAborted(inner) => { + alloy_sol_types::private::IntoLogData::into_log_data(inner) + } + Self::MaintenanceCompleted(inner) => { + alloy_sol_types::private::IntoLogData::into_log_data(inner) + } + Self::MaintenanceStarted(inner) => { + alloy_sol_types::private::IntoLogData::into_log_data(inner) + } + Self::MigrationAborted(inner) => { + alloy_sol_types::private::IntoLogData::into_log_data(inner) + } + Self::MigrationCompleted(inner) => { + alloy_sol_types::private::IntoLogData::into_log_data(inner) + } + Self::MigrationDataPullCompleted(inner) => { + alloy_sol_types::private::IntoLogData::into_log_data(inner) + } + Self::MigrationStarted(inner) => { + alloy_sol_types::private::IntoLogData::into_log_data(inner) + } + Self::NodeRemoved(inner) => { + alloy_sol_types::private::IntoLogData::into_log_data(inner) + } + Self::NodeSet(inner) => alloy_sol_types::private::IntoLogData::into_log_data(inner), + } + } + } + use alloy::contract as alloy_contract; + /// Creates a new wrapper around an on-chain [`Cluster`](self) contract + /// instance. + /// + /// See the [wrapper's documentation](`ClusterInstance`) for more details. + #[inline] + pub const fn new< + T: alloy_contract::private::Transport + ::core::clone::Clone, + P: alloy_contract::private::Provider, + N: alloy_contract::private::Network, + >( + address: alloy_sol_types::private::Address, + provider: P, + ) -> ClusterInstance { + ClusterInstance::::new(address, provider) + } + /// Deploys this contract using the given `provider` and constructor + /// arguments, if any. + /// + /// Returns a new instance of the contract, if the deployment was + /// successful. + /// + /// For more fine-grained control over the deployment process, use + /// [`deploy_builder`] instead. + #[inline] + pub fn deploy< + T: alloy_contract::private::Transport + ::core::clone::Clone, + P: alloy_contract::private::Provider, + N: alloy_contract::private::Network, + >( + provider: P, + initialSettings: ::RustType, + initialOperators: alloy::sol_types::private::Vec< + ::RustType, + >, + ) -> impl ::core::future::Future>> + { + ClusterInstance::::deploy(provider, initialSettings, initialOperators) + } + /// Creates a `RawCallBuilder` for deploying this contract using the given + /// `provider` and constructor arguments, if any. + /// + /// This is a simple wrapper around creating a `RawCallBuilder` with the + /// data set to the bytecode concatenated with the constructor's + /// ABI-encoded arguments. + #[inline] + pub fn deploy_builder< + T: alloy_contract::private::Transport + ::core::clone::Clone, + P: alloy_contract::private::Provider, + N: alloy_contract::private::Network, + >( + provider: P, + initialSettings: ::RustType, + initialOperators: alloy::sol_types::private::Vec< + ::RustType, + >, + ) -> alloy_contract::RawCallBuilder { + ClusterInstance::::deploy_builder(provider, initialSettings, initialOperators) + } + /// A [`Cluster`](self) instance. + /// + /// Contains type-safe methods for interacting with an on-chain instance of + /// the [`Cluster`](self) contract located at a given `address`, using a + /// given provider `P`. + /// + /// If the contract bytecode is available (see the + /// [`sol!`](alloy_sol_types::sol!) documentation on how to provide it), + /// the `deploy` and `deploy_builder` methods can be used to deploy a + /// new instance of the contract. + /// + /// See the [module-level documentation](self) for all the available + /// methods. + #[derive(Clone)] + pub struct ClusterInstance { + address: alloy_sol_types::private::Address, + provider: P, + _network_transport: ::core::marker::PhantomData<(N, T)>, + } + #[automatically_derived] + impl ::core::fmt::Debug for ClusterInstance { + #[inline] + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + f.debug_tuple("ClusterInstance") + .field(&self.address) + .finish() + } + } + /// Instantiation and getters/setters. + #[automatically_derived] + impl< + T: alloy_contract::private::Transport + ::core::clone::Clone, + P: alloy_contract::private::Provider, + N: alloy_contract::private::Network, + > ClusterInstance + { + /// Creates a new wrapper around an on-chain [`Cluster`](self) contract + /// instance. + /// + /// See the [wrapper's documentation](`ClusterInstance`) for more + /// details. + #[inline] + pub const fn new(address: alloy_sol_types::private::Address, provider: P) -> Self { + Self { + address, + provider, + _network_transport: ::core::marker::PhantomData, + } + } + /// Deploys this contract using the given `provider` and constructor + /// arguments, if any. + /// + /// Returns a new instance of the contract, if the deployment was + /// successful. + /// + /// For more fine-grained control over the deployment process, use + /// [`deploy_builder`] instead. + #[inline] + pub async fn deploy( + provider: P, + initialSettings: ::RustType, + initialOperators: alloy::sol_types::private::Vec< + ::RustType, + >, + ) -> alloy_contract::Result> { + let call_builder = Self::deploy_builder(provider, initialSettings, initialOperators); + let contract_address = call_builder.deploy().await?; + Ok(Self::new(contract_address, call_builder.provider)) + } + /// Creates a `RawCallBuilder` for deploying this contract using the + /// given `provider` and constructor arguments, if any. + /// + /// This is a simple wrapper around creating a `RawCallBuilder` with the + /// data set to the bytecode concatenated with the constructor's + /// ABI-encoded arguments. + #[inline] + pub fn deploy_builder( + provider: P, + initialSettings: ::RustType, + initialOperators: alloy::sol_types::private::Vec< + ::RustType, + >, + ) -> alloy_contract::RawCallBuilder { + alloy_contract::RawCallBuilder::new_raw_deploy( + provider, + [ + &BYTECODE[..], + &alloy_sol_types::SolConstructor::abi_encode(&constructorCall { + initialSettings, + initialOperators, + })[..], + ] + .concat() + .into(), + ) + } + /// Returns a reference to the address. + #[inline] + pub const fn address(&self) -> &alloy_sol_types::private::Address { + &self.address + } + /// Sets the address. + #[inline] + pub fn set_address(&mut self, address: alloy_sol_types::private::Address) { + self.address = address; + } + /// Sets the address and returns `self`. + pub fn at(mut self, address: alloy_sol_types::private::Address) -> Self { + self.set_address(address); + self + } + /// Returns a reference to the provider. + #[inline] + pub const fn provider(&self) -> &P { + &self.provider + } + } + impl ClusterInstance { + /// Clones the provider and returns a new instance with the cloned + /// provider. + #[inline] + pub fn with_cloned_provider(self) -> ClusterInstance { + ClusterInstance { + address: self.address, + provider: ::core::clone::Clone::clone(&self.provider), + _network_transport: ::core::marker::PhantomData, + } + } + } + /// Function calls. + #[automatically_derived] + impl< + T: alloy_contract::private::Transport + ::core::clone::Clone, + P: alloy_contract::private::Provider, + N: alloy_contract::private::Network, + > ClusterInstance + { + /// Creates a new call builder using this contract instance's provider + /// and address. + /// + /// Note that the call can be any function call, not just those defined + /// in this contract. Prefer using the other methods for + /// building type-safe contract calls. + pub fn call_builder( + &self, + call: &C, + ) -> alloy_contract::SolCallBuilder { + alloy_contract::SolCallBuilder::new_sol(&self.provider, &self.address, call) + } + /// Creates a new call builder for the [`abortMaintenance`] function. + pub fn abortMaintenance( + &self, + ) -> alloy_contract::SolCallBuilder { + self.call_builder(&abortMaintenanceCall {}) + } + /// Creates a new call builder for the [`abortMigration`] function. + pub fn abortMigration( + &self, + ) -> alloy_contract::SolCallBuilder { + self.call_builder(&abortMigrationCall {}) + } + /// Creates a new call builder for the [`completeMaintenance`] function. + pub fn completeMaintenance( + &self, + ) -> alloy_contract::SolCallBuilder { + self.call_builder(&completeMaintenanceCall {}) + } + /// Creates a new call builder for the [`completeMigration`] function. + pub fn completeMigration( + &self, + ) -> alloy_contract::SolCallBuilder { + self.call_builder(&completeMigrationCall {}) + } + /// Creates a new call builder for the [`getView`] function. + pub fn getView(&self) -> alloy_contract::SolCallBuilder { + self.call_builder(&getViewCall {}) + } + /// Creates a new call builder for the [`removeNode`] function. + pub fn removeNode( + &self, + id: alloy::sol_types::private::primitives::aliases::U256, + ) -> alloy_contract::SolCallBuilder { + self.call_builder(&removeNodeCall { id }) + } + /// Creates a new call builder for the [`setNode`] function. + pub fn setNode( + &self, + node: ::RustType, + ) -> alloy_contract::SolCallBuilder { + self.call_builder(&setNodeCall { node }) + } + /// Creates a new call builder for the [`startMaintenance`] function. + pub fn startMaintenance( + &self, + ) -> alloy_contract::SolCallBuilder { + self.call_builder(&startMaintenanceCall {}) + } + /// Creates a new call builder for the [`startMigration`] function. + pub fn startMigration( + &self, + operatorsToRemove: alloy::sol_types::private::Vec, + operatorsToAdd: alloy::sol_types::private::Vec< + ::RustType, + >, + ) -> alloy_contract::SolCallBuilder { + self.call_builder(&startMigrationCall { + operatorsToRemove, + operatorsToAdd, + }) + } + /// Creates a new call builder for the [`transferOwnership`] function. + pub fn transferOwnership( + &self, + newOwner: alloy::sol_types::private::Address, + ) -> alloy_contract::SolCallBuilder { + self.call_builder(&transferOwnershipCall { newOwner }) + } + /// Creates a new call builder for the [`updateSettings`] function. + pub fn updateSettings( + &self, + newSettings: ::RustType, + ) -> alloy_contract::SolCallBuilder { + self.call_builder(&updateSettingsCall { newSettings }) + } + } + /// Event filters. + #[automatically_derived] + impl< + T: alloy_contract::private::Transport + ::core::clone::Clone, + P: alloy_contract::private::Provider, + N: alloy_contract::private::Network, + > ClusterInstance + { + /// Creates a new event filter using this contract instance's provider + /// and address. + /// + /// Note that the type can be any event, not just those defined in this + /// contract. Prefer using the other methods for building + /// type-safe event filters. + pub fn event_filter( + &self, + ) -> alloy_contract::Event { + alloy_contract::Event::new_sol(&self.provider, &self.address) + } + /// Creates a new event filter for the [`MaintenanceAborted`] event. + pub fn MaintenanceAborted_filter( + &self, + ) -> alloy_contract::Event { + self.event_filter::() + } + /// Creates a new event filter for the [`MaintenanceCompleted`] event. + pub fn MaintenanceCompleted_filter( + &self, + ) -> alloy_contract::Event { + self.event_filter::() + } + /// Creates a new event filter for the [`MaintenanceStarted`] event. + pub fn MaintenanceStarted_filter( + &self, + ) -> alloy_contract::Event { + self.event_filter::() + } + /// Creates a new event filter for the [`MigrationAborted`] event. + pub fn MigrationAborted_filter(&self) -> alloy_contract::Event { + self.event_filter::() + } + /// Creates a new event filter for the [`MigrationCompleted`] event. + pub fn MigrationCompleted_filter( + &self, + ) -> alloy_contract::Event { + self.event_filter::() + } + /// Creates a new event filter for the [`MigrationDataPullCompleted`] + /// event. + pub fn MigrationDataPullCompleted_filter( + &self, + ) -> alloy_contract::Event { + self.event_filter::() + } + /// Creates a new event filter for the [`MigrationStarted`] event. + pub fn MigrationStarted_filter(&self) -> alloy_contract::Event { + self.event_filter::() + } + /// Creates a new event filter for the [`NodeRemoved`] event. + pub fn NodeRemoved_filter(&self) -> alloy_contract::Event { + self.event_filter::() + } + /// Creates a new event filter for the [`NodeSet`] event. + pub fn NodeSet_filter(&self) -> alloy_contract::Event { + self.event_filter::() + } + } +} diff --git a/crates/cluster/src/lib.rs b/crates/cluster/src/lib.rs new file mode 100644 index 00000000..a071d3c1 --- /dev/null +++ b/crates/cluster/src/lib.rs @@ -0,0 +1,4 @@ +#[rustfmt::skip] +pub mod contract; + +pub struct Cluster {} diff --git a/crates/cluster/tests/integration.rs b/crates/cluster/tests/integration.rs new file mode 100644 index 00000000..54f94862 --- /dev/null +++ b/crates/cluster/tests/integration.rs @@ -0,0 +1,6 @@ +use cluster::contract; + +#[tokio::test] +async fn test_suite() { + // cluster::contract::Cluster::deploy(); +} diff --git a/crates/core/Cargo.toml b/crates/core/Cargo.toml index bbc9f55c..7f876e09 100644 --- a/crates/core/Cargo.toml +++ b/crates/core/Cargo.toml @@ -26,7 +26,6 @@ derive_more = { workspace = true, features = ["as_ref", "display", "from", "try_ futures = "0.3" dashmap = "5.4" tap = "1.0" -async-trait = "0.1" bitflags = { version = "2.3", default-features = false, features = ["serde"] } chrono = { version = "0.4", default-features = false, features = [ "alloc", diff --git a/crates/node/Cargo.toml b/crates/node/Cargo.toml index 3b3fba60..db8c2d6d 100644 --- a/crates/node/Cargo.toml +++ b/crates/node/Cargo.toml @@ -49,7 +49,7 @@ time = { workspace = true } anyhow = "1" atty = "0.2" -axum = "0.6" +axum = "0.8" async-trait = "0.1" base64 = "0.20" backoff = { version = "0.4", features = ["tokio"] } @@ -88,12 +88,12 @@ xxhash-rust = { version = "0.8", features = ["xxh3", "const_xxh3"] } postcard = { version = "1.0", default-features = false, features = ["alloc"] } anyerror = "0.1" -alloy = { git = "https://github.com/alloy-rs/alloy", features = [ - "contract", - "providers", - "provider-http", - "signer-mnemonic", -] } +# alloy = { git = "https://github.com/alloy-rs/alloy", features = [ +# "contract", +# "providers", +# "provider-http", +# "signer-mnemonic", +# ] } reqwest = { version = "0.12", default-features = false } chrono = { version = "0.4", default-features = false } if-addrs = "0.13" diff --git a/crates/wcn/Cargo.toml b/crates/wcn/Cargo.toml index 806292c1..de6fac1c 100644 --- a/crates/wcn/Cargo.toml +++ b/crates/wcn/Cargo.toml @@ -47,12 +47,12 @@ fork = "0.1" # Smart Contract Integration -alloy = { git = "https://github.com/alloy-rs/alloy", features = [ - "contract", - "providers", - "provider-http", - "signer-mnemonic", -] } +# alloy = { git = "https://github.com/alloy-rs/alloy", features = [ +# "contract", +# "providers", +# "provider-http", +# "signer-mnemonic", +# ] } [lints] workspace = true From 4dfd645b204fca0d19af17a80718ed485584ac55 Mon Sep 17 00:00:00 2001 From: Github Bot Date: Tue, 13 May 2025 16:01:14 +0000 Subject: [PATCH 12/79] Bump VERSION to 250513.0 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 83bc0c2c..bdaa0f88 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -250508.0 +250513.0 From bb07f9213145e1667d5d8184924e757ea984bb38 Mon Sep 17 00:00:00 2001 From: Darksome Date: Wed, 14 May 2025 21:21:05 +0000 Subject: [PATCH 13/79] WIP --- Cargo.lock | 114 + crates/cluster/Cargo.toml | 11 +- .../cluster/src/contract/evm/bindings/mod.rs | 6281 +++++++++++++++++ crates/cluster/src/contract/evm/mod.rs | 98 + crates/cluster/src/contract/mod.rs | 5340 +------------- crates/cluster/src/event.rs | 40 + crates/cluster/src/lib.rs | 47 +- crates/cluster/src/node.rs | 206 + crates/cluster/tests/integration.rs | 29 +- 9 files changed, 6857 insertions(+), 5309 deletions(-) create mode 100644 crates/cluster/src/contract/evm/bindings/mod.rs create mode 100644 crates/cluster/src/contract/evm/mod.rs create mode 100644 crates/cluster/src/event.rs create mode 100644 crates/cluster/src/node.rs diff --git a/Cargo.lock b/Cargo.lock index 1c63db72..8e0b0e40 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -97,8 +97,13 @@ dependencies = [ "alloy-core", "alloy-eips", "alloy-network", + "alloy-node-bindings", "alloy-provider", "alloy-rpc-client", + "alloy-rpc-types", + "alloy-serde", + "alloy-signer", + "alloy-signer-local", "alloy-transport", "alloy-transport-http", ] @@ -257,6 +262,32 @@ dependencies = [ "sha2", ] +[[package]] +name = "alloy-genesis" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bd9e75c5dd40319ebbe807ebe9dfb10c24e4a70d9c7d638e62921d8dd093c8b" +dependencies = [ + "alloy-eips", + "alloy-primitives", + "alloy-serde", + "alloy-trie", + "serde", +] + +[[package]] +name = "alloy-hardforks" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "473ee2ab7f5262b36e8fbc1b5327d5c9d488ab247e31ac739b929dbe2444ae79" +dependencies = [ + "alloy-chains", + "alloy-eip2124", + "alloy-primitives", + "auto_impl", + "dyn-clone", +] + [[package]] name = "alloy-json-abi" version = "0.8.25" @@ -322,6 +353,27 @@ dependencies = [ "serde", ] +[[package]] +name = "alloy-node-bindings" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10f33291f6b969268b04b8f96ffab5071b3c241e593dd462372288b069787375" +dependencies = [ + "alloy-genesis", + "alloy-hardforks", + "alloy-network", + "alloy-primitives", + "alloy-signer", + "alloy-signer-local", + "k256", + "rand 0.8.5", + "serde_json", + "tempfile", + "thiserror 2.0.12", + "tracing", + "url", +] + [[package]] name = "alloy-primitives" version = "0.8.25" @@ -361,12 +413,15 @@ dependencies = [ "alloy-json-rpc", "alloy-network", "alloy-network-primitives", + "alloy-node-bindings", "alloy-primitives", "alloy-rpc-client", + "alloy-rpc-types-anvil", "alloy-rpc-types-eth", "alloy-signer", "alloy-sol-types", "alloy-transport", + "alloy-transport-http", "async-stream", "async-trait", "auto_impl", @@ -377,11 +432,13 @@ dependencies = [ "lru 0.13.0", "parking_lot", "pin-project", + "reqwest", "serde", "serde_json", "thiserror 2.0.12", "tokio", "tracing", + "url", "wasmtimer", ] @@ -420,6 +477,7 @@ dependencies = [ "async-stream", "futures", "pin-project", + "reqwest", "serde", "serde_json", "tokio", @@ -427,9 +485,35 @@ dependencies = [ "tower 0.5.2", "tracing", "tracing-futures", + "url", "wasmtimer", ] +[[package]] +name = "alloy-rpc-types" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3849f8131a18cc5d7f95f301d68a6af5aa2db28ad8522fb9db1f27b3794e8b68" +dependencies = [ + "alloy-primitives", + "alloy-rpc-types-anvil", + "alloy-rpc-types-eth", + "alloy-serde", + "serde", +] + +[[package]] +name = "alloy-rpc-types-anvil" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19051fd5e8de7e1f95ec228c9303debd776dcc7caf8d1ece3191f711f5c06541" +dependencies = [ + "alloy-primitives", + "alloy-rpc-types-eth", + "alloy-serde", + "serde", +] + [[package]] name = "alloy-rpc-types-any" version = "0.13.0" @@ -487,6 +571,22 @@ dependencies = [ "thiserror 2.0.12", ] +[[package]] +name = "alloy-signer-local" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2940353d2425bb75965cd5101075334e6271051e35610f903bf8099a52b0b1a9" +dependencies = [ + "alloy-consensus", + "alloy-network", + "alloy-primitives", + "alloy-signer", + "async-trait", + "k256", + "rand 0.8.5", + "thiserror 2.0.12", +] + [[package]] name = "alloy-sol-macro" version = "0.8.25" @@ -589,7 +689,12 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cc3079a33483afa1b1365a3add3ea3e21c75b10f704870198ba7846627d10f2" dependencies = [ + "alloy-json-rpc", "alloy-transport", + "reqwest", + "serde_json", + "tower 0.5.2", + "tracing", "url", ] @@ -1524,6 +1629,9 @@ name = "cluster" version = "0.1.0" dependencies = [ "alloy", + "libp2p", + "sharding", + "thiserror 1.0.64", "tokio", ] @@ -2164,6 +2272,12 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" +[[package]] +name = "dyn-clone" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c7a8fb8a9fbf66c1f703fe16184d10ca0ee9d23be5b4436400408ba54a95005" + [[package]] name = "ecdsa" version = "0.16.9" diff --git a/crates/cluster/Cargo.toml b/crates/cluster/Cargo.toml index 5e1d723e..1343c37b 100644 --- a/crates/cluster/Cargo.toml +++ b/crates/cluster/Cargo.toml @@ -6,8 +6,17 @@ edition = "2021" [lints] workspace = true +[features] +default = ["evm"] +evm = ["alloy"] + [dependencies] -alloy = { version = "0.13", default-features = false, features = ["sol-types", "contract"] } +sharding = { path = "../sharding" } + +alloy = { version = "0.13", default-features = false, features = ["sol-types", "contract", "signer-local", "network"], optional = true } +thiserror = "1" +libp2p = { workspace = true } [dev-dependencies] +alloy = { version = "0.13", default-features = false, features = ["provider-anvil-node"] } tokio = { version = "1", default-features = false } diff --git a/crates/cluster/src/contract/evm/bindings/mod.rs b/crates/cluster/src/contract/evm/bindings/mod.rs new file mode 100644 index 00000000..4059c590 --- /dev/null +++ b/crates/cluster/src/contract/evm/bindings/mod.rs @@ -0,0 +1,6281 @@ +#![allow(unused_imports, clippy::all, rustdoc::all)] +//! This module contains the sol! generated bindings for solidity contracts. +//! This is autogenerated code. +//! Do not manually edit these files. +//! These files may be overwritten by the codegen system at any time. +/** + +Generated by the following Solidity interface... +```solidity +interface Cluster { + struct ClusterView { + NodeOperatorsView operators; + MigrationView migration; + Maintenance maintenance; + uint64 keyspaceVersion; + uint128 version; + } + struct Maintenance { + address slot; + } + struct MigrationView { + address[] operatorsToRemove; + NodeOperatorView[] operatorsToAdd; + address[] pullingOperators; + } + struct Node { + uint256 id; + bytes data; + } + struct NodeOperatorView { + address addr; + Node[] nodes; + bytes data; + } + struct NodeOperatorsView { + NodeOperatorView[] slots; + } + struct Settings { + uint8 minOperators; + uint8 minNodes; + } + + event MaintenanceAborted(uint128 version); + event MaintenanceCompleted(address operator, uint128 version); + event MaintenanceStarted(address operator, uint128 version); + event MigrationAborted(uint128 version); + event MigrationCompleted(uint128 version); + event MigrationDataPullCompleted(address operator, uint128 version); + event MigrationStarted(address[] operatorsToRemove, NodeOperatorView[] operatorsToAdd, uint128 version); + event NodeRemoved(address operator, uint256 id, uint128 version); + event NodeSet(address operator, Node node, uint128 version); + + constructor(Settings initialSettings, NodeOperatorView[] initialOperators); + + function abortMaintenance() external; + function abortMigration() external; + function completeMaintenance() external; + function completeMigration() external; + function getView() external view returns (ClusterView memory); + function removeNode(uint256 id) external; + function setNode(Node memory node) external; + function startMaintenance() external; + function startMigration(address[] memory operatorsToRemove, NodeOperatorView[] memory operatorsToAdd) external; + function transferOwnership(address newOwner) external; + function updateSettings(Settings memory newSettings) external; +} +``` + +...which was generated by the following JSON ABI: +```json +[ + { + "type": "constructor", + "inputs": [ + { + "name": "initialSettings", + "type": "tuple", + "internalType": "struct Settings", + "components": [ + { + "name": "minOperators", + "type": "uint8", + "internalType": "uint8" + }, + { + "name": "minNodes", + "type": "uint8", + "internalType": "uint8" + } + ] + }, + { + "name": "initialOperators", + "type": "tuple[]", + "internalType": "struct NodeOperatorView[]", + "components": [ + { + "name": "addr", + "type": "address", + "internalType": "address" + }, + { + "name": "nodes", + "type": "tuple[]", + "internalType": "struct Node[]", + "components": [ + { + "name": "id", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "data", + "type": "bytes", + "internalType": "bytes" + } + ] + }, + { + "name": "data", + "type": "bytes", + "internalType": "bytes" + } + ] + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "abortMaintenance", + "inputs": [], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "abortMigration", + "inputs": [], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "completeMaintenance", + "inputs": [], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "completeMigration", + "inputs": [], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "getView", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "tuple", + "internalType": "struct ClusterView", + "components": [ + { + "name": "operators", + "type": "tuple", + "internalType": "struct NodeOperatorsView", + "components": [ + { + "name": "slots", + "type": "tuple[]", + "internalType": "struct NodeOperatorView[]", + "components": [ + { + "name": "addr", + "type": "address", + "internalType": "address" + }, + { + "name": "nodes", + "type": "tuple[]", + "internalType": "struct Node[]", + "components": [ + { + "name": "id", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "data", + "type": "bytes", + "internalType": "bytes" + } + ] + }, + { + "name": "data", + "type": "bytes", + "internalType": "bytes" + } + ] + } + ] + }, + { + "name": "migration", + "type": "tuple", + "internalType": "struct MigrationView", + "components": [ + { + "name": "operatorsToRemove", + "type": "address[]", + "internalType": "address[]" + }, + { + "name": "operatorsToAdd", + "type": "tuple[]", + "internalType": "struct NodeOperatorView[]", + "components": [ + { + "name": "addr", + "type": "address", + "internalType": "address" + }, + { + "name": "nodes", + "type": "tuple[]", + "internalType": "struct Node[]", + "components": [ + { + "name": "id", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "data", + "type": "bytes", + "internalType": "bytes" + } + ] + }, + { + "name": "data", + "type": "bytes", + "internalType": "bytes" + } + ] + }, + { + "name": "pullingOperators", + "type": "address[]", + "internalType": "address[]" + } + ] + }, + { + "name": "maintenance", + "type": "tuple", + "internalType": "struct Maintenance", + "components": [ + { + "name": "slot", + "type": "address", + "internalType": "address" + } + ] + }, + { + "name": "keyspaceVersion", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "version", + "type": "uint128", + "internalType": "uint128" + } + ] + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "removeNode", + "inputs": [ + { + "name": "id", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setNode", + "inputs": [ + { + "name": "node", + "type": "tuple", + "internalType": "struct Node", + "components": [ + { + "name": "id", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "data", + "type": "bytes", + "internalType": "bytes" + } + ] + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "startMaintenance", + "inputs": [], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "startMigration", + "inputs": [ + { + "name": "operatorsToRemove", + "type": "address[]", + "internalType": "address[]" + }, + { + "name": "operatorsToAdd", + "type": "tuple[]", + "internalType": "struct NodeOperatorView[]", + "components": [ + { + "name": "addr", + "type": "address", + "internalType": "address" + }, + { + "name": "nodes", + "type": "tuple[]", + "internalType": "struct Node[]", + "components": [ + { + "name": "id", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "data", + "type": "bytes", + "internalType": "bytes" + } + ] + }, + { + "name": "data", + "type": "bytes", + "internalType": "bytes" + } + ] + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "transferOwnership", + "inputs": [ + { + "name": "newOwner", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "updateSettings", + "inputs": [ + { + "name": "newSettings", + "type": "tuple", + "internalType": "struct Settings", + "components": [ + { + "name": "minOperators", + "type": "uint8", + "internalType": "uint8" + }, + { + "name": "minNodes", + "type": "uint8", + "internalType": "uint8" + } + ] + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "event", + "name": "MaintenanceAborted", + "inputs": [ + { + "name": "version", + "type": "uint128", + "indexed": false, + "internalType": "uint128" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "MaintenanceCompleted", + "inputs": [ + { + "name": "operator", + "type": "address", + "indexed": false, + "internalType": "address" + }, + { + "name": "version", + "type": "uint128", + "indexed": false, + "internalType": "uint128" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "MaintenanceStarted", + "inputs": [ + { + "name": "operator", + "type": "address", + "indexed": false, + "internalType": "address" + }, + { + "name": "version", + "type": "uint128", + "indexed": false, + "internalType": "uint128" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "MigrationAborted", + "inputs": [ + { + "name": "version", + "type": "uint128", + "indexed": false, + "internalType": "uint128" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "MigrationCompleted", + "inputs": [ + { + "name": "version", + "type": "uint128", + "indexed": false, + "internalType": "uint128" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "MigrationDataPullCompleted", + "inputs": [ + { + "name": "operator", + "type": "address", + "indexed": false, + "internalType": "address" + }, + { + "name": "version", + "type": "uint128", + "indexed": false, + "internalType": "uint128" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "MigrationStarted", + "inputs": [ + { + "name": "operatorsToRemove", + "type": "address[]", + "indexed": false, + "internalType": "address[]" + }, + { + "name": "operatorsToAdd", + "type": "tuple[]", + "indexed": false, + "internalType": "struct NodeOperatorView[]", + "components": [ + { + "name": "addr", + "type": "address", + "internalType": "address" + }, + { + "name": "nodes", + "type": "tuple[]", + "internalType": "struct Node[]", + "components": [ + { + "name": "id", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "data", + "type": "bytes", + "internalType": "bytes" + } + ] + }, + { + "name": "data", + "type": "bytes", + "internalType": "bytes" + } + ] + }, + { + "name": "version", + "type": "uint128", + "indexed": false, + "internalType": "uint128" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "NodeRemoved", + "inputs": [ + { + "name": "operator", + "type": "address", + "indexed": false, + "internalType": "address" + }, + { + "name": "id", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "version", + "type": "uint128", + "indexed": false, + "internalType": "uint128" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "NodeSet", + "inputs": [ + { + "name": "operator", + "type": "address", + "indexed": false, + "internalType": "address" + }, + { + "name": "node", + "type": "tuple", + "indexed": false, + "internalType": "struct Node", + "components": [ + { + "name": "id", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "data", + "type": "bytes", + "internalType": "bytes" + } + ] + }, + { + "name": "version", + "type": "uint128", + "indexed": false, + "internalType": "uint128" + } + ], + "anonymous": false + } +] +```*/ +#[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style, + clippy::empty_structs_with_brackets +)] +pub mod Cluster { + use super::*; + use alloy::sol_types as alloy_sol_types; + /// The creation / init bytecode of the contract. + /// + /// ```text + ///0x608060405234801561000f575f5ffd5b5060405161741138038061741183398181016040528101906100319190610e18565b335f5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508160015f820151815f015f6101000a81548160ff021916908360ff1602179055506020820151815f0160016101000a81548160ff021916908360ff1602179055509050506100c4815161014360201b60201c565b5f5f90505b815181101561013b576101008282815181106100e8576100e7610e72565b5b602002602001015160200151516101e160201b60201c565b61012e82828151811061011657610115610e72565b5b6020026020010151600261028060201b90919060201c565b80806001019150506100c9565b5050506114ea565b60015f015f9054906101000a900460ff1660ff16811015610199576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161019090610ef9565b60405180910390fd5b6101008111156101de576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101d590610f61565b60405180910390fd5b50565b60015f0160019054906101000a900460ff1660ff16811015610238576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161022f90610fc9565b60405180910390fd5b61010081111561027d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161027490611031565b60405180910390fd5b50565b61029382825f015161051360201b60201c565b156102d3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102ca90611099565b60405180910390fd5b5f5f8360020180549050111561036d5782600201600184600201805490506102fb91906110e4565b8154811061030c5761030b610e72565b5b905f5260205f2090602091828204019190069054906101000a900460ff169050826002018054806103405761033f611117565b5b600190038181905f5260205f2090602091828204019190066101000a81549060ff021916905590556103de565b610100835f0180549050106103b7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103ae90610f61565b60405180910390fd5b825f01805490509050825f0160018160018154018082558091505003905f5260205f209050505b80836001015f845f015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908360ff1602179055505f835f018260ff168154811061045157610450610e72565b5b905f5260205f2090600502019050825f0151815f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555082604001518160040190816104b8919061134b565b505f5f90505b83602001515181101561050c576104ff846020015182815181106104e5576104e4610e72565b5b60200260200101518360010161066b60201b90919060201c565b80806001019150506104be565b5050505050565b5f5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610582576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161057990611464565b60405180910390fd5b5f835f01805490501115610661575f836001015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1660ff1614158061065a57508173ffffffffffffffffffffffffffffffffffffffff16835f015f8154811061061457610613610e72565b5b905f5260205f2090600502015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b9050610665565b5f90505b92915050565b5f815f0151036106b0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106a7906114cc565b60405180910390fd5b5f5f835f0180549050111561076d57826001015f835f015181526020019081526020015f205f9054906101000a900460ff1690505f8160ff1614158061071b5750815f0151835f015f8154811061070a57610709610e72565b5b905f5260205f2090600202015f0154145b1561076c5781835f018260ff168154811061073957610738610e72565b5b905f5260205f2090600202015f820151815f01556020820151816001019081610762919061134b565b50905050506108ed565b5b5f8360020180549050111561080657826002016001846002018054905061079491906110e4565b815481106107a5576107a4610e72565b5b905f5260205f2090602091828204019190069054906101000a900460ff169050826002018054806107d9576107d8611117565b5b600190038181905f5260205f2090602091828204019190066101000a81549060ff02191690559055610877565b610100835f018054905010610850576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161084790611031565b60405180910390fd5b825f01805490509050825f0160018160018154018082558091505003905f5260205f209050505b80836001015f845f015181526020019081526020015f205f6101000a81548160ff021916908360ff16021790555081835f018260ff16815481106108be576108bd610e72565b5b905f5260205f2090600202015f820151815f015560208201518160010190816108e7919061134b565b50905050505b5050565b5f604051905090565b5f5ffd5b5f5ffd5b5f5ffd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b61094c82610906565b810181811067ffffffffffffffff8211171561096b5761096a610916565b5b80604052505050565b5f61097d6108f1565b90506109898282610943565b919050565b5f5ffd5b5f60ff82169050919050565b6109a781610992565b81146109b1575f5ffd5b50565b5f815190506109c28161099e565b92915050565b5f604082840312156109dd576109dc610902565b5b6109e76040610974565b90505f6109f6848285016109b4565b5f830152506020610a09848285016109b4565b60208301525092915050565b5f5ffd5b5f67ffffffffffffffff821115610a3357610a32610916565b5b602082029050602081019050919050565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f610a7182610a48565b9050919050565b610a8181610a67565b8114610a8b575f5ffd5b50565b5f81519050610a9c81610a78565b92915050565b5f67ffffffffffffffff821115610abc57610abb610916565b5b602082029050602081019050919050565b5f819050919050565b610adf81610acd565b8114610ae9575f5ffd5b50565b5f81519050610afa81610ad6565b92915050565b5f5ffd5b5f67ffffffffffffffff821115610b1e57610b1d610916565b5b610b2782610906565b9050602081019050919050565b8281835e5f83830152505050565b5f610b54610b4f84610b04565b610974565b905082815260208101848484011115610b7057610b6f610b00565b5b610b7b848285610b34565b509392505050565b5f82601f830112610b9757610b96610a15565b5b8151610ba7848260208601610b42565b91505092915050565b5f60408284031215610bc557610bc4610902565b5b610bcf6040610974565b90505f610bde84828501610aec565b5f83015250602082015167ffffffffffffffff811115610c0157610c0061098e565b5b610c0d84828501610b83565b60208301525092915050565b5f610c2b610c2684610aa2565b610974565b90508083825260208201905060208402830185811115610c4e57610c4d610a44565b5b835b81811015610c9557805167ffffffffffffffff811115610c7357610c72610a15565b5b808601610c808982610bb0565b85526020850194505050602081019050610c50565b5050509392505050565b5f82601f830112610cb357610cb2610a15565b5b8151610cc3848260208601610c19565b91505092915050565b5f60608284031215610ce157610ce0610902565b5b610ceb6060610974565b90505f610cfa84828501610a8e565b5f83015250602082015167ffffffffffffffff811115610d1d57610d1c61098e565b5b610d2984828501610c9f565b602083015250604082015167ffffffffffffffff811115610d4d57610d4c61098e565b5b610d5984828501610b83565b60408301525092915050565b5f610d77610d7284610a19565b610974565b90508083825260208201905060208402830185811115610d9a57610d99610a44565b5b835b81811015610de157805167ffffffffffffffff811115610dbf57610dbe610a15565b5b808601610dcc8982610ccc565b85526020850194505050602081019050610d9c565b5050509392505050565b5f82601f830112610dff57610dfe610a15565b5b8151610e0f848260208601610d65565b91505092915050565b5f5f60608385031215610e2e57610e2d6108fa565b5b5f610e3b858286016109c8565b925050604083015167ffffffffffffffff811115610e5c57610e5b6108fe565b5b610e6885828601610deb565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f82825260208201905092915050565b7f746f6f20666577206f70657261746f72730000000000000000000000000000005f82015250565b5f610ee3601183610e9f565b9150610eee82610eaf565b602082019050919050565b5f6020820190508181035f830152610f1081610ed7565b9050919050565b7f746f6f206d616e79206f70657261746f727300000000000000000000000000005f82015250565b5f610f4b601283610e9f565b9150610f5682610f17565b602082019050919050565b5f6020820190508181035f830152610f7881610f3f565b9050919050565b7f746f6f20666577206e6f646573000000000000000000000000000000000000005f82015250565b5f610fb3600d83610e9f565b9150610fbe82610f7f565b602082019050919050565b5f6020820190508181035f830152610fe081610fa7565b9050919050565b7f746f6f206d616e79206e6f6465730000000000000000000000000000000000005f82015250565b5f61101b600e83610e9f565b915061102682610fe7565b602082019050919050565b5f6020820190508181035f8301526110488161100f565b9050919050565b7f6f70657261746f7220616c7265616479206578697374730000000000000000005f82015250565b5f611083601783610e9f565b915061108e8261104f565b602082019050919050565b5f6020820190508181035f8301526110b081611077565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6110ee82610acd565b91506110f983610acd565b9250828203905081811115611111576111106110b7565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffd5b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061119257607f821691505b6020821081036111a5576111a461114e565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026112077fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826111cc565b61121186836111cc565b95508019841693508086168417925050509392505050565b5f819050919050565b5f61124c61124761124284610acd565b611229565b610acd565b9050919050565b5f819050919050565b61126583611232565b61127961127182611253565b8484546111d8565b825550505050565b5f5f905090565b611290611281565b61129b81848461125c565b505050565b5b818110156112be576112b35f82611288565b6001810190506112a1565b5050565b601f821115611303576112d4816111ab565b6112dd846111bd565b810160208510156112ec578190505b6113006112f8856111bd565b8301826112a0565b50505b505050565b5f82821c905092915050565b5f6113235f1984600802611308565b1980831691505092915050565b5f61133b8383611314565b9150826002028217905092915050565b61135482611144565b67ffffffffffffffff81111561136d5761136c610916565b5b611377825461117b565b6113828282856112c2565b5f60209050601f8311600181146113b3575f84156113a1578287015190505b6113ab8582611330565b865550611412565b601f1984166113c1866111ab565b5f5b828110156113e8578489015182556001820191506020850194506020810190506113c3565b868310156114055784890151611401601f891682611314565b8355505b6001600288020188555050505b505050505050565b7f696e76616c6964206164647265737300000000000000000000000000000000005f82015250565b5f61144e600f83610e9f565b91506114598261141a565b602082019050919050565b5f6020820190508181035f83015261147b81611442565b9050919050565b7f696e76616c6964206964000000000000000000000000000000000000000000005f82015250565b5f6114b6600a83610e9f565b91506114c182611482565b602082019050919050565b5f6020820190508181035f8301526114e3816114aa565b9050919050565b615f1a806114f75f395ff3fe608060405234801561000f575f5ffd5b50600436106100a7575f3560e01c8063ad36e6d01161006f578063ad36e6d014610115578063c130809a1461011f578063cc45662a14610129578063f2fde38b14610145578063f5f2d9f114610161578063ffd740df1461016b576100a7565b80633048bfba146100ab578063409900e8146100b55780634886f62c146100d15780636c0b61b9146100db57806375418b9d146100f7575b5f5ffd5b6100b3610187565b005b6100cf60048036038101906100ca91906139e2565b6102db565b005b6100d961037e565b005b6100f560048036038101906100f09190613a2b565b61082c565b005b6100ff610956565b60405161010c9190613f47565b60405180910390f35b61011d610a58565b005b610127610b7d565b005b610143600480360381019061013e919061401d565b610cd1565b005b61015f600480360381019061015a91906140c5565b61103b565b005b61016961110b565b005b6101856004803603810190610180919061411a565b61127a565b005b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610215576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161020c9061419f565b60405180910390fd5b61021f600961140e565b600a600881819054906101000a90046fffffffffffffffffffffffffffffffff168092919061024d906141ea565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507f8fb9cd054d0a022110cced239e908b834e4cd219511856d4eaae3051d932d604600a60089054906101000a90046fffffffffffffffffffffffffffffffff166040516102d19190614230565b60405180910390a1565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610369576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103609061419f565b60405180910390fd5b806001818161037891906143c4565b90505050565b6103923360056114c690919063ffffffff16565b600a600881819054906101000a90046fffffffffffffffffffffffffffffffff16809291906103c0906141ea565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507fa76a8fc1a90266ddee8937a18e12f01eade946b3b66197fff289af9277c2bd2533600a60089054906101000a90046fffffffffffffffffffffffffffffffff166040516104469291906143e1565b60405180910390a15f60056003015f9054906101000a900460ff1660ff161161082a575f5f90505b60055f01805490508110156104db576104ce60055f01828154811061049657610495614408565b5b905f5260205f20015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660026115e490919063ffffffff16565b808060010191505061046e565b505f5f90505b6005600101805490508110156107185761070b6005600101828154811061050b5761050a614408565b5b905f5260205f2090600302016040518060600160405290815f82015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160018201805480602002602001604051908101604052809291908181526020015f905b82821015610663578382905f5260205f2090600202016040518060400160405290815f82015481526020016001820180546105d490614462565b80601f016020809104026020016040519081016040528092919081815260200182805461060090614462565b801561064b5780601f106106225761010080835404028352916020019161064b565b820191905f5260205f20905b81548152906001019060200180831161062e57829003601f168201915b5050505050815250508152602001906001019061059a565b50505050815260200160028201805461067b90614462565b80601f01602080910402602001604051908101604052809291908181526020018280546106a790614462565b80156106f25780601f106106c9576101008083540402835291602001916106f2565b820191905f5260205f20905b8154815290600101906020018083116106d557829003601f168201915b505050505081525050600261187690919063ffffffff16565b80806001019150506104e1565b50600a5f81819054906101000a900467ffffffffffffffff168092919061073e90614492565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055505061076f6005611b03565b600a600881819054906101000a90046fffffffffffffffffffffffffffffffff168092919061079d906141ea565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507f11ce50160e66100537fd4b0ae26de66d51dab713ad92313353a18c24e8f6daab600a60089054906101000a90046fffffffffffffffffffffffffffffffff166040516108219190614230565b60405180910390a15b565b610840336002611bac90919063ffffffff16565b61087f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108769061450b565b60405180910390fd5b61089533826002611d049092919063ffffffff16565b600a600881819054906101000a90046fffffffffffffffffffffffffffffffff16809291906108c3906141ea565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507f6adfb896d3407681d05fb874d4dfb7068e6e2a36f09acd38a3b7d04c01745fee3382600a60089054906101000a90046fffffffffffffffffffffffffffffffff1660405161094b93929190614633565b60405180910390a150565b61095e613746565b6040518060a001604052806109736002611d96565b815260200161098f60025f016005611f9990919063ffffffff16565b815260200160096040518060200160405290815f82015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815250508152602001600a5f9054906101000a900467ffffffffffffffff1667ffffffffffffffff168152602001600a60089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff16815250905090565b610a6c336002611bac90919063ffffffff16565b610aab576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610aa29061450b565b60405180910390fd5b610abf33600961270090919063ffffffff16565b600a600881819054906101000a90046fffffffffffffffffffffffffffffffff1680929190610aed906141ea565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507ff91067eb420c28d3124865fc996e6aa9d541b9b4fef9188cb965a6cc6491638e33600a60089054906101000a90046fffffffffffffffffffffffffffffffff16604051610b739291906143e1565b60405180910390a1565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610c0b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c029061419f565b60405180910390fd5b610c156005612827565b600a600881819054906101000a90046fffffffffffffffffffffffffffffffff1680929190610c43906141ea565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507f9ce192aea5faf2151bbc246cd8918d2eba702fa26951f67f2bf7b3817e689d98600a60089054906101000a90046fffffffffffffffffffffffffffffffff16604051610cc79190614230565b60405180910390a1565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610d5f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d569061419f565b60405180910390fd5b610d69600961287b565b15610da9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610da0906146b9565b60405180910390fd5b5f5f90505b84849050811015610e4057610df4858583818110610dcf57610dce614408565b5b9050602002016020810190610de491906140c5565b6002611bac90919063ffffffff16565b610e33576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e2a90614721565b60405180910390fd5b8080600101915050610dae565b505f5f90505b82829050811015610f2557610e8f838383818110610e6757610e66614408565b5b9050602002810190610e79919061474b565b8060200190610e889190614772565b90506128d5565b610ed8838383818110610ea557610ea4614408565b5b9050602002810190610eb7919061474b565b5f016020810190610ec891906140c5565b6002611bac90919063ffffffff16565b15610f18576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f0f9061481e565b60405180910390fd5b8080600101915050610e46565b50610f548282905085859050610f3b6002612974565b610f45919061483c565b610f4f919061486f565b612995565b610f7360025f01858585856005612a339095949392919063ffffffff16565b600a600881819054906101000a90046fffffffffffffffffffffffffffffffff1680929190610fa1906141ea565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507f7e05e40117b6e18ab284c04a3508c3826422dc84a65e9c236a8248774416f8ac84848484600a60089054906101000a90046fffffffffffffffffffffffffffffffff1660405161102d959493929190614be8565b60405180910390a150505050565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146110c9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110c09061419f565b60405180910390fd5b805f5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b61111f336002611bac90919063ffffffff16565b61115e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111559061450b565b60405180910390fd5b6111686005612ed5565b156111a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161119f90614c79565b60405180910390fd5b6111bc336009612ef990919063ffffffff16565b600a600881819054906101000a90046fffffffffffffffffffffffffffffffff16809291906111ea906141ea565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507fbc2748cf02f7a1291525e866efc76ab3b96d32d7afcbb26c53daec617b38b47933600a60089054906101000a90046fffffffffffffffffffffffffffffffff166040516112709291906143e1565b60405180910390a1565b61128e336002611bac90919063ffffffff16565b6112cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112c49061450b565b60405180910390fd5b6112e33382600261303c9092919063ffffffff16565b60015f0160019054906101000a900460ff1660ff1661130c3360026130c590919063ffffffff16565b101561134d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161134490614ce1565b60405180910390fd5b600a600881819054906101000a90046fffffffffffffffffffffffffffffffff168092919061137b906141ea565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507fbd184de79f134b0f3da466d278f5417cbcb1450d72f1bd1a1b84f18b1bcd03ca3382600a60089054906101000a90046fffffffffffffffffffffffffffffffff1660405161140393929190614d0e565b60405180910390a150565b5f73ffffffffffffffffffffffffffffffffffffffff16815f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff160361149e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161149590614d8d565b60405180910390fd5b805f015f6101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905550565b816002015f8273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16611551576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161154890614df5565b60405180910390fd5b5f826002015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908315150217905550816003015f81819054906101000a900460ff16809291906115c790614e13565b91906101000a81548160ff021916908360ff160217905550505050565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611652576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161164990614e84565b60405180910390fd5b5f826001015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1690505f8160ff1614158061172057508173ffffffffffffffffffffffffffffffffffffffff16835f015f815481106116da576116d9614408565b5b905f5260205f2090600502015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b61175f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161175690614eec565b60405180910390fd5b826001015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81549060ff0219169055825f018160ff16815481106117c5576117c4614408565b5b905f5260205f2090600502015f5f82015f6101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600182015f5f82015f61180a91906137a1565b600282015f61181991906137c2565b5050600482015f61182a91906137e7565b50508260020181908060018154018082558091505060019003905f5260205f2090602091828204019190069091909190916101000a81548160ff021916908360ff160217905550505050565b61188382825f0151611bac565b156118c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118ba9061481e565b60405180910390fd5b5f5f8360020180549050111561195d5782600201600184600201805490506118eb919061483c565b815481106118fc576118fb614408565b5b905f5260205f2090602091828204019190069054906101000a900460ff169050826002018054806119305761192f614f0a565b5b600190038181905f5260205f2090602091828204019190066101000a81549060ff021916905590556119ce565b610100835f0180549050106119a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161199e90614f81565b60405180910390fd5b825f01805490509050825f0160018160018154018082558091505003905f5260205f209050505b80836001015f845f015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908360ff1602179055505f835f018260ff1681548110611a4157611a40614408565b5b905f5260205f2090600502019050825f0151815f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508260400151816004019081611aa89190615163565b505f5f90505b836020015151811015611afc57611aef84602001518281518110611ad557611ad4614408565b5b60200260200101518360010161314890919063ffffffff16565b8080600101915050611aae565b5050505050565b611b0c81612ed5565b611b4b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b429061527c565b60405180910390fd5b5f816003015f9054906101000a900460ff1660ff1614611ba0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b97906152e4565b60405180910390fd5b611ba9816133ce565b50565b5f5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611c1b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c1290614e84565b60405180910390fd5b5f835f01805490501115611cfa575f836001015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1660ff16141580611cf357508173ffffffffffffffffffffffffffffffffffffffff16835f015f81548110611cad57611cac614408565b5b905f5260205f2090600502015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b9050611cfe565b5f90505b92915050565b611d9181611d1190615460565b845f01856001015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1660ff1681548110611d7457611d73614408565b5b905f5260205f20906005020160010161314890919063ffffffff16565b505050565b611d9e613824565b5f825f018054905067ffffffffffffffff811115611dbf57611dbe614f9f565b5b604051908082528060200260200182016040528015611df857816020015b611de5613837565b815260200190600190039081611ddd5790505b5090505f5f90505b835f0180549050811015611f81576040518060600160405280855f018381548110611e2e57611e2d614408565b5b905f5260205f2090600502015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001611ea3865f018481548110611e8f57611e8e614408565b5b905f5260205f209060050201600101613401565b8152602001855f018381548110611ebd57611ebc614408565b5b905f5260205f2090600502016004018054611ed790614462565b80601f0160208091040260200160405190810160405280929190818152602001828054611f0390614462565b8015611f4e5780601f10611f2557610100808354040283529160200191611f4e565b820191905f5260205f20905b815481529060010190602001808311611f3157829003601f168201915b5050505050815250828281518110611f6957611f68614408565b5b60200260200101819052508080600101915050611e00565b50604051806020016040528082815250915050919050565b611fa161386d565b5f835f018054905067ffffffffffffffff811115611fc257611fc1614f9f565b5b604051908082528060200260200182016040528015611ff05781602001602082028036833780820191505090505b5090505f5f90505b845f018054905081101561209d57845f01818154811061201b5761201a614408565b5b905f5260205f20015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682828151811061205657612055614408565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508080600101915050611ff8565b505f846001018054905067ffffffffffffffff8111156120c0576120bf614f9f565b5b6040519080825280602002602001820160405280156120f957816020015b6120e6613837565b8152602001906001900390816120de5790505b5090505f5f90505b85600101805490508110156123415785600101818154811061212657612125614408565b5b905f5260205f2090600302016040518060600160405290815f82015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160018201805480602002602001604051908101604052809291908181526020015f905b8282101561227e578382905f5260205f2090600202016040518060400160405290815f82015481526020016001820180546121ef90614462565b80601f016020809104026020016040519081016040528092919081815260200182805461221b90614462565b80156122665780601f1061223d57610100808354040283529160200191612266565b820191905f5260205f20905b81548152906001019060200180831161224957829003601f168201915b505050505081525050815260200190600101906121b5565b50505050815260200160028201805461229690614462565b80601f01602080910402602001604051908101604052809291908181526020018280546122c290614462565b801561230d5780601f106122e45761010080835404028352916020019161230d565b820191905f5260205f20905b8154815290600101906020018083116122f057829003601f168201915b50505050508152505082828151811061232957612328614408565b5b60200260200101819052508080600101915050612101565b505f856003015f9054906101000a900460ff1660ff1667ffffffffffffffff8111156123705761236f614f9f565b5b60405190808252806020026020018201604052801561239e5781602001602082028036833780820191505090505b5090505f866003015f9054906101000a900460ff1660ff1611156126da575f5f5f90505b8680549050811015612581575f73ffffffffffffffffffffffffffffffffffffffff168782815481106123f8576123f7614408565b5b905f5260205f2090600502015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141580156124d25750876002015f88838154811061245d5761245c614408565b5b905f5260205f2090600502015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff165b15612574578681815481106124ea576124e9614408565b5b905f5260205f2090600502015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683838151811061252b5761252a614408565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050818061257090615472565b9250505b80806001019150506123c2565b505f5f90505b87600101805490508110156126d757876002015f8960010183815481106125b1576125b0614408565b5b905f5260205f2090600302015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16156126ca578760010181815481106126405761263f614408565b5b905f5260205f2090600302015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683838151811061268157612680614408565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505081806126c690615472565b9250505b8080600101915050612587565b50505b604051806060016040528084815260200183815260200182815250935050505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361276e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161276590614e84565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16825f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146127fe576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127f590614d8d565b60405180910390fd5b815f015f6101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690555050565b61283081612ed5565b61286f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016128669061527c565b60405180910390fd5b612878816133ce565b50565b5f5f73ffffffffffffffffffffffffffffffffffffffff16825f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614159050919050565b60015f0160019054906101000a900460ff1660ff1681101561292c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161292390614ce1565b60405180910390fd5b610100811115612971576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161296890615503565b60405180910390fd5b50565b5f8160020180549050825f018054905061298e919061483c565b9050919050565b60015f015f9054906101000a900460ff1660ff168110156129eb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129e29061556b565b60405180910390fd5b610100811115612a30576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a2790614f81565b60405180910390fd5b50565b612a3c86612ed5565b15612a7c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a73906155d3565b60405180910390fd5b5f848490501180612a8f57505f82829050115b612ace576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612ac59061563b565b60405180910390fd5b5f5f90505b8580549050811015612c30575f73ffffffffffffffffffffffffffffffffffffffff16868281548110612b0957612b08614408565b5b905f5260205f2090600502015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612c23576001876002015f888481548110612b6c57612b6b614408565b5b905f5260205f2090600502015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908315150217905550866003015f81819054906101000a900460ff1680929190612c0990615659565b91906101000a81548160ff021916908360ff160217905550505b8080600101915050612ad3565b505f5f90505b84849050811015612d8c57865f01858583818110612c5757612c56614408565b5b9050602002016020810190612c6c91906140c5565b908060018154018082558091505060019003905f5260205f20015f9091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505f876002015f878785818110612ce257612ce1614408565b5b9050602002016020810190612cf791906140c5565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908315150217905550866003015f81819054906101000a900460ff1680929190612d6690614e13565b91906101000a81548160ff021916908360ff160217905550508080600101915050612c36565b505f5f90505b82829050811015612ecc5786600101838383818110612db457612db3614408565b5b9050602002810190612dc6919061474b565b908060018154018082558091505060019003905f5260205f2090600302015f909190919091508181612df89190615d9e565b50506001876002015f858585818110612e1457612e13614408565b5b9050602002810190612e26919061474b565b5f016020810190612e3791906140c5565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908315150217905550866003015f81819054906101000a900460ff1680929190612ea690615659565b91906101000a81548160ff021916908360ff160217905550508080600101915050612d92565b50505050505050565b5f5f825f0180549050141580612ef257505f826001018054905014155b9050919050565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612f67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612f5e90614e84565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff16825f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612ff7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612fee90615df6565b60405180910390fd5b80825f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b6130c081845f01856001015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1660ff16815481106130a3576130a2614408565b5b905f5260205f2090600502016001016135c790919063ffffffff16565b505050565b5f613140835f01846001015f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1660ff168154811061312c5761312b614408565b5b905f5260205f209060050201600101613725565b905092915050565b5f815f01510361318d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161318490615e5e565b60405180910390fd5b5f5f835f0180549050111561324a57826001015f835f015181526020019081526020015f205f9054906101000a900460ff1690505f8160ff161415806131f85750815f0151835f015f815481106131e7576131e6614408565b5b905f5260205f2090600202015f0154145b156132495781835f018260ff168154811061321657613215614408565b5b905f5260205f2090600202015f820151815f0155602082015181600101908161323f9190615163565b50905050506133ca565b5b5f836002018054905011156132e3578260020160018460020180549050613271919061483c565b8154811061328257613281614408565b5b905f5260205f2090602091828204019190069054906101000a900460ff169050826002018054806132b6576132b5614f0a565b5b600190038181905f5260205f2090602091828204019190066101000a81549060ff02191690559055613354565b610100835f01805490501061332d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161332490615503565b60405180910390fd5b825f01805490509050825f0160018160018154018082558091505003905f5260205f209050505b80836001015f845f015181526020019081526020015f205f6101000a81548160ff021916908360ff16021790555081835f018260ff168154811061339b5761339a614408565b5b905f5260205f2090600202015f820151815f015560208201518160010190816133c49190615163565b50905050505b5050565b805f015f6133dc919061388e565b806001015f6133eb91906138ac565b806003015f6101000a81549060ff021916905550565b60605f61340d83613725565b67ffffffffffffffff81111561342657613425614f9f565b5b60405190808252806020026020018201604052801561345f57816020015b61344c6138cd565b8152602001906001900390816134445790505b5090505f5f5f90505b845f01805490508110156135bc575f855f01828154811061348c5761348b614408565b5b905f5260205f2090600202015f0154146135af576040518060400160405280865f0183815481106134c0576134bf614408565b5b905f5260205f2090600202015f01548152602001865f0183815481106134e9576134e8614408565b5b905f5260205f209060020201600101805461350390614462565b80601f016020809104026020016040519081016040528092919081815260200182805461352f90614462565b801561357a5780601f106135515761010080835404028352916020019161357a565b820191905f5260205f20905b81548152906001019060200180831161355d57829003601f168201915b505050505081525083838151811061359557613594614408565b5b602002602001018190525081806135ab90615472565b9250505b8080600101915050613468565b508192505050919050565b5f8103613609576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161360090615e5e565b60405180910390fd5b5f826001015f8381526020019081526020015f205f9054906101000a900460ff1690505f8160ff16141580613660575081835f015f8154811061364f5761364e614408565b5b905f5260205f2090600202015f0154145b61369f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161369690615ec6565b60405180910390fd5b825f018160ff16815481106136b7576136b6614408565b5b905f5260205f2090600202015f5f82015f9055600182015f6136d991906137e7565b50508260020181908060018154018082558091505060019003905f5260205f2090602091828204019190069091909190916101000a81548160ff021916908360ff160217905550505050565b5f8160020180549050825f018054905061373f919061483c565b9050919050565b6040518060a00160405280613759613824565b815260200161376661386d565b81526020016137736138e6565b81526020015f67ffffffffffffffff1681526020015f6fffffffffffffffffffffffffffffffff1681525090565b5080545f8255600202905f5260205f20908101906137bf919061390e565b50565b5080545f8255601f0160209004905f5260205f20908101906137e4919061393a565b50565b5080546137f390614462565b5f825580601f106138045750613821565b601f0160209004905f5260205f2090810190613820919061393a565b5b50565b6040518060200160405280606081525090565b60405180606001604052805f73ffffffffffffffffffffffffffffffffffffffff16815260200160608152602001606081525090565b60405180606001604052806060815260200160608152602001606081525090565b5080545f8255905f5260205f20908101906138a9919061393a565b50565b5080545f8255600302905f5260205f20908101906138ca9190613955565b50565b60405180604001604052805f8152602001606081525090565b60405180602001604052805f73ffffffffffffffffffffffffffffffffffffffff1681525090565b5b80821115613936575f5f82015f9055600182015f61392d91906137e7565b5060020161390f565b5090565b5b80821115613951575f815f90555060010161393b565b5090565b5b808211156139ab575f5f82015f6101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600182015f61399391906137a1565b600282015f6139a291906137e7565b50600301613956565b5090565b5f604051905090565b5f5ffd5b5f5ffd5b5f5ffd5b5f604082840312156139d9576139d86139c0565b5b81905092915050565b5f604082840312156139f7576139f66139b8565b5b5f613a04848285016139c4565b91505092915050565b5f60408284031215613a2257613a216139c0565b5b81905092915050565b5f60208284031215613a4057613a3f6139b8565b5b5f82013567ffffffffffffffff811115613a5d57613a5c6139bc565b5b613a6984828501613a0d565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f613ac482613a9b565b9050919050565b613ad481613aba565b82525050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f819050919050565b613b1581613b03565b82525050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f613b5d82613b1b565b613b678185613b25565b9350613b77818560208601613b35565b613b8081613b43565b840191505092915050565b5f604083015f830151613ba05f860182613b0c565b5060208301518482036020860152613bb88282613b53565b9150508091505092915050565b5f613bd08383613b8b565b905092915050565b5f602082019050919050565b5f613bee82613ada565b613bf88185613ae4565b935083602082028501613c0a85613af4565b805f5b85811015613c455784840389528151613c268582613bc5565b9450613c3183613bd8565b925060208a01995050600181019050613c0d565b50829750879550505050505092915050565b5f606083015f830151613c6c5f860182613acb565b5060208301518482036020860152613c848282613be4565b91505060408301518482036040860152613c9e8282613b53565b9150508091505092915050565b5f613cb68383613c57565b905092915050565b5f602082019050919050565b5f613cd482613a72565b613cde8185613a7c565b935083602082028501613cf085613a8c565b805f5b85811015613d2b5784840389528151613d0c8582613cab565b9450613d1783613cbe565b925060208a01995050600181019050613cf3565b50829750879550505050505092915050565b5f602083015f8301518482035f860152613d578282613cca565b9150508091505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f613d988383613acb565b60208301905092915050565b5f602082019050919050565b5f613dba82613d64565b613dc48185613d6e565b9350613dcf83613d7e565b805f5b83811015613dff578151613de68882613d8d565b9750613df183613da4565b925050600181019050613dd2565b5085935050505092915050565b5f606083015f8301518482035f860152613e268282613db0565b91505060208301518482036020860152613e408282613cca565b91505060408301518482036040860152613e5a8282613db0565b9150508091505092915050565b602082015f820151613e7b5f850182613acb565b50505050565b5f67ffffffffffffffff82169050919050565b613e9d81613e81565b82525050565b5f6fffffffffffffffffffffffffffffffff82169050919050565b613ec781613ea3565b82525050565b5f60a083015f8301518482035f860152613ee78282613d3d565b91505060208301518482036020860152613f018282613e0c565b9150506040830151613f166040860182613e67565b506060830151613f296060860182613e94565b506080830151613f3c6080860182613ebe565b508091505092915050565b5f6020820190508181035f830152613f5f8184613ecd565b905092915050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f83601f840112613f8857613f87613f67565b5b8235905067ffffffffffffffff811115613fa557613fa4613f6b565b5b602083019150836020820283011115613fc157613fc0613f6f565b5b9250929050565b5f5f83601f840112613fdd57613fdc613f67565b5b8235905067ffffffffffffffff811115613ffa57613ff9613f6b565b5b60208301915083602082028301111561401657614015613f6f565b5b9250929050565b5f5f5f5f60408587031215614035576140346139b8565b5b5f85013567ffffffffffffffff811115614052576140516139bc565b5b61405e87828801613f73565b9450945050602085013567ffffffffffffffff811115614081576140806139bc565b5b61408d87828801613fc8565b925092505092959194509250565b6140a481613aba565b81146140ae575f5ffd5b50565b5f813590506140bf8161409b565b92915050565b5f602082840312156140da576140d96139b8565b5b5f6140e7848285016140b1565b91505092915050565b6140f981613b03565b8114614103575f5ffd5b50565b5f81359050614114816140f0565b92915050565b5f6020828403121561412f5761412e6139b8565b5b5f61413c84828501614106565b91505092915050565b5f82825260208201905092915050565b7f6e6f7420746865206f776e6572000000000000000000000000000000000000005f82015250565b5f614189600d83614145565b915061419482614155565b602082019050919050565b5f6020820190508181035f8301526141b68161417d565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6141f482613ea3565b91506fffffffffffffffffffffffffffffffff8203614216576142156141bd565b5b600182019050919050565b61422a81613ea3565b82525050565b5f6020820190506142435f830184614221565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b5f60ff82169050919050565b61428a81614275565b8114614294575f5ffd5b50565b5f81356142a381614281565b80915050919050565b5f815f1b9050919050565b5f60ff6142c3846142ac565b9350801983169250808416831791505092915050565b5f819050919050565b5f6142fc6142f76142f284614275565b6142d9565b614275565b9050919050565b5f819050919050565b614315826142e2565b61432861432182614303565b83546142b7565b8255505050565b5f8160081b9050919050565b5f61ff006143488461432f565b9350801983169250808416831791505092915050565b614367826142e2565b61437a61437382614303565b835461433b565b8255505050565b5f81015f83018061439181614297565b905061439d818461430c565b5050505f810160208301806143b181614297565b90506143bd818461435e565b5050505050565b6143ce8282614381565b5050565b6143db81613aba565b82525050565b5f6040820190506143f45f8301856143d2565b6144016020830184614221565b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061447957607f821691505b60208210810361448c5761448b614435565b5b50919050565b5f61449c82613e81565b915067ffffffffffffffff82036144b6576144b56141bd565b5b600182019050919050565b7f6e6f7420616e206f70657261746f7200000000000000000000000000000000005f82015250565b5f6144f5600f83614145565b9150614500826144c1565b602082019050919050565b5f6020820190508181035f830152614522816144e9565b9050919050565b5f6145376020840184614106565b905092915050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f8335600160200384360303811261456757614566614547565b5b83810192508235915060208301925067ffffffffffffffff82111561458f5761458e61453f565b5b6001820236038313156145a5576145a4614543565b5b509250929050565b828183375f83830152505050565b5f6145c68385613b25565b93506145d38385846145ad565b6145dc83613b43565b840190509392505050565b5f604083016145f85f840184614529565b6146045f860182613b0c565b50614612602084018461454b565b85830360208701526146258382846145bb565b925050508091505092915050565b5f6060820190506146465f8301866143d2565b818103602083015261465881856145e7565b90506146676040830184614221565b949350505050565b7f6d61696e74656e616e636520696e2070726f67726573730000000000000000005f82015250565b5f6146a3601783614145565b91506146ae8261466f565b602082019050919050565b5f6020820190508181035f8301526146d081614697565b9050919050565b7f756e6b6e6f776e206f70657261746f72000000000000000000000000000000005f82015250565b5f61470b601083614145565b9150614716826146d7565b602082019050919050565b5f6020820190508181035f830152614738816146ff565b9050919050565b5f5ffd5b5f5ffd5b5f5ffd5b5f823560016060038336030381126147665761476561473f565b5b80830191505092915050565b5f5f8335600160200384360303811261478e5761478d61473f565b5b80840192508235915067ffffffffffffffff8211156147b0576147af614743565b5b6020830192506020820236038313156147cc576147cb614747565b5b509250929050565b7f6f70657261746f7220616c7265616479206578697374730000000000000000005f82015250565b5f614808601783614145565b9150614813826147d4565b602082019050919050565b5f6020820190508181035f830152614835816147fc565b9050919050565b5f61484682613b03565b915061485183613b03565b9250828203905081811115614869576148686141bd565b5b92915050565b5f61487982613b03565b915061488483613b03565b925082820190508082111561489c5761489b6141bd565b5b92915050565b5f82825260208201905092915050565b5f819050919050565b5f6148c960208401846140b1565b905092915050565b5f602082019050919050565b5f6148e883856148a2565b93506148f3826148b2565b805f5b8581101561492b5761490882846148bb565b6149128882613d8d565b975061491d836148d1565b9250506001810190506148f6565b5085925050509392505050565b5f82825260208201905092915050565b5f819050919050565b5f5f8335600160200384360303811261496d5761496c614547565b5b83810192508235915060208301925067ffffffffffffffff8211156149955761499461453f565b5b6020820236038313156149ab576149aa614543565b5b509250929050565b5f819050919050565b5f604083016149cd5f840184614529565b6149d95f860182613b0c565b506149e7602084018461454b565b85830360208701526149fa8382846145bb565b925050508091505092915050565b5f614a1383836149bc565b905092915050565b5f82356001604003833603038112614a3657614a35614547565b5b82810191505092915050565b5f602082019050919050565b5f614a598385613ae4565b935083602084028501614a6b846149b3565b805f5b87811015614aae578484038952614a858284614a1b565b614a8f8582614a08565b9450614a9a83614a42565b925060208a01995050600181019050614a6e565b50829750879450505050509392505050565b5f60608301614ad15f8401846148bb565b614add5f860182613acb565b50614aeb6020840184614951565b8583036020870152614afe838284614a4e565b92505050614b0f604084018461454b565b8583036040870152614b228382846145bb565b925050508091505092915050565b5f614b3b8383614ac0565b905092915050565b5f82356001606003833603038112614b5e57614b5d614547565b5b82810191505092915050565b5f602082019050919050565b5f614b818385614938565b935083602084028501614b9384614948565b805f5b87811015614bd6578484038952614bad8284614b43565b614bb78582614b30565b9450614bc283614b6a565b925060208a01995050600181019050614b96565b50829750879450505050509392505050565b5f6060820190508181035f830152614c018187896148dd565b90508181036020830152614c16818587614b76565b9050614c256040830184614221565b9695505050505050565b7f6d6967726174696f6e20696e2070726f677265737300000000000000000000005f82015250565b5f614c63601583614145565b9150614c6e82614c2f565b602082019050919050565b5f6020820190508181035f830152614c9081614c57565b9050919050565b7f746f6f20666577206e6f646573000000000000000000000000000000000000005f82015250565b5f614ccb600d83614145565b9150614cd682614c97565b602082019050919050565b5f6020820190508181035f830152614cf881614cbf565b9050919050565b614d0881613b03565b82525050565b5f606082019050614d215f8301866143d2565b614d2e6020830185614cff565b614d3b6040830184614221565b949350505050565b7f6e6f7420756e646572206d61696e74656e616e636500000000000000000000005f82015250565b5f614d77601583614145565b9150614d8282614d43565b602082019050919050565b5f6020820190508181035f830152614da481614d6b565b9050919050565b7f6e6f742070756c6c696e670000000000000000000000000000000000000000005f82015250565b5f614ddf600b83614145565b9150614dea82614dab565b602082019050919050565b5f6020820190508181035f830152614e0c81614dd3565b9050919050565b5f614e1d82614275565b91505f8203614e2f57614e2e6141bd565b5b600182039050919050565b7f696e76616c6964206164647265737300000000000000000000000000000000005f82015250565b5f614e6e600f83614145565b9150614e7982614e3a565b602082019050919050565b5f6020820190508181035f830152614e9b81614e62565b9050919050565b7f6f70657261746f7220646f65736e2774206578697374000000000000000000005f82015250565b5f614ed6601683614145565b9150614ee182614ea2565b602082019050919050565b5f6020820190508181035f830152614f0381614eca565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffd5b7f746f6f206d616e79206f70657261746f727300000000000000000000000000005f82015250565b5f614f6b601283614145565b9150614f7682614f37565b602082019050919050565b5f6020820190508181035f830152614f9881614f5f565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026150287fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82614fed565b6150328683614fed565b95508019841693508086168417925050509392505050565b5f61506461505f61505a84613b03565b6142d9565b613b03565b9050919050565b5f819050919050565b61507d8361504a565b6150916150898261506b565b848454614ff9565b825550505050565b5f5f905090565b6150a8615099565b6150b3818484615074565b505050565b5b818110156150d6576150cb5f826150a0565b6001810190506150b9565b5050565b601f82111561511b576150ec81614fcc565b6150f584614fde565b81016020851015615104578190505b61511861511085614fde565b8301826150b8565b50505b505050565b5f82821c905092915050565b5f61513b5f1984600802615120565b1980831691505092915050565b5f615153838361512c565b9150826002028217905092915050565b61516c82613b1b565b67ffffffffffffffff81111561518557615184614f9f565b5b61518f8254614462565b61519a8282856150da565b5f60209050601f8311600181146151cb575f84156151b9578287015190505b6151c38582615148565b86555061522a565b601f1984166151d986614fcc565b5f5b82811015615200578489015182556001820191506020850194506020810190506151db565b8683101561521d5784890151615219601f89168261512c565b8355505b6001600288020188555050505b505050505050565b7f6e6f7420696e2070726f677265737300000000000000000000000000000000005f82015250565b5f615266600f83614145565b915061527182615232565b602082019050919050565b5f6020820190508181035f8301526152938161525a565b9050919050565b7f646174612070756c6c20696e2070726f677265737300000000000000000000005f82015250565b5f6152ce601583614145565b91506152d98261529a565b602082019050919050565b5f6020820190508181035f8301526152fb816152c2565b9050919050565b5f5ffd5b61530f82613b43565b810181811067ffffffffffffffff8211171561532e5761532d614f9f565b5b80604052505050565b5f6153406139af565b905061534c8282615306565b919050565b5f5ffd5b5f5ffd5b5f67ffffffffffffffff82111561537357615372614f9f565b5b61537c82613b43565b9050602081019050919050565b5f61539b61539684615359565b615337565b9050828152602081018484840111156153b7576153b6615355565b5b6153c28482856145ad565b509392505050565b5f82601f8301126153de576153dd613f67565b5b81356153ee848260208601615389565b91505092915050565b5f6040828403121561540c5761540b615302565b5b6154166040615337565b90505f61542584828501614106565b5f83015250602082013567ffffffffffffffff81111561544857615447615351565b5b615454848285016153ca565b60208301525092915050565b5f61546b36836153f7565b9050919050565b5f61547c82613b03565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036154ae576154ad6141bd565b5b600182019050919050565b7f746f6f206d616e79206e6f6465730000000000000000000000000000000000005f82015250565b5f6154ed600e83614145565b91506154f8826154b9565b602082019050919050565b5f6020820190508181035f83015261551a816154e1565b9050919050565b7f746f6f20666577206f70657261746f72730000000000000000000000000000005f82015250565b5f615555601183614145565b915061556082615521565b602082019050919050565b5f6020820190508181035f83015261558281615549565b9050919050565b7f6d6967726174696f6e20616c726561647920696e2070726f67726573730000005f82015250565b5f6155bd601d83614145565b91506155c882615589565b602082019050919050565b5f6020820190508181035f8301526155ea816155b1565b9050919050565b7f6e6f7468696e6720746f20646f000000000000000000000000000000000000005f82015250565b5f615625600d83614145565b9150615630826155f1565b602082019050919050565b5f6020820190508181035f83015261565281615619565b9050919050565b5f61566382614275565b915060ff8203615676576156756141bd565b5b600182019050919050565b5f813561568d8161409b565b80915050919050565b5f73ffffffffffffffffffffffffffffffffffffffff6156b5846142ac565b9350801983169250808416831791505092915050565b5f6156e56156e06156db84613a9b565b6142d9565b613a9b565b9050919050565b5f6156f6826156cb565b9050919050565b5f615707826156ec565b9050919050565b5f819050919050565b615720826156fd565b61573361572c8261570e565b8354615696565b8255505050565b5f823560016040038336030381126157555761575461473f565b5b80830191505092915050565b5f81549050919050565b5f61577582613b03565b915061578083613b03565b925082820261578e81613b03565b915082820484148315176157a5576157a46141bd565b5b5092915050565b5f8190506157bb82600261576b565b9050919050565b5f819050815f5260205f209050919050565b6158047fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83602003600802615120565b815481168255505050565b61581881614fcc565b615823838254615148565b8083555f825550505050565b602084105f811461588957601f841160018114615857576158508685615148565b8355615883565b61586083614fcc565b61587761586c87614fde565b8201600183016150b8565b615881878561580f565b505b506158d6565b61589282614fcc565b61589b86614fde565b8101601f871680156158b5576158b481600184036157d4565b5b6158c96158c188614fde565b8401836150b8565b6001886002021785555050505b5050505050565b680100000000000000008411156158f7576158f6614f9f565b5b602083105f811461594057602085105f811461591e576159178685615148565b835561593a565b8360ff191693508361592f84614fcc565b556001866002020183555b5061594a565b6001856002020182555b5050505050565b805461595c81614462565b8084111561597157615970848284866158dd565b5b80841015615986576159858482848661582f565b5b50505050565b818110156159a95761599e5f826150a0565b60018101905061598c565b5050565b6159b75f82615951565b50565b5f82146159ca576159c9614249565b5b6159d3816159ad565b5050565b6159e35f5f83016150a0565b6159f05f600183016159ba565b50565b5f8214615a0357615a02614249565b5b615a0c816159d7565b5050565b5b81811015615a2e57615a235f826159f3565b600281019050615a11565b5050565b81831015615a6b57615a43826157ac565b615a4c846157ac565b615a55836157c2565b818101838201615a658183615a10565b50505050505b505050565b68010000000000000000821115615a8a57615a89614f9f565b5b615a9381615761565b828255615aa1838284615a32565b505050565b5f82905092915050565b5f8135615abc816140f0565b80915050919050565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff615af0846142ac565b9350801983169250808416831791505092915050565b615b0f8261504a565b615b22615b1b8261506b565b8354615ac5565b8255505050565b5f5f83356001602003843603038112615b4557615b4461473f565b5b80840192508235915067ffffffffffffffff821115615b6757615b66614743565b5b602083019250600182023603831315615b8357615b82614747565b5b509250929050565b5f82905092915050565b615b9f8383615b8b565b67ffffffffffffffff811115615bb857615bb7614f9f565b5b615bc28254614462565b615bcd8282856150da565b5f601f831160018114615bfa575f8415615be8578287013590505b615bf28582615148565b865550615c59565b601f198416615c0886614fcc565b5f5b82811015615c2f57848901358255600182019150602085019450602081019050615c0a565b86831015615c4c5784890135615c48601f89168261512c565b8355505b6001600288020188555050505b50505050505050565b615c6d838383615b95565b505050565b5f81015f830180615c8281615ab0565b9050615c8e8184615b06565b5050506001810160208301615ca38185615b29565b615cae818386615c62565b505050505050565b615cc08282615c72565b5050565b615cce8383615aa6565b615cd88183615a70565b615ce1836149b3565b615cea836157c2565b5f5b83811015615d2057615cfe838761573a565b615d088184615cb6565b60208401935060028301925050600181019050615cec565b50505050505050565b615d34838383615cc4565b505050565b5f81015f830180615d4981615681565b9050615d558184615717565b5050506001810160208301615d6a8185614772565b615d75818386615d29565b505050506002810160408301615d8b8185615b29565b615d96818386615c62565b505050505050565b615da88282615d39565b5050565b7f616e6f74686572206d61696e74656e616e636520696e2070726f6772657373005f82015250565b5f615de0601f83614145565b9150615deb82615dac565b602082019050919050565b5f6020820190508181035f830152615e0d81615dd4565b9050919050565b7f696e76616c6964206964000000000000000000000000000000000000000000005f82015250565b5f615e48600a83614145565b9150615e5382615e14565b602082019050919050565b5f6020820190508181035f830152615e7581615e3c565b9050919050565b7f6e6f646520646f65736e277420657869737400000000000000000000000000005f82015250565b5f615eb0601283614145565b9150615ebb82615e7c565b602082019050919050565b5f6020820190508181035f830152615edd81615ea4565b905091905056fea26469706673582212205ec0504f700c355842dfb4a4d399a8e48b0ca02d4766027c3ae5b1d4f339375864736f6c634300081c0033 + /// ``` + #[rustfmt::skip] + #[allow(clippy::all)] + pub static BYTECODE: alloy_sol_types::private::Bytes = alloy_sol_types::private::Bytes::from_static( + b"`\x80`@R4\x80\x15a\0\x0FW__\xFD[P`@Qat\x118\x03\x80at\x11\x839\x81\x81\x01`@R\x81\x01\x90a\x001\x91\x90a\x0E\x18V[3__a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UP\x81`\x01_\x82\x01Q\x81_\x01_a\x01\0\n\x81T\x81`\xFF\x02\x19\x16\x90\x83`\xFF\x16\x02\x17\x90UP` \x82\x01Q\x81_\x01`\x01a\x01\0\n\x81T\x81`\xFF\x02\x19\x16\x90\x83`\xFF\x16\x02\x17\x90UP\x90PPa\0\xC4\x81Qa\x01C` \x1B` \x1CV[__\x90P[\x81Q\x81\x10\x15a\x01;Wa\x01\0\x82\x82\x81Q\x81\x10a\0\xE8Wa\0\xE7a\x0ErV[[` \x02` \x01\x01Q` \x01QQa\x01\xE1` \x1B` \x1CV[a\x01.\x82\x82\x81Q\x81\x10a\x01\x16Wa\x01\x15a\x0ErV[[` \x02` \x01\x01Q`\x02a\x02\x80` \x1B\x90\x91\x90` \x1CV[\x80\x80`\x01\x01\x91PPa\0\xC9V[PPPa\x14\xEAV[`\x01_\x01_\x90T\x90a\x01\0\n\x90\x04`\xFF\x16`\xFF\x16\x81\x10\x15a\x01\x99W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x01\x90\x90a\x0E\xF9V[`@Q\x80\x91\x03\x90\xFD[a\x01\0\x81\x11\x15a\x01\xDEW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x01\xD5\x90a\x0FaV[`@Q\x80\x91\x03\x90\xFD[PV[`\x01_\x01`\x01\x90T\x90a\x01\0\n\x90\x04`\xFF\x16`\xFF\x16\x81\x10\x15a\x028W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x02/\x90a\x0F\xC9V[`@Q\x80\x91\x03\x90\xFD[a\x01\0\x81\x11\x15a\x02}W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x02t\x90a\x101V[`@Q\x80\x91\x03\x90\xFD[PV[a\x02\x93\x82\x82_\x01Qa\x05\x13` \x1B` \x1CV[\x15a\x02\xD3W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x02\xCA\x90a\x10\x99V[`@Q\x80\x91\x03\x90\xFD[__\x83`\x02\x01\x80T\x90P\x11\x15a\x03mW\x82`\x02\x01`\x01\x84`\x02\x01\x80T\x90Pa\x02\xFB\x91\x90a\x10\xE4V[\x81T\x81\x10a\x03\x0CWa\x03\x0Ba\x0ErV[[\x90_R` _ \x90` \x91\x82\x82\x04\x01\x91\x90\x06\x90T\x90a\x01\0\n\x90\x04`\xFF\x16\x90P\x82`\x02\x01\x80T\x80a\x03@Wa\x03?a\x11\x17V[[`\x01\x90\x03\x81\x81\x90_R` _ \x90` \x91\x82\x82\x04\x01\x91\x90\x06a\x01\0\n\x81T\x90`\xFF\x02\x19\x16\x90U\x90Ua\x03\xDEV[a\x01\0\x83_\x01\x80T\x90P\x10a\x03\xB7W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x03\xAE\x90a\x0FaV[`@Q\x80\x91\x03\x90\xFD[\x82_\x01\x80T\x90P\x90P\x82_\x01`\x01\x81`\x01\x81T\x01\x80\x82U\x80\x91PP\x03\x90_R` _ \x90PP[\x80\x83`\x01\x01_\x84_\x01Qs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ _a\x01\0\n\x81T\x81`\xFF\x02\x19\x16\x90\x83`\xFF\x16\x02\x17\x90UP_\x83_\x01\x82`\xFF\x16\x81T\x81\x10a\x04QWa\x04Pa\x0ErV[[\x90_R` _ \x90`\x05\x02\x01\x90P\x82_\x01Q\x81_\x01_a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UP\x82`@\x01Q\x81`\x04\x01\x90\x81a\x04\xB8\x91\x90a\x13KV[P__\x90P[\x83` \x01QQ\x81\x10\x15a\x05\x0CWa\x04\xFF\x84` \x01Q\x82\x81Q\x81\x10a\x04\xE5Wa\x04\xE4a\x0ErV[[` \x02` \x01\x01Q\x83`\x01\x01a\x06k` \x1B\x90\x91\x90` \x1CV[\x80\x80`\x01\x01\x91PPa\x04\xBEV[PPPPPV[__s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x82s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x03a\x05\x82W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x05y\x90a\x14dV[`@Q\x80\x91\x03\x90\xFD[_\x83_\x01\x80T\x90P\x11\x15a\x06aW_\x83`\x01\x01_\x84s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ _\x90T\x90a\x01\0\n\x90\x04`\xFF\x16`\xFF\x16\x14\x15\x80a\x06ZWP\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x83_\x01_\x81T\x81\x10a\x06\x14Wa\x06\x13a\x0ErV[[\x90_R` _ \x90`\x05\x02\x01_\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14[\x90Pa\x06eV[_\x90P[\x92\x91PPV[_\x81_\x01Q\x03a\x06\xB0W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x06\xA7\x90a\x14\xCCV[`@Q\x80\x91\x03\x90\xFD[__\x83_\x01\x80T\x90P\x11\x15a\x07mW\x82`\x01\x01_\x83_\x01Q\x81R` \x01\x90\x81R` \x01_ _\x90T\x90a\x01\0\n\x90\x04`\xFF\x16\x90P_\x81`\xFF\x16\x14\x15\x80a\x07\x1BWP\x81_\x01Q\x83_\x01_\x81T\x81\x10a\x07\nWa\x07\ta\x0ErV[[\x90_R` _ \x90`\x02\x02\x01_\x01T\x14[\x15a\x07lW\x81\x83_\x01\x82`\xFF\x16\x81T\x81\x10a\x079Wa\x078a\x0ErV[[\x90_R` _ \x90`\x02\x02\x01_\x82\x01Q\x81_\x01U` \x82\x01Q\x81`\x01\x01\x90\x81a\x07b\x91\x90a\x13KV[P\x90PPPa\x08\xEDV[[_\x83`\x02\x01\x80T\x90P\x11\x15a\x08\x06W\x82`\x02\x01`\x01\x84`\x02\x01\x80T\x90Pa\x07\x94\x91\x90a\x10\xE4V[\x81T\x81\x10a\x07\xA5Wa\x07\xA4a\x0ErV[[\x90_R` _ \x90` \x91\x82\x82\x04\x01\x91\x90\x06\x90T\x90a\x01\0\n\x90\x04`\xFF\x16\x90P\x82`\x02\x01\x80T\x80a\x07\xD9Wa\x07\xD8a\x11\x17V[[`\x01\x90\x03\x81\x81\x90_R` _ \x90` \x91\x82\x82\x04\x01\x91\x90\x06a\x01\0\n\x81T\x90`\xFF\x02\x19\x16\x90U\x90Ua\x08wV[a\x01\0\x83_\x01\x80T\x90P\x10a\x08PW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x08G\x90a\x101V[`@Q\x80\x91\x03\x90\xFD[\x82_\x01\x80T\x90P\x90P\x82_\x01`\x01\x81`\x01\x81T\x01\x80\x82U\x80\x91PP\x03\x90_R` _ \x90PP[\x80\x83`\x01\x01_\x84_\x01Q\x81R` \x01\x90\x81R` \x01_ _a\x01\0\n\x81T\x81`\xFF\x02\x19\x16\x90\x83`\xFF\x16\x02\x17\x90UP\x81\x83_\x01\x82`\xFF\x16\x81T\x81\x10a\x08\xBEWa\x08\xBDa\x0ErV[[\x90_R` _ \x90`\x02\x02\x01_\x82\x01Q\x81_\x01U` \x82\x01Q\x81`\x01\x01\x90\x81a\x08\xE7\x91\x90a\x13KV[P\x90PPP[PPV[_`@Q\x90P\x90V[__\xFD[__\xFD[__\xFD[_`\x1F\x19`\x1F\x83\x01\x16\x90P\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`A`\x04R`$_\xFD[a\tL\x82a\t\x06V[\x81\x01\x81\x81\x10g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x17\x15a\tkWa\tja\t\x16V[[\x80`@RPPPV[_a\t}a\x08\xF1V[\x90Pa\t\x89\x82\x82a\tCV[\x91\x90PV[__\xFD[_`\xFF\x82\x16\x90P\x91\x90PV[a\t\xA7\x81a\t\x92V[\x81\x14a\t\xB1W__\xFD[PV[_\x81Q\x90Pa\t\xC2\x81a\t\x9EV[\x92\x91PPV[_`@\x82\x84\x03\x12\x15a\t\xDDWa\t\xDCa\t\x02V[[a\t\xE7`@a\ttV[\x90P_a\t\xF6\x84\x82\x85\x01a\t\xB4V[_\x83\x01RP` a\n\t\x84\x82\x85\x01a\t\xB4V[` \x83\x01RP\x92\x91PPV[__\xFD[_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15a\n3Wa\n2a\t\x16V[[` \x82\x02\x90P` \x81\x01\x90P\x91\x90PV[__\xFD[_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[_a\nq\x82a\nHV[\x90P\x91\x90PV[a\n\x81\x81a\ngV[\x81\x14a\n\x8BW__\xFD[PV[_\x81Q\x90Pa\n\x9C\x81a\nxV[\x92\x91PPV[_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15a\n\xBCWa\n\xBBa\t\x16V[[` \x82\x02\x90P` \x81\x01\x90P\x91\x90PV[_\x81\x90P\x91\x90PV[a\n\xDF\x81a\n\xCDV[\x81\x14a\n\xE9W__\xFD[PV[_\x81Q\x90Pa\n\xFA\x81a\n\xD6V[\x92\x91PPV[__\xFD[_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15a\x0B\x1EWa\x0B\x1Da\t\x16V[[a\x0B'\x82a\t\x06V[\x90P` \x81\x01\x90P\x91\x90PV[\x82\x81\x83^_\x83\x83\x01RPPPV[_a\x0BTa\x0BO\x84a\x0B\x04V[a\ttV[\x90P\x82\x81R` \x81\x01\x84\x84\x84\x01\x11\x15a\x0BpWa\x0Boa\x0B\0V[[a\x0B{\x84\x82\x85a\x0B4V[P\x93\x92PPPV[_\x82`\x1F\x83\x01\x12a\x0B\x97Wa\x0B\x96a\n\x15V[[\x81Qa\x0B\xA7\x84\x82` \x86\x01a\x0BBV[\x91PP\x92\x91PPV[_`@\x82\x84\x03\x12\x15a\x0B\xC5Wa\x0B\xC4a\t\x02V[[a\x0B\xCF`@a\ttV[\x90P_a\x0B\xDE\x84\x82\x85\x01a\n\xECV[_\x83\x01RP` \x82\x01Qg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x0C\x01Wa\x0C\0a\t\x8EV[[a\x0C\r\x84\x82\x85\x01a\x0B\x83V[` \x83\x01RP\x92\x91PPV[_a\x0C+a\x0C&\x84a\n\xA2V[a\ttV[\x90P\x80\x83\x82R` \x82\x01\x90P` \x84\x02\x83\x01\x85\x81\x11\x15a\x0CNWa\x0CMa\nDV[[\x83[\x81\x81\x10\x15a\x0C\x95W\x80Qg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x0CsWa\x0Cra\n\x15V[[\x80\x86\x01a\x0C\x80\x89\x82a\x0B\xB0V[\x85R` \x85\x01\x94PPP` \x81\x01\x90Pa\x0CPV[PPP\x93\x92PPPV[_\x82`\x1F\x83\x01\x12a\x0C\xB3Wa\x0C\xB2a\n\x15V[[\x81Qa\x0C\xC3\x84\x82` \x86\x01a\x0C\x19V[\x91PP\x92\x91PPV[_``\x82\x84\x03\x12\x15a\x0C\xE1Wa\x0C\xE0a\t\x02V[[a\x0C\xEB``a\ttV[\x90P_a\x0C\xFA\x84\x82\x85\x01a\n\x8EV[_\x83\x01RP` \x82\x01Qg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\r\x1DWa\r\x1Ca\t\x8EV[[a\r)\x84\x82\x85\x01a\x0C\x9FV[` \x83\x01RP`@\x82\x01Qg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\rMWa\rLa\t\x8EV[[a\rY\x84\x82\x85\x01a\x0B\x83V[`@\x83\x01RP\x92\x91PPV[_a\rwa\rr\x84a\n\x19V[a\ttV[\x90P\x80\x83\x82R` \x82\x01\x90P` \x84\x02\x83\x01\x85\x81\x11\x15a\r\x9AWa\r\x99a\nDV[[\x83[\x81\x81\x10\x15a\r\xE1W\x80Qg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\r\xBFWa\r\xBEa\n\x15V[[\x80\x86\x01a\r\xCC\x89\x82a\x0C\xCCV[\x85R` \x85\x01\x94PPP` \x81\x01\x90Pa\r\x9CV[PPP\x93\x92PPPV[_\x82`\x1F\x83\x01\x12a\r\xFFWa\r\xFEa\n\x15V[[\x81Qa\x0E\x0F\x84\x82` \x86\x01a\reV[\x91PP\x92\x91PPV[__``\x83\x85\x03\x12\x15a\x0E.Wa\x0E-a\x08\xFAV[[_a\x0E;\x85\x82\x86\x01a\t\xC8V[\x92PP`@\x83\x01Qg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x0E\\Wa\x0E[a\x08\xFEV[[a\x0Eh\x85\x82\x86\x01a\r\xEBV[\x91PP\x92P\x92\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`2`\x04R`$_\xFD[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[\x7Ftoo few operators\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a\x0E\xE3`\x11\x83a\x0E\x9FV[\x91Pa\x0E\xEE\x82a\x0E\xAFV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra\x0F\x10\x81a\x0E\xD7V[\x90P\x91\x90PV[\x7Ftoo many operators\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a\x0FK`\x12\x83a\x0E\x9FV[\x91Pa\x0FV\x82a\x0F\x17V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra\x0Fx\x81a\x0F?V[\x90P\x91\x90PV[\x7Ftoo few nodes\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a\x0F\xB3`\r\x83a\x0E\x9FV[\x91Pa\x0F\xBE\x82a\x0F\x7FV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra\x0F\xE0\x81a\x0F\xA7V[\x90P\x91\x90PV[\x7Ftoo many nodes\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a\x10\x1B`\x0E\x83a\x0E\x9FV[\x91Pa\x10&\x82a\x0F\xE7V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra\x10H\x81a\x10\x0FV[\x90P\x91\x90PV[\x7Foperator already exists\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a\x10\x83`\x17\x83a\x0E\x9FV[\x91Pa\x10\x8E\x82a\x10OV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra\x10\xB0\x81a\x10wV[\x90P\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`\x11`\x04R`$_\xFD[_a\x10\xEE\x82a\n\xCDV[\x91Pa\x10\xF9\x83a\n\xCDV[\x92P\x82\x82\x03\x90P\x81\x81\x11\x15a\x11\x11Wa\x11\x10a\x10\xB7V[[\x92\x91PPV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`1`\x04R`$_\xFD[_\x81Q\x90P\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`\"`\x04R`$_\xFD[_`\x02\x82\x04\x90P`\x01\x82\x16\x80a\x11\x92W`\x7F\x82\x16\x91P[` \x82\x10\x81\x03a\x11\xA5Wa\x11\xA4a\x11NV[[P\x91\x90PV[_\x81\x90P\x81_R` _ \x90P\x91\x90PV[_` `\x1F\x83\x01\x04\x90P\x91\x90PV[_\x82\x82\x1B\x90P\x92\x91PPV[_`\x08\x83\x02a\x12\x07\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82a\x11\xCCV[a\x12\x11\x86\x83a\x11\xCCV[\x95P\x80\x19\x84\x16\x93P\x80\x86\x16\x84\x17\x92PPP\x93\x92PPPV[_\x81\x90P\x91\x90PV[_a\x12La\x12Ga\x12B\x84a\n\xCDV[a\x12)V[a\n\xCDV[\x90P\x91\x90PV[_\x81\x90P\x91\x90PV[a\x12e\x83a\x122V[a\x12ya\x12q\x82a\x12SV[\x84\x84Ta\x11\xD8V[\x82UPPPPV[__\x90P\x90V[a\x12\x90a\x12\x81V[a\x12\x9B\x81\x84\x84a\x12\\V[PPPV[[\x81\x81\x10\x15a\x12\xBEWa\x12\xB3_\x82a\x12\x88V[`\x01\x81\x01\x90Pa\x12\xA1V[PPV[`\x1F\x82\x11\x15a\x13\x03Wa\x12\xD4\x81a\x11\xABV[a\x12\xDD\x84a\x11\xBDV[\x81\x01` \x85\x10\x15a\x12\xECW\x81\x90P[a\x13\0a\x12\xF8\x85a\x11\xBDV[\x83\x01\x82a\x12\xA0V[PP[PPPV[_\x82\x82\x1C\x90P\x92\x91PPV[_a\x13#_\x19\x84`\x08\x02a\x13\x08V[\x19\x80\x83\x16\x91PP\x92\x91PPV[_a\x13;\x83\x83a\x13\x14V[\x91P\x82`\x02\x02\x82\x17\x90P\x92\x91PPV[a\x13T\x82a\x11DV[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x13mWa\x13la\t\x16V[[a\x13w\x82Ta\x11{V[a\x13\x82\x82\x82\x85a\x12\xC2V[_` \x90P`\x1F\x83\x11`\x01\x81\x14a\x13\xB3W_\x84\x15a\x13\xA1W\x82\x87\x01Q\x90P[a\x13\xAB\x85\x82a\x130V[\x86UPa\x14\x12V[`\x1F\x19\x84\x16a\x13\xC1\x86a\x11\xABV[_[\x82\x81\x10\x15a\x13\xE8W\x84\x89\x01Q\x82U`\x01\x82\x01\x91P` \x85\x01\x94P` \x81\x01\x90Pa\x13\xC3V[\x86\x83\x10\x15a\x14\x05W\x84\x89\x01Qa\x14\x01`\x1F\x89\x16\x82a\x13\x14V[\x83UP[`\x01`\x02\x88\x02\x01\x88UPPP[PPPPPPV[\x7Finvalid address\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a\x14N`\x0F\x83a\x0E\x9FV[\x91Pa\x14Y\x82a\x14\x1AV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra\x14{\x81a\x14BV[\x90P\x91\x90PV[\x7Finvalid id\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a\x14\xB6`\n\x83a\x0E\x9FV[\x91Pa\x14\xC1\x82a\x14\x82V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra\x14\xE3\x81a\x14\xAAV[\x90P\x91\x90PV[a_\x1A\x80a\x14\xF7_9_\xF3\xFE`\x80`@R4\x80\x15a\0\x0FW__\xFD[P`\x046\x10a\0\xA7W_5`\xE0\x1C\x80c\xAD6\xE6\xD0\x11a\0oW\x80c\xAD6\xE6\xD0\x14a\x01\x15W\x80c\xC10\x80\x9A\x14a\x01\x1FW\x80c\xCCEf*\x14a\x01)W\x80c\xF2\xFD\xE3\x8B\x14a\x01EW\x80c\xF5\xF2\xD9\xF1\x14a\x01aW\x80c\xFF\xD7@\xDF\x14a\x01kWa\0\xA7V[\x80c0H\xBF\xBA\x14a\0\xABW\x80c@\x99\0\xE8\x14a\0\xB5W\x80cH\x86\xF6,\x14a\0\xD1W\x80cl\x0Ba\xB9\x14a\0\xDBW\x80cuA\x8B\x9D\x14a\0\xF7W[__\xFD[a\0\xB3a\x01\x87V[\0[a\0\xCF`\x04\x806\x03\x81\x01\x90a\0\xCA\x91\x90a9\xE2V[a\x02\xDBV[\0[a\0\xD9a\x03~V[\0[a\0\xF5`\x04\x806\x03\x81\x01\x90a\0\xF0\x91\x90a:+V[a\x08,V[\0[a\0\xFFa\tVV[`@Qa\x01\x0C\x91\x90a?GV[`@Q\x80\x91\x03\x90\xF3[a\x01\x1Da\nXV[\0[a\x01'a\x0B}V[\0[a\x01C`\x04\x806\x03\x81\x01\x90a\x01>\x91\x90a@\x1DV[a\x0C\xD1V[\0[a\x01_`\x04\x806\x03\x81\x01\x90a\x01Z\x91\x90a@\xC5V[a\x10;V[\0[a\x01ia\x11\x0BV[\0[a\x01\x85`\x04\x806\x03\x81\x01\x90a\x01\x80\x91\x90aA\x1AV[a\x12zV[\0[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x02\x15W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x02\x0C\x90aA\x9FV[`@Q\x80\x91\x03\x90\xFD[a\x02\x1F`\ta\x14\x0EV[`\n`\x08\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x02M\x90aA\xEAV[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\x8F\xB9\xCD\x05M\n\x02!\x10\xCC\xED#\x9E\x90\x8B\x83NL\xD2\x19Q\x18V\xD4\xEA\xAE0Q\xD92\xD6\x04`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x02\xD1\x91\x90aB0V[`@Q\x80\x91\x03\x90\xA1V[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x03iW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x03`\x90aA\x9FV[`@Q\x80\x91\x03\x90\xFD[\x80`\x01\x81\x81a\x03x\x91\x90aC\xC4V[\x90PPPV[a\x03\x923`\x05a\x14\xC6\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[`\n`\x08\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x03\xC0\x90aA\xEAV[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\xA7j\x8F\xC1\xA9\x02f\xDD\xEE\x897\xA1\x8E\x12\xF0\x1E\xAD\xE9F\xB3\xB6a\x97\xFF\xF2\x89\xAF\x92w\xC2\xBD%3`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x04F\x92\x91\x90aC\xE1V[`@Q\x80\x91\x03\x90\xA1_`\x05`\x03\x01_\x90T\x90a\x01\0\n\x90\x04`\xFF\x16`\xFF\x16\x11a\x08*W__\x90P[`\x05_\x01\x80T\x90P\x81\x10\x15a\x04\xDBWa\x04\xCE`\x05_\x01\x82\x81T\x81\x10a\x04\x96Wa\x04\x95aD\x08V[[\x90_R` _ \x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02a\x15\xE4\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x80\x80`\x01\x01\x91PPa\x04nV[P__\x90P[`\x05`\x01\x01\x80T\x90P\x81\x10\x15a\x07\x18Wa\x07\x0B`\x05`\x01\x01\x82\x81T\x81\x10a\x05\x0BWa\x05\naD\x08V[[\x90_R` _ \x90`\x03\x02\x01`@Q\x80``\x01`@R\x90\x81_\x82\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01`\x01\x82\x01\x80T\x80` \x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01_\x90[\x82\x82\x10\x15a\x06cW\x83\x82\x90_R` _ \x90`\x02\x02\x01`@Q\x80`@\x01`@R\x90\x81_\x82\x01T\x81R` \x01`\x01\x82\x01\x80Ta\x05\xD4\x90aDbV[\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01\x82\x80Ta\x06\0\x90aDbV[\x80\x15a\x06KW\x80`\x1F\x10a\x06\"Wa\x01\0\x80\x83T\x04\x02\x83R\x91` \x01\x91a\x06KV[\x82\x01\x91\x90_R` _ \x90[\x81T\x81R\x90`\x01\x01\x90` \x01\x80\x83\x11a\x06.W\x82\x90\x03`\x1F\x16\x82\x01\x91[PPPPP\x81RPP\x81R` \x01\x90`\x01\x01\x90a\x05\x9AV[PPPP\x81R` \x01`\x02\x82\x01\x80Ta\x06{\x90aDbV[\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01\x82\x80Ta\x06\xA7\x90aDbV[\x80\x15a\x06\xF2W\x80`\x1F\x10a\x06\xC9Wa\x01\0\x80\x83T\x04\x02\x83R\x91` \x01\x91a\x06\xF2V[\x82\x01\x91\x90_R` _ \x90[\x81T\x81R\x90`\x01\x01\x90` \x01\x80\x83\x11a\x06\xD5W\x82\x90\x03`\x1F\x16\x82\x01\x91[PPPPP\x81RPP`\x02a\x18v\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x80\x80`\x01\x01\x91PPa\x04\xE1V[P`\n_\x81\x81\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x07>\x90aD\x92V[\x91\x90a\x01\0\n\x81T\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPPa\x07o`\x05a\x1B\x03V[`\n`\x08\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x07\x9D\x90aA\xEAV[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\x11\xCEP\x16\x0Ef\x10\x057\xFDK\n\xE2m\xE6mQ\xDA\xB7\x13\xAD\x9213S\xA1\x8C$\xE8\xF6\xDA\xAB`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x08!\x91\x90aB0V[`@Q\x80\x91\x03\x90\xA1[V[a\x08@3`\x02a\x1B\xAC\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x08\x7FW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x08v\x90aE\x0BV[`@Q\x80\x91\x03\x90\xFD[a\x08\x953\x82`\x02a\x1D\x04\x90\x92\x91\x90c\xFF\xFF\xFF\xFF\x16V[`\n`\x08\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x08\xC3\x90aA\xEAV[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7Fj\xDF\xB8\x96\xD3@v\x81\xD0_\xB8t\xD4\xDF\xB7\x06\x8En*6\xF0\x9A\xCD8\xA3\xB7\xD0L\x01t_\xEE3\x82`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\tK\x93\x92\x91\x90aF3V[`@Q\x80\x91\x03\x90\xA1PV[a\t^a7FV[`@Q\x80`\xA0\x01`@R\x80a\ts`\x02a\x1D\x96V[\x81R` \x01a\t\x8F`\x02_\x01`\x05a\x1F\x99\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x81R` \x01`\t`@Q\x80` \x01`@R\x90\x81_\x82\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RPP\x81R` \x01`\n_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RP\x90P\x90V[a\nl3`\x02a\x1B\xAC\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\n\xABW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\n\xA2\x90aE\x0BV[`@Q\x80\x91\x03\x90\xFD[a\n\xBF3`\ta'\0\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[`\n`\x08\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\n\xED\x90aA\xEAV[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\xF9\x10g\xEBB\x0C(\xD3\x12He\xFC\x99nj\xA9\xD5A\xB9\xB4\xFE\xF9\x18\x8C\xB9e\xA6\xCCd\x91c\x8E3`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x0Bs\x92\x91\x90aC\xE1V[`@Q\x80\x91\x03\x90\xA1V[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x0C\x0BW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x0C\x02\x90aA\x9FV[`@Q\x80\x91\x03\x90\xFD[a\x0C\x15`\x05a('V[`\n`\x08\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x0CC\x90aA\xEAV[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\x9C\xE1\x92\xAE\xA5\xFA\xF2\x15\x1B\xBC$l\xD8\x91\x8D.\xBAp/\xA2iQ\xF6\x7F+\xF7\xB3\x81~h\x9D\x98`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x0C\xC7\x91\x90aB0V[`@Q\x80\x91\x03\x90\xA1V[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\r_W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\rV\x90aA\x9FV[`@Q\x80\x91\x03\x90\xFD[a\ri`\ta({V[\x15a\r\xA9W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\r\xA0\x90aF\xB9V[`@Q\x80\x91\x03\x90\xFD[__\x90P[\x84\x84\x90P\x81\x10\x15a\x0E@Wa\r\xF4\x85\x85\x83\x81\x81\x10a\r\xCFWa\r\xCEaD\x08V[[\x90P` \x02\x01` \x81\x01\x90a\r\xE4\x91\x90a@\xC5V[`\x02a\x1B\xAC\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x0E3W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x0E*\x90aG!V[`@Q\x80\x91\x03\x90\xFD[\x80\x80`\x01\x01\x91PPa\r\xAEV[P__\x90P[\x82\x82\x90P\x81\x10\x15a\x0F%Wa\x0E\x8F\x83\x83\x83\x81\x81\x10a\x0EgWa\x0EfaD\x08V[[\x90P` \x02\x81\x01\x90a\x0Ey\x91\x90aGKV[\x80` \x01\x90a\x0E\x88\x91\x90aGrV[\x90Pa(\xD5V[a\x0E\xD8\x83\x83\x83\x81\x81\x10a\x0E\xA5Wa\x0E\xA4aD\x08V[[\x90P` \x02\x81\x01\x90a\x0E\xB7\x91\x90aGKV[_\x01` \x81\x01\x90a\x0E\xC8\x91\x90a@\xC5V[`\x02a\x1B\xAC\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x15a\x0F\x18W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x0F\x0F\x90aH\x1EV[`@Q\x80\x91\x03\x90\xFD[\x80\x80`\x01\x01\x91PPa\x0EFV[Pa\x0FT\x82\x82\x90P\x85\x85\x90Pa\x0F;`\x02a)tV[a\x0FE\x91\x90aH&\x82\x82a=\xB0V[\x91PP` \x83\x01Q\x84\x82\x03` \x86\x01Ra>@\x82\x82a<\xCAV[\x91PP`@\x83\x01Q\x84\x82\x03`@\x86\x01Ra>Z\x82\x82a=\xB0V[\x91PP\x80\x91PP\x92\x91PPV[` \x82\x01_\x82\x01Qa>{_\x85\x01\x82a:\xCBV[PPPPV[_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[a>\x9D\x81a>\x81V[\x82RPPV[_o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[a>\xC7\x81a>\xA3V[\x82RPPV[_`\xA0\x83\x01_\x83\x01Q\x84\x82\x03_\x86\x01Ra>\xE7\x82\x82a==V[\x91PP` \x83\x01Q\x84\x82\x03` \x86\x01Ra?\x01\x82\x82a>\x0CV[\x91PP`@\x83\x01Qa?\x16`@\x86\x01\x82a>gV[P``\x83\x01Qa?)``\x86\x01\x82a>\x94V[P`\x80\x83\x01Qa?<`\x80\x86\x01\x82a>\xBEV[P\x80\x91PP\x92\x91PPV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra?_\x81\x84a>\xCDV[\x90P\x92\x91PPV[__\xFD[__\xFD[__\xFD[__\x83`\x1F\x84\x01\x12a?\x88Wa?\x87a?gV[[\x825\x90Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a?\xA5Wa?\xA4a?kV[[` \x83\x01\x91P\x83` \x82\x02\x83\x01\x11\x15a?\xC1Wa?\xC0a?oV[[\x92P\x92\x90PV[__\x83`\x1F\x84\x01\x12a?\xDDWa?\xDCa?gV[[\x825\x90Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a?\xFAWa?\xF9a?kV[[` \x83\x01\x91P\x83` \x82\x02\x83\x01\x11\x15a@\x16Wa@\x15a?oV[[\x92P\x92\x90PV[____`@\x85\x87\x03\x12\x15a@5Wa@4a9\xB8V[[_\x85\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a@RWa@Qa9\xBCV[[a@^\x87\x82\x88\x01a?sV[\x94P\x94PP` \x85\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a@\x81Wa@\x80a9\xBCV[[a@\x8D\x87\x82\x88\x01a?\xC8V[\x92P\x92PP\x92\x95\x91\x94P\x92PV[a@\xA4\x81a:\xBAV[\x81\x14a@\xAEW__\xFD[PV[_\x815\x90Pa@\xBF\x81a@\x9BV[\x92\x91PPV[_` \x82\x84\x03\x12\x15a@\xDAWa@\xD9a9\xB8V[[_a@\xE7\x84\x82\x85\x01a@\xB1V[\x91PP\x92\x91PPV[a@\xF9\x81a;\x03V[\x81\x14aA\x03W__\xFD[PV[_\x815\x90PaA\x14\x81a@\xF0V[\x92\x91PPV[_` \x82\x84\x03\x12\x15aA/WaA.a9\xB8V[[_aA<\x84\x82\x85\x01aA\x06V[\x91PP\x92\x91PPV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[\x7Fnot the owner\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aA\x89`\r\x83aAEV[\x91PaA\x94\x82aAUV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaA\xB6\x81aA}V[\x90P\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`\x11`\x04R`$_\xFD[_aA\xF4\x82a>\xA3V[\x91Po\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x03aB\x16WaB\x15aA\xBDV[[`\x01\x82\x01\x90P\x91\x90PV[aB*\x81a>\xA3V[\x82RPPV[_` \x82\x01\x90PaBC_\x83\x01\x84aB!V[\x92\x91PPV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R_`\x04R`$_\xFD[_`\xFF\x82\x16\x90P\x91\x90PV[aB\x8A\x81aBuV[\x81\x14aB\x94W__\xFD[PV[_\x815aB\xA3\x81aB\x81V[\x80\x91PP\x91\x90PV[_\x81_\x1B\x90P\x91\x90PV[_`\xFFaB\xC3\x84aB\xACV[\x93P\x80\x19\x83\x16\x92P\x80\x84\x16\x83\x17\x91PP\x92\x91PPV[_\x81\x90P\x91\x90PV[_aB\xFCaB\xF7aB\xF2\x84aBuV[aB\xD9V[aBuV[\x90P\x91\x90PV[_\x81\x90P\x91\x90PV[aC\x15\x82aB\xE2V[aC(aC!\x82aC\x03V[\x83TaB\xB7V[\x82UPPPV[_\x81`\x08\x1B\x90P\x91\x90PV[_a\xFF\0aCH\x84aC/V[\x93P\x80\x19\x83\x16\x92P\x80\x84\x16\x83\x17\x91PP\x92\x91PPV[aCg\x82aB\xE2V[aCzaCs\x82aC\x03V[\x83TaC;V[\x82UPPPV[_\x81\x01_\x83\x01\x80aC\x91\x81aB\x97V[\x90PaC\x9D\x81\x84aC\x0CV[PPP_\x81\x01` \x83\x01\x80aC\xB1\x81aB\x97V[\x90PaC\xBD\x81\x84aC^V[PPPPPV[aC\xCE\x82\x82aC\x81V[PPV[aC\xDB\x81a:\xBAV[\x82RPPV[_`@\x82\x01\x90PaC\xF4_\x83\x01\x85aC\xD2V[aD\x01` \x83\x01\x84aB!V[\x93\x92PPPV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`2`\x04R`$_\xFD[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`\"`\x04R`$_\xFD[_`\x02\x82\x04\x90P`\x01\x82\x16\x80aDyW`\x7F\x82\x16\x91P[` \x82\x10\x81\x03aD\x8CWaD\x8BaD5V[[P\x91\x90PV[_aD\x9C\x82a>\x81V[\x91Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x03aD\xB6WaD\xB5aA\xBDV[[`\x01\x82\x01\x90P\x91\x90PV[\x7Fnot an operator\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aD\xF5`\x0F\x83aAEV[\x91PaE\0\x82aD\xC1V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaE\"\x81aD\xE9V[\x90P\x91\x90PV[_aE7` \x84\x01\x84aA\x06V[\x90P\x92\x91PPV[__\xFD[__\xFD[__\xFD[__\x835`\x01` \x03\x846\x03\x03\x81\x12aEgWaEfaEGV[[\x83\x81\x01\x92P\x825\x91P` \x83\x01\x92Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15aE\x8FWaE\x8EaE?V[[`\x01\x82\x026\x03\x83\x13\x15aE\xA5WaE\xA4aECV[[P\x92P\x92\x90PV[\x82\x81\x837_\x83\x83\x01RPPPV[_aE\xC6\x83\x85a;%V[\x93PaE\xD3\x83\x85\x84aE\xADV[aE\xDC\x83a;CV[\x84\x01\x90P\x93\x92PPPV[_`@\x83\x01aE\xF8_\x84\x01\x84aE)V[aF\x04_\x86\x01\x82a;\x0CV[PaF\x12` \x84\x01\x84aEKV[\x85\x83\x03` \x87\x01RaF%\x83\x82\x84aE\xBBV[\x92PPP\x80\x91PP\x92\x91PPV[_``\x82\x01\x90PaFF_\x83\x01\x86aC\xD2V[\x81\x81\x03` \x83\x01RaFX\x81\x85aE\xE7V[\x90PaFg`@\x83\x01\x84aB!V[\x94\x93PPPPV[\x7Fmaintenance in progress\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aF\xA3`\x17\x83aAEV[\x91PaF\xAE\x82aFoV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaF\xD0\x81aF\x97V[\x90P\x91\x90PV[\x7Funknown operator\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aG\x0B`\x10\x83aAEV[\x91PaG\x16\x82aF\xD7V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaG8\x81aF\xFFV[\x90P\x91\x90PV[__\xFD[__\xFD[__\xFD[_\x825`\x01``\x03\x836\x03\x03\x81\x12aGfWaGeaG?V[[\x80\x83\x01\x91PP\x92\x91PPV[__\x835`\x01` \x03\x846\x03\x03\x81\x12aG\x8EWaG\x8DaG?V[[\x80\x84\x01\x92P\x825\x91Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15aG\xB0WaG\xAFaGCV[[` \x83\x01\x92P` \x82\x026\x03\x83\x13\x15aG\xCCWaG\xCBaGGV[[P\x92P\x92\x90PV[\x7Foperator already exists\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aH\x08`\x17\x83aAEV[\x91PaH\x13\x82aG\xD4V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaH5\x81aG\xFCV[\x90P\x91\x90PV[_aHF\x82a;\x03V[\x91PaHQ\x83a;\x03V[\x92P\x82\x82\x03\x90P\x81\x81\x11\x15aHiWaHhaA\xBDV[[\x92\x91PPV[_aHy\x82a;\x03V[\x91PaH\x84\x83a;\x03V[\x92P\x82\x82\x01\x90P\x80\x82\x11\x15aH\x9CWaH\x9BaA\xBDV[[\x92\x91PPV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[_\x81\x90P\x91\x90PV[_aH\xC9` \x84\x01\x84a@\xB1V[\x90P\x92\x91PPV[_` \x82\x01\x90P\x91\x90PV[_aH\xE8\x83\x85aH\xA2V[\x93PaH\xF3\x82aH\xB2V[\x80_[\x85\x81\x10\x15aI+WaI\x08\x82\x84aH\xBBV[aI\x12\x88\x82a=\x8DV[\x97PaI\x1D\x83aH\xD1V[\x92PP`\x01\x81\x01\x90PaH\xF6V[P\x85\x92PPP\x93\x92PPPV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[_\x81\x90P\x91\x90PV[__\x835`\x01` \x03\x846\x03\x03\x81\x12aImWaIlaEGV[[\x83\x81\x01\x92P\x825\x91P` \x83\x01\x92Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15aI\x95WaI\x94aE?V[[` \x82\x026\x03\x83\x13\x15aI\xABWaI\xAAaECV[[P\x92P\x92\x90PV[_\x81\x90P\x91\x90PV[_`@\x83\x01aI\xCD_\x84\x01\x84aE)V[aI\xD9_\x86\x01\x82a;\x0CV[PaI\xE7` \x84\x01\x84aEKV[\x85\x83\x03` \x87\x01RaI\xFA\x83\x82\x84aE\xBBV[\x92PPP\x80\x91PP\x92\x91PPV[_aJ\x13\x83\x83aI\xBCV[\x90P\x92\x91PPV[_\x825`\x01`@\x03\x836\x03\x03\x81\x12aJ6WaJ5aEGV[[\x82\x81\x01\x91PP\x92\x91PPV[_` \x82\x01\x90P\x91\x90PV[_aJY\x83\x85a:\xE4V[\x93P\x83` \x84\x02\x85\x01aJk\x84aI\xB3V[\x80_[\x87\x81\x10\x15aJ\xAEW\x84\x84\x03\x89RaJ\x85\x82\x84aJ\x1BV[aJ\x8F\x85\x82aJ\x08V[\x94PaJ\x9A\x83aJBV[\x92P` \x8A\x01\x99PP`\x01\x81\x01\x90PaJnV[P\x82\x97P\x87\x94PPPPP\x93\x92PPPV[_``\x83\x01aJ\xD1_\x84\x01\x84aH\xBBV[aJ\xDD_\x86\x01\x82a:\xCBV[PaJ\xEB` \x84\x01\x84aIQV[\x85\x83\x03` \x87\x01RaJ\xFE\x83\x82\x84aJNV[\x92PPPaK\x0F`@\x84\x01\x84aEKV[\x85\x83\x03`@\x87\x01RaK\"\x83\x82\x84aE\xBBV[\x92PPP\x80\x91PP\x92\x91PPV[_aK;\x83\x83aJ\xC0V[\x90P\x92\x91PPV[_\x825`\x01``\x03\x836\x03\x03\x81\x12aK^WaK]aEGV[[\x82\x81\x01\x91PP\x92\x91PPV[_` \x82\x01\x90P\x91\x90PV[_aK\x81\x83\x85aI8V[\x93P\x83` \x84\x02\x85\x01aK\x93\x84aIHV[\x80_[\x87\x81\x10\x15aK\xD6W\x84\x84\x03\x89RaK\xAD\x82\x84aKCV[aK\xB7\x85\x82aK0V[\x94PaK\xC2\x83aKjV[\x92P` \x8A\x01\x99PP`\x01\x81\x01\x90PaK\x96V[P\x82\x97P\x87\x94PPPPP\x93\x92PPPV[_``\x82\x01\x90P\x81\x81\x03_\x83\x01RaL\x01\x81\x87\x89aH\xDDV[\x90P\x81\x81\x03` \x83\x01RaL\x16\x81\x85\x87aKvV[\x90PaL%`@\x83\x01\x84aB!V[\x96\x95PPPPPPV[\x7Fmigration in progress\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aLc`\x15\x83aAEV[\x91PaLn\x82aL/V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaL\x90\x81aLWV[\x90P\x91\x90PV[\x7Ftoo few nodes\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aL\xCB`\r\x83aAEV[\x91PaL\xD6\x82aL\x97V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaL\xF8\x81aL\xBFV[\x90P\x91\x90PV[aM\x08\x81a;\x03V[\x82RPPV[_``\x82\x01\x90PaM!_\x83\x01\x86aC\xD2V[aM.` \x83\x01\x85aL\xFFV[aM;`@\x83\x01\x84aB!V[\x94\x93PPPPV[\x7Fnot under maintenance\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aMw`\x15\x83aAEV[\x91PaM\x82\x82aMCV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaM\xA4\x81aMkV[\x90P\x91\x90PV[\x7Fnot pulling\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aM\xDF`\x0B\x83aAEV[\x91PaM\xEA\x82aM\xABV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaN\x0C\x81aM\xD3V[\x90P\x91\x90PV[_aN\x1D\x82aBuV[\x91P_\x82\x03aN/WaN.aA\xBDV[[`\x01\x82\x03\x90P\x91\x90PV[\x7Finvalid address\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aNn`\x0F\x83aAEV[\x91PaNy\x82aN:V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaN\x9B\x81aNbV[\x90P\x91\x90PV[\x7Foperator doesn't exist\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aN\xD6`\x16\x83aAEV[\x91PaN\xE1\x82aN\xA2V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaO\x03\x81aN\xCAV[\x90P\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`1`\x04R`$_\xFD[\x7Ftoo many operators\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aOk`\x12\x83aAEV[\x91PaOv\x82aO7V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaO\x98\x81aO_V[\x90P\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`A`\x04R`$_\xFD[_\x81\x90P\x81_R` _ \x90P\x91\x90PV[_` `\x1F\x83\x01\x04\x90P\x91\x90PV[_\x82\x82\x1B\x90P\x92\x91PPV[_`\x08\x83\x02aP(\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82aO\xEDV[aP2\x86\x83aO\xEDV[\x95P\x80\x19\x84\x16\x93P\x80\x86\x16\x84\x17\x92PPP\x93\x92PPPV[_aPdaP_aPZ\x84a;\x03V[aB\xD9V[a;\x03V[\x90P\x91\x90PV[_\x81\x90P\x91\x90PV[aP}\x83aPJV[aP\x91aP\x89\x82aPkV[\x84\x84TaO\xF9V[\x82UPPPPV[__\x90P\x90V[aP\xA8aP\x99V[aP\xB3\x81\x84\x84aPtV[PPPV[[\x81\x81\x10\x15aP\xD6WaP\xCB_\x82aP\xA0V[`\x01\x81\x01\x90PaP\xB9V[PPV[`\x1F\x82\x11\x15aQ\x1BWaP\xEC\x81aO\xCCV[aP\xF5\x84aO\xDEV[\x81\x01` \x85\x10\x15aQ\x04W\x81\x90P[aQ\x18aQ\x10\x85aO\xDEV[\x83\x01\x82aP\xB8V[PP[PPPV[_\x82\x82\x1C\x90P\x92\x91PPV[_aQ;_\x19\x84`\x08\x02aQ V[\x19\x80\x83\x16\x91PP\x92\x91PPV[_aQS\x83\x83aQ,V[\x91P\x82`\x02\x02\x82\x17\x90P\x92\x91PPV[aQl\x82a;\x1BV[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15aQ\x85WaQ\x84aO\x9FV[[aQ\x8F\x82TaDbV[aQ\x9A\x82\x82\x85aP\xDAV[_` \x90P`\x1F\x83\x11`\x01\x81\x14aQ\xCBW_\x84\x15aQ\xB9W\x82\x87\x01Q\x90P[aQ\xC3\x85\x82aQHV[\x86UPaR*V[`\x1F\x19\x84\x16aQ\xD9\x86aO\xCCV[_[\x82\x81\x10\x15aR\0W\x84\x89\x01Q\x82U`\x01\x82\x01\x91P` \x85\x01\x94P` \x81\x01\x90PaQ\xDBV[\x86\x83\x10\x15aR\x1DW\x84\x89\x01QaR\x19`\x1F\x89\x16\x82aQ,V[\x83UP[`\x01`\x02\x88\x02\x01\x88UPPP[PPPPPPV[\x7Fnot in progress\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aRf`\x0F\x83aAEV[\x91PaRq\x82aR2V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaR\x93\x81aRZV[\x90P\x91\x90PV[\x7Fdata pull in progress\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aR\xCE`\x15\x83aAEV[\x91PaR\xD9\x82aR\x9AV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaR\xFB\x81aR\xC2V[\x90P\x91\x90PV[__\xFD[aS\x0F\x82a;CV[\x81\x01\x81\x81\x10g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x17\x15aS.WaS-aO\x9FV[[\x80`@RPPPV[_aS@a9\xAFV[\x90PaSL\x82\x82aS\x06V[\x91\x90PV[__\xFD[__\xFD[_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15aSsWaSraO\x9FV[[aS|\x82a;CV[\x90P` \x81\x01\x90P\x91\x90PV[_aS\x9BaS\x96\x84aSYV[aS7V[\x90P\x82\x81R` \x81\x01\x84\x84\x84\x01\x11\x15aS\xB7WaS\xB6aSUV[[aS\xC2\x84\x82\x85aE\xADV[P\x93\x92PPPV[_\x82`\x1F\x83\x01\x12aS\xDEWaS\xDDa?gV[[\x815aS\xEE\x84\x82` \x86\x01aS\x89V[\x91PP\x92\x91PPV[_`@\x82\x84\x03\x12\x15aT\x0CWaT\x0BaS\x02V[[aT\x16`@aS7V[\x90P_aT%\x84\x82\x85\x01aA\x06V[_\x83\x01RP` \x82\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15aTHWaTGaSQV[[aTT\x84\x82\x85\x01aS\xCAV[` \x83\x01RP\x92\x91PPV[_aTk6\x83aS\xF7V[\x90P\x91\x90PV[_aT|\x82a;\x03V[\x91P\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x03aT\xAEWaT\xADaA\xBDV[[`\x01\x82\x01\x90P\x91\x90PV[\x7Ftoo many nodes\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aT\xED`\x0E\x83aAEV[\x91PaT\xF8\x82aT\xB9V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaU\x1A\x81aT\xE1V[\x90P\x91\x90PV[\x7Ftoo few operators\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aUU`\x11\x83aAEV[\x91PaU`\x82aU!V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaU\x82\x81aUIV[\x90P\x91\x90PV[\x7Fmigration already in progress\0\0\0_\x82\x01RPV[_aU\xBD`\x1D\x83aAEV[\x91PaU\xC8\x82aU\x89V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaU\xEA\x81aU\xB1V[\x90P\x91\x90PV[\x7Fnothing to do\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aV%`\r\x83aAEV[\x91PaV0\x82aU\xF1V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaVR\x81aV\x19V[\x90P\x91\x90PV[_aVc\x82aBuV[\x91P`\xFF\x82\x03aVvWaVuaA\xBDV[[`\x01\x82\x01\x90P\x91\x90PV[_\x815aV\x8D\x81a@\x9BV[\x80\x91PP\x91\x90PV[_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFFaV\xB5\x84aB\xACV[\x93P\x80\x19\x83\x16\x92P\x80\x84\x16\x83\x17\x91PP\x92\x91PPV[_aV\xE5aV\xE0aV\xDB\x84a:\x9BV[aB\xD9V[a:\x9BV[\x90P\x91\x90PV[_aV\xF6\x82aV\xCBV[\x90P\x91\x90PV[_aW\x07\x82aV\xECV[\x90P\x91\x90PV[_\x81\x90P\x91\x90PV[aW \x82aV\xFDV[aW3aW,\x82aW\x0EV[\x83TaV\x96V[\x82UPPPV[_\x825`\x01`@\x03\x836\x03\x03\x81\x12aWUWaWTaG?V[[\x80\x83\x01\x91PP\x92\x91PPV[_\x81T\x90P\x91\x90PV[_aWu\x82a;\x03V[\x91PaW\x80\x83a;\x03V[\x92P\x82\x82\x02aW\x8E\x81a;\x03V[\x91P\x82\x82\x04\x84\x14\x83\x15\x17aW\xA5WaW\xA4aA\xBDV[[P\x92\x91PPV[_\x81\x90PaW\xBB\x82`\x02aWkV[\x90P\x91\x90PV[_\x81\x90P\x81_R` _ \x90P\x91\x90PV[aX\x04\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x83` \x03`\x08\x02aQ V[\x81T\x81\x16\x82UPPPV[aX\x18\x81aO\xCCV[aX#\x83\x82TaQHV[\x80\x83U_\x82UPPPPV[` \x84\x10_\x81\x14aX\x89W`\x1F\x84\x11`\x01\x81\x14aXWWaXP\x86\x85aQHV[\x83UaX\x83V[aX`\x83aO\xCCV[aXwaXl\x87aO\xDEV[\x82\x01`\x01\x83\x01aP\xB8V[aX\x81\x87\x85aX\x0FV[P[PaX\xD6V[aX\x92\x82aO\xCCV[aX\x9B\x86aO\xDEV[\x81\x01`\x1F\x87\x16\x80\x15aX\xB5WaX\xB4\x81`\x01\x84\x03aW\xD4V[[aX\xC9aX\xC1\x88aO\xDEV[\x84\x01\x83aP\xB8V[`\x01\x88`\x02\x02\x17\x85UPPP[PPPPPV[h\x01\0\0\0\0\0\0\0\0\x84\x11\x15aX\xF7WaX\xF6aO\x9FV[[` \x83\x10_\x81\x14aY@W` \x85\x10_\x81\x14aY\x1EWaY\x17\x86\x85aQHV[\x83UaY:V[\x83`\xFF\x19\x16\x93P\x83aY/\x84aO\xCCV[U`\x01\x86`\x02\x02\x01\x83U[PaYJV[`\x01\x85`\x02\x02\x01\x82U[PPPPPV[\x80TaY\\\x81aDbV[\x80\x84\x11\x15aYqWaYp\x84\x82\x84\x86aX\xDDV[[\x80\x84\x10\x15aY\x86WaY\x85\x84\x82\x84\x86aX/V[[PPPPV[\x81\x81\x10\x15aY\xA9WaY\x9E_\x82aP\xA0V[`\x01\x81\x01\x90PaY\x8CV[PPV[aY\xB7_\x82aYQV[PV[_\x82\x14aY\xCAWaY\xC9aBIV[[aY\xD3\x81aY\xADV[PPV[aY\xE3__\x83\x01aP\xA0V[aY\xF0_`\x01\x83\x01aY\xBAV[PV[_\x82\x14aZ\x03WaZ\x02aBIV[[aZ\x0C\x81aY\xD7V[PPV[[\x81\x81\x10\x15aZ.WaZ#_\x82aY\xF3V[`\x02\x81\x01\x90PaZ\x11V[PPV[\x81\x83\x10\x15aZkWaZC\x82aW\xACV[aZL\x84aW\xACV[aZU\x83aW\xC2V[\x81\x81\x01\x83\x82\x01aZe\x81\x83aZ\x10V[PPPPP[PPPV[h\x01\0\0\0\0\0\0\0\0\x82\x11\x15aZ\x8AWaZ\x89aO\x9FV[[aZ\x93\x81aWaV[\x82\x82UaZ\xA1\x83\x82\x84aZ2V[PPPV[_\x82\x90P\x92\x91PPV[_\x815aZ\xBC\x81a@\xF0V[\x80\x91PP\x91\x90PV[_\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFFaZ\xF0\x84aB\xACV[\x93P\x80\x19\x83\x16\x92P\x80\x84\x16\x83\x17\x91PP\x92\x91PPV[a[\x0F\x82aPJV[a[\"a[\x1B\x82aPkV[\x83TaZ\xC5V[\x82UPPPV[__\x835`\x01` \x03\x846\x03\x03\x81\x12a[EWa[DaG?V[[\x80\x84\x01\x92P\x825\x91Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15a[gWa[faGCV[[` \x83\x01\x92P`\x01\x82\x026\x03\x83\x13\x15a[\x83Wa[\x82aGGV[[P\x92P\x92\x90PV[_\x82\x90P\x92\x91PPV[a[\x9F\x83\x83a[\x8BV[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a[\xB8Wa[\xB7aO\x9FV[[a[\xC2\x82TaDbV[a[\xCD\x82\x82\x85aP\xDAV[_`\x1F\x83\x11`\x01\x81\x14a[\xFAW_\x84\x15a[\xE8W\x82\x87\x015\x90P[a[\xF2\x85\x82aQHV[\x86UPa\\YV[`\x1F\x19\x84\x16a\\\x08\x86aO\xCCV[_[\x82\x81\x10\x15a\\/W\x84\x89\x015\x82U`\x01\x82\x01\x91P` \x85\x01\x94P` \x81\x01\x90Pa\\\nV[\x86\x83\x10\x15a\\LW\x84\x89\x015a\\H`\x1F\x89\x16\x82aQ,V[\x83UP[`\x01`\x02\x88\x02\x01\x88UPPP[PPPPPPPV[a\\m\x83\x83\x83a[\x95V[PPPV[_\x81\x01_\x83\x01\x80a\\\x82\x81aZ\xB0V[\x90Pa\\\x8E\x81\x84a[\x06V[PPP`\x01\x81\x01` \x83\x01a\\\xA3\x81\x85a[)V[a\\\xAE\x81\x83\x86a\\bV[PPPPPPV[a\\\xC0\x82\x82a\\rV[PPV[a\\\xCE\x83\x83aZ\xA6V[a\\\xD8\x81\x83aZpV[a\\\xE1\x83aI\xB3V[a\\\xEA\x83aW\xC2V[_[\x83\x81\x10\x15a] Wa\\\xFE\x83\x87aW:V[a]\x08\x81\x84a\\\xB6V[` \x84\x01\x93P`\x02\x83\x01\x92PP`\x01\x81\x01\x90Pa\\\xECV[PPPPPPPV[a]4\x83\x83\x83a\\\xC4V[PPPV[_\x81\x01_\x83\x01\x80a]I\x81aV\x81V[\x90Pa]U\x81\x84aW\x17V[PPP`\x01\x81\x01` \x83\x01a]j\x81\x85aGrV[a]u\x81\x83\x86a])V[PPPP`\x02\x81\x01`@\x83\x01a]\x8B\x81\x85a[)V[a]\x96\x81\x83\x86a\\bV[PPPPPPV[a]\xA8\x82\x82a]9V[PPV[\x7Fanother maintenance in progress\0_\x82\x01RPV[_a]\xE0`\x1F\x83aAEV[\x91Pa]\xEB\x82a]\xACV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra^\r\x81a]\xD4V[\x90P\x91\x90PV[\x7Finvalid id\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a^H`\n\x83aAEV[\x91Pa^S\x82a^\x14V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra^u\x81a^\x91\x90a@\x1DV[a\x0C\xD1V[\0[a\x01_`\x04\x806\x03\x81\x01\x90a\x01Z\x91\x90a@\xC5V[a\x10;V[\0[a\x01ia\x11\x0BV[\0[a\x01\x85`\x04\x806\x03\x81\x01\x90a\x01\x80\x91\x90aA\x1AV[a\x12zV[\0[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x02\x15W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x02\x0C\x90aA\x9FV[`@Q\x80\x91\x03\x90\xFD[a\x02\x1F`\ta\x14\x0EV[`\n`\x08\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x02M\x90aA\xEAV[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\x8F\xB9\xCD\x05M\n\x02!\x10\xCC\xED#\x9E\x90\x8B\x83NL\xD2\x19Q\x18V\xD4\xEA\xAE0Q\xD92\xD6\x04`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x02\xD1\x91\x90aB0V[`@Q\x80\x91\x03\x90\xA1V[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x03iW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x03`\x90aA\x9FV[`@Q\x80\x91\x03\x90\xFD[\x80`\x01\x81\x81a\x03x\x91\x90aC\xC4V[\x90PPPV[a\x03\x923`\x05a\x14\xC6\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[`\n`\x08\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x03\xC0\x90aA\xEAV[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\xA7j\x8F\xC1\xA9\x02f\xDD\xEE\x897\xA1\x8E\x12\xF0\x1E\xAD\xE9F\xB3\xB6a\x97\xFF\xF2\x89\xAF\x92w\xC2\xBD%3`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x04F\x92\x91\x90aC\xE1V[`@Q\x80\x91\x03\x90\xA1_`\x05`\x03\x01_\x90T\x90a\x01\0\n\x90\x04`\xFF\x16`\xFF\x16\x11a\x08*W__\x90P[`\x05_\x01\x80T\x90P\x81\x10\x15a\x04\xDBWa\x04\xCE`\x05_\x01\x82\x81T\x81\x10a\x04\x96Wa\x04\x95aD\x08V[[\x90_R` _ \x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02a\x15\xE4\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x80\x80`\x01\x01\x91PPa\x04nV[P__\x90P[`\x05`\x01\x01\x80T\x90P\x81\x10\x15a\x07\x18Wa\x07\x0B`\x05`\x01\x01\x82\x81T\x81\x10a\x05\x0BWa\x05\naD\x08V[[\x90_R` _ \x90`\x03\x02\x01`@Q\x80``\x01`@R\x90\x81_\x82\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01`\x01\x82\x01\x80T\x80` \x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01_\x90[\x82\x82\x10\x15a\x06cW\x83\x82\x90_R` _ \x90`\x02\x02\x01`@Q\x80`@\x01`@R\x90\x81_\x82\x01T\x81R` \x01`\x01\x82\x01\x80Ta\x05\xD4\x90aDbV[\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01\x82\x80Ta\x06\0\x90aDbV[\x80\x15a\x06KW\x80`\x1F\x10a\x06\"Wa\x01\0\x80\x83T\x04\x02\x83R\x91` \x01\x91a\x06KV[\x82\x01\x91\x90_R` _ \x90[\x81T\x81R\x90`\x01\x01\x90` \x01\x80\x83\x11a\x06.W\x82\x90\x03`\x1F\x16\x82\x01\x91[PPPPP\x81RPP\x81R` \x01\x90`\x01\x01\x90a\x05\x9AV[PPPP\x81R` \x01`\x02\x82\x01\x80Ta\x06{\x90aDbV[\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01\x82\x80Ta\x06\xA7\x90aDbV[\x80\x15a\x06\xF2W\x80`\x1F\x10a\x06\xC9Wa\x01\0\x80\x83T\x04\x02\x83R\x91` \x01\x91a\x06\xF2V[\x82\x01\x91\x90_R` _ \x90[\x81T\x81R\x90`\x01\x01\x90` \x01\x80\x83\x11a\x06\xD5W\x82\x90\x03`\x1F\x16\x82\x01\x91[PPPPP\x81RPP`\x02a\x18v\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x80\x80`\x01\x01\x91PPa\x04\xE1V[P`\n_\x81\x81\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x07>\x90aD\x92V[\x91\x90a\x01\0\n\x81T\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPPa\x07o`\x05a\x1B\x03V[`\n`\x08\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x07\x9D\x90aA\xEAV[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\x11\xCEP\x16\x0Ef\x10\x057\xFDK\n\xE2m\xE6mQ\xDA\xB7\x13\xAD\x9213S\xA1\x8C$\xE8\xF6\xDA\xAB`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x08!\x91\x90aB0V[`@Q\x80\x91\x03\x90\xA1[V[a\x08@3`\x02a\x1B\xAC\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x08\x7FW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x08v\x90aE\x0BV[`@Q\x80\x91\x03\x90\xFD[a\x08\x953\x82`\x02a\x1D\x04\x90\x92\x91\x90c\xFF\xFF\xFF\xFF\x16V[`\n`\x08\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x08\xC3\x90aA\xEAV[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7Fj\xDF\xB8\x96\xD3@v\x81\xD0_\xB8t\xD4\xDF\xB7\x06\x8En*6\xF0\x9A\xCD8\xA3\xB7\xD0L\x01t_\xEE3\x82`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\tK\x93\x92\x91\x90aF3V[`@Q\x80\x91\x03\x90\xA1PV[a\t^a7FV[`@Q\x80`\xA0\x01`@R\x80a\ts`\x02a\x1D\x96V[\x81R` \x01a\t\x8F`\x02_\x01`\x05a\x1F\x99\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x81R` \x01`\t`@Q\x80` \x01`@R\x90\x81_\x82\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RPP\x81R` \x01`\n_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RP\x90P\x90V[a\nl3`\x02a\x1B\xAC\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\n\xABW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\n\xA2\x90aE\x0BV[`@Q\x80\x91\x03\x90\xFD[a\n\xBF3`\ta'\0\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[`\n`\x08\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\n\xED\x90aA\xEAV[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\xF9\x10g\xEBB\x0C(\xD3\x12He\xFC\x99nj\xA9\xD5A\xB9\xB4\xFE\xF9\x18\x8C\xB9e\xA6\xCCd\x91c\x8E3`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x0Bs\x92\x91\x90aC\xE1V[`@Q\x80\x91\x03\x90\xA1V[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x0C\x0BW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x0C\x02\x90aA\x9FV[`@Q\x80\x91\x03\x90\xFD[a\x0C\x15`\x05a('V[`\n`\x08\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x0CC\x90aA\xEAV[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\x9C\xE1\x92\xAE\xA5\xFA\xF2\x15\x1B\xBC$l\xD8\x91\x8D.\xBAp/\xA2iQ\xF6\x7F+\xF7\xB3\x81~h\x9D\x98`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x0C\xC7\x91\x90aB0V[`@Q\x80\x91\x03\x90\xA1V[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\r_W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\rV\x90aA\x9FV[`@Q\x80\x91\x03\x90\xFD[a\ri`\ta({V[\x15a\r\xA9W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\r\xA0\x90aF\xB9V[`@Q\x80\x91\x03\x90\xFD[__\x90P[\x84\x84\x90P\x81\x10\x15a\x0E@Wa\r\xF4\x85\x85\x83\x81\x81\x10a\r\xCFWa\r\xCEaD\x08V[[\x90P` \x02\x01` \x81\x01\x90a\r\xE4\x91\x90a@\xC5V[`\x02a\x1B\xAC\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x0E3W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x0E*\x90aG!V[`@Q\x80\x91\x03\x90\xFD[\x80\x80`\x01\x01\x91PPa\r\xAEV[P__\x90P[\x82\x82\x90P\x81\x10\x15a\x0F%Wa\x0E\x8F\x83\x83\x83\x81\x81\x10a\x0EgWa\x0EfaD\x08V[[\x90P` \x02\x81\x01\x90a\x0Ey\x91\x90aGKV[\x80` \x01\x90a\x0E\x88\x91\x90aGrV[\x90Pa(\xD5V[a\x0E\xD8\x83\x83\x83\x81\x81\x10a\x0E\xA5Wa\x0E\xA4aD\x08V[[\x90P` \x02\x81\x01\x90a\x0E\xB7\x91\x90aGKV[_\x01` \x81\x01\x90a\x0E\xC8\x91\x90a@\xC5V[`\x02a\x1B\xAC\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x15a\x0F\x18W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x0F\x0F\x90aH\x1EV[`@Q\x80\x91\x03\x90\xFD[\x80\x80`\x01\x01\x91PPa\x0EFV[Pa\x0FT\x82\x82\x90P\x85\x85\x90Pa\x0F;`\x02a)tV[a\x0FE\x91\x90aH&\x82\x82a=\xB0V[\x91PP` \x83\x01Q\x84\x82\x03` \x86\x01Ra>@\x82\x82a<\xCAV[\x91PP`@\x83\x01Q\x84\x82\x03`@\x86\x01Ra>Z\x82\x82a=\xB0V[\x91PP\x80\x91PP\x92\x91PPV[` \x82\x01_\x82\x01Qa>{_\x85\x01\x82a:\xCBV[PPPPV[_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[a>\x9D\x81a>\x81V[\x82RPPV[_o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[a>\xC7\x81a>\xA3V[\x82RPPV[_`\xA0\x83\x01_\x83\x01Q\x84\x82\x03_\x86\x01Ra>\xE7\x82\x82a==V[\x91PP` \x83\x01Q\x84\x82\x03` \x86\x01Ra?\x01\x82\x82a>\x0CV[\x91PP`@\x83\x01Qa?\x16`@\x86\x01\x82a>gV[P``\x83\x01Qa?)``\x86\x01\x82a>\x94V[P`\x80\x83\x01Qa?<`\x80\x86\x01\x82a>\xBEV[P\x80\x91PP\x92\x91PPV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra?_\x81\x84a>\xCDV[\x90P\x92\x91PPV[__\xFD[__\xFD[__\xFD[__\x83`\x1F\x84\x01\x12a?\x88Wa?\x87a?gV[[\x825\x90Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a?\xA5Wa?\xA4a?kV[[` \x83\x01\x91P\x83` \x82\x02\x83\x01\x11\x15a?\xC1Wa?\xC0a?oV[[\x92P\x92\x90PV[__\x83`\x1F\x84\x01\x12a?\xDDWa?\xDCa?gV[[\x825\x90Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a?\xFAWa?\xF9a?kV[[` \x83\x01\x91P\x83` \x82\x02\x83\x01\x11\x15a@\x16Wa@\x15a?oV[[\x92P\x92\x90PV[____`@\x85\x87\x03\x12\x15a@5Wa@4a9\xB8V[[_\x85\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a@RWa@Qa9\xBCV[[a@^\x87\x82\x88\x01a?sV[\x94P\x94PP` \x85\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a@\x81Wa@\x80a9\xBCV[[a@\x8D\x87\x82\x88\x01a?\xC8V[\x92P\x92PP\x92\x95\x91\x94P\x92PV[a@\xA4\x81a:\xBAV[\x81\x14a@\xAEW__\xFD[PV[_\x815\x90Pa@\xBF\x81a@\x9BV[\x92\x91PPV[_` \x82\x84\x03\x12\x15a@\xDAWa@\xD9a9\xB8V[[_a@\xE7\x84\x82\x85\x01a@\xB1V[\x91PP\x92\x91PPV[a@\xF9\x81a;\x03V[\x81\x14aA\x03W__\xFD[PV[_\x815\x90PaA\x14\x81a@\xF0V[\x92\x91PPV[_` \x82\x84\x03\x12\x15aA/WaA.a9\xB8V[[_aA<\x84\x82\x85\x01aA\x06V[\x91PP\x92\x91PPV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[\x7Fnot the owner\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aA\x89`\r\x83aAEV[\x91PaA\x94\x82aAUV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaA\xB6\x81aA}V[\x90P\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`\x11`\x04R`$_\xFD[_aA\xF4\x82a>\xA3V[\x91Po\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x03aB\x16WaB\x15aA\xBDV[[`\x01\x82\x01\x90P\x91\x90PV[aB*\x81a>\xA3V[\x82RPPV[_` \x82\x01\x90PaBC_\x83\x01\x84aB!V[\x92\x91PPV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R_`\x04R`$_\xFD[_`\xFF\x82\x16\x90P\x91\x90PV[aB\x8A\x81aBuV[\x81\x14aB\x94W__\xFD[PV[_\x815aB\xA3\x81aB\x81V[\x80\x91PP\x91\x90PV[_\x81_\x1B\x90P\x91\x90PV[_`\xFFaB\xC3\x84aB\xACV[\x93P\x80\x19\x83\x16\x92P\x80\x84\x16\x83\x17\x91PP\x92\x91PPV[_\x81\x90P\x91\x90PV[_aB\xFCaB\xF7aB\xF2\x84aBuV[aB\xD9V[aBuV[\x90P\x91\x90PV[_\x81\x90P\x91\x90PV[aC\x15\x82aB\xE2V[aC(aC!\x82aC\x03V[\x83TaB\xB7V[\x82UPPPV[_\x81`\x08\x1B\x90P\x91\x90PV[_a\xFF\0aCH\x84aC/V[\x93P\x80\x19\x83\x16\x92P\x80\x84\x16\x83\x17\x91PP\x92\x91PPV[aCg\x82aB\xE2V[aCzaCs\x82aC\x03V[\x83TaC;V[\x82UPPPV[_\x81\x01_\x83\x01\x80aC\x91\x81aB\x97V[\x90PaC\x9D\x81\x84aC\x0CV[PPP_\x81\x01` \x83\x01\x80aC\xB1\x81aB\x97V[\x90PaC\xBD\x81\x84aC^V[PPPPPV[aC\xCE\x82\x82aC\x81V[PPV[aC\xDB\x81a:\xBAV[\x82RPPV[_`@\x82\x01\x90PaC\xF4_\x83\x01\x85aC\xD2V[aD\x01` \x83\x01\x84aB!V[\x93\x92PPPV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`2`\x04R`$_\xFD[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`\"`\x04R`$_\xFD[_`\x02\x82\x04\x90P`\x01\x82\x16\x80aDyW`\x7F\x82\x16\x91P[` \x82\x10\x81\x03aD\x8CWaD\x8BaD5V[[P\x91\x90PV[_aD\x9C\x82a>\x81V[\x91Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x03aD\xB6WaD\xB5aA\xBDV[[`\x01\x82\x01\x90P\x91\x90PV[\x7Fnot an operator\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aD\xF5`\x0F\x83aAEV[\x91PaE\0\x82aD\xC1V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaE\"\x81aD\xE9V[\x90P\x91\x90PV[_aE7` \x84\x01\x84aA\x06V[\x90P\x92\x91PPV[__\xFD[__\xFD[__\xFD[__\x835`\x01` \x03\x846\x03\x03\x81\x12aEgWaEfaEGV[[\x83\x81\x01\x92P\x825\x91P` \x83\x01\x92Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15aE\x8FWaE\x8EaE?V[[`\x01\x82\x026\x03\x83\x13\x15aE\xA5WaE\xA4aECV[[P\x92P\x92\x90PV[\x82\x81\x837_\x83\x83\x01RPPPV[_aE\xC6\x83\x85a;%V[\x93PaE\xD3\x83\x85\x84aE\xADV[aE\xDC\x83a;CV[\x84\x01\x90P\x93\x92PPPV[_`@\x83\x01aE\xF8_\x84\x01\x84aE)V[aF\x04_\x86\x01\x82a;\x0CV[PaF\x12` \x84\x01\x84aEKV[\x85\x83\x03` \x87\x01RaF%\x83\x82\x84aE\xBBV[\x92PPP\x80\x91PP\x92\x91PPV[_``\x82\x01\x90PaFF_\x83\x01\x86aC\xD2V[\x81\x81\x03` \x83\x01RaFX\x81\x85aE\xE7V[\x90PaFg`@\x83\x01\x84aB!V[\x94\x93PPPPV[\x7Fmaintenance in progress\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aF\xA3`\x17\x83aAEV[\x91PaF\xAE\x82aFoV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaF\xD0\x81aF\x97V[\x90P\x91\x90PV[\x7Funknown operator\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aG\x0B`\x10\x83aAEV[\x91PaG\x16\x82aF\xD7V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaG8\x81aF\xFFV[\x90P\x91\x90PV[__\xFD[__\xFD[__\xFD[_\x825`\x01``\x03\x836\x03\x03\x81\x12aGfWaGeaG?V[[\x80\x83\x01\x91PP\x92\x91PPV[__\x835`\x01` \x03\x846\x03\x03\x81\x12aG\x8EWaG\x8DaG?V[[\x80\x84\x01\x92P\x825\x91Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15aG\xB0WaG\xAFaGCV[[` \x83\x01\x92P` \x82\x026\x03\x83\x13\x15aG\xCCWaG\xCBaGGV[[P\x92P\x92\x90PV[\x7Foperator already exists\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aH\x08`\x17\x83aAEV[\x91PaH\x13\x82aG\xD4V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaH5\x81aG\xFCV[\x90P\x91\x90PV[_aHF\x82a;\x03V[\x91PaHQ\x83a;\x03V[\x92P\x82\x82\x03\x90P\x81\x81\x11\x15aHiWaHhaA\xBDV[[\x92\x91PPV[_aHy\x82a;\x03V[\x91PaH\x84\x83a;\x03V[\x92P\x82\x82\x01\x90P\x80\x82\x11\x15aH\x9CWaH\x9BaA\xBDV[[\x92\x91PPV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[_\x81\x90P\x91\x90PV[_aH\xC9` \x84\x01\x84a@\xB1V[\x90P\x92\x91PPV[_` \x82\x01\x90P\x91\x90PV[_aH\xE8\x83\x85aH\xA2V[\x93PaH\xF3\x82aH\xB2V[\x80_[\x85\x81\x10\x15aI+WaI\x08\x82\x84aH\xBBV[aI\x12\x88\x82a=\x8DV[\x97PaI\x1D\x83aH\xD1V[\x92PP`\x01\x81\x01\x90PaH\xF6V[P\x85\x92PPP\x93\x92PPPV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[_\x81\x90P\x91\x90PV[__\x835`\x01` \x03\x846\x03\x03\x81\x12aImWaIlaEGV[[\x83\x81\x01\x92P\x825\x91P` \x83\x01\x92Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15aI\x95WaI\x94aE?V[[` \x82\x026\x03\x83\x13\x15aI\xABWaI\xAAaECV[[P\x92P\x92\x90PV[_\x81\x90P\x91\x90PV[_`@\x83\x01aI\xCD_\x84\x01\x84aE)V[aI\xD9_\x86\x01\x82a;\x0CV[PaI\xE7` \x84\x01\x84aEKV[\x85\x83\x03` \x87\x01RaI\xFA\x83\x82\x84aE\xBBV[\x92PPP\x80\x91PP\x92\x91PPV[_aJ\x13\x83\x83aI\xBCV[\x90P\x92\x91PPV[_\x825`\x01`@\x03\x836\x03\x03\x81\x12aJ6WaJ5aEGV[[\x82\x81\x01\x91PP\x92\x91PPV[_` \x82\x01\x90P\x91\x90PV[_aJY\x83\x85a:\xE4V[\x93P\x83` \x84\x02\x85\x01aJk\x84aI\xB3V[\x80_[\x87\x81\x10\x15aJ\xAEW\x84\x84\x03\x89RaJ\x85\x82\x84aJ\x1BV[aJ\x8F\x85\x82aJ\x08V[\x94PaJ\x9A\x83aJBV[\x92P` \x8A\x01\x99PP`\x01\x81\x01\x90PaJnV[P\x82\x97P\x87\x94PPPPP\x93\x92PPPV[_``\x83\x01aJ\xD1_\x84\x01\x84aH\xBBV[aJ\xDD_\x86\x01\x82a:\xCBV[PaJ\xEB` \x84\x01\x84aIQV[\x85\x83\x03` \x87\x01RaJ\xFE\x83\x82\x84aJNV[\x92PPPaK\x0F`@\x84\x01\x84aEKV[\x85\x83\x03`@\x87\x01RaK\"\x83\x82\x84aE\xBBV[\x92PPP\x80\x91PP\x92\x91PPV[_aK;\x83\x83aJ\xC0V[\x90P\x92\x91PPV[_\x825`\x01``\x03\x836\x03\x03\x81\x12aK^WaK]aEGV[[\x82\x81\x01\x91PP\x92\x91PPV[_` \x82\x01\x90P\x91\x90PV[_aK\x81\x83\x85aI8V[\x93P\x83` \x84\x02\x85\x01aK\x93\x84aIHV[\x80_[\x87\x81\x10\x15aK\xD6W\x84\x84\x03\x89RaK\xAD\x82\x84aKCV[aK\xB7\x85\x82aK0V[\x94PaK\xC2\x83aKjV[\x92P` \x8A\x01\x99PP`\x01\x81\x01\x90PaK\x96V[P\x82\x97P\x87\x94PPPPP\x93\x92PPPV[_``\x82\x01\x90P\x81\x81\x03_\x83\x01RaL\x01\x81\x87\x89aH\xDDV[\x90P\x81\x81\x03` \x83\x01RaL\x16\x81\x85\x87aKvV[\x90PaL%`@\x83\x01\x84aB!V[\x96\x95PPPPPPV[\x7Fmigration in progress\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aLc`\x15\x83aAEV[\x91PaLn\x82aL/V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaL\x90\x81aLWV[\x90P\x91\x90PV[\x7Ftoo few nodes\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aL\xCB`\r\x83aAEV[\x91PaL\xD6\x82aL\x97V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaL\xF8\x81aL\xBFV[\x90P\x91\x90PV[aM\x08\x81a;\x03V[\x82RPPV[_``\x82\x01\x90PaM!_\x83\x01\x86aC\xD2V[aM.` \x83\x01\x85aL\xFFV[aM;`@\x83\x01\x84aB!V[\x94\x93PPPPV[\x7Fnot under maintenance\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aMw`\x15\x83aAEV[\x91PaM\x82\x82aMCV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaM\xA4\x81aMkV[\x90P\x91\x90PV[\x7Fnot pulling\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aM\xDF`\x0B\x83aAEV[\x91PaM\xEA\x82aM\xABV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaN\x0C\x81aM\xD3V[\x90P\x91\x90PV[_aN\x1D\x82aBuV[\x91P_\x82\x03aN/WaN.aA\xBDV[[`\x01\x82\x03\x90P\x91\x90PV[\x7Finvalid address\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aNn`\x0F\x83aAEV[\x91PaNy\x82aN:V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaN\x9B\x81aNbV[\x90P\x91\x90PV[\x7Foperator doesn't exist\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aN\xD6`\x16\x83aAEV[\x91PaN\xE1\x82aN\xA2V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaO\x03\x81aN\xCAV[\x90P\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`1`\x04R`$_\xFD[\x7Ftoo many operators\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aOk`\x12\x83aAEV[\x91PaOv\x82aO7V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaO\x98\x81aO_V[\x90P\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`A`\x04R`$_\xFD[_\x81\x90P\x81_R` _ \x90P\x91\x90PV[_` `\x1F\x83\x01\x04\x90P\x91\x90PV[_\x82\x82\x1B\x90P\x92\x91PPV[_`\x08\x83\x02aP(\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82aO\xEDV[aP2\x86\x83aO\xEDV[\x95P\x80\x19\x84\x16\x93P\x80\x86\x16\x84\x17\x92PPP\x93\x92PPPV[_aPdaP_aPZ\x84a;\x03V[aB\xD9V[a;\x03V[\x90P\x91\x90PV[_\x81\x90P\x91\x90PV[aP}\x83aPJV[aP\x91aP\x89\x82aPkV[\x84\x84TaO\xF9V[\x82UPPPPV[__\x90P\x90V[aP\xA8aP\x99V[aP\xB3\x81\x84\x84aPtV[PPPV[[\x81\x81\x10\x15aP\xD6WaP\xCB_\x82aP\xA0V[`\x01\x81\x01\x90PaP\xB9V[PPV[`\x1F\x82\x11\x15aQ\x1BWaP\xEC\x81aO\xCCV[aP\xF5\x84aO\xDEV[\x81\x01` \x85\x10\x15aQ\x04W\x81\x90P[aQ\x18aQ\x10\x85aO\xDEV[\x83\x01\x82aP\xB8V[PP[PPPV[_\x82\x82\x1C\x90P\x92\x91PPV[_aQ;_\x19\x84`\x08\x02aQ V[\x19\x80\x83\x16\x91PP\x92\x91PPV[_aQS\x83\x83aQ,V[\x91P\x82`\x02\x02\x82\x17\x90P\x92\x91PPV[aQl\x82a;\x1BV[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15aQ\x85WaQ\x84aO\x9FV[[aQ\x8F\x82TaDbV[aQ\x9A\x82\x82\x85aP\xDAV[_` \x90P`\x1F\x83\x11`\x01\x81\x14aQ\xCBW_\x84\x15aQ\xB9W\x82\x87\x01Q\x90P[aQ\xC3\x85\x82aQHV[\x86UPaR*V[`\x1F\x19\x84\x16aQ\xD9\x86aO\xCCV[_[\x82\x81\x10\x15aR\0W\x84\x89\x01Q\x82U`\x01\x82\x01\x91P` \x85\x01\x94P` \x81\x01\x90PaQ\xDBV[\x86\x83\x10\x15aR\x1DW\x84\x89\x01QaR\x19`\x1F\x89\x16\x82aQ,V[\x83UP[`\x01`\x02\x88\x02\x01\x88UPPP[PPPPPPV[\x7Fnot in progress\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aRf`\x0F\x83aAEV[\x91PaRq\x82aR2V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaR\x93\x81aRZV[\x90P\x91\x90PV[\x7Fdata pull in progress\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aR\xCE`\x15\x83aAEV[\x91PaR\xD9\x82aR\x9AV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaR\xFB\x81aR\xC2V[\x90P\x91\x90PV[__\xFD[aS\x0F\x82a;CV[\x81\x01\x81\x81\x10g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x17\x15aS.WaS-aO\x9FV[[\x80`@RPPPV[_aS@a9\xAFV[\x90PaSL\x82\x82aS\x06V[\x91\x90PV[__\xFD[__\xFD[_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15aSsWaSraO\x9FV[[aS|\x82a;CV[\x90P` \x81\x01\x90P\x91\x90PV[_aS\x9BaS\x96\x84aSYV[aS7V[\x90P\x82\x81R` \x81\x01\x84\x84\x84\x01\x11\x15aS\xB7WaS\xB6aSUV[[aS\xC2\x84\x82\x85aE\xADV[P\x93\x92PPPV[_\x82`\x1F\x83\x01\x12aS\xDEWaS\xDDa?gV[[\x815aS\xEE\x84\x82` \x86\x01aS\x89V[\x91PP\x92\x91PPV[_`@\x82\x84\x03\x12\x15aT\x0CWaT\x0BaS\x02V[[aT\x16`@aS7V[\x90P_aT%\x84\x82\x85\x01aA\x06V[_\x83\x01RP` \x82\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15aTHWaTGaSQV[[aTT\x84\x82\x85\x01aS\xCAV[` \x83\x01RP\x92\x91PPV[_aTk6\x83aS\xF7V[\x90P\x91\x90PV[_aT|\x82a;\x03V[\x91P\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x03aT\xAEWaT\xADaA\xBDV[[`\x01\x82\x01\x90P\x91\x90PV[\x7Ftoo many nodes\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aT\xED`\x0E\x83aAEV[\x91PaT\xF8\x82aT\xB9V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaU\x1A\x81aT\xE1V[\x90P\x91\x90PV[\x7Ftoo few operators\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aUU`\x11\x83aAEV[\x91PaU`\x82aU!V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaU\x82\x81aUIV[\x90P\x91\x90PV[\x7Fmigration already in progress\0\0\0_\x82\x01RPV[_aU\xBD`\x1D\x83aAEV[\x91PaU\xC8\x82aU\x89V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaU\xEA\x81aU\xB1V[\x90P\x91\x90PV[\x7Fnothing to do\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aV%`\r\x83aAEV[\x91PaV0\x82aU\xF1V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaVR\x81aV\x19V[\x90P\x91\x90PV[_aVc\x82aBuV[\x91P`\xFF\x82\x03aVvWaVuaA\xBDV[[`\x01\x82\x01\x90P\x91\x90PV[_\x815aV\x8D\x81a@\x9BV[\x80\x91PP\x91\x90PV[_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFFaV\xB5\x84aB\xACV[\x93P\x80\x19\x83\x16\x92P\x80\x84\x16\x83\x17\x91PP\x92\x91PPV[_aV\xE5aV\xE0aV\xDB\x84a:\x9BV[aB\xD9V[a:\x9BV[\x90P\x91\x90PV[_aV\xF6\x82aV\xCBV[\x90P\x91\x90PV[_aW\x07\x82aV\xECV[\x90P\x91\x90PV[_\x81\x90P\x91\x90PV[aW \x82aV\xFDV[aW3aW,\x82aW\x0EV[\x83TaV\x96V[\x82UPPPV[_\x825`\x01`@\x03\x836\x03\x03\x81\x12aWUWaWTaG?V[[\x80\x83\x01\x91PP\x92\x91PPV[_\x81T\x90P\x91\x90PV[_aWu\x82a;\x03V[\x91PaW\x80\x83a;\x03V[\x92P\x82\x82\x02aW\x8E\x81a;\x03V[\x91P\x82\x82\x04\x84\x14\x83\x15\x17aW\xA5WaW\xA4aA\xBDV[[P\x92\x91PPV[_\x81\x90PaW\xBB\x82`\x02aWkV[\x90P\x91\x90PV[_\x81\x90P\x81_R` _ \x90P\x91\x90PV[aX\x04\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x83` \x03`\x08\x02aQ V[\x81T\x81\x16\x82UPPPV[aX\x18\x81aO\xCCV[aX#\x83\x82TaQHV[\x80\x83U_\x82UPPPPV[` \x84\x10_\x81\x14aX\x89W`\x1F\x84\x11`\x01\x81\x14aXWWaXP\x86\x85aQHV[\x83UaX\x83V[aX`\x83aO\xCCV[aXwaXl\x87aO\xDEV[\x82\x01`\x01\x83\x01aP\xB8V[aX\x81\x87\x85aX\x0FV[P[PaX\xD6V[aX\x92\x82aO\xCCV[aX\x9B\x86aO\xDEV[\x81\x01`\x1F\x87\x16\x80\x15aX\xB5WaX\xB4\x81`\x01\x84\x03aW\xD4V[[aX\xC9aX\xC1\x88aO\xDEV[\x84\x01\x83aP\xB8V[`\x01\x88`\x02\x02\x17\x85UPPP[PPPPPV[h\x01\0\0\0\0\0\0\0\0\x84\x11\x15aX\xF7WaX\xF6aO\x9FV[[` \x83\x10_\x81\x14aY@W` \x85\x10_\x81\x14aY\x1EWaY\x17\x86\x85aQHV[\x83UaY:V[\x83`\xFF\x19\x16\x93P\x83aY/\x84aO\xCCV[U`\x01\x86`\x02\x02\x01\x83U[PaYJV[`\x01\x85`\x02\x02\x01\x82U[PPPPPV[\x80TaY\\\x81aDbV[\x80\x84\x11\x15aYqWaYp\x84\x82\x84\x86aX\xDDV[[\x80\x84\x10\x15aY\x86WaY\x85\x84\x82\x84\x86aX/V[[PPPPV[\x81\x81\x10\x15aY\xA9WaY\x9E_\x82aP\xA0V[`\x01\x81\x01\x90PaY\x8CV[PPV[aY\xB7_\x82aYQV[PV[_\x82\x14aY\xCAWaY\xC9aBIV[[aY\xD3\x81aY\xADV[PPV[aY\xE3__\x83\x01aP\xA0V[aY\xF0_`\x01\x83\x01aY\xBAV[PV[_\x82\x14aZ\x03WaZ\x02aBIV[[aZ\x0C\x81aY\xD7V[PPV[[\x81\x81\x10\x15aZ.WaZ#_\x82aY\xF3V[`\x02\x81\x01\x90PaZ\x11V[PPV[\x81\x83\x10\x15aZkWaZC\x82aW\xACV[aZL\x84aW\xACV[aZU\x83aW\xC2V[\x81\x81\x01\x83\x82\x01aZe\x81\x83aZ\x10V[PPPPP[PPPV[h\x01\0\0\0\0\0\0\0\0\x82\x11\x15aZ\x8AWaZ\x89aO\x9FV[[aZ\x93\x81aWaV[\x82\x82UaZ\xA1\x83\x82\x84aZ2V[PPPV[_\x82\x90P\x92\x91PPV[_\x815aZ\xBC\x81a@\xF0V[\x80\x91PP\x91\x90PV[_\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFFaZ\xF0\x84aB\xACV[\x93P\x80\x19\x83\x16\x92P\x80\x84\x16\x83\x17\x91PP\x92\x91PPV[a[\x0F\x82aPJV[a[\"a[\x1B\x82aPkV[\x83TaZ\xC5V[\x82UPPPV[__\x835`\x01` \x03\x846\x03\x03\x81\x12a[EWa[DaG?V[[\x80\x84\x01\x92P\x825\x91Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15a[gWa[faGCV[[` \x83\x01\x92P`\x01\x82\x026\x03\x83\x13\x15a[\x83Wa[\x82aGGV[[P\x92P\x92\x90PV[_\x82\x90P\x92\x91PPV[a[\x9F\x83\x83a[\x8BV[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a[\xB8Wa[\xB7aO\x9FV[[a[\xC2\x82TaDbV[a[\xCD\x82\x82\x85aP\xDAV[_`\x1F\x83\x11`\x01\x81\x14a[\xFAW_\x84\x15a[\xE8W\x82\x87\x015\x90P[a[\xF2\x85\x82aQHV[\x86UPa\\YV[`\x1F\x19\x84\x16a\\\x08\x86aO\xCCV[_[\x82\x81\x10\x15a\\/W\x84\x89\x015\x82U`\x01\x82\x01\x91P` \x85\x01\x94P` \x81\x01\x90Pa\\\nV[\x86\x83\x10\x15a\\LW\x84\x89\x015a\\H`\x1F\x89\x16\x82aQ,V[\x83UP[`\x01`\x02\x88\x02\x01\x88UPPP[PPPPPPPV[a\\m\x83\x83\x83a[\x95V[PPPV[_\x81\x01_\x83\x01\x80a\\\x82\x81aZ\xB0V[\x90Pa\\\x8E\x81\x84a[\x06V[PPP`\x01\x81\x01` \x83\x01a\\\xA3\x81\x85a[)V[a\\\xAE\x81\x83\x86a\\bV[PPPPPPV[a\\\xC0\x82\x82a\\rV[PPV[a\\\xCE\x83\x83aZ\xA6V[a\\\xD8\x81\x83aZpV[a\\\xE1\x83aI\xB3V[a\\\xEA\x83aW\xC2V[_[\x83\x81\x10\x15a] Wa\\\xFE\x83\x87aW:V[a]\x08\x81\x84a\\\xB6V[` \x84\x01\x93P`\x02\x83\x01\x92PP`\x01\x81\x01\x90Pa\\\xECV[PPPPPPPV[a]4\x83\x83\x83a\\\xC4V[PPPV[_\x81\x01_\x83\x01\x80a]I\x81aV\x81V[\x90Pa]U\x81\x84aW\x17V[PPP`\x01\x81\x01` \x83\x01a]j\x81\x85aGrV[a]u\x81\x83\x86a])V[PPPP`\x02\x81\x01`@\x83\x01a]\x8B\x81\x85a[)V[a]\x96\x81\x83\x86a\\bV[PPPPPPV[a]\xA8\x82\x82a]9V[PPV[\x7Fanother maintenance in progress\0_\x82\x01RPV[_a]\xE0`\x1F\x83aAEV[\x91Pa]\xEB\x82a]\xACV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra^\r\x81a]\xD4V[\x90P\x91\x90PV[\x7Finvalid id\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a^H`\n\x83aAEV[\x91Pa^S\x82a^\x14V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra^u\x81a^::RustType, + #[allow(missing_docs)] + pub migration: ::RustType, + #[allow(missing_docs)] + pub maintenance: ::RustType, + #[allow(missing_docs)] + pub keyspaceVersion: u64, + #[allow(missing_docs)] + pub version: u128, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + NodeOperatorsView, + MigrationView, + Maintenance, + alloy::sol_types::sol_data::Uint<64>, + alloy::sol_types::sol_data::Uint<128>, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + ::RustType, + ::RustType, + ::RustType, + u64, + u128, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: ClusterView) -> Self { + ( + value.operators, + value.migration, + value.maintenance, + value.keyspaceVersion, + value.version, + ) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for ClusterView { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + operators: tuple.0, + migration: tuple.1, + maintenance: tuple.2, + keyspaceVersion: tuple.3, + version: tuple.4, + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolValue for ClusterView { + type SolType = Self; + } + #[automatically_derived] + impl alloy_sol_types::private::SolTypeValue for ClusterView { + #[inline] + fn stv_to_tokens(&self) -> ::Token<'_> { + ( + ::tokenize( + &self.operators, + ), + ::tokenize( + &self.migration, + ), + ::tokenize( + &self.maintenance, + ), + as alloy_sol_types::SolType>::tokenize(&self.keyspaceVersion), + as alloy_sol_types::SolType>::tokenize(&self.version), + ) + } + #[inline] + fn stv_abi_encoded_size(&self) -> usize { + if let Some(size) = ::ENCODED_SIZE { + return size; + } + let tuple = as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encoded_size(&tuple) + } + #[inline] + fn stv_eip712_data_word(&self) -> alloy_sol_types::Word { + ::eip712_hash_struct(self) + } + #[inline] + fn stv_abi_encode_packed_to( + &self, + out: &mut alloy_sol_types::private::Vec, + ) { + let tuple = as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encode_packed_to(&tuple, out) + } + #[inline] + fn stv_abi_packed_encoded_size(&self) -> usize { + if let Some(size) = ::PACKED_ENCODED_SIZE { + return size; + } + let tuple = as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_packed_encoded_size(&tuple) + } + } + #[automatically_derived] + impl alloy_sol_types::SolType for ClusterView { + type RustType = Self; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SOL_NAME: &'static str = ::NAME; + const ENCODED_SIZE: Option = as alloy_sol_types::SolType>::ENCODED_SIZE; + const PACKED_ENCODED_SIZE: Option = as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; + #[inline] + fn valid_token(token: &Self::Token<'_>) -> bool { + as alloy_sol_types::SolType>::valid_token(token) + } + #[inline] + fn detokenize(token: Self::Token<'_>) -> Self::RustType { + let tuple = as alloy_sol_types::SolType>::detokenize(token); + >>::from(tuple) + } + } + #[automatically_derived] + impl alloy_sol_types::SolStruct for ClusterView { + const NAME: &'static str = "ClusterView"; + #[inline] + fn eip712_root_type() -> alloy_sol_types::private::Cow<'static, str> { + alloy_sol_types::private::Cow::Borrowed( + "ClusterView(NodeOperatorsView operators,MigrationView migration,Maintenance maintenance,uint64 keyspaceVersion,uint128 version)", + ) + } + #[inline] + fn eip712_components() -> alloy_sol_types::private::Vec< + alloy_sol_types::private::Cow<'static, str>, + > { + let mut components = alloy_sol_types::private::Vec::with_capacity(3); + components + .push( + ::eip712_root_type(), + ); + components + .extend( + ::eip712_components(), + ); + components + .push( + ::eip712_root_type(), + ); + components + .extend( + ::eip712_components(), + ); + components + .push( + ::eip712_root_type(), + ); + components + .extend( + ::eip712_components(), + ); + components + } + #[inline] + fn eip712_encode_data(&self) -> alloy_sol_types::private::Vec { + [ + ::eip712_data_word( + &self.operators, + ) + .0, + ::eip712_data_word( + &self.migration, + ) + .0, + ::eip712_data_word( + &self.maintenance, + ) + .0, + as alloy_sol_types::SolType>::eip712_data_word( + &self.keyspaceVersion, + ) + .0, + as alloy_sol_types::SolType>::eip712_data_word(&self.version) + .0, + ] + .concat() + } + } + #[automatically_derived] + impl alloy_sol_types::EventTopic for ClusterView { + #[inline] + fn topic_preimage_length(rust: &Self::RustType) -> usize { + 0usize + + ::topic_preimage_length( + &rust.operators, + ) + + ::topic_preimage_length( + &rust.migration, + ) + + ::topic_preimage_length( + &rust.maintenance, + ) + + as alloy_sol_types::EventTopic>::topic_preimage_length( + &rust.keyspaceVersion, + ) + + as alloy_sol_types::EventTopic>::topic_preimage_length( + &rust.version, + ) + } + #[inline] + fn encode_topic_preimage( + rust: &Self::RustType, + out: &mut alloy_sol_types::private::Vec, + ) { + out.reserve( + ::topic_preimage_length(rust), + ); + ::encode_topic_preimage( + &rust.operators, + out, + ); + ::encode_topic_preimage( + &rust.migration, + out, + ); + ::encode_topic_preimage( + &rust.maintenance, + out, + ); + as alloy_sol_types::EventTopic>::encode_topic_preimage( + &rust.keyspaceVersion, + out, + ); + as alloy_sol_types::EventTopic>::encode_topic_preimage( + &rust.version, + out, + ); + } + #[inline] + fn encode_topic( + rust: &Self::RustType, + ) -> alloy_sol_types::abi::token::WordToken { + let mut out = alloy_sol_types::private::Vec::new(); + ::encode_topic_preimage( + rust, + &mut out, + ); + alloy_sol_types::abi::token::WordToken( + alloy_sol_types::private::keccak256(out), + ) + } + } + }; + /**```solidity +struct Maintenance { address slot; } +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct Maintenance { + #[allow(missing_docs)] + pub slot: alloy::sol_types::private::Address, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Address,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::Address,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: Maintenance) -> Self { + (value.slot,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for Maintenance { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { slot: tuple.0 } + } + } + #[automatically_derived] + impl alloy_sol_types::SolValue for Maintenance { + type SolType = Self; + } + #[automatically_derived] + impl alloy_sol_types::private::SolTypeValue for Maintenance { + #[inline] + fn stv_to_tokens(&self) -> ::Token<'_> { + ( + ::tokenize( + &self.slot, + ), + ) + } + #[inline] + fn stv_abi_encoded_size(&self) -> usize { + if let Some(size) = ::ENCODED_SIZE { + return size; + } + let tuple = as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encoded_size(&tuple) + } + #[inline] + fn stv_eip712_data_word(&self) -> alloy_sol_types::Word { + ::eip712_hash_struct(self) + } + #[inline] + fn stv_abi_encode_packed_to( + &self, + out: &mut alloy_sol_types::private::Vec, + ) { + let tuple = as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encode_packed_to(&tuple, out) + } + #[inline] + fn stv_abi_packed_encoded_size(&self) -> usize { + if let Some(size) = ::PACKED_ENCODED_SIZE { + return size; + } + let tuple = as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_packed_encoded_size(&tuple) + } + } + #[automatically_derived] + impl alloy_sol_types::SolType for Maintenance { + type RustType = Self; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SOL_NAME: &'static str = ::NAME; + const ENCODED_SIZE: Option = as alloy_sol_types::SolType>::ENCODED_SIZE; + const PACKED_ENCODED_SIZE: Option = as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; + #[inline] + fn valid_token(token: &Self::Token<'_>) -> bool { + as alloy_sol_types::SolType>::valid_token(token) + } + #[inline] + fn detokenize(token: Self::Token<'_>) -> Self::RustType { + let tuple = as alloy_sol_types::SolType>::detokenize(token); + >>::from(tuple) + } + } + #[automatically_derived] + impl alloy_sol_types::SolStruct for Maintenance { + const NAME: &'static str = "Maintenance"; + #[inline] + fn eip712_root_type() -> alloy_sol_types::private::Cow<'static, str> { + alloy_sol_types::private::Cow::Borrowed("Maintenance(address slot)") + } + #[inline] + fn eip712_components() -> alloy_sol_types::private::Vec< + alloy_sol_types::private::Cow<'static, str>, + > { + alloy_sol_types::private::Vec::new() + } + #[inline] + fn eip712_encode_type() -> alloy_sol_types::private::Cow<'static, str> { + ::eip712_root_type() + } + #[inline] + fn eip712_encode_data(&self) -> alloy_sol_types::private::Vec { + ::eip712_data_word( + &self.slot, + ) + .0 + .to_vec() + } + } + #[automatically_derived] + impl alloy_sol_types::EventTopic for Maintenance { + #[inline] + fn topic_preimage_length(rust: &Self::RustType) -> usize { + 0usize + + ::topic_preimage_length( + &rust.slot, + ) + } + #[inline] + fn encode_topic_preimage( + rust: &Self::RustType, + out: &mut alloy_sol_types::private::Vec, + ) { + out.reserve( + ::topic_preimage_length(rust), + ); + ::encode_topic_preimage( + &rust.slot, + out, + ); + } + #[inline] + fn encode_topic( + rust: &Self::RustType, + ) -> alloy_sol_types::abi::token::WordToken { + let mut out = alloy_sol_types::private::Vec::new(); + ::encode_topic_preimage( + rust, + &mut out, + ); + alloy_sol_types::abi::token::WordToken( + alloy_sol_types::private::keccak256(out), + ) + } + } + }; + /**```solidity +struct MigrationView { address[] operatorsToRemove; NodeOperatorView[] operatorsToAdd; address[] pullingOperators; } +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct MigrationView { + #[allow(missing_docs)] + pub operatorsToRemove: alloy::sol_types::private::Vec< + alloy::sol_types::private::Address, + >, + #[allow(missing_docs)] + pub operatorsToAdd: alloy::sol_types::private::Vec< + ::RustType, + >, + #[allow(missing_docs)] + pub pullingOperators: alloy::sol_types::private::Vec< + alloy::sol_types::private::Address, + >, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::Array, + alloy::sol_types::sol_data::Array, + alloy::sol_types::sol_data::Array, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::Vec, + alloy::sol_types::private::Vec< + ::RustType, + >, + alloy::sol_types::private::Vec, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: MigrationView) -> Self { + (value.operatorsToRemove, value.operatorsToAdd, value.pullingOperators) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for MigrationView { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + operatorsToRemove: tuple.0, + operatorsToAdd: tuple.1, + pullingOperators: tuple.2, + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolValue for MigrationView { + type SolType = Self; + } + #[automatically_derived] + impl alloy_sol_types::private::SolTypeValue for MigrationView { + #[inline] + fn stv_to_tokens(&self) -> ::Token<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.operatorsToRemove), + as alloy_sol_types::SolType>::tokenize(&self.operatorsToAdd), + as alloy_sol_types::SolType>::tokenize(&self.pullingOperators), + ) + } + #[inline] + fn stv_abi_encoded_size(&self) -> usize { + if let Some(size) = ::ENCODED_SIZE { + return size; + } + let tuple = as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encoded_size(&tuple) + } + #[inline] + fn stv_eip712_data_word(&self) -> alloy_sol_types::Word { + ::eip712_hash_struct(self) + } + #[inline] + fn stv_abi_encode_packed_to( + &self, + out: &mut alloy_sol_types::private::Vec, + ) { + let tuple = as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encode_packed_to(&tuple, out) + } + #[inline] + fn stv_abi_packed_encoded_size(&self) -> usize { + if let Some(size) = ::PACKED_ENCODED_SIZE { + return size; + } + let tuple = as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_packed_encoded_size(&tuple) + } + } + #[automatically_derived] + impl alloy_sol_types::SolType for MigrationView { + type RustType = Self; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SOL_NAME: &'static str = ::NAME; + const ENCODED_SIZE: Option = as alloy_sol_types::SolType>::ENCODED_SIZE; + const PACKED_ENCODED_SIZE: Option = as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; + #[inline] + fn valid_token(token: &Self::Token<'_>) -> bool { + as alloy_sol_types::SolType>::valid_token(token) + } + #[inline] + fn detokenize(token: Self::Token<'_>) -> Self::RustType { + let tuple = as alloy_sol_types::SolType>::detokenize(token); + >>::from(tuple) + } + } + #[automatically_derived] + impl alloy_sol_types::SolStruct for MigrationView { + const NAME: &'static str = "MigrationView"; + #[inline] + fn eip712_root_type() -> alloy_sol_types::private::Cow<'static, str> { + alloy_sol_types::private::Cow::Borrowed( + "MigrationView(address[] operatorsToRemove,NodeOperatorView[] operatorsToAdd,address[] pullingOperators)", + ) + } + #[inline] + fn eip712_components() -> alloy_sol_types::private::Vec< + alloy_sol_types::private::Cow<'static, str>, + > { + let mut components = alloy_sol_types::private::Vec::with_capacity(1); + components + .push( + ::eip712_root_type(), + ); + components + .extend( + ::eip712_components(), + ); + components + } + #[inline] + fn eip712_encode_data(&self) -> alloy_sol_types::private::Vec { + [ + as alloy_sol_types::SolType>::eip712_data_word( + &self.operatorsToRemove, + ) + .0, + as alloy_sol_types::SolType>::eip712_data_word( + &self.operatorsToAdd, + ) + .0, + as alloy_sol_types::SolType>::eip712_data_word( + &self.pullingOperators, + ) + .0, + ] + .concat() + } + } + #[automatically_derived] + impl alloy_sol_types::EventTopic for MigrationView { + #[inline] + fn topic_preimage_length(rust: &Self::RustType) -> usize { + 0usize + + as alloy_sol_types::EventTopic>::topic_preimage_length( + &rust.operatorsToRemove, + ) + + as alloy_sol_types::EventTopic>::topic_preimage_length( + &rust.operatorsToAdd, + ) + + as alloy_sol_types::EventTopic>::topic_preimage_length( + &rust.pullingOperators, + ) + } + #[inline] + fn encode_topic_preimage( + rust: &Self::RustType, + out: &mut alloy_sol_types::private::Vec, + ) { + out.reserve( + ::topic_preimage_length(rust), + ); + as alloy_sol_types::EventTopic>::encode_topic_preimage( + &rust.operatorsToRemove, + out, + ); + as alloy_sol_types::EventTopic>::encode_topic_preimage( + &rust.operatorsToAdd, + out, + ); + as alloy_sol_types::EventTopic>::encode_topic_preimage( + &rust.pullingOperators, + out, + ); + } + #[inline] + fn encode_topic( + rust: &Self::RustType, + ) -> alloy_sol_types::abi::token::WordToken { + let mut out = alloy_sol_types::private::Vec::new(); + ::encode_topic_preimage( + rust, + &mut out, + ); + alloy_sol_types::abi::token::WordToken( + alloy_sol_types::private::keccak256(out), + ) + } + } + }; + /**```solidity +struct Node { uint256 id; bytes data; } +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct Node { + #[allow(missing_docs)] + pub id: alloy::sol_types::private::primitives::aliases::U256, + #[allow(missing_docs)] + pub data: alloy::sol_types::private::Bytes, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::Uint<256>, + alloy::sol_types::sol_data::Bytes, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::primitives::aliases::U256, + alloy::sol_types::private::Bytes, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: Node) -> Self { + (value.id, value.data) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for Node { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { id: tuple.0, data: tuple.1 } + } + } + #[automatically_derived] + impl alloy_sol_types::SolValue for Node { + type SolType = Self; + } + #[automatically_derived] + impl alloy_sol_types::private::SolTypeValue for Node { + #[inline] + fn stv_to_tokens(&self) -> ::Token<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.id), + ::tokenize( + &self.data, + ), + ) + } + #[inline] + fn stv_abi_encoded_size(&self) -> usize { + if let Some(size) = ::ENCODED_SIZE { + return size; + } + let tuple = as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encoded_size(&tuple) + } + #[inline] + fn stv_eip712_data_word(&self) -> alloy_sol_types::Word { + ::eip712_hash_struct(self) + } + #[inline] + fn stv_abi_encode_packed_to( + &self, + out: &mut alloy_sol_types::private::Vec, + ) { + let tuple = as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encode_packed_to(&tuple, out) + } + #[inline] + fn stv_abi_packed_encoded_size(&self) -> usize { + if let Some(size) = ::PACKED_ENCODED_SIZE { + return size; + } + let tuple = as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_packed_encoded_size(&tuple) + } + } + #[automatically_derived] + impl alloy_sol_types::SolType for Node { + type RustType = Self; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SOL_NAME: &'static str = ::NAME; + const ENCODED_SIZE: Option = as alloy_sol_types::SolType>::ENCODED_SIZE; + const PACKED_ENCODED_SIZE: Option = as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; + #[inline] + fn valid_token(token: &Self::Token<'_>) -> bool { + as alloy_sol_types::SolType>::valid_token(token) + } + #[inline] + fn detokenize(token: Self::Token<'_>) -> Self::RustType { + let tuple = as alloy_sol_types::SolType>::detokenize(token); + >>::from(tuple) + } + } + #[automatically_derived] + impl alloy_sol_types::SolStruct for Node { + const NAME: &'static str = "Node"; + #[inline] + fn eip712_root_type() -> alloy_sol_types::private::Cow<'static, str> { + alloy_sol_types::private::Cow::Borrowed("Node(uint256 id,bytes data)") + } + #[inline] + fn eip712_components() -> alloy_sol_types::private::Vec< + alloy_sol_types::private::Cow<'static, str>, + > { + alloy_sol_types::private::Vec::new() + } + #[inline] + fn eip712_encode_type() -> alloy_sol_types::private::Cow<'static, str> { + ::eip712_root_type() + } + #[inline] + fn eip712_encode_data(&self) -> alloy_sol_types::private::Vec { + [ + as alloy_sol_types::SolType>::eip712_data_word(&self.id) + .0, + ::eip712_data_word( + &self.data, + ) + .0, + ] + .concat() + } + } + #[automatically_derived] + impl alloy_sol_types::EventTopic for Node { + #[inline] + fn topic_preimage_length(rust: &Self::RustType) -> usize { + 0usize + + as alloy_sol_types::EventTopic>::topic_preimage_length(&rust.id) + + ::topic_preimage_length( + &rust.data, + ) + } + #[inline] + fn encode_topic_preimage( + rust: &Self::RustType, + out: &mut alloy_sol_types::private::Vec, + ) { + out.reserve( + ::topic_preimage_length(rust), + ); + as alloy_sol_types::EventTopic>::encode_topic_preimage(&rust.id, out); + ::encode_topic_preimage( + &rust.data, + out, + ); + } + #[inline] + fn encode_topic( + rust: &Self::RustType, + ) -> alloy_sol_types::abi::token::WordToken { + let mut out = alloy_sol_types::private::Vec::new(); + ::encode_topic_preimage( + rust, + &mut out, + ); + alloy_sol_types::abi::token::WordToken( + alloy_sol_types::private::keccak256(out), + ) + } + } + }; + /**```solidity +struct NodeOperatorView { address addr; Node[] nodes; bytes data; } +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct NodeOperatorView { + #[allow(missing_docs)] + pub addr: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub nodes: alloy::sol_types::private::Vec< + ::RustType, + >, + #[allow(missing_docs)] + pub data: alloy::sol_types::private::Bytes, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Array, + alloy::sol_types::sol_data::Bytes, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::Address, + alloy::sol_types::private::Vec< + ::RustType, + >, + alloy::sol_types::private::Bytes, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: NodeOperatorView) -> Self { + (value.addr, value.nodes, value.data) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for NodeOperatorView { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + addr: tuple.0, + nodes: tuple.1, + data: tuple.2, + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolValue for NodeOperatorView { + type SolType = Self; + } + #[automatically_derived] + impl alloy_sol_types::private::SolTypeValue for NodeOperatorView { + #[inline] + fn stv_to_tokens(&self) -> ::Token<'_> { + ( + ::tokenize( + &self.addr, + ), + as alloy_sol_types::SolType>::tokenize(&self.nodes), + ::tokenize( + &self.data, + ), + ) + } + #[inline] + fn stv_abi_encoded_size(&self) -> usize { + if let Some(size) = ::ENCODED_SIZE { + return size; + } + let tuple = as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encoded_size(&tuple) + } + #[inline] + fn stv_eip712_data_word(&self) -> alloy_sol_types::Word { + ::eip712_hash_struct(self) + } + #[inline] + fn stv_abi_encode_packed_to( + &self, + out: &mut alloy_sol_types::private::Vec, + ) { + let tuple = as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encode_packed_to(&tuple, out) + } + #[inline] + fn stv_abi_packed_encoded_size(&self) -> usize { + if let Some(size) = ::PACKED_ENCODED_SIZE { + return size; + } + let tuple = as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_packed_encoded_size(&tuple) + } + } + #[automatically_derived] + impl alloy_sol_types::SolType for NodeOperatorView { + type RustType = Self; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SOL_NAME: &'static str = ::NAME; + const ENCODED_SIZE: Option = as alloy_sol_types::SolType>::ENCODED_SIZE; + const PACKED_ENCODED_SIZE: Option = as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; + #[inline] + fn valid_token(token: &Self::Token<'_>) -> bool { + as alloy_sol_types::SolType>::valid_token(token) + } + #[inline] + fn detokenize(token: Self::Token<'_>) -> Self::RustType { + let tuple = as alloy_sol_types::SolType>::detokenize(token); + >>::from(tuple) + } + } + #[automatically_derived] + impl alloy_sol_types::SolStruct for NodeOperatorView { + const NAME: &'static str = "NodeOperatorView"; + #[inline] + fn eip712_root_type() -> alloy_sol_types::private::Cow<'static, str> { + alloy_sol_types::private::Cow::Borrowed( + "NodeOperatorView(address addr,Node[] nodes,bytes data)", + ) + } + #[inline] + fn eip712_components() -> alloy_sol_types::private::Vec< + alloy_sol_types::private::Cow<'static, str>, + > { + let mut components = alloy_sol_types::private::Vec::with_capacity(1); + components + .push(::eip712_root_type()); + components + .extend(::eip712_components()); + components + } + #[inline] + fn eip712_encode_data(&self) -> alloy_sol_types::private::Vec { + [ + ::eip712_data_word( + &self.addr, + ) + .0, + as alloy_sol_types::SolType>::eip712_data_word(&self.nodes) + .0, + ::eip712_data_word( + &self.data, + ) + .0, + ] + .concat() + } + } + #[automatically_derived] + impl alloy_sol_types::EventTopic for NodeOperatorView { + #[inline] + fn topic_preimage_length(rust: &Self::RustType) -> usize { + 0usize + + ::topic_preimage_length( + &rust.addr, + ) + + as alloy_sol_types::EventTopic>::topic_preimage_length(&rust.nodes) + + ::topic_preimage_length( + &rust.data, + ) + } + #[inline] + fn encode_topic_preimage( + rust: &Self::RustType, + out: &mut alloy_sol_types::private::Vec, + ) { + out.reserve( + ::topic_preimage_length(rust), + ); + ::encode_topic_preimage( + &rust.addr, + out, + ); + as alloy_sol_types::EventTopic>::encode_topic_preimage( + &rust.nodes, + out, + ); + ::encode_topic_preimage( + &rust.data, + out, + ); + } + #[inline] + fn encode_topic( + rust: &Self::RustType, + ) -> alloy_sol_types::abi::token::WordToken { + let mut out = alloy_sol_types::private::Vec::new(); + ::encode_topic_preimage( + rust, + &mut out, + ); + alloy_sol_types::abi::token::WordToken( + alloy_sol_types::private::keccak256(out), + ) + } + } + }; + /**```solidity +struct NodeOperatorsView { NodeOperatorView[] slots; } +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct NodeOperatorsView { + #[allow(missing_docs)] + pub slots: alloy::sol_types::private::Vec< + ::RustType, + >, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::Array, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::Vec< + ::RustType, + >, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: NodeOperatorsView) -> Self { + (value.slots,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for NodeOperatorsView { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { slots: tuple.0 } + } + } + #[automatically_derived] + impl alloy_sol_types::SolValue for NodeOperatorsView { + type SolType = Self; + } + #[automatically_derived] + impl alloy_sol_types::private::SolTypeValue for NodeOperatorsView { + #[inline] + fn stv_to_tokens(&self) -> ::Token<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.slots), + ) + } + #[inline] + fn stv_abi_encoded_size(&self) -> usize { + if let Some(size) = ::ENCODED_SIZE { + return size; + } + let tuple = as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encoded_size(&tuple) + } + #[inline] + fn stv_eip712_data_word(&self) -> alloy_sol_types::Word { + ::eip712_hash_struct(self) + } + #[inline] + fn stv_abi_encode_packed_to( + &self, + out: &mut alloy_sol_types::private::Vec, + ) { + let tuple = as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encode_packed_to(&tuple, out) + } + #[inline] + fn stv_abi_packed_encoded_size(&self) -> usize { + if let Some(size) = ::PACKED_ENCODED_SIZE { + return size; + } + let tuple = as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_packed_encoded_size(&tuple) + } + } + #[automatically_derived] + impl alloy_sol_types::SolType for NodeOperatorsView { + type RustType = Self; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SOL_NAME: &'static str = ::NAME; + const ENCODED_SIZE: Option = as alloy_sol_types::SolType>::ENCODED_SIZE; + const PACKED_ENCODED_SIZE: Option = as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; + #[inline] + fn valid_token(token: &Self::Token<'_>) -> bool { + as alloy_sol_types::SolType>::valid_token(token) + } + #[inline] + fn detokenize(token: Self::Token<'_>) -> Self::RustType { + let tuple = as alloy_sol_types::SolType>::detokenize(token); + >>::from(tuple) + } + } + #[automatically_derived] + impl alloy_sol_types::SolStruct for NodeOperatorsView { + const NAME: &'static str = "NodeOperatorsView"; + #[inline] + fn eip712_root_type() -> alloy_sol_types::private::Cow<'static, str> { + alloy_sol_types::private::Cow::Borrowed( + "NodeOperatorsView(NodeOperatorView[] slots)", + ) + } + #[inline] + fn eip712_components() -> alloy_sol_types::private::Vec< + alloy_sol_types::private::Cow<'static, str>, + > { + let mut components = alloy_sol_types::private::Vec::with_capacity(1); + components + .push( + ::eip712_root_type(), + ); + components + .extend( + ::eip712_components(), + ); + components + } + #[inline] + fn eip712_encode_data(&self) -> alloy_sol_types::private::Vec { + as alloy_sol_types::SolType>::eip712_data_word(&self.slots) + .0 + .to_vec() + } + } + #[automatically_derived] + impl alloy_sol_types::EventTopic for NodeOperatorsView { + #[inline] + fn topic_preimage_length(rust: &Self::RustType) -> usize { + 0usize + + as alloy_sol_types::EventTopic>::topic_preimage_length(&rust.slots) + } + #[inline] + fn encode_topic_preimage( + rust: &Self::RustType, + out: &mut alloy_sol_types::private::Vec, + ) { + out.reserve( + ::topic_preimage_length(rust), + ); + as alloy_sol_types::EventTopic>::encode_topic_preimage( + &rust.slots, + out, + ); + } + #[inline] + fn encode_topic( + rust: &Self::RustType, + ) -> alloy_sol_types::abi::token::WordToken { + let mut out = alloy_sol_types::private::Vec::new(); + ::encode_topic_preimage( + rust, + &mut out, + ); + alloy_sol_types::abi::token::WordToken( + alloy_sol_types::private::keccak256(out), + ) + } + } + }; + /**```solidity +struct Settings { uint8 minOperators; uint8 minNodes; } +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct Settings { + #[allow(missing_docs)] + pub minOperators: u8, + #[allow(missing_docs)] + pub minNodes: u8, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::Uint<8>, + alloy::sol_types::sol_data::Uint<8>, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (u8, u8); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: Settings) -> Self { + (value.minOperators, value.minNodes) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for Settings { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + minOperators: tuple.0, + minNodes: tuple.1, + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolValue for Settings { + type SolType = Self; + } + #[automatically_derived] + impl alloy_sol_types::private::SolTypeValue for Settings { + #[inline] + fn stv_to_tokens(&self) -> ::Token<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.minOperators), + as alloy_sol_types::SolType>::tokenize(&self.minNodes), + ) + } + #[inline] + fn stv_abi_encoded_size(&self) -> usize { + if let Some(size) = ::ENCODED_SIZE { + return size; + } + let tuple = as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encoded_size(&tuple) + } + #[inline] + fn stv_eip712_data_word(&self) -> alloy_sol_types::Word { + ::eip712_hash_struct(self) + } + #[inline] + fn stv_abi_encode_packed_to( + &self, + out: &mut alloy_sol_types::private::Vec, + ) { + let tuple = as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encode_packed_to(&tuple, out) + } + #[inline] + fn stv_abi_packed_encoded_size(&self) -> usize { + if let Some(size) = ::PACKED_ENCODED_SIZE { + return size; + } + let tuple = as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_packed_encoded_size(&tuple) + } + } + #[automatically_derived] + impl alloy_sol_types::SolType for Settings { + type RustType = Self; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SOL_NAME: &'static str = ::NAME; + const ENCODED_SIZE: Option = as alloy_sol_types::SolType>::ENCODED_SIZE; + const PACKED_ENCODED_SIZE: Option = as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; + #[inline] + fn valid_token(token: &Self::Token<'_>) -> bool { + as alloy_sol_types::SolType>::valid_token(token) + } + #[inline] + fn detokenize(token: Self::Token<'_>) -> Self::RustType { + let tuple = as alloy_sol_types::SolType>::detokenize(token); + >>::from(tuple) + } + } + #[automatically_derived] + impl alloy_sol_types::SolStruct for Settings { + const NAME: &'static str = "Settings"; + #[inline] + fn eip712_root_type() -> alloy_sol_types::private::Cow<'static, str> { + alloy_sol_types::private::Cow::Borrowed( + "Settings(uint8 minOperators,uint8 minNodes)", + ) + } + #[inline] + fn eip712_components() -> alloy_sol_types::private::Vec< + alloy_sol_types::private::Cow<'static, str>, + > { + alloy_sol_types::private::Vec::new() + } + #[inline] + fn eip712_encode_type() -> alloy_sol_types::private::Cow<'static, str> { + ::eip712_root_type() + } + #[inline] + fn eip712_encode_data(&self) -> alloy_sol_types::private::Vec { + [ + as alloy_sol_types::SolType>::eip712_data_word(&self.minOperators) + .0, + as alloy_sol_types::SolType>::eip712_data_word(&self.minNodes) + .0, + ] + .concat() + } + } + #[automatically_derived] + impl alloy_sol_types::EventTopic for Settings { + #[inline] + fn topic_preimage_length(rust: &Self::RustType) -> usize { + 0usize + + as alloy_sol_types::EventTopic>::topic_preimage_length( + &rust.minOperators, + ) + + as alloy_sol_types::EventTopic>::topic_preimage_length( + &rust.minNodes, + ) + } + #[inline] + fn encode_topic_preimage( + rust: &Self::RustType, + out: &mut alloy_sol_types::private::Vec, + ) { + out.reserve( + ::topic_preimage_length(rust), + ); + as alloy_sol_types::EventTopic>::encode_topic_preimage( + &rust.minOperators, + out, + ); + as alloy_sol_types::EventTopic>::encode_topic_preimage( + &rust.minNodes, + out, + ); + } + #[inline] + fn encode_topic( + rust: &Self::RustType, + ) -> alloy_sol_types::abi::token::WordToken { + let mut out = alloy_sol_types::private::Vec::new(); + ::encode_topic_preimage( + rust, + &mut out, + ); + alloy_sol_types::abi::token::WordToken( + alloy_sol_types::private::keccak256(out), + ) + } + } + }; + /**Event with signature `MaintenanceAborted(uint128)` and selector `0x8fb9cd054d0a022110cced239e908b834e4cd219511856d4eaae3051d932d604`. +```solidity +event MaintenanceAborted(uint128 version); +```*/ + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + #[derive(Clone)] + pub struct MaintenanceAborted { + #[allow(missing_docs)] + pub version: u128, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[automatically_derived] + impl alloy_sol_types::SolEvent for MaintenanceAborted { + type DataTuple<'a> = (alloy::sol_types::sol_data::Uint<128>,); + type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); + const SIGNATURE: &'static str = "MaintenanceAborted(uint128)"; + const SIGNATURE_HASH: alloy_sol_types::private::B256 = alloy_sol_types::private::B256::new([ + 143u8, + 185u8, + 205u8, + 5u8, + 77u8, + 10u8, + 2u8, + 33u8, + 16u8, + 204u8, + 237u8, + 35u8, + 158u8, + 144u8, + 139u8, + 131u8, + 78u8, + 76u8, + 210u8, + 25u8, + 81u8, + 24u8, + 86u8, + 212u8, + 234u8, + 174u8, + 48u8, + 81u8, + 217u8, + 50u8, + 214u8, + 4u8, + ]); + const ANONYMOUS: bool = false; + #[allow(unused_variables)] + #[inline] + fn new( + topics: ::RustType, + data: as alloy_sol_types::SolType>::RustType, + ) -> Self { + Self { version: data.0 } + } + #[inline] + fn check_signature( + topics: &::RustType, + ) -> alloy_sol_types::Result<()> { + if topics.0 != Self::SIGNATURE_HASH { + return Err( + alloy_sol_types::Error::invalid_event_signature_hash( + Self::SIGNATURE, + topics.0, + Self::SIGNATURE_HASH, + ), + ); + } + Ok(()) + } + #[inline] + fn tokenize_body(&self) -> Self::DataToken<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.version), + ) + } + #[inline] + fn topics(&self) -> ::RustType { + (Self::SIGNATURE_HASH.into(),) + } + #[inline] + fn encode_topics_raw( + &self, + out: &mut [alloy_sol_types::abi::token::WordToken], + ) -> alloy_sol_types::Result<()> { + if out.len() < ::COUNT { + return Err(alloy_sol_types::Error::Overrun); + } + out[0usize] = alloy_sol_types::abi::token::WordToken( + Self::SIGNATURE_HASH, + ); + Ok(()) + } + } + #[automatically_derived] + impl alloy_sol_types::private::IntoLogData for MaintenanceAborted { + fn to_log_data(&self) -> alloy_sol_types::private::LogData { + From::from(self) + } + fn into_log_data(self) -> alloy_sol_types::private::LogData { + From::from(&self) + } + } + #[automatically_derived] + impl From<&MaintenanceAborted> for alloy_sol_types::private::LogData { + #[inline] + fn from(this: &MaintenanceAborted) -> alloy_sol_types::private::LogData { + alloy_sol_types::SolEvent::encode_log_data(this) + } + } + }; + /**Event with signature `MaintenanceCompleted(address,uint128)` and selector `0xf91067eb420c28d3124865fc996e6aa9d541b9b4fef9188cb965a6cc6491638e`. +```solidity +event MaintenanceCompleted(address operator, uint128 version); +```*/ + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + #[derive(Clone)] + pub struct MaintenanceCompleted { + #[allow(missing_docs)] + pub operator: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub version: u128, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[automatically_derived] + impl alloy_sol_types::SolEvent for MaintenanceCompleted { + type DataTuple<'a> = ( + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Uint<128>, + ); + type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); + const SIGNATURE: &'static str = "MaintenanceCompleted(address,uint128)"; + const SIGNATURE_HASH: alloy_sol_types::private::B256 = alloy_sol_types::private::B256::new([ + 249u8, + 16u8, + 103u8, + 235u8, + 66u8, + 12u8, + 40u8, + 211u8, + 18u8, + 72u8, + 101u8, + 252u8, + 153u8, + 110u8, + 106u8, + 169u8, + 213u8, + 65u8, + 185u8, + 180u8, + 254u8, + 249u8, + 24u8, + 140u8, + 185u8, + 101u8, + 166u8, + 204u8, + 100u8, + 145u8, + 99u8, + 142u8, + ]); + const ANONYMOUS: bool = false; + #[allow(unused_variables)] + #[inline] + fn new( + topics: ::RustType, + data: as alloy_sol_types::SolType>::RustType, + ) -> Self { + Self { + operator: data.0, + version: data.1, + } + } + #[inline] + fn check_signature( + topics: &::RustType, + ) -> alloy_sol_types::Result<()> { + if topics.0 != Self::SIGNATURE_HASH { + return Err( + alloy_sol_types::Error::invalid_event_signature_hash( + Self::SIGNATURE, + topics.0, + Self::SIGNATURE_HASH, + ), + ); + } + Ok(()) + } + #[inline] + fn tokenize_body(&self) -> Self::DataToken<'_> { + ( + ::tokenize( + &self.operator, + ), + as alloy_sol_types::SolType>::tokenize(&self.version), + ) + } + #[inline] + fn topics(&self) -> ::RustType { + (Self::SIGNATURE_HASH.into(),) + } + #[inline] + fn encode_topics_raw( + &self, + out: &mut [alloy_sol_types::abi::token::WordToken], + ) -> alloy_sol_types::Result<()> { + if out.len() < ::COUNT { + return Err(alloy_sol_types::Error::Overrun); + } + out[0usize] = alloy_sol_types::abi::token::WordToken( + Self::SIGNATURE_HASH, + ); + Ok(()) + } + } + #[automatically_derived] + impl alloy_sol_types::private::IntoLogData for MaintenanceCompleted { + fn to_log_data(&self) -> alloy_sol_types::private::LogData { + From::from(self) + } + fn into_log_data(self) -> alloy_sol_types::private::LogData { + From::from(&self) + } + } + #[automatically_derived] + impl From<&MaintenanceCompleted> for alloy_sol_types::private::LogData { + #[inline] + fn from(this: &MaintenanceCompleted) -> alloy_sol_types::private::LogData { + alloy_sol_types::SolEvent::encode_log_data(this) + } + } + }; + /**Event with signature `MaintenanceStarted(address,uint128)` and selector `0xbc2748cf02f7a1291525e866efc76ab3b96d32d7afcbb26c53daec617b38b479`. +```solidity +event MaintenanceStarted(address operator, uint128 version); +```*/ + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + #[derive(Clone)] + pub struct MaintenanceStarted { + #[allow(missing_docs)] + pub operator: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub version: u128, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[automatically_derived] + impl alloy_sol_types::SolEvent for MaintenanceStarted { + type DataTuple<'a> = ( + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Uint<128>, + ); + type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); + const SIGNATURE: &'static str = "MaintenanceStarted(address,uint128)"; + const SIGNATURE_HASH: alloy_sol_types::private::B256 = alloy_sol_types::private::B256::new([ + 188u8, + 39u8, + 72u8, + 207u8, + 2u8, + 247u8, + 161u8, + 41u8, + 21u8, + 37u8, + 232u8, + 102u8, + 239u8, + 199u8, + 106u8, + 179u8, + 185u8, + 109u8, + 50u8, + 215u8, + 175u8, + 203u8, + 178u8, + 108u8, + 83u8, + 218u8, + 236u8, + 97u8, + 123u8, + 56u8, + 180u8, + 121u8, + ]); + const ANONYMOUS: bool = false; + #[allow(unused_variables)] + #[inline] + fn new( + topics: ::RustType, + data: as alloy_sol_types::SolType>::RustType, + ) -> Self { + Self { + operator: data.0, + version: data.1, + } + } + #[inline] + fn check_signature( + topics: &::RustType, + ) -> alloy_sol_types::Result<()> { + if topics.0 != Self::SIGNATURE_HASH { + return Err( + alloy_sol_types::Error::invalid_event_signature_hash( + Self::SIGNATURE, + topics.0, + Self::SIGNATURE_HASH, + ), + ); + } + Ok(()) + } + #[inline] + fn tokenize_body(&self) -> Self::DataToken<'_> { + ( + ::tokenize( + &self.operator, + ), + as alloy_sol_types::SolType>::tokenize(&self.version), + ) + } + #[inline] + fn topics(&self) -> ::RustType { + (Self::SIGNATURE_HASH.into(),) + } + #[inline] + fn encode_topics_raw( + &self, + out: &mut [alloy_sol_types::abi::token::WordToken], + ) -> alloy_sol_types::Result<()> { + if out.len() < ::COUNT { + return Err(alloy_sol_types::Error::Overrun); + } + out[0usize] = alloy_sol_types::abi::token::WordToken( + Self::SIGNATURE_HASH, + ); + Ok(()) + } + } + #[automatically_derived] + impl alloy_sol_types::private::IntoLogData for MaintenanceStarted { + fn to_log_data(&self) -> alloy_sol_types::private::LogData { + From::from(self) + } + fn into_log_data(self) -> alloy_sol_types::private::LogData { + From::from(&self) + } + } + #[automatically_derived] + impl From<&MaintenanceStarted> for alloy_sol_types::private::LogData { + #[inline] + fn from(this: &MaintenanceStarted) -> alloy_sol_types::private::LogData { + alloy_sol_types::SolEvent::encode_log_data(this) + } + } + }; + /**Event with signature `MigrationAborted(uint128)` and selector `0x9ce192aea5faf2151bbc246cd8918d2eba702fa26951f67f2bf7b3817e689d98`. +```solidity +event MigrationAborted(uint128 version); +```*/ + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + #[derive(Clone)] + pub struct MigrationAborted { + #[allow(missing_docs)] + pub version: u128, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[automatically_derived] + impl alloy_sol_types::SolEvent for MigrationAborted { + type DataTuple<'a> = (alloy::sol_types::sol_data::Uint<128>,); + type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); + const SIGNATURE: &'static str = "MigrationAborted(uint128)"; + const SIGNATURE_HASH: alloy_sol_types::private::B256 = alloy_sol_types::private::B256::new([ + 156u8, + 225u8, + 146u8, + 174u8, + 165u8, + 250u8, + 242u8, + 21u8, + 27u8, + 188u8, + 36u8, + 108u8, + 216u8, + 145u8, + 141u8, + 46u8, + 186u8, + 112u8, + 47u8, + 162u8, + 105u8, + 81u8, + 246u8, + 127u8, + 43u8, + 247u8, + 179u8, + 129u8, + 126u8, + 104u8, + 157u8, + 152u8, + ]); + const ANONYMOUS: bool = false; + #[allow(unused_variables)] + #[inline] + fn new( + topics: ::RustType, + data: as alloy_sol_types::SolType>::RustType, + ) -> Self { + Self { version: data.0 } + } + #[inline] + fn check_signature( + topics: &::RustType, + ) -> alloy_sol_types::Result<()> { + if topics.0 != Self::SIGNATURE_HASH { + return Err( + alloy_sol_types::Error::invalid_event_signature_hash( + Self::SIGNATURE, + topics.0, + Self::SIGNATURE_HASH, + ), + ); + } + Ok(()) + } + #[inline] + fn tokenize_body(&self) -> Self::DataToken<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.version), + ) + } + #[inline] + fn topics(&self) -> ::RustType { + (Self::SIGNATURE_HASH.into(),) + } + #[inline] + fn encode_topics_raw( + &self, + out: &mut [alloy_sol_types::abi::token::WordToken], + ) -> alloy_sol_types::Result<()> { + if out.len() < ::COUNT { + return Err(alloy_sol_types::Error::Overrun); + } + out[0usize] = alloy_sol_types::abi::token::WordToken( + Self::SIGNATURE_HASH, + ); + Ok(()) + } + } + #[automatically_derived] + impl alloy_sol_types::private::IntoLogData for MigrationAborted { + fn to_log_data(&self) -> alloy_sol_types::private::LogData { + From::from(self) + } + fn into_log_data(self) -> alloy_sol_types::private::LogData { + From::from(&self) + } + } + #[automatically_derived] + impl From<&MigrationAborted> for alloy_sol_types::private::LogData { + #[inline] + fn from(this: &MigrationAborted) -> alloy_sol_types::private::LogData { + alloy_sol_types::SolEvent::encode_log_data(this) + } + } + }; + /**Event with signature `MigrationCompleted(uint128)` and selector `0x11ce50160e66100537fd4b0ae26de66d51dab713ad92313353a18c24e8f6daab`. +```solidity +event MigrationCompleted(uint128 version); +```*/ + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + #[derive(Clone)] + pub struct MigrationCompleted { + #[allow(missing_docs)] + pub version: u128, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[automatically_derived] + impl alloy_sol_types::SolEvent for MigrationCompleted { + type DataTuple<'a> = (alloy::sol_types::sol_data::Uint<128>,); + type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); + const SIGNATURE: &'static str = "MigrationCompleted(uint128)"; + const SIGNATURE_HASH: alloy_sol_types::private::B256 = alloy_sol_types::private::B256::new([ + 17u8, + 206u8, + 80u8, + 22u8, + 14u8, + 102u8, + 16u8, + 5u8, + 55u8, + 253u8, + 75u8, + 10u8, + 226u8, + 109u8, + 230u8, + 109u8, + 81u8, + 218u8, + 183u8, + 19u8, + 173u8, + 146u8, + 49u8, + 51u8, + 83u8, + 161u8, + 140u8, + 36u8, + 232u8, + 246u8, + 218u8, + 171u8, + ]); + const ANONYMOUS: bool = false; + #[allow(unused_variables)] + #[inline] + fn new( + topics: ::RustType, + data: as alloy_sol_types::SolType>::RustType, + ) -> Self { + Self { version: data.0 } + } + #[inline] + fn check_signature( + topics: &::RustType, + ) -> alloy_sol_types::Result<()> { + if topics.0 != Self::SIGNATURE_HASH { + return Err( + alloy_sol_types::Error::invalid_event_signature_hash( + Self::SIGNATURE, + topics.0, + Self::SIGNATURE_HASH, + ), + ); + } + Ok(()) + } + #[inline] + fn tokenize_body(&self) -> Self::DataToken<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.version), + ) + } + #[inline] + fn topics(&self) -> ::RustType { + (Self::SIGNATURE_HASH.into(),) + } + #[inline] + fn encode_topics_raw( + &self, + out: &mut [alloy_sol_types::abi::token::WordToken], + ) -> alloy_sol_types::Result<()> { + if out.len() < ::COUNT { + return Err(alloy_sol_types::Error::Overrun); + } + out[0usize] = alloy_sol_types::abi::token::WordToken( + Self::SIGNATURE_HASH, + ); + Ok(()) + } + } + #[automatically_derived] + impl alloy_sol_types::private::IntoLogData for MigrationCompleted { + fn to_log_data(&self) -> alloy_sol_types::private::LogData { + From::from(self) + } + fn into_log_data(self) -> alloy_sol_types::private::LogData { + From::from(&self) + } + } + #[automatically_derived] + impl From<&MigrationCompleted> for alloy_sol_types::private::LogData { + #[inline] + fn from(this: &MigrationCompleted) -> alloy_sol_types::private::LogData { + alloy_sol_types::SolEvent::encode_log_data(this) + } + } + }; + /**Event with signature `MigrationDataPullCompleted(address,uint128)` and selector `0xa76a8fc1a90266ddee8937a18e12f01eade946b3b66197fff289af9277c2bd25`. +```solidity +event MigrationDataPullCompleted(address operator, uint128 version); +```*/ + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + #[derive(Clone)] + pub struct MigrationDataPullCompleted { + #[allow(missing_docs)] + pub operator: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub version: u128, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[automatically_derived] + impl alloy_sol_types::SolEvent for MigrationDataPullCompleted { + type DataTuple<'a> = ( + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Uint<128>, + ); + type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); + const SIGNATURE: &'static str = "MigrationDataPullCompleted(address,uint128)"; + const SIGNATURE_HASH: alloy_sol_types::private::B256 = alloy_sol_types::private::B256::new([ + 167u8, + 106u8, + 143u8, + 193u8, + 169u8, + 2u8, + 102u8, + 221u8, + 238u8, + 137u8, + 55u8, + 161u8, + 142u8, + 18u8, + 240u8, + 30u8, + 173u8, + 233u8, + 70u8, + 179u8, + 182u8, + 97u8, + 151u8, + 255u8, + 242u8, + 137u8, + 175u8, + 146u8, + 119u8, + 194u8, + 189u8, + 37u8, + ]); + const ANONYMOUS: bool = false; + #[allow(unused_variables)] + #[inline] + fn new( + topics: ::RustType, + data: as alloy_sol_types::SolType>::RustType, + ) -> Self { + Self { + operator: data.0, + version: data.1, + } + } + #[inline] + fn check_signature( + topics: &::RustType, + ) -> alloy_sol_types::Result<()> { + if topics.0 != Self::SIGNATURE_HASH { + return Err( + alloy_sol_types::Error::invalid_event_signature_hash( + Self::SIGNATURE, + topics.0, + Self::SIGNATURE_HASH, + ), + ); + } + Ok(()) + } + #[inline] + fn tokenize_body(&self) -> Self::DataToken<'_> { + ( + ::tokenize( + &self.operator, + ), + as alloy_sol_types::SolType>::tokenize(&self.version), + ) + } + #[inline] + fn topics(&self) -> ::RustType { + (Self::SIGNATURE_HASH.into(),) + } + #[inline] + fn encode_topics_raw( + &self, + out: &mut [alloy_sol_types::abi::token::WordToken], + ) -> alloy_sol_types::Result<()> { + if out.len() < ::COUNT { + return Err(alloy_sol_types::Error::Overrun); + } + out[0usize] = alloy_sol_types::abi::token::WordToken( + Self::SIGNATURE_HASH, + ); + Ok(()) + } + } + #[automatically_derived] + impl alloy_sol_types::private::IntoLogData for MigrationDataPullCompleted { + fn to_log_data(&self) -> alloy_sol_types::private::LogData { + From::from(self) + } + fn into_log_data(self) -> alloy_sol_types::private::LogData { + From::from(&self) + } + } + #[automatically_derived] + impl From<&MigrationDataPullCompleted> for alloy_sol_types::private::LogData { + #[inline] + fn from( + this: &MigrationDataPullCompleted, + ) -> alloy_sol_types::private::LogData { + alloy_sol_types::SolEvent::encode_log_data(this) + } + } + }; + /**Event with signature `MigrationStarted(address[],(address,(uint256,bytes)[],bytes)[],uint128)` and selector `0x7e05e40117b6e18ab284c04a3508c3826422dc84a65e9c236a8248774416f8ac`. +```solidity +event MigrationStarted(address[] operatorsToRemove, NodeOperatorView[] operatorsToAdd, uint128 version); +```*/ + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + #[derive(Clone)] + pub struct MigrationStarted { + #[allow(missing_docs)] + pub operatorsToRemove: alloy::sol_types::private::Vec< + alloy::sol_types::private::Address, + >, + #[allow(missing_docs)] + pub operatorsToAdd: alloy::sol_types::private::Vec< + ::RustType, + >, + #[allow(missing_docs)] + pub version: u128, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[automatically_derived] + impl alloy_sol_types::SolEvent for MigrationStarted { + type DataTuple<'a> = ( + alloy::sol_types::sol_data::Array, + alloy::sol_types::sol_data::Array, + alloy::sol_types::sol_data::Uint<128>, + ); + type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); + const SIGNATURE: &'static str = "MigrationStarted(address[],(address,(uint256,bytes)[],bytes)[],uint128)"; + const SIGNATURE_HASH: alloy_sol_types::private::B256 = alloy_sol_types::private::B256::new([ + 126u8, + 5u8, + 228u8, + 1u8, + 23u8, + 182u8, + 225u8, + 138u8, + 178u8, + 132u8, + 192u8, + 74u8, + 53u8, + 8u8, + 195u8, + 130u8, + 100u8, + 34u8, + 220u8, + 132u8, + 166u8, + 94u8, + 156u8, + 35u8, + 106u8, + 130u8, + 72u8, + 119u8, + 68u8, + 22u8, + 248u8, + 172u8, + ]); + const ANONYMOUS: bool = false; + #[allow(unused_variables)] + #[inline] + fn new( + topics: ::RustType, + data: as alloy_sol_types::SolType>::RustType, + ) -> Self { + Self { + operatorsToRemove: data.0, + operatorsToAdd: data.1, + version: data.2, + } + } + #[inline] + fn check_signature( + topics: &::RustType, + ) -> alloy_sol_types::Result<()> { + if topics.0 != Self::SIGNATURE_HASH { + return Err( + alloy_sol_types::Error::invalid_event_signature_hash( + Self::SIGNATURE, + topics.0, + Self::SIGNATURE_HASH, + ), + ); + } + Ok(()) + } + #[inline] + fn tokenize_body(&self) -> Self::DataToken<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.operatorsToRemove), + as alloy_sol_types::SolType>::tokenize(&self.operatorsToAdd), + as alloy_sol_types::SolType>::tokenize(&self.version), + ) + } + #[inline] + fn topics(&self) -> ::RustType { + (Self::SIGNATURE_HASH.into(),) + } + #[inline] + fn encode_topics_raw( + &self, + out: &mut [alloy_sol_types::abi::token::WordToken], + ) -> alloy_sol_types::Result<()> { + if out.len() < ::COUNT { + return Err(alloy_sol_types::Error::Overrun); + } + out[0usize] = alloy_sol_types::abi::token::WordToken( + Self::SIGNATURE_HASH, + ); + Ok(()) + } + } + #[automatically_derived] + impl alloy_sol_types::private::IntoLogData for MigrationStarted { + fn to_log_data(&self) -> alloy_sol_types::private::LogData { + From::from(self) + } + fn into_log_data(self) -> alloy_sol_types::private::LogData { + From::from(&self) + } + } + #[automatically_derived] + impl From<&MigrationStarted> for alloy_sol_types::private::LogData { + #[inline] + fn from(this: &MigrationStarted) -> alloy_sol_types::private::LogData { + alloy_sol_types::SolEvent::encode_log_data(this) + } + } + }; + /**Event with signature `NodeRemoved(address,uint256,uint128)` and selector `0xbd184de79f134b0f3da466d278f5417cbcb1450d72f1bd1a1b84f18b1bcd03ca`. +```solidity +event NodeRemoved(address operator, uint256 id, uint128 version); +```*/ + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + #[derive(Clone)] + pub struct NodeRemoved { + #[allow(missing_docs)] + pub operator: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub id: alloy::sol_types::private::primitives::aliases::U256, + #[allow(missing_docs)] + pub version: u128, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[automatically_derived] + impl alloy_sol_types::SolEvent for NodeRemoved { + type DataTuple<'a> = ( + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Uint<256>, + alloy::sol_types::sol_data::Uint<128>, + ); + type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); + const SIGNATURE: &'static str = "NodeRemoved(address,uint256,uint128)"; + const SIGNATURE_HASH: alloy_sol_types::private::B256 = alloy_sol_types::private::B256::new([ + 189u8, + 24u8, + 77u8, + 231u8, + 159u8, + 19u8, + 75u8, + 15u8, + 61u8, + 164u8, + 102u8, + 210u8, + 120u8, + 245u8, + 65u8, + 124u8, + 188u8, + 177u8, + 69u8, + 13u8, + 114u8, + 241u8, + 189u8, + 26u8, + 27u8, + 132u8, + 241u8, + 139u8, + 27u8, + 205u8, + 3u8, + 202u8, + ]); + const ANONYMOUS: bool = false; + #[allow(unused_variables)] + #[inline] + fn new( + topics: ::RustType, + data: as alloy_sol_types::SolType>::RustType, + ) -> Self { + Self { + operator: data.0, + id: data.1, + version: data.2, + } + } + #[inline] + fn check_signature( + topics: &::RustType, + ) -> alloy_sol_types::Result<()> { + if topics.0 != Self::SIGNATURE_HASH { + return Err( + alloy_sol_types::Error::invalid_event_signature_hash( + Self::SIGNATURE, + topics.0, + Self::SIGNATURE_HASH, + ), + ); + } + Ok(()) + } + #[inline] + fn tokenize_body(&self) -> Self::DataToken<'_> { + ( + ::tokenize( + &self.operator, + ), + as alloy_sol_types::SolType>::tokenize(&self.id), + as alloy_sol_types::SolType>::tokenize(&self.version), + ) + } + #[inline] + fn topics(&self) -> ::RustType { + (Self::SIGNATURE_HASH.into(),) + } + #[inline] + fn encode_topics_raw( + &self, + out: &mut [alloy_sol_types::abi::token::WordToken], + ) -> alloy_sol_types::Result<()> { + if out.len() < ::COUNT { + return Err(alloy_sol_types::Error::Overrun); + } + out[0usize] = alloy_sol_types::abi::token::WordToken( + Self::SIGNATURE_HASH, + ); + Ok(()) + } + } + #[automatically_derived] + impl alloy_sol_types::private::IntoLogData for NodeRemoved { + fn to_log_data(&self) -> alloy_sol_types::private::LogData { + From::from(self) + } + fn into_log_data(self) -> alloy_sol_types::private::LogData { + From::from(&self) + } + } + #[automatically_derived] + impl From<&NodeRemoved> for alloy_sol_types::private::LogData { + #[inline] + fn from(this: &NodeRemoved) -> alloy_sol_types::private::LogData { + alloy_sol_types::SolEvent::encode_log_data(this) + } + } + }; + /**Event with signature `NodeSet(address,(uint256,bytes),uint128)` and selector `0x6adfb896d3407681d05fb874d4dfb7068e6e2a36f09acd38a3b7d04c01745fee`. +```solidity +event NodeSet(address operator, Node node, uint128 version); +```*/ + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + #[derive(Clone)] + pub struct NodeSet { + #[allow(missing_docs)] + pub operator: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub node: ::RustType, + #[allow(missing_docs)] + pub version: u128, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[automatically_derived] + impl alloy_sol_types::SolEvent for NodeSet { + type DataTuple<'a> = ( + alloy::sol_types::sol_data::Address, + Node, + alloy::sol_types::sol_data::Uint<128>, + ); + type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); + const SIGNATURE: &'static str = "NodeSet(address,(uint256,bytes),uint128)"; + const SIGNATURE_HASH: alloy_sol_types::private::B256 = alloy_sol_types::private::B256::new([ + 106u8, + 223u8, + 184u8, + 150u8, + 211u8, + 64u8, + 118u8, + 129u8, + 208u8, + 95u8, + 184u8, + 116u8, + 212u8, + 223u8, + 183u8, + 6u8, + 142u8, + 110u8, + 42u8, + 54u8, + 240u8, + 154u8, + 205u8, + 56u8, + 163u8, + 183u8, + 208u8, + 76u8, + 1u8, + 116u8, + 95u8, + 238u8, + ]); + const ANONYMOUS: bool = false; + #[allow(unused_variables)] + #[inline] + fn new( + topics: ::RustType, + data: as alloy_sol_types::SolType>::RustType, + ) -> Self { + Self { + operator: data.0, + node: data.1, + version: data.2, + } + } + #[inline] + fn check_signature( + topics: &::RustType, + ) -> alloy_sol_types::Result<()> { + if topics.0 != Self::SIGNATURE_HASH { + return Err( + alloy_sol_types::Error::invalid_event_signature_hash( + Self::SIGNATURE, + topics.0, + Self::SIGNATURE_HASH, + ), + ); + } + Ok(()) + } + #[inline] + fn tokenize_body(&self) -> Self::DataToken<'_> { + ( + ::tokenize( + &self.operator, + ), + ::tokenize(&self.node), + as alloy_sol_types::SolType>::tokenize(&self.version), + ) + } + #[inline] + fn topics(&self) -> ::RustType { + (Self::SIGNATURE_HASH.into(),) + } + #[inline] + fn encode_topics_raw( + &self, + out: &mut [alloy_sol_types::abi::token::WordToken], + ) -> alloy_sol_types::Result<()> { + if out.len() < ::COUNT { + return Err(alloy_sol_types::Error::Overrun); + } + out[0usize] = alloy_sol_types::abi::token::WordToken( + Self::SIGNATURE_HASH, + ); + Ok(()) + } + } + #[automatically_derived] + impl alloy_sol_types::private::IntoLogData for NodeSet { + fn to_log_data(&self) -> alloy_sol_types::private::LogData { + From::from(self) + } + fn into_log_data(self) -> alloy_sol_types::private::LogData { + From::from(&self) + } + } + #[automatically_derived] + impl From<&NodeSet> for alloy_sol_types::private::LogData { + #[inline] + fn from(this: &NodeSet) -> alloy_sol_types::private::LogData { + alloy_sol_types::SolEvent::encode_log_data(this) + } + } + }; + /**Constructor`. +```solidity +constructor(Settings initialSettings, NodeOperatorView[] initialOperators); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct constructorCall { + #[allow(missing_docs)] + pub initialSettings: ::RustType, + #[allow(missing_docs)] + pub initialOperators: alloy::sol_types::private::Vec< + ::RustType, + >, + } + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + Settings, + alloy::sol_types::sol_data::Array, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + ::RustType, + alloy::sol_types::private::Vec< + ::RustType, + >, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: constructorCall) -> Self { + (value.initialSettings, value.initialOperators) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for constructorCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + initialSettings: tuple.0, + initialOperators: tuple.1, + } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolConstructor for constructorCall { + type Parameters<'a> = ( + Settings, + alloy::sol_types::sol_data::Array, + ); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + ::tokenize( + &self.initialSettings, + ), + as alloy_sol_types::SolType>::tokenize(&self.initialOperators), + ) + } + } + }; + /**Function with signature `abortMaintenance()` and selector `0x3048bfba`. +```solidity +function abortMaintenance() external; +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct abortMaintenanceCall {} + ///Container type for the return parameters of the [`abortMaintenance()`](abortMaintenanceCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct abortMaintenanceReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: abortMaintenanceCall) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for abortMaintenanceCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: abortMaintenanceReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for abortMaintenanceReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for abortMaintenanceCall { + type Parameters<'a> = (); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = abortMaintenanceReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "abortMaintenance()"; + const SELECTOR: [u8; 4] = [48u8, 72u8, 191u8, 186u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn abi_decode_returns( + data: &[u8], + validate: bool, + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data, validate) + .map(Into::into) + } + } + }; + /**Function with signature `abortMigration()` and selector `0xc130809a`. +```solidity +function abortMigration() external; +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct abortMigrationCall {} + ///Container type for the return parameters of the [`abortMigration()`](abortMigrationCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct abortMigrationReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: abortMigrationCall) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for abortMigrationCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: abortMigrationReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for abortMigrationReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for abortMigrationCall { + type Parameters<'a> = (); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = abortMigrationReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "abortMigration()"; + const SELECTOR: [u8; 4] = [193u8, 48u8, 128u8, 154u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn abi_decode_returns( + data: &[u8], + validate: bool, + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data, validate) + .map(Into::into) + } + } + }; + /**Function with signature `completeMaintenance()` and selector `0xad36e6d0`. +```solidity +function completeMaintenance() external; +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct completeMaintenanceCall {} + ///Container type for the return parameters of the [`completeMaintenance()`](completeMaintenanceCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct completeMaintenanceReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: completeMaintenanceCall) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for completeMaintenanceCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: completeMaintenanceReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for completeMaintenanceReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for completeMaintenanceCall { + type Parameters<'a> = (); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = completeMaintenanceReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "completeMaintenance()"; + const SELECTOR: [u8; 4] = [173u8, 54u8, 230u8, 208u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn abi_decode_returns( + data: &[u8], + validate: bool, + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data, validate) + .map(Into::into) + } + } + }; + /**Function with signature `completeMigration()` and selector `0x4886f62c`. +```solidity +function completeMigration() external; +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct completeMigrationCall {} + ///Container type for the return parameters of the [`completeMigration()`](completeMigrationCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct completeMigrationReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: completeMigrationCall) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for completeMigrationCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: completeMigrationReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for completeMigrationReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for completeMigrationCall { + type Parameters<'a> = (); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = completeMigrationReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "completeMigration()"; + const SELECTOR: [u8; 4] = [72u8, 134u8, 246u8, 44u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn abi_decode_returns( + data: &[u8], + validate: bool, + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data, validate) + .map(Into::into) + } + } + }; + /**Function with signature `getView()` and selector `0x75418b9d`. +```solidity +function getView() external view returns (ClusterView memory); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct getViewCall {} + ///Container type for the return parameters of the [`getView()`](getViewCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct getViewReturn { + #[allow(missing_docs)] + pub _0: ::RustType, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: getViewCall) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for getViewCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (ClusterView,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + ::RustType, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: getViewReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for getViewReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for getViewCall { + type Parameters<'a> = (); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = getViewReturn; + type ReturnTuple<'a> = (ClusterView,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "getView()"; + const SELECTOR: [u8; 4] = [117u8, 65u8, 139u8, 157u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn abi_decode_returns( + data: &[u8], + validate: bool, + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data, validate) + .map(Into::into) + } + } + }; + /**Function with signature `removeNode(uint256)` and selector `0xffd740df`. +```solidity +function removeNode(uint256 id) external; +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct removeNodeCall { + #[allow(missing_docs)] + pub id: alloy::sol_types::private::primitives::aliases::U256, + } + ///Container type for the return parameters of the [`removeNode(uint256)`](removeNodeCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct removeNodeReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Uint<256>,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::primitives::aliases::U256, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: removeNodeCall) -> Self { + (value.id,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for removeNodeCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { id: tuple.0 } + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: removeNodeReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for removeNodeReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for removeNodeCall { + type Parameters<'a> = (alloy::sol_types::sol_data::Uint<256>,); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = removeNodeReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "removeNode(uint256)"; + const SELECTOR: [u8; 4] = [255u8, 215u8, 64u8, 223u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.id), + ) + } + #[inline] + fn abi_decode_returns( + data: &[u8], + validate: bool, + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data, validate) + .map(Into::into) + } + } + }; + /**Function with signature `setNode((uint256,bytes))` and selector `0x6c0b61b9`. +```solidity +function setNode(Node memory node) external; +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct setNodeCall { + #[allow(missing_docs)] + pub node: ::RustType, + } + ///Container type for the return parameters of the [`setNode((uint256,bytes))`](setNodeCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct setNodeReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (Node,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + ::RustType, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: setNodeCall) -> Self { + (value.node,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for setNodeCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { node: tuple.0 } + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: setNodeReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for setNodeReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for setNodeCall { + type Parameters<'a> = (Node,); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = setNodeReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "setNode((uint256,bytes))"; + const SELECTOR: [u8; 4] = [108u8, 11u8, 97u8, 185u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + (::tokenize(&self.node),) + } + #[inline] + fn abi_decode_returns( + data: &[u8], + validate: bool, + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data, validate) + .map(Into::into) + } + } + }; + /**Function with signature `startMaintenance()` and selector `0xf5f2d9f1`. +```solidity +function startMaintenance() external; +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct startMaintenanceCall {} + ///Container type for the return parameters of the [`startMaintenance()`](startMaintenanceCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct startMaintenanceReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: startMaintenanceCall) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for startMaintenanceCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: startMaintenanceReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for startMaintenanceReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for startMaintenanceCall { + type Parameters<'a> = (); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = startMaintenanceReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "startMaintenance()"; + const SELECTOR: [u8; 4] = [245u8, 242u8, 217u8, 241u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn abi_decode_returns( + data: &[u8], + validate: bool, + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data, validate) + .map(Into::into) + } + } + }; + /**Function with signature `startMigration(address[],(address,(uint256,bytes)[],bytes)[])` and selector `0xcc45662a`. +```solidity +function startMigration(address[] memory operatorsToRemove, NodeOperatorView[] memory operatorsToAdd) external; +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct startMigrationCall { + #[allow(missing_docs)] + pub operatorsToRemove: alloy::sol_types::private::Vec< + alloy::sol_types::private::Address, + >, + #[allow(missing_docs)] + pub operatorsToAdd: alloy::sol_types::private::Vec< + ::RustType, + >, + } + ///Container type for the return parameters of the [`startMigration(address[],(address,(uint256,bytes)[],bytes)[])`](startMigrationCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct startMigrationReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::Array, + alloy::sol_types::sol_data::Array, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::Vec, + alloy::sol_types::private::Vec< + ::RustType, + >, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: startMigrationCall) -> Self { + (value.operatorsToRemove, value.operatorsToAdd) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for startMigrationCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + operatorsToRemove: tuple.0, + operatorsToAdd: tuple.1, + } + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: startMigrationReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for startMigrationReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for startMigrationCall { + type Parameters<'a> = ( + alloy::sol_types::sol_data::Array, + alloy::sol_types::sol_data::Array, + ); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = startMigrationReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "startMigration(address[],(address,(uint256,bytes)[],bytes)[])"; + const SELECTOR: [u8; 4] = [204u8, 69u8, 102u8, 42u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.operatorsToRemove), + as alloy_sol_types::SolType>::tokenize(&self.operatorsToAdd), + ) + } + #[inline] + fn abi_decode_returns( + data: &[u8], + validate: bool, + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data, validate) + .map(Into::into) + } + } + }; + /**Function with signature `transferOwnership(address)` and selector `0xf2fde38b`. +```solidity +function transferOwnership(address newOwner) external; +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct transferOwnershipCall { + #[allow(missing_docs)] + pub newOwner: alloy::sol_types::private::Address, + } + ///Container type for the return parameters of the [`transferOwnership(address)`](transferOwnershipCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct transferOwnershipReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Address,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::Address,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: transferOwnershipCall) -> Self { + (value.newOwner,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for transferOwnershipCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { newOwner: tuple.0 } + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: transferOwnershipReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for transferOwnershipReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for transferOwnershipCall { + type Parameters<'a> = (alloy::sol_types::sol_data::Address,); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = transferOwnershipReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "transferOwnership(address)"; + const SELECTOR: [u8; 4] = [242u8, 253u8, 227u8, 139u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + ::tokenize( + &self.newOwner, + ), + ) + } + #[inline] + fn abi_decode_returns( + data: &[u8], + validate: bool, + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data, validate) + .map(Into::into) + } + } + }; + /**Function with signature `updateSettings((uint8,uint8))` and selector `0x409900e8`. +```solidity +function updateSettings(Settings memory newSettings) external; +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct updateSettingsCall { + #[allow(missing_docs)] + pub newSettings: ::RustType, + } + ///Container type for the return parameters of the [`updateSettings((uint8,uint8))`](updateSettingsCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct updateSettingsReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (Settings,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + ::RustType, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: updateSettingsCall) -> Self { + (value.newSettings,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for updateSettingsCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { newSettings: tuple.0 } + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: updateSettingsReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for updateSettingsReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for updateSettingsCall { + type Parameters<'a> = (Settings,); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = updateSettingsReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "updateSettings((uint8,uint8))"; + const SELECTOR: [u8; 4] = [64u8, 153u8, 0u8, 232u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + (::tokenize(&self.newSettings),) + } + #[inline] + fn abi_decode_returns( + data: &[u8], + validate: bool, + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data, validate) + .map(Into::into) + } + } + }; + ///Container for all the [`Cluster`](self) function calls. + pub enum ClusterCalls { + #[allow(missing_docs)] + abortMaintenance(abortMaintenanceCall), + #[allow(missing_docs)] + abortMigration(abortMigrationCall), + #[allow(missing_docs)] + completeMaintenance(completeMaintenanceCall), + #[allow(missing_docs)] + completeMigration(completeMigrationCall), + #[allow(missing_docs)] + getView(getViewCall), + #[allow(missing_docs)] + removeNode(removeNodeCall), + #[allow(missing_docs)] + setNode(setNodeCall), + #[allow(missing_docs)] + startMaintenance(startMaintenanceCall), + #[allow(missing_docs)] + startMigration(startMigrationCall), + #[allow(missing_docs)] + transferOwnership(transferOwnershipCall), + #[allow(missing_docs)] + updateSettings(updateSettingsCall), + } + #[automatically_derived] + impl ClusterCalls { + /// All the selectors of this enum. + /// + /// Note that the selectors might not be in the same order as the variants. + /// No guarantees are made about the order of the selectors. + /// + /// Prefer using `SolInterface` methods instead. + pub const SELECTORS: &'static [[u8; 4usize]] = &[ + [48u8, 72u8, 191u8, 186u8], + [64u8, 153u8, 0u8, 232u8], + [72u8, 134u8, 246u8, 44u8], + [108u8, 11u8, 97u8, 185u8], + [117u8, 65u8, 139u8, 157u8], + [173u8, 54u8, 230u8, 208u8], + [193u8, 48u8, 128u8, 154u8], + [204u8, 69u8, 102u8, 42u8], + [242u8, 253u8, 227u8, 139u8], + [245u8, 242u8, 217u8, 241u8], + [255u8, 215u8, 64u8, 223u8], + ]; + } + #[automatically_derived] + impl alloy_sol_types::SolInterface for ClusterCalls { + const NAME: &'static str = "ClusterCalls"; + const MIN_DATA_LENGTH: usize = 0usize; + const COUNT: usize = 11usize; + #[inline] + fn selector(&self) -> [u8; 4] { + match self { + Self::abortMaintenance(_) => { + ::SELECTOR + } + Self::abortMigration(_) => { + ::SELECTOR + } + Self::completeMaintenance(_) => { + ::SELECTOR + } + Self::completeMigration(_) => { + ::SELECTOR + } + Self::getView(_) => ::SELECTOR, + Self::removeNode(_) => { + ::SELECTOR + } + Self::setNode(_) => ::SELECTOR, + Self::startMaintenance(_) => { + ::SELECTOR + } + Self::startMigration(_) => { + ::SELECTOR + } + Self::transferOwnership(_) => { + ::SELECTOR + } + Self::updateSettings(_) => { + ::SELECTOR + } + } + } + #[inline] + fn selector_at(i: usize) -> ::core::option::Option<[u8; 4]> { + Self::SELECTORS.get(i).copied() + } + #[inline] + fn valid_selector(selector: [u8; 4]) -> bool { + Self::SELECTORS.binary_search(&selector).is_ok() + } + #[inline] + #[allow(non_snake_case)] + fn abi_decode_raw( + selector: [u8; 4], + data: &[u8], + validate: bool, + ) -> alloy_sol_types::Result { + static DECODE_SHIMS: &[fn( + &[u8], + bool, + ) -> alloy_sol_types::Result] = &[ + { + fn abortMaintenance( + data: &[u8], + validate: bool, + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + validate, + ) + .map(ClusterCalls::abortMaintenance) + } + abortMaintenance + }, + { + fn updateSettings( + data: &[u8], + validate: bool, + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + validate, + ) + .map(ClusterCalls::updateSettings) + } + updateSettings + }, + { + fn completeMigration( + data: &[u8], + validate: bool, + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + validate, + ) + .map(ClusterCalls::completeMigration) + } + completeMigration + }, + { + fn setNode( + data: &[u8], + validate: bool, + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + validate, + ) + .map(ClusterCalls::setNode) + } + setNode + }, + { + fn getView( + data: &[u8], + validate: bool, + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + validate, + ) + .map(ClusterCalls::getView) + } + getView + }, + { + fn completeMaintenance( + data: &[u8], + validate: bool, + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + validate, + ) + .map(ClusterCalls::completeMaintenance) + } + completeMaintenance + }, + { + fn abortMigration( + data: &[u8], + validate: bool, + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + validate, + ) + .map(ClusterCalls::abortMigration) + } + abortMigration + }, + { + fn startMigration( + data: &[u8], + validate: bool, + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + validate, + ) + .map(ClusterCalls::startMigration) + } + startMigration + }, + { + fn transferOwnership( + data: &[u8], + validate: bool, + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + validate, + ) + .map(ClusterCalls::transferOwnership) + } + transferOwnership + }, + { + fn startMaintenance( + data: &[u8], + validate: bool, + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + validate, + ) + .map(ClusterCalls::startMaintenance) + } + startMaintenance + }, + { + fn removeNode( + data: &[u8], + validate: bool, + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + validate, + ) + .map(ClusterCalls::removeNode) + } + removeNode + }, + ]; + let Ok(idx) = Self::SELECTORS.binary_search(&selector) else { + return Err( + alloy_sol_types::Error::unknown_selector( + ::NAME, + selector, + ), + ); + }; + DECODE_SHIMS[idx](data, validate) + } + #[inline] + fn abi_encoded_size(&self) -> usize { + match self { + Self::abortMaintenance(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::abortMigration(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::completeMaintenance(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::completeMigration(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::getView(inner) => { + ::abi_encoded_size(inner) + } + Self::removeNode(inner) => { + ::abi_encoded_size(inner) + } + Self::setNode(inner) => { + ::abi_encoded_size(inner) + } + Self::startMaintenance(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::startMigration(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::transferOwnership(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::updateSettings(inner) => { + ::abi_encoded_size( + inner, + ) + } + } + } + #[inline] + fn abi_encode_raw(&self, out: &mut alloy_sol_types::private::Vec) { + match self { + Self::abortMaintenance(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::abortMigration(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::completeMaintenance(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::completeMigration(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::getView(inner) => { + ::abi_encode_raw(inner, out) + } + Self::removeNode(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::setNode(inner) => { + ::abi_encode_raw(inner, out) + } + Self::startMaintenance(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::startMigration(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::transferOwnership(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::updateSettings(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + } + } + } + ///Container for all the [`Cluster`](self) events. + pub enum ClusterEvents { + #[allow(missing_docs)] + MaintenanceAborted(MaintenanceAborted), + #[allow(missing_docs)] + MaintenanceCompleted(MaintenanceCompleted), + #[allow(missing_docs)] + MaintenanceStarted(MaintenanceStarted), + #[allow(missing_docs)] + MigrationAborted(MigrationAborted), + #[allow(missing_docs)] + MigrationCompleted(MigrationCompleted), + #[allow(missing_docs)] + MigrationDataPullCompleted(MigrationDataPullCompleted), + #[allow(missing_docs)] + MigrationStarted(MigrationStarted), + #[allow(missing_docs)] + NodeRemoved(NodeRemoved), + #[allow(missing_docs)] + NodeSet(NodeSet), + } + #[automatically_derived] + impl ClusterEvents { + /// All the selectors of this enum. + /// + /// Note that the selectors might not be in the same order as the variants. + /// No guarantees are made about the order of the selectors. + /// + /// Prefer using `SolInterface` methods instead. + pub const SELECTORS: &'static [[u8; 32usize]] = &[ + [ + 17u8, + 206u8, + 80u8, + 22u8, + 14u8, + 102u8, + 16u8, + 5u8, + 55u8, + 253u8, + 75u8, + 10u8, + 226u8, + 109u8, + 230u8, + 109u8, + 81u8, + 218u8, + 183u8, + 19u8, + 173u8, + 146u8, + 49u8, + 51u8, + 83u8, + 161u8, + 140u8, + 36u8, + 232u8, + 246u8, + 218u8, + 171u8, + ], + [ + 106u8, + 223u8, + 184u8, + 150u8, + 211u8, + 64u8, + 118u8, + 129u8, + 208u8, + 95u8, + 184u8, + 116u8, + 212u8, + 223u8, + 183u8, + 6u8, + 142u8, + 110u8, + 42u8, + 54u8, + 240u8, + 154u8, + 205u8, + 56u8, + 163u8, + 183u8, + 208u8, + 76u8, + 1u8, + 116u8, + 95u8, + 238u8, + ], + [ + 126u8, + 5u8, + 228u8, + 1u8, + 23u8, + 182u8, + 225u8, + 138u8, + 178u8, + 132u8, + 192u8, + 74u8, + 53u8, + 8u8, + 195u8, + 130u8, + 100u8, + 34u8, + 220u8, + 132u8, + 166u8, + 94u8, + 156u8, + 35u8, + 106u8, + 130u8, + 72u8, + 119u8, + 68u8, + 22u8, + 248u8, + 172u8, + ], + [ + 143u8, + 185u8, + 205u8, + 5u8, + 77u8, + 10u8, + 2u8, + 33u8, + 16u8, + 204u8, + 237u8, + 35u8, + 158u8, + 144u8, + 139u8, + 131u8, + 78u8, + 76u8, + 210u8, + 25u8, + 81u8, + 24u8, + 86u8, + 212u8, + 234u8, + 174u8, + 48u8, + 81u8, + 217u8, + 50u8, + 214u8, + 4u8, + ], + [ + 156u8, + 225u8, + 146u8, + 174u8, + 165u8, + 250u8, + 242u8, + 21u8, + 27u8, + 188u8, + 36u8, + 108u8, + 216u8, + 145u8, + 141u8, + 46u8, + 186u8, + 112u8, + 47u8, + 162u8, + 105u8, + 81u8, + 246u8, + 127u8, + 43u8, + 247u8, + 179u8, + 129u8, + 126u8, + 104u8, + 157u8, + 152u8, + ], + [ + 167u8, + 106u8, + 143u8, + 193u8, + 169u8, + 2u8, + 102u8, + 221u8, + 238u8, + 137u8, + 55u8, + 161u8, + 142u8, + 18u8, + 240u8, + 30u8, + 173u8, + 233u8, + 70u8, + 179u8, + 182u8, + 97u8, + 151u8, + 255u8, + 242u8, + 137u8, + 175u8, + 146u8, + 119u8, + 194u8, + 189u8, + 37u8, + ], + [ + 188u8, + 39u8, + 72u8, + 207u8, + 2u8, + 247u8, + 161u8, + 41u8, + 21u8, + 37u8, + 232u8, + 102u8, + 239u8, + 199u8, + 106u8, + 179u8, + 185u8, + 109u8, + 50u8, + 215u8, + 175u8, + 203u8, + 178u8, + 108u8, + 83u8, + 218u8, + 236u8, + 97u8, + 123u8, + 56u8, + 180u8, + 121u8, + ], + [ + 189u8, + 24u8, + 77u8, + 231u8, + 159u8, + 19u8, + 75u8, + 15u8, + 61u8, + 164u8, + 102u8, + 210u8, + 120u8, + 245u8, + 65u8, + 124u8, + 188u8, + 177u8, + 69u8, + 13u8, + 114u8, + 241u8, + 189u8, + 26u8, + 27u8, + 132u8, + 241u8, + 139u8, + 27u8, + 205u8, + 3u8, + 202u8, + ], + [ + 249u8, + 16u8, + 103u8, + 235u8, + 66u8, + 12u8, + 40u8, + 211u8, + 18u8, + 72u8, + 101u8, + 252u8, + 153u8, + 110u8, + 106u8, + 169u8, + 213u8, + 65u8, + 185u8, + 180u8, + 254u8, + 249u8, + 24u8, + 140u8, + 185u8, + 101u8, + 166u8, + 204u8, + 100u8, + 145u8, + 99u8, + 142u8, + ], + ]; + } + #[automatically_derived] + impl alloy_sol_types::SolEventInterface for ClusterEvents { + const NAME: &'static str = "ClusterEvents"; + const COUNT: usize = 9usize; + fn decode_raw_log( + topics: &[alloy_sol_types::Word], + data: &[u8], + validate: bool, + ) -> alloy_sol_types::Result { + match topics.first().copied() { + Some( + ::SIGNATURE_HASH, + ) => { + ::decode_raw_log( + topics, + data, + validate, + ) + .map(Self::MaintenanceAborted) + } + Some( + ::SIGNATURE_HASH, + ) => { + ::decode_raw_log( + topics, + data, + validate, + ) + .map(Self::MaintenanceCompleted) + } + Some( + ::SIGNATURE_HASH, + ) => { + ::decode_raw_log( + topics, + data, + validate, + ) + .map(Self::MaintenanceStarted) + } + Some(::SIGNATURE_HASH) => { + ::decode_raw_log( + topics, + data, + validate, + ) + .map(Self::MigrationAborted) + } + Some( + ::SIGNATURE_HASH, + ) => { + ::decode_raw_log( + topics, + data, + validate, + ) + .map(Self::MigrationCompleted) + } + Some( + ::SIGNATURE_HASH, + ) => { + ::decode_raw_log( + topics, + data, + validate, + ) + .map(Self::MigrationDataPullCompleted) + } + Some(::SIGNATURE_HASH) => { + ::decode_raw_log( + topics, + data, + validate, + ) + .map(Self::MigrationStarted) + } + Some(::SIGNATURE_HASH) => { + ::decode_raw_log( + topics, + data, + validate, + ) + .map(Self::NodeRemoved) + } + Some(::SIGNATURE_HASH) => { + ::decode_raw_log( + topics, + data, + validate, + ) + .map(Self::NodeSet) + } + _ => { + alloy_sol_types::private::Err(alloy_sol_types::Error::InvalidLog { + name: ::NAME, + log: alloy_sol_types::private::Box::new( + alloy_sol_types::private::LogData::new_unchecked( + topics.to_vec(), + data.to_vec().into(), + ), + ), + }) + } + } + } + } + #[automatically_derived] + impl alloy_sol_types::private::IntoLogData for ClusterEvents { + fn to_log_data(&self) -> alloy_sol_types::private::LogData { + match self { + Self::MaintenanceAborted(inner) => { + alloy_sol_types::private::IntoLogData::to_log_data(inner) + } + Self::MaintenanceCompleted(inner) => { + alloy_sol_types::private::IntoLogData::to_log_data(inner) + } + Self::MaintenanceStarted(inner) => { + alloy_sol_types::private::IntoLogData::to_log_data(inner) + } + Self::MigrationAborted(inner) => { + alloy_sol_types::private::IntoLogData::to_log_data(inner) + } + Self::MigrationCompleted(inner) => { + alloy_sol_types::private::IntoLogData::to_log_data(inner) + } + Self::MigrationDataPullCompleted(inner) => { + alloy_sol_types::private::IntoLogData::to_log_data(inner) + } + Self::MigrationStarted(inner) => { + alloy_sol_types::private::IntoLogData::to_log_data(inner) + } + Self::NodeRemoved(inner) => { + alloy_sol_types::private::IntoLogData::to_log_data(inner) + } + Self::NodeSet(inner) => { + alloy_sol_types::private::IntoLogData::to_log_data(inner) + } + } + } + fn into_log_data(self) -> alloy_sol_types::private::LogData { + match self { + Self::MaintenanceAborted(inner) => { + alloy_sol_types::private::IntoLogData::into_log_data(inner) + } + Self::MaintenanceCompleted(inner) => { + alloy_sol_types::private::IntoLogData::into_log_data(inner) + } + Self::MaintenanceStarted(inner) => { + alloy_sol_types::private::IntoLogData::into_log_data(inner) + } + Self::MigrationAborted(inner) => { + alloy_sol_types::private::IntoLogData::into_log_data(inner) + } + Self::MigrationCompleted(inner) => { + alloy_sol_types::private::IntoLogData::into_log_data(inner) + } + Self::MigrationDataPullCompleted(inner) => { + alloy_sol_types::private::IntoLogData::into_log_data(inner) + } + Self::MigrationStarted(inner) => { + alloy_sol_types::private::IntoLogData::into_log_data(inner) + } + Self::NodeRemoved(inner) => { + alloy_sol_types::private::IntoLogData::into_log_data(inner) + } + Self::NodeSet(inner) => { + alloy_sol_types::private::IntoLogData::into_log_data(inner) + } + } + } + } + use alloy::contract as alloy_contract; + /**Creates a new wrapper around an on-chain [`Cluster`](self) contract instance. + +See the [wrapper's documentation](`ClusterInstance`) for more details.*/ + #[inline] + pub const fn new< + T: alloy_contract::private::Transport + ::core::clone::Clone, + P: alloy_contract::private::Provider, + N: alloy_contract::private::Network, + >( + address: alloy_sol_types::private::Address, + provider: P, + ) -> ClusterInstance { + ClusterInstance::::new(address, provider) + } + /**Deploys this contract using the given `provider` and constructor arguments, if any. + +Returns a new instance of the contract, if the deployment was successful. + +For more fine-grained control over the deployment process, use [`deploy_builder`] instead.*/ + #[inline] + pub fn deploy< + T: alloy_contract::private::Transport + ::core::clone::Clone, + P: alloy_contract::private::Provider, + N: alloy_contract::private::Network, + >( + provider: P, + initialSettings: ::RustType, + initialOperators: alloy::sol_types::private::Vec< + ::RustType, + >, + ) -> impl ::core::future::Future< + Output = alloy_contract::Result>, + > { + ClusterInstance::::deploy(provider, initialSettings, initialOperators) + } + /**Creates a `RawCallBuilder` for deploying this contract using the given `provider` +and constructor arguments, if any. + +This is a simple wrapper around creating a `RawCallBuilder` with the data set to +the bytecode concatenated with the constructor's ABI-encoded arguments.*/ + #[inline] + pub fn deploy_builder< + T: alloy_contract::private::Transport + ::core::clone::Clone, + P: alloy_contract::private::Provider, + N: alloy_contract::private::Network, + >( + provider: P, + initialSettings: ::RustType, + initialOperators: alloy::sol_types::private::Vec< + ::RustType, + >, + ) -> alloy_contract::RawCallBuilder { + ClusterInstance::< + T, + P, + N, + >::deploy_builder(provider, initialSettings, initialOperators) + } + /**A [`Cluster`](self) instance. + +Contains type-safe methods for interacting with an on-chain instance of the +[`Cluster`](self) contract located at a given `address`, using a given +provider `P`. + +If the contract bytecode is available (see the [`sol!`](alloy_sol_types::sol!) +documentation on how to provide it), the `deploy` and `deploy_builder` methods can +be used to deploy a new instance of the contract. + +See the [module-level documentation](self) for all the available methods.*/ + #[derive(Clone)] + pub struct ClusterInstance { + address: alloy_sol_types::private::Address, + provider: P, + _network_transport: ::core::marker::PhantomData<(N, T)>, + } + #[automatically_derived] + impl ::core::fmt::Debug for ClusterInstance { + #[inline] + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + f.debug_tuple("ClusterInstance").field(&self.address).finish() + } + } + /// Instantiation and getters/setters. + #[automatically_derived] + impl< + T: alloy_contract::private::Transport + ::core::clone::Clone, + P: alloy_contract::private::Provider, + N: alloy_contract::private::Network, + > ClusterInstance { + /**Creates a new wrapper around an on-chain [`Cluster`](self) contract instance. + +See the [wrapper's documentation](`ClusterInstance`) for more details.*/ + #[inline] + pub const fn new( + address: alloy_sol_types::private::Address, + provider: P, + ) -> Self { + Self { + address, + provider, + _network_transport: ::core::marker::PhantomData, + } + } + /**Deploys this contract using the given `provider` and constructor arguments, if any. + +Returns a new instance of the contract, if the deployment was successful. + +For more fine-grained control over the deployment process, use [`deploy_builder`] instead.*/ + #[inline] + pub async fn deploy( + provider: P, + initialSettings: ::RustType, + initialOperators: alloy::sol_types::private::Vec< + ::RustType, + >, + ) -> alloy_contract::Result> { + let call_builder = Self::deploy_builder( + provider, + initialSettings, + initialOperators, + ); + let contract_address = call_builder.deploy().await?; + Ok(Self::new(contract_address, call_builder.provider)) + } + /**Creates a `RawCallBuilder` for deploying this contract using the given `provider` +and constructor arguments, if any. + +This is a simple wrapper around creating a `RawCallBuilder` with the data set to +the bytecode concatenated with the constructor's ABI-encoded arguments.*/ + #[inline] + pub fn deploy_builder( + provider: P, + initialSettings: ::RustType, + initialOperators: alloy::sol_types::private::Vec< + ::RustType, + >, + ) -> alloy_contract::RawCallBuilder { + alloy_contract::RawCallBuilder::new_raw_deploy( + provider, + [ + &BYTECODE[..], + &alloy_sol_types::SolConstructor::abi_encode( + &constructorCall { + initialSettings, + initialOperators, + }, + )[..], + ] + .concat() + .into(), + ) + } + /// Returns a reference to the address. + #[inline] + pub const fn address(&self) -> &alloy_sol_types::private::Address { + &self.address + } + /// Sets the address. + #[inline] + pub fn set_address(&mut self, address: alloy_sol_types::private::Address) { + self.address = address; + } + /// Sets the address and returns `self`. + pub fn at(mut self, address: alloy_sol_types::private::Address) -> Self { + self.set_address(address); + self + } + /// Returns a reference to the provider. + #[inline] + pub const fn provider(&self) -> &P { + &self.provider + } + } + impl ClusterInstance { + /// Clones the provider and returns a new instance with the cloned provider. + #[inline] + pub fn with_cloned_provider(self) -> ClusterInstance { + ClusterInstance { + address: self.address, + provider: ::core::clone::Clone::clone(&self.provider), + _network_transport: ::core::marker::PhantomData, + } + } + } + /// Function calls. + #[automatically_derived] + impl< + T: alloy_contract::private::Transport + ::core::clone::Clone, + P: alloy_contract::private::Provider, + N: alloy_contract::private::Network, + > ClusterInstance { + /// Creates a new call builder using this contract instance's provider and address. + /// + /// Note that the call can be any function call, not just those defined in this + /// contract. Prefer using the other methods for building type-safe contract calls. + pub fn call_builder( + &self, + call: &C, + ) -> alloy_contract::SolCallBuilder { + alloy_contract::SolCallBuilder::new_sol(&self.provider, &self.address, call) + } + ///Creates a new call builder for the [`abortMaintenance`] function. + pub fn abortMaintenance( + &self, + ) -> alloy_contract::SolCallBuilder { + self.call_builder(&abortMaintenanceCall {}) + } + ///Creates a new call builder for the [`abortMigration`] function. + pub fn abortMigration( + &self, + ) -> alloy_contract::SolCallBuilder { + self.call_builder(&abortMigrationCall {}) + } + ///Creates a new call builder for the [`completeMaintenance`] function. + pub fn completeMaintenance( + &self, + ) -> alloy_contract::SolCallBuilder { + self.call_builder(&completeMaintenanceCall {}) + } + ///Creates a new call builder for the [`completeMigration`] function. + pub fn completeMigration( + &self, + ) -> alloy_contract::SolCallBuilder { + self.call_builder(&completeMigrationCall {}) + } + ///Creates a new call builder for the [`getView`] function. + pub fn getView(&self) -> alloy_contract::SolCallBuilder { + self.call_builder(&getViewCall {}) + } + ///Creates a new call builder for the [`removeNode`] function. + pub fn removeNode( + &self, + id: alloy::sol_types::private::primitives::aliases::U256, + ) -> alloy_contract::SolCallBuilder { + self.call_builder(&removeNodeCall { id }) + } + ///Creates a new call builder for the [`setNode`] function. + pub fn setNode( + &self, + node: ::RustType, + ) -> alloy_contract::SolCallBuilder { + self.call_builder(&setNodeCall { node }) + } + ///Creates a new call builder for the [`startMaintenance`] function. + pub fn startMaintenance( + &self, + ) -> alloy_contract::SolCallBuilder { + self.call_builder(&startMaintenanceCall {}) + } + ///Creates a new call builder for the [`startMigration`] function. + pub fn startMigration( + &self, + operatorsToRemove: alloy::sol_types::private::Vec< + alloy::sol_types::private::Address, + >, + operatorsToAdd: alloy::sol_types::private::Vec< + ::RustType, + >, + ) -> alloy_contract::SolCallBuilder { + self.call_builder( + &startMigrationCall { + operatorsToRemove, + operatorsToAdd, + }, + ) + } + ///Creates a new call builder for the [`transferOwnership`] function. + pub fn transferOwnership( + &self, + newOwner: alloy::sol_types::private::Address, + ) -> alloy_contract::SolCallBuilder { + self.call_builder(&transferOwnershipCall { newOwner }) + } + ///Creates a new call builder for the [`updateSettings`] function. + pub fn updateSettings( + &self, + newSettings: ::RustType, + ) -> alloy_contract::SolCallBuilder { + self.call_builder(&updateSettingsCall { newSettings }) + } + } + /// Event filters. + #[automatically_derived] + impl< + T: alloy_contract::private::Transport + ::core::clone::Clone, + P: alloy_contract::private::Provider, + N: alloy_contract::private::Network, + > ClusterInstance { + /// Creates a new event filter using this contract instance's provider and address. + /// + /// Note that the type can be any event, not just those defined in this contract. + /// Prefer using the other methods for building type-safe event filters. + pub fn event_filter( + &self, + ) -> alloy_contract::Event { + alloy_contract::Event::new_sol(&self.provider, &self.address) + } + ///Creates a new event filter for the [`MaintenanceAborted`] event. + pub fn MaintenanceAborted_filter( + &self, + ) -> alloy_contract::Event { + self.event_filter::() + } + ///Creates a new event filter for the [`MaintenanceCompleted`] event. + pub fn MaintenanceCompleted_filter( + &self, + ) -> alloy_contract::Event { + self.event_filter::() + } + ///Creates a new event filter for the [`MaintenanceStarted`] event. + pub fn MaintenanceStarted_filter( + &self, + ) -> alloy_contract::Event { + self.event_filter::() + } + ///Creates a new event filter for the [`MigrationAborted`] event. + pub fn MigrationAborted_filter( + &self, + ) -> alloy_contract::Event { + self.event_filter::() + } + ///Creates a new event filter for the [`MigrationCompleted`] event. + pub fn MigrationCompleted_filter( + &self, + ) -> alloy_contract::Event { + self.event_filter::() + } + ///Creates a new event filter for the [`MigrationDataPullCompleted`] event. + pub fn MigrationDataPullCompleted_filter( + &self, + ) -> alloy_contract::Event { + self.event_filter::() + } + ///Creates a new event filter for the [`MigrationStarted`] event. + pub fn MigrationStarted_filter( + &self, + ) -> alloy_contract::Event { + self.event_filter::() + } + ///Creates a new event filter for the [`NodeRemoved`] event. + pub fn NodeRemoved_filter( + &self, + ) -> alloy_contract::Event { + self.event_filter::() + } + ///Creates a new event filter for the [`NodeSet`] event. + pub fn NodeSet_filter(&self) -> alloy_contract::Event { + self.event_filter::() + } + } +} diff --git a/crates/cluster/src/contract/evm/mod.rs b/crates/cluster/src/contract/evm/mod.rs new file mode 100644 index 00000000..00e09773 --- /dev/null +++ b/crates/cluster/src/contract/evm/mod.rs @@ -0,0 +1,98 @@ +#[rustfmt::skip] +mod bindings; + +use { + alloy::{ + network::EthereumWallet, + providers::{Provider, ProviderBuilder}, + signers::local::PrivateKeySigner, + transports::http::reqwest, + }, + std::{str::FromStr, sync::Arc}, +}; + +pub struct ContractSettings { + pub min_operators: u8, + pub min_nodes: u8, +} + +pub struct ContractManager { + provider: Arc, +} + +impl ContractManager { + pub fn new(signer: Signer, rpc_url: RpcUrl) -> Self { + let wallet: EthereumWallet = match signer.inner { + SignerInner::PrivateKey(key) => key.into(), + }; + + Self { + provider: Arc::new(ProviderBuilder::new().wallet(wallet).on_http(rpc_url.0)), + } + } + + pub fn deploy_contract(&self, settings: ContractSettings) {} +} + +#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] +pub struct Address(alloy::primitives::Address); + +impl FromStr for Address { + type Err = InvalidAddress; + + fn from_str(s: &str) -> Result { + alloy::primitives::Address::from_str(s) + .map(Address) + .map_err(|err| InvalidAddress(err.to_string())) + } +} + +pub struct Signer { + inner: SignerInner, +} + +impl Signer { + pub fn try_from_private_key(hex: &str) -> Result { + PrivateKeySigner::from_str(hex) + .map(SignerInner::PrivateKey) + .map(|inner| Self { inner }) + .map_err(|err| InvalidPrivateKey(err.to_string())) + } +} + +pub enum SignerInner { + PrivateKey(PrivateKeySigner), +} + +pub struct RpcUrl(reqwest::Url); + +impl FromStr for RpcUrl { + type Err = InvalidRpcUrl; + + fn from_str(s: &str) -> Result { + reqwest::Url::from_str(s) + .map(Self) + .map_err(|err| InvalidRpcUrl(err.to_string())) + } +} + +impl From for bindings::Cluster::Settings { + fn from(s: ContractSettings) -> Self { + Self { + minOperators: s.min_operators, + minNodes: s.min_nodes, + } + } +} + +#[derive(Debug, thiserror::Error)] +#[error("Invalid RPC URL: {0:?}")] +pub struct InvalidRpcUrl(String); + +#[derive(Debug, thiserror::Error)] +#[error("Invalid private key: {0:?}")] +pub struct InvalidPrivateKey(String); + +#[derive(Debug, thiserror::Error)] +#[error("Invalid address: {0:?}")] +pub struct InvalidAddress(String); diff --git a/crates/cluster/src/contract/mod.rs b/crates/cluster/src/contract/mod.rs index da5ccddd..53137d9c 100644 --- a/crates/cluster/src/contract/mod.rs +++ b/crates/cluster/src/contract/mod.rs @@ -1,5306 +1,38 @@ -#![allow(unused_imports, clippy::all, rustdoc::all)] -//! This module contains the sol! generated bindings for solidity contracts. -//! This is autogenerated code. -//! Do not manually edit these files. -//! These files may be overwritten by the codegen system at any time. -/// Generated by the following Solidity interface... -/// ```solidity +use {crate::node, std::future::Future}; -/// interface Cluster { -/// struct ClusterView { -/// NodeOperatorsView operators; -/// MigrationView migration; -/// Maintenance maintenance; -/// uint64 keyspaceVersion; -/// uint128 version; -/// } -/// struct Maintenance { -/// address slot; -/// } -/// struct MigrationView { -/// address[] operatorsToRemove; -/// NodeOperatorView[] operatorsToAdd; -/// address[] pullingOperators; -/// } -/// struct Node { -/// uint256 id; -/// bytes data; -/// } -/// struct NodeOperatorView { -/// address addr; -/// Node[] nodes; -/// bytes data; -/// } -/// struct NodeOperatorsView { -/// NodeOperatorView[] slots; -/// } -/// struct Settings { -/// uint8 minOperators; -/// uint8 minNodes; -/// } -/// -/// event MaintenanceAborted(uint128 version); -/// event MaintenanceCompleted(address operator, uint128 version); -/// event MaintenanceStarted(address operator, uint128 version); -/// event MigrationAborted(uint128 version); -/// event MigrationCompleted(uint128 version); -/// event MigrationDataPullCompleted(address operator, uint128 version); -/// event MigrationStarted(address[] operatorsToRemove, NodeOperatorView[] -/// operatorsToAdd, uint128 version); event NodeRemoved(address operator, -/// uint256 id, uint128 version); event NodeSet(address operator, Node node, -/// uint128 version); -/// -/// constructor(Settings initialSettings, NodeOperatorView[] initialOperators); -/// -/// function abortMaintenance() external; -/// function abortMigration() external; -/// function completeMaintenance() external; -/// function completeMigration() external; -/// function getView() external view returns (ClusterView memory); -/// function removeNode(uint256 id) external; -/// function setNode(Node memory node) external; -/// function startMaintenance() external; -/// function startMigration(address[] memory operatorsToRemove, -/// NodeOperatorView[] memory operatorsToAdd) external; -/// function transferOwnership(address newOwner) external; -/// function updateSettings(Settings memory newSettings) external; -/// } -/// ``` -/// -/// ...which was generated by the following JSON ABI: -/// ```json -/// [ -/// { -/// "type": "constructor", -/// "inputs": [ -/// { -/// "name": "initialSettings", -/// "type": "tuple", -/// "internalType": "struct Settings", -/// "components": [ -/// { -/// "name": "minOperators", -/// "type": "uint8", -/// "internalType": "uint8" -/// }, -/// { -/// "name": "minNodes", -/// "type": "uint8", -/// "internalType": "uint8" -/// } -/// ] -/// }, -/// { -/// "name": "initialOperators", -/// "type": "tuple[]", -/// "internalType": "struct NodeOperatorView[]", -/// "components": [ -/// { -/// "name": "addr", -/// "type": "address", -/// "internalType": "address" -/// }, -/// { -/// "name": "nodes", -/// "type": "tuple[]", -/// "internalType": "struct Node[]", -/// "components": [ -/// { -/// "name": "id", -/// "type": "uint256", -/// "internalType": "uint256" -/// }, -/// { -/// "name": "data", -/// "type": "bytes", -/// "internalType": "bytes" -/// } -/// ] -/// }, -/// { -/// "name": "data", -/// "type": "bytes", -/// "internalType": "bytes" -/// } -/// ] -/// } -/// ], -/// "stateMutability": "nonpayable" -/// }, -/// { -/// "type": "function", -/// "name": "abortMaintenance", -/// "inputs": [], -/// "outputs": [], -/// "stateMutability": "nonpayable" -/// }, -/// { -/// "type": "function", -/// "name": "abortMigration", -/// "inputs": [], -/// "outputs": [], -/// "stateMutability": "nonpayable" -/// }, -/// { -/// "type": "function", -/// "name": "completeMaintenance", -/// "inputs": [], -/// "outputs": [], -/// "stateMutability": "nonpayable" -/// }, -/// { -/// "type": "function", -/// "name": "completeMigration", -/// "inputs": [], -/// "outputs": [], -/// "stateMutability": "nonpayable" -/// }, -/// { -/// "type": "function", -/// "name": "getView", -/// "inputs": [], -/// "outputs": [ -/// { -/// "name": "", -/// "type": "tuple", -/// "internalType": "struct ClusterView", -/// "components": [ -/// { -/// "name": "operators", -/// "type": "tuple", -/// "internalType": "struct NodeOperatorsView", -/// "components": [ -/// { -/// "name": "slots", -/// "type": "tuple[]", -/// "internalType": "struct NodeOperatorView[]", -/// "components": [ -/// { -/// "name": "addr", -/// "type": "address", -/// "internalType": "address" -/// }, -/// { -/// "name": "nodes", -/// "type": "tuple[]", -/// "internalType": "struct Node[]", -/// "components": [ -/// { -/// "name": "id", -/// "type": "uint256", -/// "internalType": "uint256" -/// }, -/// { -/// "name": "data", -/// "type": "bytes", -/// "internalType": "bytes" -/// } -/// ] -/// }, -/// { -/// "name": "data", -/// "type": "bytes", -/// "internalType": "bytes" -/// } -/// ] -/// } -/// ] -/// }, -/// { -/// "name": "migration", -/// "type": "tuple", -/// "internalType": "struct MigrationView", -/// "components": [ -/// { -/// "name": "operatorsToRemove", -/// "type": "address[]", -/// "internalType": "address[]" -/// }, -/// { -/// "name": "operatorsToAdd", -/// "type": "tuple[]", -/// "internalType": "struct NodeOperatorView[]", -/// "components": [ -/// { -/// "name": "addr", -/// "type": "address", -/// "internalType": "address" -/// }, -/// { -/// "name": "nodes", -/// "type": "tuple[]", -/// "internalType": "struct Node[]", -/// "components": [ -/// { -/// "name": "id", -/// "type": "uint256", -/// "internalType": "uint256" -/// }, -/// { -/// "name": "data", -/// "type": "bytes", -/// "internalType": "bytes" -/// } -/// ] -/// }, -/// { -/// "name": "data", -/// "type": "bytes", -/// "internalType": "bytes" -/// } -/// ] -/// }, -/// { -/// "name": "pullingOperators", -/// "type": "address[]", -/// "internalType": "address[]" -/// } -/// ] -/// }, -/// { -/// "name": "maintenance", -/// "type": "tuple", -/// "internalType": "struct Maintenance", -/// "components": [ -/// { -/// "name": "slot", -/// "type": "address", -/// "internalType": "address" -/// } -/// ] -/// }, -/// { -/// "name": "keyspaceVersion", -/// "type": "uint64", -/// "internalType": "uint64" -/// }, -/// { -/// "name": "version", -/// "type": "uint128", -/// "internalType": "uint128" -/// } -/// ] -/// } -/// ], -/// "stateMutability": "view" -/// }, -/// { -/// "type": "function", -/// "name": "removeNode", -/// "inputs": [ -/// { -/// "name": "id", -/// "type": "uint256", -/// "internalType": "uint256" -/// } -/// ], -/// "outputs": [], -/// "stateMutability": "nonpayable" -/// }, -/// { -/// "type": "function", -/// "name": "setNode", -/// "inputs": [ -/// { -/// "name": "node", -/// "type": "tuple", -/// "internalType": "struct Node", -/// "components": [ -/// { -/// "name": "id", -/// "type": "uint256", -/// "internalType": "uint256" -/// }, -/// { -/// "name": "data", -/// "type": "bytes", -/// "internalType": "bytes" -/// } -/// ] -/// } -/// ], -/// "outputs": [], -/// "stateMutability": "nonpayable" -/// }, -/// { -/// "type": "function", -/// "name": "startMaintenance", -/// "inputs": [], -/// "outputs": [], -/// "stateMutability": "nonpayable" -/// }, -/// { -/// "type": "function", -/// "name": "startMigration", -/// "inputs": [ -/// { -/// "name": "operatorsToRemove", -/// "type": "address[]", -/// "internalType": "address[]" -/// }, -/// { -/// "name": "operatorsToAdd", -/// "type": "tuple[]", -/// "internalType": "struct NodeOperatorView[]", -/// "components": [ -/// { -/// "name": "addr", -/// "type": "address", -/// "internalType": "address" -/// }, -/// { -/// "name": "nodes", -/// "type": "tuple[]", -/// "internalType": "struct Node[]", -/// "components": [ -/// { -/// "name": "id", -/// "type": "uint256", -/// "internalType": "uint256" -/// }, -/// { -/// "name": "data", -/// "type": "bytes", -/// "internalType": "bytes" -/// } -/// ] -/// }, -/// { -/// "name": "data", -/// "type": "bytes", -/// "internalType": "bytes" -/// } -/// ] -/// } -/// ], -/// "outputs": [], -/// "stateMutability": "nonpayable" -/// }, -/// { -/// "type": "function", -/// "name": "transferOwnership", -/// "inputs": [ -/// { -/// "name": "newOwner", -/// "type": "address", -/// "internalType": "address" -/// } -/// ], -/// "outputs": [], -/// "stateMutability": "nonpayable" -/// }, -/// { -/// "type": "function", -/// "name": "updateSettings", -/// "inputs": [ -/// { -/// "name": "newSettings", -/// "type": "tuple", -/// "internalType": "struct Settings", -/// "components": [ -/// { -/// "name": "minOperators", -/// "type": "uint8", -/// "internalType": "uint8" -/// }, -/// { -/// "name": "minNodes", -/// "type": "uint8", -/// "internalType": "uint8" -/// } -/// ] -/// } -/// ], -/// "outputs": [], -/// "stateMutability": "nonpayable" -/// }, -/// { -/// "type": "event", -/// "name": "MaintenanceAborted", -/// "inputs": [ -/// { -/// "name": "version", -/// "type": "uint128", -/// "indexed": false, -/// "internalType": "uint128" -/// } -/// ], -/// "anonymous": false -/// }, -/// { -/// "type": "event", -/// "name": "MaintenanceCompleted", -/// "inputs": [ -/// { -/// "name": "operator", -/// "type": "address", -/// "indexed": false, -/// "internalType": "address" -/// }, -/// { -/// "name": "version", -/// "type": "uint128", -/// "indexed": false, -/// "internalType": "uint128" -/// } -/// ], -/// "anonymous": false -/// }, -/// { -/// "type": "event", -/// "name": "MaintenanceStarted", -/// "inputs": [ -/// { -/// "name": "operator", -/// "type": "address", -/// "indexed": false, -/// "internalType": "address" -/// }, -/// { -/// "name": "version", -/// "type": "uint128", -/// "indexed": false, -/// "internalType": "uint128" -/// } -/// ], -/// "anonymous": false -/// }, -/// { -/// "type": "event", -/// "name": "MigrationAborted", -/// "inputs": [ -/// { -/// "name": "version", -/// "type": "uint128", -/// "indexed": false, -/// "internalType": "uint128" -/// } -/// ], -/// "anonymous": false -/// }, -/// { -/// "type": "event", -/// "name": "MigrationCompleted", -/// "inputs": [ -/// { -/// "name": "version", -/// "type": "uint128", -/// "indexed": false, -/// "internalType": "uint128" -/// } -/// ], -/// "anonymous": false -/// }, -/// { -/// "type": "event", -/// "name": "MigrationDataPullCompleted", -/// "inputs": [ -/// { -/// "name": "operator", -/// "type": "address", -/// "indexed": false, -/// "internalType": "address" -/// }, -/// { -/// "name": "version", -/// "type": "uint128", -/// "indexed": false, -/// "internalType": "uint128" -/// } -/// ], -/// "anonymous": false -/// }, -/// { -/// "type": "event", -/// "name": "MigrationStarted", -/// "inputs": [ -/// { -/// "name": "operatorsToRemove", -/// "type": "address[]", -/// "indexed": false, -/// "internalType": "address[]" -/// }, -/// { -/// "name": "operatorsToAdd", -/// "type": "tuple[]", -/// "indexed": false, -/// "internalType": "struct NodeOperatorView[]", -/// "components": [ -/// { -/// "name": "addr", -/// "type": "address", -/// "internalType": "address" -/// }, -/// { -/// "name": "nodes", -/// "type": "tuple[]", -/// "internalType": "struct Node[]", -/// "components": [ -/// { -/// "name": "id", -/// "type": "uint256", -/// "internalType": "uint256" -/// }, -/// { -/// "name": "data", -/// "type": "bytes", -/// "internalType": "bytes" -/// } -/// ] -/// }, -/// { -/// "name": "data", -/// "type": "bytes", -/// "internalType": "bytes" -/// } -/// ] -/// }, -/// { -/// "name": "version", -/// "type": "uint128", -/// "indexed": false, -/// "internalType": "uint128" -/// } -/// ], -/// "anonymous": false -/// }, -/// { -/// "type": "event", -/// "name": "NodeRemoved", -/// "inputs": [ -/// { -/// "name": "operator", -/// "type": "address", -/// "indexed": false, -/// "internalType": "address" -/// }, -/// { -/// "name": "id", -/// "type": "uint256", -/// "indexed": false, -/// "internalType": "uint256" -/// }, -/// { -/// "name": "version", -/// "type": "uint128", -/// "indexed": false, -/// "internalType": "uint128" -/// } -/// ], -/// "anonymous": false -/// }, -/// { -/// "type": "event", -/// "name": "NodeSet", -/// "inputs": [ -/// { -/// "name": "operator", -/// "type": "address", -/// "indexed": false, -/// "internalType": "address" -/// }, -/// { -/// "name": "node", -/// "type": "tuple", -/// "indexed": false, -/// "internalType": "struct Node", -/// "components": [ -/// { -/// "name": "id", -/// "type": "uint256", -/// "internalType": "uint256" -/// }, -/// { -/// "name": "data", -/// "type": "bytes", -/// "internalType": "bytes" -/// } -/// ] -/// }, -/// { -/// "name": "version", -/// "type": "uint128", -/// "indexed": false, -/// "internalType": "uint128" -/// } -/// ], -/// "anonymous": false -/// } -/// ] -/// ``` -#[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style, - clippy::empty_structs_with_brackets -)] -pub mod Cluster { - use {super::*, alloy::sol_types as alloy_sol_types}; - /// The creation / init bytecode of the contract. - /// - /// ```text - ///0x608060405234801561000f575f5ffd5b5060405161741138038061741183398181016040528101906100319190610e18565b335f5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508160015f820151815f015f6101000a81548160ff021916908360ff1602179055506020820151815f0160016101000a81548160ff021916908360ff1602179055509050506100c4815161014360201b60201c565b5f5f90505b815181101561013b576101008282815181106100e8576100e7610e72565b5b602002602001015160200151516101e160201b60201c565b61012e82828151811061011657610115610e72565b5b6020026020010151600261028060201b90919060201c565b80806001019150506100c9565b5050506114ea565b60015f015f9054906101000a900460ff1660ff16811015610199576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161019090610ef9565b60405180910390fd5b6101008111156101de576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101d590610f61565b60405180910390fd5b50565b60015f0160019054906101000a900460ff1660ff16811015610238576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161022f90610fc9565b60405180910390fd5b61010081111561027d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161027490611031565b60405180910390fd5b50565b61029382825f015161051360201b60201c565b156102d3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102ca90611099565b60405180910390fd5b5f5f8360020180549050111561036d5782600201600184600201805490506102fb91906110e4565b8154811061030c5761030b610e72565b5b905f5260205f2090602091828204019190069054906101000a900460ff169050826002018054806103405761033f611117565b5b600190038181905f5260205f2090602091828204019190066101000a81549060ff021916905590556103de565b610100835f0180549050106103b7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103ae90610f61565b60405180910390fd5b825f01805490509050825f0160018160018154018082558091505003905f5260205f209050505b80836001015f845f015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908360ff1602179055505f835f018260ff168154811061045157610450610e72565b5b905f5260205f2090600502019050825f0151815f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555082604001518160040190816104b8919061134b565b505f5f90505b83602001515181101561050c576104ff846020015182815181106104e5576104e4610e72565b5b60200260200101518360010161066b60201b90919060201c565b80806001019150506104be565b5050505050565b5f5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610582576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161057990611464565b60405180910390fd5b5f835f01805490501115610661575f836001015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1660ff1614158061065a57508173ffffffffffffffffffffffffffffffffffffffff16835f015f8154811061061457610613610e72565b5b905f5260205f2090600502015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b9050610665565b5f90505b92915050565b5f815f0151036106b0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106a7906114cc565b60405180910390fd5b5f5f835f0180549050111561076d57826001015f835f015181526020019081526020015f205f9054906101000a900460ff1690505f8160ff1614158061071b5750815f0151835f015f8154811061070a57610709610e72565b5b905f5260205f2090600202015f0154145b1561076c5781835f018260ff168154811061073957610738610e72565b5b905f5260205f2090600202015f820151815f01556020820151816001019081610762919061134b565b50905050506108ed565b5b5f8360020180549050111561080657826002016001846002018054905061079491906110e4565b815481106107a5576107a4610e72565b5b905f5260205f2090602091828204019190069054906101000a900460ff169050826002018054806107d9576107d8611117565b5b600190038181905f5260205f2090602091828204019190066101000a81549060ff02191690559055610877565b610100835f018054905010610850576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161084790611031565b60405180910390fd5b825f01805490509050825f0160018160018154018082558091505003905f5260205f209050505b80836001015f845f015181526020019081526020015f205f6101000a81548160ff021916908360ff16021790555081835f018260ff16815481106108be576108bd610e72565b5b905f5260205f2090600202015f820151815f015560208201518160010190816108e7919061134b565b50905050505b5050565b5f604051905090565b5f5ffd5b5f5ffd5b5f5ffd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b61094c82610906565b810181811067ffffffffffffffff8211171561096b5761096a610916565b5b80604052505050565b5f61097d6108f1565b90506109898282610943565b919050565b5f5ffd5b5f60ff82169050919050565b6109a781610992565b81146109b1575f5ffd5b50565b5f815190506109c28161099e565b92915050565b5f604082840312156109dd576109dc610902565b5b6109e76040610974565b90505f6109f6848285016109b4565b5f830152506020610a09848285016109b4565b60208301525092915050565b5f5ffd5b5f67ffffffffffffffff821115610a3357610a32610916565b5b602082029050602081019050919050565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f610a7182610a48565b9050919050565b610a8181610a67565b8114610a8b575f5ffd5b50565b5f81519050610a9c81610a78565b92915050565b5f67ffffffffffffffff821115610abc57610abb610916565b5b602082029050602081019050919050565b5f819050919050565b610adf81610acd565b8114610ae9575f5ffd5b50565b5f81519050610afa81610ad6565b92915050565b5f5ffd5b5f67ffffffffffffffff821115610b1e57610b1d610916565b5b610b2782610906565b9050602081019050919050565b8281835e5f83830152505050565b5f610b54610b4f84610b04565b610974565b905082815260208101848484011115610b7057610b6f610b00565b5b610b7b848285610b34565b509392505050565b5f82601f830112610b9757610b96610a15565b5b8151610ba7848260208601610b42565b91505092915050565b5f60408284031215610bc557610bc4610902565b5b610bcf6040610974565b90505f610bde84828501610aec565b5f83015250602082015167ffffffffffffffff811115610c0157610c0061098e565b5b610c0d84828501610b83565b60208301525092915050565b5f610c2b610c2684610aa2565b610974565b90508083825260208201905060208402830185811115610c4e57610c4d610a44565b5b835b81811015610c9557805167ffffffffffffffff811115610c7357610c72610a15565b5b808601610c808982610bb0565b85526020850194505050602081019050610c50565b5050509392505050565b5f82601f830112610cb357610cb2610a15565b5b8151610cc3848260208601610c19565b91505092915050565b5f60608284031215610ce157610ce0610902565b5b610ceb6060610974565b90505f610cfa84828501610a8e565b5f83015250602082015167ffffffffffffffff811115610d1d57610d1c61098e565b5b610d2984828501610c9f565b602083015250604082015167ffffffffffffffff811115610d4d57610d4c61098e565b5b610d5984828501610b83565b60408301525092915050565b5f610d77610d7284610a19565b610974565b90508083825260208201905060208402830185811115610d9a57610d99610a44565b5b835b81811015610de157805167ffffffffffffffff811115610dbf57610dbe610a15565b5b808601610dcc8982610ccc565b85526020850194505050602081019050610d9c565b5050509392505050565b5f82601f830112610dff57610dfe610a15565b5b8151610e0f848260208601610d65565b91505092915050565b5f5f60608385031215610e2e57610e2d6108fa565b5b5f610e3b858286016109c8565b925050604083015167ffffffffffffffff811115610e5c57610e5b6108fe565b5b610e6885828601610deb565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f82825260208201905092915050565b7f746f6f20666577206f70657261746f72730000000000000000000000000000005f82015250565b5f610ee3601183610e9f565b9150610eee82610eaf565b602082019050919050565b5f6020820190508181035f830152610f1081610ed7565b9050919050565b7f746f6f206d616e79206f70657261746f727300000000000000000000000000005f82015250565b5f610f4b601283610e9f565b9150610f5682610f17565b602082019050919050565b5f6020820190508181035f830152610f7881610f3f565b9050919050565b7f746f6f20666577206e6f646573000000000000000000000000000000000000005f82015250565b5f610fb3600d83610e9f565b9150610fbe82610f7f565b602082019050919050565b5f6020820190508181035f830152610fe081610fa7565b9050919050565b7f746f6f206d616e79206e6f6465730000000000000000000000000000000000005f82015250565b5f61101b600e83610e9f565b915061102682610fe7565b602082019050919050565b5f6020820190508181035f8301526110488161100f565b9050919050565b7f6f70657261746f7220616c7265616479206578697374730000000000000000005f82015250565b5f611083601783610e9f565b915061108e8261104f565b602082019050919050565b5f6020820190508181035f8301526110b081611077565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6110ee82610acd565b91506110f983610acd565b9250828203905081811115611111576111106110b7565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffd5b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061119257607f821691505b6020821081036111a5576111a461114e565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026112077fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826111cc565b61121186836111cc565b95508019841693508086168417925050509392505050565b5f819050919050565b5f61124c61124761124284610acd565b611229565b610acd565b9050919050565b5f819050919050565b61126583611232565b61127961127182611253565b8484546111d8565b825550505050565b5f5f905090565b611290611281565b61129b81848461125c565b505050565b5b818110156112be576112b35f82611288565b6001810190506112a1565b5050565b601f821115611303576112d4816111ab565b6112dd846111bd565b810160208510156112ec578190505b6113006112f8856111bd565b8301826112a0565b50505b505050565b5f82821c905092915050565b5f6113235f1984600802611308565b1980831691505092915050565b5f61133b8383611314565b9150826002028217905092915050565b61135482611144565b67ffffffffffffffff81111561136d5761136c610916565b5b611377825461117b565b6113828282856112c2565b5f60209050601f8311600181146113b3575f84156113a1578287015190505b6113ab8582611330565b865550611412565b601f1984166113c1866111ab565b5f5b828110156113e8578489015182556001820191506020850194506020810190506113c3565b868310156114055784890151611401601f891682611314565b8355505b6001600288020188555050505b505050505050565b7f696e76616c6964206164647265737300000000000000000000000000000000005f82015250565b5f61144e600f83610e9f565b91506114598261141a565b602082019050919050565b5f6020820190508181035f83015261147b81611442565b9050919050565b7f696e76616c6964206964000000000000000000000000000000000000000000005f82015250565b5f6114b6600a83610e9f565b91506114c182611482565b602082019050919050565b5f6020820190508181035f8301526114e3816114aa565b9050919050565b615f1a806114f75f395ff3fe608060405234801561000f575f5ffd5b50600436106100a7575f3560e01c8063ad36e6d01161006f578063ad36e6d014610115578063c130809a1461011f578063cc45662a14610129578063f2fde38b14610145578063f5f2d9f114610161578063ffd740df1461016b576100a7565b80633048bfba146100ab578063409900e8146100b55780634886f62c146100d15780636c0b61b9146100db57806375418b9d146100f7575b5f5ffd5b6100b3610187565b005b6100cf60048036038101906100ca91906139e2565b6102db565b005b6100d961037e565b005b6100f560048036038101906100f09190613a2b565b61082c565b005b6100ff610956565b60405161010c9190613f47565b60405180910390f35b61011d610a58565b005b610127610b7d565b005b610143600480360381019061013e919061401d565b610cd1565b005b61015f600480360381019061015a91906140c5565b61103b565b005b61016961110b565b005b6101856004803603810190610180919061411a565b61127a565b005b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610215576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161020c9061419f565b60405180910390fd5b61021f600961140e565b600a600881819054906101000a90046fffffffffffffffffffffffffffffffff168092919061024d906141ea565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507f8fb9cd054d0a022110cced239e908b834e4cd219511856d4eaae3051d932d604600a60089054906101000a90046fffffffffffffffffffffffffffffffff166040516102d19190614230565b60405180910390a1565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610369576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103609061419f565b60405180910390fd5b806001818161037891906143c4565b90505050565b6103923360056114c690919063ffffffff16565b600a600881819054906101000a90046fffffffffffffffffffffffffffffffff16809291906103c0906141ea565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507fa76a8fc1a90266ddee8937a18e12f01eade946b3b66197fff289af9277c2bd2533600a60089054906101000a90046fffffffffffffffffffffffffffffffff166040516104469291906143e1565b60405180910390a15f60056003015f9054906101000a900460ff1660ff161161082a575f5f90505b60055f01805490508110156104db576104ce60055f01828154811061049657610495614408565b5b905f5260205f20015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660026115e490919063ffffffff16565b808060010191505061046e565b505f5f90505b6005600101805490508110156107185761070b6005600101828154811061050b5761050a614408565b5b905f5260205f2090600302016040518060600160405290815f82015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160018201805480602002602001604051908101604052809291908181526020015f905b82821015610663578382905f5260205f2090600202016040518060400160405290815f82015481526020016001820180546105d490614462565b80601f016020809104026020016040519081016040528092919081815260200182805461060090614462565b801561064b5780601f106106225761010080835404028352916020019161064b565b820191905f5260205f20905b81548152906001019060200180831161062e57829003601f168201915b5050505050815250508152602001906001019061059a565b50505050815260200160028201805461067b90614462565b80601f01602080910402602001604051908101604052809291908181526020018280546106a790614462565b80156106f25780601f106106c9576101008083540402835291602001916106f2565b820191905f5260205f20905b8154815290600101906020018083116106d557829003601f168201915b505050505081525050600261187690919063ffffffff16565b80806001019150506104e1565b50600a5f81819054906101000a900467ffffffffffffffff168092919061073e90614492565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055505061076f6005611b03565b600a600881819054906101000a90046fffffffffffffffffffffffffffffffff168092919061079d906141ea565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507f11ce50160e66100537fd4b0ae26de66d51dab713ad92313353a18c24e8f6daab600a60089054906101000a90046fffffffffffffffffffffffffffffffff166040516108219190614230565b60405180910390a15b565b610840336002611bac90919063ffffffff16565b61087f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108769061450b565b60405180910390fd5b61089533826002611d049092919063ffffffff16565b600a600881819054906101000a90046fffffffffffffffffffffffffffffffff16809291906108c3906141ea565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507f6adfb896d3407681d05fb874d4dfb7068e6e2a36f09acd38a3b7d04c01745fee3382600a60089054906101000a90046fffffffffffffffffffffffffffffffff1660405161094b93929190614633565b60405180910390a150565b61095e613746565b6040518060a001604052806109736002611d96565b815260200161098f60025f016005611f9990919063ffffffff16565b815260200160096040518060200160405290815f82015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815250508152602001600a5f9054906101000a900467ffffffffffffffff1667ffffffffffffffff168152602001600a60089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff16815250905090565b610a6c336002611bac90919063ffffffff16565b610aab576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610aa29061450b565b60405180910390fd5b610abf33600961270090919063ffffffff16565b600a600881819054906101000a90046fffffffffffffffffffffffffffffffff1680929190610aed906141ea565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507ff91067eb420c28d3124865fc996e6aa9d541b9b4fef9188cb965a6cc6491638e33600a60089054906101000a90046fffffffffffffffffffffffffffffffff16604051610b739291906143e1565b60405180910390a1565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610c0b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c029061419f565b60405180910390fd5b610c156005612827565b600a600881819054906101000a90046fffffffffffffffffffffffffffffffff1680929190610c43906141ea565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507f9ce192aea5faf2151bbc246cd8918d2eba702fa26951f67f2bf7b3817e689d98600a60089054906101000a90046fffffffffffffffffffffffffffffffff16604051610cc79190614230565b60405180910390a1565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610d5f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d569061419f565b60405180910390fd5b610d69600961287b565b15610da9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610da0906146b9565b60405180910390fd5b5f5f90505b84849050811015610e4057610df4858583818110610dcf57610dce614408565b5b9050602002016020810190610de491906140c5565b6002611bac90919063ffffffff16565b610e33576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e2a90614721565b60405180910390fd5b8080600101915050610dae565b505f5f90505b82829050811015610f2557610e8f838383818110610e6757610e66614408565b5b9050602002810190610e79919061474b565b8060200190610e889190614772565b90506128d5565b610ed8838383818110610ea557610ea4614408565b5b9050602002810190610eb7919061474b565b5f016020810190610ec891906140c5565b6002611bac90919063ffffffff16565b15610f18576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f0f9061481e565b60405180910390fd5b8080600101915050610e46565b50610f548282905085859050610f3b6002612974565b610f45919061483c565b610f4f919061486f565b612995565b610f7360025f01858585856005612a339095949392919063ffffffff16565b600a600881819054906101000a90046fffffffffffffffffffffffffffffffff1680929190610fa1906141ea565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507f7e05e40117b6e18ab284c04a3508c3826422dc84a65e9c236a8248774416f8ac84848484600a60089054906101000a90046fffffffffffffffffffffffffffffffff1660405161102d959493929190614be8565b60405180910390a150505050565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146110c9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110c09061419f565b60405180910390fd5b805f5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b61111f336002611bac90919063ffffffff16565b61115e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111559061450b565b60405180910390fd5b6111686005612ed5565b156111a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161119f90614c79565b60405180910390fd5b6111bc336009612ef990919063ffffffff16565b600a600881819054906101000a90046fffffffffffffffffffffffffffffffff16809291906111ea906141ea565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507fbc2748cf02f7a1291525e866efc76ab3b96d32d7afcbb26c53daec617b38b47933600a60089054906101000a90046fffffffffffffffffffffffffffffffff166040516112709291906143e1565b60405180910390a1565b61128e336002611bac90919063ffffffff16565b6112cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112c49061450b565b60405180910390fd5b6112e33382600261303c9092919063ffffffff16565b60015f0160019054906101000a900460ff1660ff1661130c3360026130c590919063ffffffff16565b101561134d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161134490614ce1565b60405180910390fd5b600a600881819054906101000a90046fffffffffffffffffffffffffffffffff168092919061137b906141ea565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507fbd184de79f134b0f3da466d278f5417cbcb1450d72f1bd1a1b84f18b1bcd03ca3382600a60089054906101000a90046fffffffffffffffffffffffffffffffff1660405161140393929190614d0e565b60405180910390a150565b5f73ffffffffffffffffffffffffffffffffffffffff16815f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff160361149e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161149590614d8d565b60405180910390fd5b805f015f6101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905550565b816002015f8273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16611551576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161154890614df5565b60405180910390fd5b5f826002015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908315150217905550816003015f81819054906101000a900460ff16809291906115c790614e13565b91906101000a81548160ff021916908360ff160217905550505050565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611652576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161164990614e84565b60405180910390fd5b5f826001015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1690505f8160ff1614158061172057508173ffffffffffffffffffffffffffffffffffffffff16835f015f815481106116da576116d9614408565b5b905f5260205f2090600502015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b61175f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161175690614eec565b60405180910390fd5b826001015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81549060ff0219169055825f018160ff16815481106117c5576117c4614408565b5b905f5260205f2090600502015f5f82015f6101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600182015f5f82015f61180a91906137a1565b600282015f61181991906137c2565b5050600482015f61182a91906137e7565b50508260020181908060018154018082558091505060019003905f5260205f2090602091828204019190069091909190916101000a81548160ff021916908360ff160217905550505050565b61188382825f0151611bac565b156118c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118ba9061481e565b60405180910390fd5b5f5f8360020180549050111561195d5782600201600184600201805490506118eb919061483c565b815481106118fc576118fb614408565b5b905f5260205f2090602091828204019190069054906101000a900460ff169050826002018054806119305761192f614f0a565b5b600190038181905f5260205f2090602091828204019190066101000a81549060ff021916905590556119ce565b610100835f0180549050106119a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161199e90614f81565b60405180910390fd5b825f01805490509050825f0160018160018154018082558091505003905f5260205f209050505b80836001015f845f015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908360ff1602179055505f835f018260ff1681548110611a4157611a40614408565b5b905f5260205f2090600502019050825f0151815f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508260400151816004019081611aa89190615163565b505f5f90505b836020015151811015611afc57611aef84602001518281518110611ad557611ad4614408565b5b60200260200101518360010161314890919063ffffffff16565b8080600101915050611aae565b5050505050565b611b0c81612ed5565b611b4b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b429061527c565b60405180910390fd5b5f816003015f9054906101000a900460ff1660ff1614611ba0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b97906152e4565b60405180910390fd5b611ba9816133ce565b50565b5f5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611c1b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c1290614e84565b60405180910390fd5b5f835f01805490501115611cfa575f836001015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1660ff16141580611cf357508173ffffffffffffffffffffffffffffffffffffffff16835f015f81548110611cad57611cac614408565b5b905f5260205f2090600502015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b9050611cfe565b5f90505b92915050565b611d9181611d1190615460565b845f01856001015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1660ff1681548110611d7457611d73614408565b5b905f5260205f20906005020160010161314890919063ffffffff16565b505050565b611d9e613824565b5f825f018054905067ffffffffffffffff811115611dbf57611dbe614f9f565b5b604051908082528060200260200182016040528015611df857816020015b611de5613837565b815260200190600190039081611ddd5790505b5090505f5f90505b835f0180549050811015611f81576040518060600160405280855f018381548110611e2e57611e2d614408565b5b905f5260205f2090600502015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001611ea3865f018481548110611e8f57611e8e614408565b5b905f5260205f209060050201600101613401565b8152602001855f018381548110611ebd57611ebc614408565b5b905f5260205f2090600502016004018054611ed790614462565b80601f0160208091040260200160405190810160405280929190818152602001828054611f0390614462565b8015611f4e5780601f10611f2557610100808354040283529160200191611f4e565b820191905f5260205f20905b815481529060010190602001808311611f3157829003601f168201915b5050505050815250828281518110611f6957611f68614408565b5b60200260200101819052508080600101915050611e00565b50604051806020016040528082815250915050919050565b611fa161386d565b5f835f018054905067ffffffffffffffff811115611fc257611fc1614f9f565b5b604051908082528060200260200182016040528015611ff05781602001602082028036833780820191505090505b5090505f5f90505b845f018054905081101561209d57845f01818154811061201b5761201a614408565b5b905f5260205f20015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682828151811061205657612055614408565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508080600101915050611ff8565b505f846001018054905067ffffffffffffffff8111156120c0576120bf614f9f565b5b6040519080825280602002602001820160405280156120f957816020015b6120e6613837565b8152602001906001900390816120de5790505b5090505f5f90505b85600101805490508110156123415785600101818154811061212657612125614408565b5b905f5260205f2090600302016040518060600160405290815f82015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160018201805480602002602001604051908101604052809291908181526020015f905b8282101561227e578382905f5260205f2090600202016040518060400160405290815f82015481526020016001820180546121ef90614462565b80601f016020809104026020016040519081016040528092919081815260200182805461221b90614462565b80156122665780601f1061223d57610100808354040283529160200191612266565b820191905f5260205f20905b81548152906001019060200180831161224957829003601f168201915b505050505081525050815260200190600101906121b5565b50505050815260200160028201805461229690614462565b80601f01602080910402602001604051908101604052809291908181526020018280546122c290614462565b801561230d5780601f106122e45761010080835404028352916020019161230d565b820191905f5260205f20905b8154815290600101906020018083116122f057829003601f168201915b50505050508152505082828151811061232957612328614408565b5b60200260200101819052508080600101915050612101565b505f856003015f9054906101000a900460ff1660ff1667ffffffffffffffff8111156123705761236f614f9f565b5b60405190808252806020026020018201604052801561239e5781602001602082028036833780820191505090505b5090505f866003015f9054906101000a900460ff1660ff1611156126da575f5f5f90505b8680549050811015612581575f73ffffffffffffffffffffffffffffffffffffffff168782815481106123f8576123f7614408565b5b905f5260205f2090600502015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141580156124d25750876002015f88838154811061245d5761245c614408565b5b905f5260205f2090600502015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff165b15612574578681815481106124ea576124e9614408565b5b905f5260205f2090600502015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683838151811061252b5761252a614408565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050818061257090615472565b9250505b80806001019150506123c2565b505f5f90505b87600101805490508110156126d757876002015f8960010183815481106125b1576125b0614408565b5b905f5260205f2090600302015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16156126ca578760010181815481106126405761263f614408565b5b905f5260205f2090600302015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683838151811061268157612680614408565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505081806126c690615472565b9250505b8080600101915050612587565b50505b604051806060016040528084815260200183815260200182815250935050505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361276e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161276590614e84565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16825f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146127fe576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127f590614d8d565b60405180910390fd5b815f015f6101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690555050565b61283081612ed5565b61286f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016128669061527c565b60405180910390fd5b612878816133ce565b50565b5f5f73ffffffffffffffffffffffffffffffffffffffff16825f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614159050919050565b60015f0160019054906101000a900460ff1660ff1681101561292c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161292390614ce1565b60405180910390fd5b610100811115612971576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161296890615503565b60405180910390fd5b50565b5f8160020180549050825f018054905061298e919061483c565b9050919050565b60015f015f9054906101000a900460ff1660ff168110156129eb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129e29061556b565b60405180910390fd5b610100811115612a30576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a2790614f81565b60405180910390fd5b50565b612a3c86612ed5565b15612a7c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a73906155d3565b60405180910390fd5b5f848490501180612a8f57505f82829050115b612ace576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612ac59061563b565b60405180910390fd5b5f5f90505b8580549050811015612c30575f73ffffffffffffffffffffffffffffffffffffffff16868281548110612b0957612b08614408565b5b905f5260205f2090600502015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612c23576001876002015f888481548110612b6c57612b6b614408565b5b905f5260205f2090600502015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908315150217905550866003015f81819054906101000a900460ff1680929190612c0990615659565b91906101000a81548160ff021916908360ff160217905550505b8080600101915050612ad3565b505f5f90505b84849050811015612d8c57865f01858583818110612c5757612c56614408565b5b9050602002016020810190612c6c91906140c5565b908060018154018082558091505060019003905f5260205f20015f9091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505f876002015f878785818110612ce257612ce1614408565b5b9050602002016020810190612cf791906140c5565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908315150217905550866003015f81819054906101000a900460ff1680929190612d6690614e13565b91906101000a81548160ff021916908360ff160217905550508080600101915050612c36565b505f5f90505b82829050811015612ecc5786600101838383818110612db457612db3614408565b5b9050602002810190612dc6919061474b565b908060018154018082558091505060019003905f5260205f2090600302015f909190919091508181612df89190615d9e565b50506001876002015f858585818110612e1457612e13614408565b5b9050602002810190612e26919061474b565b5f016020810190612e3791906140c5565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908315150217905550866003015f81819054906101000a900460ff1680929190612ea690615659565b91906101000a81548160ff021916908360ff160217905550508080600101915050612d92565b50505050505050565b5f5f825f0180549050141580612ef257505f826001018054905014155b9050919050565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612f67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612f5e90614e84565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff16825f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612ff7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612fee90615df6565b60405180910390fd5b80825f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b6130c081845f01856001015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1660ff16815481106130a3576130a2614408565b5b905f5260205f2090600502016001016135c790919063ffffffff16565b505050565b5f613140835f01846001015f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1660ff168154811061312c5761312b614408565b5b905f5260205f209060050201600101613725565b905092915050565b5f815f01510361318d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161318490615e5e565b60405180910390fd5b5f5f835f0180549050111561324a57826001015f835f015181526020019081526020015f205f9054906101000a900460ff1690505f8160ff161415806131f85750815f0151835f015f815481106131e7576131e6614408565b5b905f5260205f2090600202015f0154145b156132495781835f018260ff168154811061321657613215614408565b5b905f5260205f2090600202015f820151815f0155602082015181600101908161323f9190615163565b50905050506133ca565b5b5f836002018054905011156132e3578260020160018460020180549050613271919061483c565b8154811061328257613281614408565b5b905f5260205f2090602091828204019190069054906101000a900460ff169050826002018054806132b6576132b5614f0a565b5b600190038181905f5260205f2090602091828204019190066101000a81549060ff02191690559055613354565b610100835f01805490501061332d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161332490615503565b60405180910390fd5b825f01805490509050825f0160018160018154018082558091505003905f5260205f209050505b80836001015f845f015181526020019081526020015f205f6101000a81548160ff021916908360ff16021790555081835f018260ff168154811061339b5761339a614408565b5b905f5260205f2090600202015f820151815f015560208201518160010190816133c49190615163565b50905050505b5050565b805f015f6133dc919061388e565b806001015f6133eb91906138ac565b806003015f6101000a81549060ff021916905550565b60605f61340d83613725565b67ffffffffffffffff81111561342657613425614f9f565b5b60405190808252806020026020018201604052801561345f57816020015b61344c6138cd565b8152602001906001900390816134445790505b5090505f5f5f90505b845f01805490508110156135bc575f855f01828154811061348c5761348b614408565b5b905f5260205f2090600202015f0154146135af576040518060400160405280865f0183815481106134c0576134bf614408565b5b905f5260205f2090600202015f01548152602001865f0183815481106134e9576134e8614408565b5b905f5260205f209060020201600101805461350390614462565b80601f016020809104026020016040519081016040528092919081815260200182805461352f90614462565b801561357a5780601f106135515761010080835404028352916020019161357a565b820191905f5260205f20905b81548152906001019060200180831161355d57829003601f168201915b505050505081525083838151811061359557613594614408565b5b602002602001018190525081806135ab90615472565b9250505b8080600101915050613468565b508192505050919050565b5f8103613609576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161360090615e5e565b60405180910390fd5b5f826001015f8381526020019081526020015f205f9054906101000a900460ff1690505f8160ff16141580613660575081835f015f8154811061364f5761364e614408565b5b905f5260205f2090600202015f0154145b61369f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161369690615ec6565b60405180910390fd5b825f018160ff16815481106136b7576136b6614408565b5b905f5260205f2090600202015f5f82015f9055600182015f6136d991906137e7565b50508260020181908060018154018082558091505060019003905f5260205f2090602091828204019190069091909190916101000a81548160ff021916908360ff160217905550505050565b5f8160020180549050825f018054905061373f919061483c565b9050919050565b6040518060a00160405280613759613824565b815260200161376661386d565b81526020016137736138e6565b81526020015f67ffffffffffffffff1681526020015f6fffffffffffffffffffffffffffffffff1681525090565b5080545f8255600202905f5260205f20908101906137bf919061390e565b50565b5080545f8255601f0160209004905f5260205f20908101906137e4919061393a565b50565b5080546137f390614462565b5f825580601f106138045750613821565b601f0160209004905f5260205f2090810190613820919061393a565b5b50565b6040518060200160405280606081525090565b60405180606001604052805f73ffffffffffffffffffffffffffffffffffffffff16815260200160608152602001606081525090565b60405180606001604052806060815260200160608152602001606081525090565b5080545f8255905f5260205f20908101906138a9919061393a565b50565b5080545f8255600302905f5260205f20908101906138ca9190613955565b50565b60405180604001604052805f8152602001606081525090565b60405180602001604052805f73ffffffffffffffffffffffffffffffffffffffff1681525090565b5b80821115613936575f5f82015f9055600182015f61392d91906137e7565b5060020161390f565b5090565b5b80821115613951575f815f90555060010161393b565b5090565b5b808211156139ab575f5f82015f6101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600182015f61399391906137a1565b600282015f6139a291906137e7565b50600301613956565b5090565b5f604051905090565b5f5ffd5b5f5ffd5b5f5ffd5b5f604082840312156139d9576139d86139c0565b5b81905092915050565b5f604082840312156139f7576139f66139b8565b5b5f613a04848285016139c4565b91505092915050565b5f60408284031215613a2257613a216139c0565b5b81905092915050565b5f60208284031215613a4057613a3f6139b8565b5b5f82013567ffffffffffffffff811115613a5d57613a5c6139bc565b5b613a6984828501613a0d565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f613ac482613a9b565b9050919050565b613ad481613aba565b82525050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f819050919050565b613b1581613b03565b82525050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f613b5d82613b1b565b613b678185613b25565b9350613b77818560208601613b35565b613b8081613b43565b840191505092915050565b5f604083015f830151613ba05f860182613b0c565b5060208301518482036020860152613bb88282613b53565b9150508091505092915050565b5f613bd08383613b8b565b905092915050565b5f602082019050919050565b5f613bee82613ada565b613bf88185613ae4565b935083602082028501613c0a85613af4565b805f5b85811015613c455784840389528151613c268582613bc5565b9450613c3183613bd8565b925060208a01995050600181019050613c0d565b50829750879550505050505092915050565b5f606083015f830151613c6c5f860182613acb565b5060208301518482036020860152613c848282613be4565b91505060408301518482036040860152613c9e8282613b53565b9150508091505092915050565b5f613cb68383613c57565b905092915050565b5f602082019050919050565b5f613cd482613a72565b613cde8185613a7c565b935083602082028501613cf085613a8c565b805f5b85811015613d2b5784840389528151613d0c8582613cab565b9450613d1783613cbe565b925060208a01995050600181019050613cf3565b50829750879550505050505092915050565b5f602083015f8301518482035f860152613d578282613cca565b9150508091505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f613d988383613acb565b60208301905092915050565b5f602082019050919050565b5f613dba82613d64565b613dc48185613d6e565b9350613dcf83613d7e565b805f5b83811015613dff578151613de68882613d8d565b9750613df183613da4565b925050600181019050613dd2565b5085935050505092915050565b5f606083015f8301518482035f860152613e268282613db0565b91505060208301518482036020860152613e408282613cca565b91505060408301518482036040860152613e5a8282613db0565b9150508091505092915050565b602082015f820151613e7b5f850182613acb565b50505050565b5f67ffffffffffffffff82169050919050565b613e9d81613e81565b82525050565b5f6fffffffffffffffffffffffffffffffff82169050919050565b613ec781613ea3565b82525050565b5f60a083015f8301518482035f860152613ee78282613d3d565b91505060208301518482036020860152613f018282613e0c565b9150506040830151613f166040860182613e67565b506060830151613f296060860182613e94565b506080830151613f3c6080860182613ebe565b508091505092915050565b5f6020820190508181035f830152613f5f8184613ecd565b905092915050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f83601f840112613f8857613f87613f67565b5b8235905067ffffffffffffffff811115613fa557613fa4613f6b565b5b602083019150836020820283011115613fc157613fc0613f6f565b5b9250929050565b5f5f83601f840112613fdd57613fdc613f67565b5b8235905067ffffffffffffffff811115613ffa57613ff9613f6b565b5b60208301915083602082028301111561401657614015613f6f565b5b9250929050565b5f5f5f5f60408587031215614035576140346139b8565b5b5f85013567ffffffffffffffff811115614052576140516139bc565b5b61405e87828801613f73565b9450945050602085013567ffffffffffffffff811115614081576140806139bc565b5b61408d87828801613fc8565b925092505092959194509250565b6140a481613aba565b81146140ae575f5ffd5b50565b5f813590506140bf8161409b565b92915050565b5f602082840312156140da576140d96139b8565b5b5f6140e7848285016140b1565b91505092915050565b6140f981613b03565b8114614103575f5ffd5b50565b5f81359050614114816140f0565b92915050565b5f6020828403121561412f5761412e6139b8565b5b5f61413c84828501614106565b91505092915050565b5f82825260208201905092915050565b7f6e6f7420746865206f776e6572000000000000000000000000000000000000005f82015250565b5f614189600d83614145565b915061419482614155565b602082019050919050565b5f6020820190508181035f8301526141b68161417d565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6141f482613ea3565b91506fffffffffffffffffffffffffffffffff8203614216576142156141bd565b5b600182019050919050565b61422a81613ea3565b82525050565b5f6020820190506142435f830184614221565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b5f60ff82169050919050565b61428a81614275565b8114614294575f5ffd5b50565b5f81356142a381614281565b80915050919050565b5f815f1b9050919050565b5f60ff6142c3846142ac565b9350801983169250808416831791505092915050565b5f819050919050565b5f6142fc6142f76142f284614275565b6142d9565b614275565b9050919050565b5f819050919050565b614315826142e2565b61432861432182614303565b83546142b7565b8255505050565b5f8160081b9050919050565b5f61ff006143488461432f565b9350801983169250808416831791505092915050565b614367826142e2565b61437a61437382614303565b835461433b565b8255505050565b5f81015f83018061439181614297565b905061439d818461430c565b5050505f810160208301806143b181614297565b90506143bd818461435e565b5050505050565b6143ce8282614381565b5050565b6143db81613aba565b82525050565b5f6040820190506143f45f8301856143d2565b6144016020830184614221565b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061447957607f821691505b60208210810361448c5761448b614435565b5b50919050565b5f61449c82613e81565b915067ffffffffffffffff82036144b6576144b56141bd565b5b600182019050919050565b7f6e6f7420616e206f70657261746f7200000000000000000000000000000000005f82015250565b5f6144f5600f83614145565b9150614500826144c1565b602082019050919050565b5f6020820190508181035f830152614522816144e9565b9050919050565b5f6145376020840184614106565b905092915050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f8335600160200384360303811261456757614566614547565b5b83810192508235915060208301925067ffffffffffffffff82111561458f5761458e61453f565b5b6001820236038313156145a5576145a4614543565b5b509250929050565b828183375f83830152505050565b5f6145c68385613b25565b93506145d38385846145ad565b6145dc83613b43565b840190509392505050565b5f604083016145f85f840184614529565b6146045f860182613b0c565b50614612602084018461454b565b85830360208701526146258382846145bb565b925050508091505092915050565b5f6060820190506146465f8301866143d2565b818103602083015261465881856145e7565b90506146676040830184614221565b949350505050565b7f6d61696e74656e616e636520696e2070726f67726573730000000000000000005f82015250565b5f6146a3601783614145565b91506146ae8261466f565b602082019050919050565b5f6020820190508181035f8301526146d081614697565b9050919050565b7f756e6b6e6f776e206f70657261746f72000000000000000000000000000000005f82015250565b5f61470b601083614145565b9150614716826146d7565b602082019050919050565b5f6020820190508181035f830152614738816146ff565b9050919050565b5f5ffd5b5f5ffd5b5f5ffd5b5f823560016060038336030381126147665761476561473f565b5b80830191505092915050565b5f5f8335600160200384360303811261478e5761478d61473f565b5b80840192508235915067ffffffffffffffff8211156147b0576147af614743565b5b6020830192506020820236038313156147cc576147cb614747565b5b509250929050565b7f6f70657261746f7220616c7265616479206578697374730000000000000000005f82015250565b5f614808601783614145565b9150614813826147d4565b602082019050919050565b5f6020820190508181035f830152614835816147fc565b9050919050565b5f61484682613b03565b915061485183613b03565b9250828203905081811115614869576148686141bd565b5b92915050565b5f61487982613b03565b915061488483613b03565b925082820190508082111561489c5761489b6141bd565b5b92915050565b5f82825260208201905092915050565b5f819050919050565b5f6148c960208401846140b1565b905092915050565b5f602082019050919050565b5f6148e883856148a2565b93506148f3826148b2565b805f5b8581101561492b5761490882846148bb565b6149128882613d8d565b975061491d836148d1565b9250506001810190506148f6565b5085925050509392505050565b5f82825260208201905092915050565b5f819050919050565b5f5f8335600160200384360303811261496d5761496c614547565b5b83810192508235915060208301925067ffffffffffffffff8211156149955761499461453f565b5b6020820236038313156149ab576149aa614543565b5b509250929050565b5f819050919050565b5f604083016149cd5f840184614529565b6149d95f860182613b0c565b506149e7602084018461454b565b85830360208701526149fa8382846145bb565b925050508091505092915050565b5f614a1383836149bc565b905092915050565b5f82356001604003833603038112614a3657614a35614547565b5b82810191505092915050565b5f602082019050919050565b5f614a598385613ae4565b935083602084028501614a6b846149b3565b805f5b87811015614aae578484038952614a858284614a1b565b614a8f8582614a08565b9450614a9a83614a42565b925060208a01995050600181019050614a6e565b50829750879450505050509392505050565b5f60608301614ad15f8401846148bb565b614add5f860182613acb565b50614aeb6020840184614951565b8583036020870152614afe838284614a4e565b92505050614b0f604084018461454b565b8583036040870152614b228382846145bb565b925050508091505092915050565b5f614b3b8383614ac0565b905092915050565b5f82356001606003833603038112614b5e57614b5d614547565b5b82810191505092915050565b5f602082019050919050565b5f614b818385614938565b935083602084028501614b9384614948565b805f5b87811015614bd6578484038952614bad8284614b43565b614bb78582614b30565b9450614bc283614b6a565b925060208a01995050600181019050614b96565b50829750879450505050509392505050565b5f6060820190508181035f830152614c018187896148dd565b90508181036020830152614c16818587614b76565b9050614c256040830184614221565b9695505050505050565b7f6d6967726174696f6e20696e2070726f677265737300000000000000000000005f82015250565b5f614c63601583614145565b9150614c6e82614c2f565b602082019050919050565b5f6020820190508181035f830152614c9081614c57565b9050919050565b7f746f6f20666577206e6f646573000000000000000000000000000000000000005f82015250565b5f614ccb600d83614145565b9150614cd682614c97565b602082019050919050565b5f6020820190508181035f830152614cf881614cbf565b9050919050565b614d0881613b03565b82525050565b5f606082019050614d215f8301866143d2565b614d2e6020830185614cff565b614d3b6040830184614221565b949350505050565b7f6e6f7420756e646572206d61696e74656e616e636500000000000000000000005f82015250565b5f614d77601583614145565b9150614d8282614d43565b602082019050919050565b5f6020820190508181035f830152614da481614d6b565b9050919050565b7f6e6f742070756c6c696e670000000000000000000000000000000000000000005f82015250565b5f614ddf600b83614145565b9150614dea82614dab565b602082019050919050565b5f6020820190508181035f830152614e0c81614dd3565b9050919050565b5f614e1d82614275565b91505f8203614e2f57614e2e6141bd565b5b600182039050919050565b7f696e76616c6964206164647265737300000000000000000000000000000000005f82015250565b5f614e6e600f83614145565b9150614e7982614e3a565b602082019050919050565b5f6020820190508181035f830152614e9b81614e62565b9050919050565b7f6f70657261746f7220646f65736e2774206578697374000000000000000000005f82015250565b5f614ed6601683614145565b9150614ee182614ea2565b602082019050919050565b5f6020820190508181035f830152614f0381614eca565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffd5b7f746f6f206d616e79206f70657261746f727300000000000000000000000000005f82015250565b5f614f6b601283614145565b9150614f7682614f37565b602082019050919050565b5f6020820190508181035f830152614f9881614f5f565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026150287fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82614fed565b6150328683614fed565b95508019841693508086168417925050509392505050565b5f61506461505f61505a84613b03565b6142d9565b613b03565b9050919050565b5f819050919050565b61507d8361504a565b6150916150898261506b565b848454614ff9565b825550505050565b5f5f905090565b6150a8615099565b6150b3818484615074565b505050565b5b818110156150d6576150cb5f826150a0565b6001810190506150b9565b5050565b601f82111561511b576150ec81614fcc565b6150f584614fde565b81016020851015615104578190505b61511861511085614fde565b8301826150b8565b50505b505050565b5f82821c905092915050565b5f61513b5f1984600802615120565b1980831691505092915050565b5f615153838361512c565b9150826002028217905092915050565b61516c82613b1b565b67ffffffffffffffff81111561518557615184614f9f565b5b61518f8254614462565b61519a8282856150da565b5f60209050601f8311600181146151cb575f84156151b9578287015190505b6151c38582615148565b86555061522a565b601f1984166151d986614fcc565b5f5b82811015615200578489015182556001820191506020850194506020810190506151db565b8683101561521d5784890151615219601f89168261512c565b8355505b6001600288020188555050505b505050505050565b7f6e6f7420696e2070726f677265737300000000000000000000000000000000005f82015250565b5f615266600f83614145565b915061527182615232565b602082019050919050565b5f6020820190508181035f8301526152938161525a565b9050919050565b7f646174612070756c6c20696e2070726f677265737300000000000000000000005f82015250565b5f6152ce601583614145565b91506152d98261529a565b602082019050919050565b5f6020820190508181035f8301526152fb816152c2565b9050919050565b5f5ffd5b61530f82613b43565b810181811067ffffffffffffffff8211171561532e5761532d614f9f565b5b80604052505050565b5f6153406139af565b905061534c8282615306565b919050565b5f5ffd5b5f5ffd5b5f67ffffffffffffffff82111561537357615372614f9f565b5b61537c82613b43565b9050602081019050919050565b5f61539b61539684615359565b615337565b9050828152602081018484840111156153b7576153b6615355565b5b6153c28482856145ad565b509392505050565b5f82601f8301126153de576153dd613f67565b5b81356153ee848260208601615389565b91505092915050565b5f6040828403121561540c5761540b615302565b5b6154166040615337565b90505f61542584828501614106565b5f83015250602082013567ffffffffffffffff81111561544857615447615351565b5b615454848285016153ca565b60208301525092915050565b5f61546b36836153f7565b9050919050565b5f61547c82613b03565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036154ae576154ad6141bd565b5b600182019050919050565b7f746f6f206d616e79206e6f6465730000000000000000000000000000000000005f82015250565b5f6154ed600e83614145565b91506154f8826154b9565b602082019050919050565b5f6020820190508181035f83015261551a816154e1565b9050919050565b7f746f6f20666577206f70657261746f72730000000000000000000000000000005f82015250565b5f615555601183614145565b915061556082615521565b602082019050919050565b5f6020820190508181035f83015261558281615549565b9050919050565b7f6d6967726174696f6e20616c726561647920696e2070726f67726573730000005f82015250565b5f6155bd601d83614145565b91506155c882615589565b602082019050919050565b5f6020820190508181035f8301526155ea816155b1565b9050919050565b7f6e6f7468696e6720746f20646f000000000000000000000000000000000000005f82015250565b5f615625600d83614145565b9150615630826155f1565b602082019050919050565b5f6020820190508181035f83015261565281615619565b9050919050565b5f61566382614275565b915060ff8203615676576156756141bd565b5b600182019050919050565b5f813561568d8161409b565b80915050919050565b5f73ffffffffffffffffffffffffffffffffffffffff6156b5846142ac565b9350801983169250808416831791505092915050565b5f6156e56156e06156db84613a9b565b6142d9565b613a9b565b9050919050565b5f6156f6826156cb565b9050919050565b5f615707826156ec565b9050919050565b5f819050919050565b615720826156fd565b61573361572c8261570e565b8354615696565b8255505050565b5f823560016040038336030381126157555761575461473f565b5b80830191505092915050565b5f81549050919050565b5f61577582613b03565b915061578083613b03565b925082820261578e81613b03565b915082820484148315176157a5576157a46141bd565b5b5092915050565b5f8190506157bb82600261576b565b9050919050565b5f819050815f5260205f209050919050565b6158047fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83602003600802615120565b815481168255505050565b61581881614fcc565b615823838254615148565b8083555f825550505050565b602084105f811461588957601f841160018114615857576158508685615148565b8355615883565b61586083614fcc565b61587761586c87614fde565b8201600183016150b8565b615881878561580f565b505b506158d6565b61589282614fcc565b61589b86614fde565b8101601f871680156158b5576158b481600184036157d4565b5b6158c96158c188614fde565b8401836150b8565b6001886002021785555050505b5050505050565b680100000000000000008411156158f7576158f6614f9f565b5b602083105f811461594057602085105f811461591e576159178685615148565b835561593a565b8360ff191693508361592f84614fcc565b556001866002020183555b5061594a565b6001856002020182555b5050505050565b805461595c81614462565b8084111561597157615970848284866158dd565b5b80841015615986576159858482848661582f565b5b50505050565b818110156159a95761599e5f826150a0565b60018101905061598c565b5050565b6159b75f82615951565b50565b5f82146159ca576159c9614249565b5b6159d3816159ad565b5050565b6159e35f5f83016150a0565b6159f05f600183016159ba565b50565b5f8214615a0357615a02614249565b5b615a0c816159d7565b5050565b5b81811015615a2e57615a235f826159f3565b600281019050615a11565b5050565b81831015615a6b57615a43826157ac565b615a4c846157ac565b615a55836157c2565b818101838201615a658183615a10565b50505050505b505050565b68010000000000000000821115615a8a57615a89614f9f565b5b615a9381615761565b828255615aa1838284615a32565b505050565b5f82905092915050565b5f8135615abc816140f0565b80915050919050565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff615af0846142ac565b9350801983169250808416831791505092915050565b615b0f8261504a565b615b22615b1b8261506b565b8354615ac5565b8255505050565b5f5f83356001602003843603038112615b4557615b4461473f565b5b80840192508235915067ffffffffffffffff821115615b6757615b66614743565b5b602083019250600182023603831315615b8357615b82614747565b5b509250929050565b5f82905092915050565b615b9f8383615b8b565b67ffffffffffffffff811115615bb857615bb7614f9f565b5b615bc28254614462565b615bcd8282856150da565b5f601f831160018114615bfa575f8415615be8578287013590505b615bf28582615148565b865550615c59565b601f198416615c0886614fcc565b5f5b82811015615c2f57848901358255600182019150602085019450602081019050615c0a565b86831015615c4c5784890135615c48601f89168261512c565b8355505b6001600288020188555050505b50505050505050565b615c6d838383615b95565b505050565b5f81015f830180615c8281615ab0565b9050615c8e8184615b06565b5050506001810160208301615ca38185615b29565b615cae818386615c62565b505050505050565b615cc08282615c72565b5050565b615cce8383615aa6565b615cd88183615a70565b615ce1836149b3565b615cea836157c2565b5f5b83811015615d2057615cfe838761573a565b615d088184615cb6565b60208401935060028301925050600181019050615cec565b50505050505050565b615d34838383615cc4565b505050565b5f81015f830180615d4981615681565b9050615d558184615717565b5050506001810160208301615d6a8185614772565b615d75818386615d29565b505050506002810160408301615d8b8185615b29565b615d96818386615c62565b505050505050565b615da88282615d39565b5050565b7f616e6f74686572206d61696e74656e616e636520696e2070726f6772657373005f82015250565b5f615de0601f83614145565b9150615deb82615dac565b602082019050919050565b5f6020820190508181035f830152615e0d81615dd4565b9050919050565b7f696e76616c6964206964000000000000000000000000000000000000000000005f82015250565b5f615e48600a83614145565b9150615e5382615e14565b602082019050919050565b5f6020820190508181035f830152615e7581615e3c565b9050919050565b7f6e6f646520646f65736e277420657869737400000000000000000000000000005f82015250565b5f615eb0601283614145565b9150615ebb82615e7c565b602082019050919050565b5f6020820190508181035f830152615edd81615ea4565b905091905056fea26469706673582212205ec0504f700c355842dfb4a4d399a8e48b0ca02d4766027c3ae5b1d4f339375864736f6c634300081c0033 - /// ``` - #[rustfmt::skip] - #[allow(clippy::all)] - pub static BYTECODE: alloy_sol_types::private::Bytes = alloy_sol_types::private::Bytes::from_static( - b"`\x80`@R4\x80\x15a\0\x0FW__\xFD[P`@Qat\x118\x03\x80at\x11\x839\x81\x81\x01`@R\x81\x01\x90a\x001\x91\x90a\x0E\x18V[3__a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UP\x81`\x01_\x82\x01Q\x81_\x01_a\x01\0\n\x81T\x81`\xFF\x02\x19\x16\x90\x83`\xFF\x16\x02\x17\x90UP` \x82\x01Q\x81_\x01`\x01a\x01\0\n\x81T\x81`\xFF\x02\x19\x16\x90\x83`\xFF\x16\x02\x17\x90UP\x90PPa\0\xC4\x81Qa\x01C` \x1B` \x1CV[__\x90P[\x81Q\x81\x10\x15a\x01;Wa\x01\0\x82\x82\x81Q\x81\x10a\0\xE8Wa\0\xE7a\x0ErV[[` \x02` \x01\x01Q` \x01QQa\x01\xE1` \x1B` \x1CV[a\x01.\x82\x82\x81Q\x81\x10a\x01\x16Wa\x01\x15a\x0ErV[[` \x02` \x01\x01Q`\x02a\x02\x80` \x1B\x90\x91\x90` \x1CV[\x80\x80`\x01\x01\x91PPa\0\xC9V[PPPa\x14\xEAV[`\x01_\x01_\x90T\x90a\x01\0\n\x90\x04`\xFF\x16`\xFF\x16\x81\x10\x15a\x01\x99W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x01\x90\x90a\x0E\xF9V[`@Q\x80\x91\x03\x90\xFD[a\x01\0\x81\x11\x15a\x01\xDEW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x01\xD5\x90a\x0FaV[`@Q\x80\x91\x03\x90\xFD[PV[`\x01_\x01`\x01\x90T\x90a\x01\0\n\x90\x04`\xFF\x16`\xFF\x16\x81\x10\x15a\x028W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x02/\x90a\x0F\xC9V[`@Q\x80\x91\x03\x90\xFD[a\x01\0\x81\x11\x15a\x02}W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x02t\x90a\x101V[`@Q\x80\x91\x03\x90\xFD[PV[a\x02\x93\x82\x82_\x01Qa\x05\x13` \x1B` \x1CV[\x15a\x02\xD3W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x02\xCA\x90a\x10\x99V[`@Q\x80\x91\x03\x90\xFD[__\x83`\x02\x01\x80T\x90P\x11\x15a\x03mW\x82`\x02\x01`\x01\x84`\x02\x01\x80T\x90Pa\x02\xFB\x91\x90a\x10\xE4V[\x81T\x81\x10a\x03\x0CWa\x03\x0Ba\x0ErV[[\x90_R` _ \x90` \x91\x82\x82\x04\x01\x91\x90\x06\x90T\x90a\x01\0\n\x90\x04`\xFF\x16\x90P\x82`\x02\x01\x80T\x80a\x03@Wa\x03?a\x11\x17V[[`\x01\x90\x03\x81\x81\x90_R` _ \x90` \x91\x82\x82\x04\x01\x91\x90\x06a\x01\0\n\x81T\x90`\xFF\x02\x19\x16\x90U\x90Ua\x03\xDEV[a\x01\0\x83_\x01\x80T\x90P\x10a\x03\xB7W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x03\xAE\x90a\x0FaV[`@Q\x80\x91\x03\x90\xFD[\x82_\x01\x80T\x90P\x90P\x82_\x01`\x01\x81`\x01\x81T\x01\x80\x82U\x80\x91PP\x03\x90_R` _ \x90PP[\x80\x83`\x01\x01_\x84_\x01Qs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ _a\x01\0\n\x81T\x81`\xFF\x02\x19\x16\x90\x83`\xFF\x16\x02\x17\x90UP_\x83_\x01\x82`\xFF\x16\x81T\x81\x10a\x04QWa\x04Pa\x0ErV[[\x90_R` _ \x90`\x05\x02\x01\x90P\x82_\x01Q\x81_\x01_a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UP\x82`@\x01Q\x81`\x04\x01\x90\x81a\x04\xB8\x91\x90a\x13KV[P__\x90P[\x83` \x01QQ\x81\x10\x15a\x05\x0CWa\x04\xFF\x84` \x01Q\x82\x81Q\x81\x10a\x04\xE5Wa\x04\xE4a\x0ErV[[` \x02` \x01\x01Q\x83`\x01\x01a\x06k` \x1B\x90\x91\x90` \x1CV[\x80\x80`\x01\x01\x91PPa\x04\xBEV[PPPPPV[__s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x82s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x03a\x05\x82W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x05y\x90a\x14dV[`@Q\x80\x91\x03\x90\xFD[_\x83_\x01\x80T\x90P\x11\x15a\x06aW_\x83`\x01\x01_\x84s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ _\x90T\x90a\x01\0\n\x90\x04`\xFF\x16`\xFF\x16\x14\x15\x80a\x06ZWP\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x83_\x01_\x81T\x81\x10a\x06\x14Wa\x06\x13a\x0ErV[[\x90_R` _ \x90`\x05\x02\x01_\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14[\x90Pa\x06eV[_\x90P[\x92\x91PPV[_\x81_\x01Q\x03a\x06\xB0W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x06\xA7\x90a\x14\xCCV[`@Q\x80\x91\x03\x90\xFD[__\x83_\x01\x80T\x90P\x11\x15a\x07mW\x82`\x01\x01_\x83_\x01Q\x81R` \x01\x90\x81R` \x01_ _\x90T\x90a\x01\0\n\x90\x04`\xFF\x16\x90P_\x81`\xFF\x16\x14\x15\x80a\x07\x1BWP\x81_\x01Q\x83_\x01_\x81T\x81\x10a\x07\nWa\x07\ta\x0ErV[[\x90_R` _ \x90`\x02\x02\x01_\x01T\x14[\x15a\x07lW\x81\x83_\x01\x82`\xFF\x16\x81T\x81\x10a\x079Wa\x078a\x0ErV[[\x90_R` _ \x90`\x02\x02\x01_\x82\x01Q\x81_\x01U` \x82\x01Q\x81`\x01\x01\x90\x81a\x07b\x91\x90a\x13KV[P\x90PPPa\x08\xEDV[[_\x83`\x02\x01\x80T\x90P\x11\x15a\x08\x06W\x82`\x02\x01`\x01\x84`\x02\x01\x80T\x90Pa\x07\x94\x91\x90a\x10\xE4V[\x81T\x81\x10a\x07\xA5Wa\x07\xA4a\x0ErV[[\x90_R` _ \x90` \x91\x82\x82\x04\x01\x91\x90\x06\x90T\x90a\x01\0\n\x90\x04`\xFF\x16\x90P\x82`\x02\x01\x80T\x80a\x07\xD9Wa\x07\xD8a\x11\x17V[[`\x01\x90\x03\x81\x81\x90_R` _ \x90` \x91\x82\x82\x04\x01\x91\x90\x06a\x01\0\n\x81T\x90`\xFF\x02\x19\x16\x90U\x90Ua\x08wV[a\x01\0\x83_\x01\x80T\x90P\x10a\x08PW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x08G\x90a\x101V[`@Q\x80\x91\x03\x90\xFD[\x82_\x01\x80T\x90P\x90P\x82_\x01`\x01\x81`\x01\x81T\x01\x80\x82U\x80\x91PP\x03\x90_R` _ \x90PP[\x80\x83`\x01\x01_\x84_\x01Q\x81R` \x01\x90\x81R` \x01_ _a\x01\0\n\x81T\x81`\xFF\x02\x19\x16\x90\x83`\xFF\x16\x02\x17\x90UP\x81\x83_\x01\x82`\xFF\x16\x81T\x81\x10a\x08\xBEWa\x08\xBDa\x0ErV[[\x90_R` _ \x90`\x02\x02\x01_\x82\x01Q\x81_\x01U` \x82\x01Q\x81`\x01\x01\x90\x81a\x08\xE7\x91\x90a\x13KV[P\x90PPP[PPV[_`@Q\x90P\x90V[__\xFD[__\xFD[__\xFD[_`\x1F\x19`\x1F\x83\x01\x16\x90P\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`A`\x04R`$_\xFD[a\tL\x82a\t\x06V[\x81\x01\x81\x81\x10g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x17\x15a\tkWa\tja\t\x16V[[\x80`@RPPPV[_a\t}a\x08\xF1V[\x90Pa\t\x89\x82\x82a\tCV[\x91\x90PV[__\xFD[_`\xFF\x82\x16\x90P\x91\x90PV[a\t\xA7\x81a\t\x92V[\x81\x14a\t\xB1W__\xFD[PV[_\x81Q\x90Pa\t\xC2\x81a\t\x9EV[\x92\x91PPV[_`@\x82\x84\x03\x12\x15a\t\xDDWa\t\xDCa\t\x02V[[a\t\xE7`@a\ttV[\x90P_a\t\xF6\x84\x82\x85\x01a\t\xB4V[_\x83\x01RP` a\n\t\x84\x82\x85\x01a\t\xB4V[` \x83\x01RP\x92\x91PPV[__\xFD[_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15a\n3Wa\n2a\t\x16V[[` \x82\x02\x90P` \x81\x01\x90P\x91\x90PV[__\xFD[_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[_a\nq\x82a\nHV[\x90P\x91\x90PV[a\n\x81\x81a\ngV[\x81\x14a\n\x8BW__\xFD[PV[_\x81Q\x90Pa\n\x9C\x81a\nxV[\x92\x91PPV[_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15a\n\xBCWa\n\xBBa\t\x16V[[` \x82\x02\x90P` \x81\x01\x90P\x91\x90PV[_\x81\x90P\x91\x90PV[a\n\xDF\x81a\n\xCDV[\x81\x14a\n\xE9W__\xFD[PV[_\x81Q\x90Pa\n\xFA\x81a\n\xD6V[\x92\x91PPV[__\xFD[_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15a\x0B\x1EWa\x0B\x1Da\t\x16V[[a\x0B'\x82a\t\x06V[\x90P` \x81\x01\x90P\x91\x90PV[\x82\x81\x83^_\x83\x83\x01RPPPV[_a\x0BTa\x0BO\x84a\x0B\x04V[a\ttV[\x90P\x82\x81R` \x81\x01\x84\x84\x84\x01\x11\x15a\x0BpWa\x0Boa\x0B\0V[[a\x0B{\x84\x82\x85a\x0B4V[P\x93\x92PPPV[_\x82`\x1F\x83\x01\x12a\x0B\x97Wa\x0B\x96a\n\x15V[[\x81Qa\x0B\xA7\x84\x82` \x86\x01a\x0BBV[\x91PP\x92\x91PPV[_`@\x82\x84\x03\x12\x15a\x0B\xC5Wa\x0B\xC4a\t\x02V[[a\x0B\xCF`@a\ttV[\x90P_a\x0B\xDE\x84\x82\x85\x01a\n\xECV[_\x83\x01RP` \x82\x01Qg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x0C\x01Wa\x0C\0a\t\x8EV[[a\x0C\r\x84\x82\x85\x01a\x0B\x83V[` \x83\x01RP\x92\x91PPV[_a\x0C+a\x0C&\x84a\n\xA2V[a\ttV[\x90P\x80\x83\x82R` \x82\x01\x90P` \x84\x02\x83\x01\x85\x81\x11\x15a\x0CNWa\x0CMa\nDV[[\x83[\x81\x81\x10\x15a\x0C\x95W\x80Qg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x0CsWa\x0Cra\n\x15V[[\x80\x86\x01a\x0C\x80\x89\x82a\x0B\xB0V[\x85R` \x85\x01\x94PPP` \x81\x01\x90Pa\x0CPV[PPP\x93\x92PPPV[_\x82`\x1F\x83\x01\x12a\x0C\xB3Wa\x0C\xB2a\n\x15V[[\x81Qa\x0C\xC3\x84\x82` \x86\x01a\x0C\x19V[\x91PP\x92\x91PPV[_``\x82\x84\x03\x12\x15a\x0C\xE1Wa\x0C\xE0a\t\x02V[[a\x0C\xEB``a\ttV[\x90P_a\x0C\xFA\x84\x82\x85\x01a\n\x8EV[_\x83\x01RP` \x82\x01Qg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\r\x1DWa\r\x1Ca\t\x8EV[[a\r)\x84\x82\x85\x01a\x0C\x9FV[` \x83\x01RP`@\x82\x01Qg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\rMWa\rLa\t\x8EV[[a\rY\x84\x82\x85\x01a\x0B\x83V[`@\x83\x01RP\x92\x91PPV[_a\rwa\rr\x84a\n\x19V[a\ttV[\x90P\x80\x83\x82R` \x82\x01\x90P` \x84\x02\x83\x01\x85\x81\x11\x15a\r\x9AWa\r\x99a\nDV[[\x83[\x81\x81\x10\x15a\r\xE1W\x80Qg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\r\xBFWa\r\xBEa\n\x15V[[\x80\x86\x01a\r\xCC\x89\x82a\x0C\xCCV[\x85R` \x85\x01\x94PPP` \x81\x01\x90Pa\r\x9CV[PPP\x93\x92PPPV[_\x82`\x1F\x83\x01\x12a\r\xFFWa\r\xFEa\n\x15V[[\x81Qa\x0E\x0F\x84\x82` \x86\x01a\reV[\x91PP\x92\x91PPV[__``\x83\x85\x03\x12\x15a\x0E.Wa\x0E-a\x08\xFAV[[_a\x0E;\x85\x82\x86\x01a\t\xC8V[\x92PP`@\x83\x01Qg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x0E\\Wa\x0E[a\x08\xFEV[[a\x0Eh\x85\x82\x86\x01a\r\xEBV[\x91PP\x92P\x92\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`2`\x04R`$_\xFD[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[\x7Ftoo few operators\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a\x0E\xE3`\x11\x83a\x0E\x9FV[\x91Pa\x0E\xEE\x82a\x0E\xAFV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra\x0F\x10\x81a\x0E\xD7V[\x90P\x91\x90PV[\x7Ftoo many operators\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a\x0FK`\x12\x83a\x0E\x9FV[\x91Pa\x0FV\x82a\x0F\x17V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra\x0Fx\x81a\x0F?V[\x90P\x91\x90PV[\x7Ftoo few nodes\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a\x0F\xB3`\r\x83a\x0E\x9FV[\x91Pa\x0F\xBE\x82a\x0F\x7FV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra\x0F\xE0\x81a\x0F\xA7V[\x90P\x91\x90PV[\x7Ftoo many nodes\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a\x10\x1B`\x0E\x83a\x0E\x9FV[\x91Pa\x10&\x82a\x0F\xE7V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra\x10H\x81a\x10\x0FV[\x90P\x91\x90PV[\x7Foperator already exists\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a\x10\x83`\x17\x83a\x0E\x9FV[\x91Pa\x10\x8E\x82a\x10OV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra\x10\xB0\x81a\x10wV[\x90P\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`\x11`\x04R`$_\xFD[_a\x10\xEE\x82a\n\xCDV[\x91Pa\x10\xF9\x83a\n\xCDV[\x92P\x82\x82\x03\x90P\x81\x81\x11\x15a\x11\x11Wa\x11\x10a\x10\xB7V[[\x92\x91PPV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`1`\x04R`$_\xFD[_\x81Q\x90P\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`\"`\x04R`$_\xFD[_`\x02\x82\x04\x90P`\x01\x82\x16\x80a\x11\x92W`\x7F\x82\x16\x91P[` \x82\x10\x81\x03a\x11\xA5Wa\x11\xA4a\x11NV[[P\x91\x90PV[_\x81\x90P\x81_R` _ \x90P\x91\x90PV[_` `\x1F\x83\x01\x04\x90P\x91\x90PV[_\x82\x82\x1B\x90P\x92\x91PPV[_`\x08\x83\x02a\x12\x07\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82a\x11\xCCV[a\x12\x11\x86\x83a\x11\xCCV[\x95P\x80\x19\x84\x16\x93P\x80\x86\x16\x84\x17\x92PPP\x93\x92PPPV[_\x81\x90P\x91\x90PV[_a\x12La\x12Ga\x12B\x84a\n\xCDV[a\x12)V[a\n\xCDV[\x90P\x91\x90PV[_\x81\x90P\x91\x90PV[a\x12e\x83a\x122V[a\x12ya\x12q\x82a\x12SV[\x84\x84Ta\x11\xD8V[\x82UPPPPV[__\x90P\x90V[a\x12\x90a\x12\x81V[a\x12\x9B\x81\x84\x84a\x12\\V[PPPV[[\x81\x81\x10\x15a\x12\xBEWa\x12\xB3_\x82a\x12\x88V[`\x01\x81\x01\x90Pa\x12\xA1V[PPV[`\x1F\x82\x11\x15a\x13\x03Wa\x12\xD4\x81a\x11\xABV[a\x12\xDD\x84a\x11\xBDV[\x81\x01` \x85\x10\x15a\x12\xECW\x81\x90P[a\x13\0a\x12\xF8\x85a\x11\xBDV[\x83\x01\x82a\x12\xA0V[PP[PPPV[_\x82\x82\x1C\x90P\x92\x91PPV[_a\x13#_\x19\x84`\x08\x02a\x13\x08V[\x19\x80\x83\x16\x91PP\x92\x91PPV[_a\x13;\x83\x83a\x13\x14V[\x91P\x82`\x02\x02\x82\x17\x90P\x92\x91PPV[a\x13T\x82a\x11DV[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x13mWa\x13la\t\x16V[[a\x13w\x82Ta\x11{V[a\x13\x82\x82\x82\x85a\x12\xC2V[_` \x90P`\x1F\x83\x11`\x01\x81\x14a\x13\xB3W_\x84\x15a\x13\xA1W\x82\x87\x01Q\x90P[a\x13\xAB\x85\x82a\x130V[\x86UPa\x14\x12V[`\x1F\x19\x84\x16a\x13\xC1\x86a\x11\xABV[_[\x82\x81\x10\x15a\x13\xE8W\x84\x89\x01Q\x82U`\x01\x82\x01\x91P` \x85\x01\x94P` \x81\x01\x90Pa\x13\xC3V[\x86\x83\x10\x15a\x14\x05W\x84\x89\x01Qa\x14\x01`\x1F\x89\x16\x82a\x13\x14V[\x83UP[`\x01`\x02\x88\x02\x01\x88UPPP[PPPPPPV[\x7Finvalid address\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a\x14N`\x0F\x83a\x0E\x9FV[\x91Pa\x14Y\x82a\x14\x1AV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra\x14{\x81a\x14BV[\x90P\x91\x90PV[\x7Finvalid id\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a\x14\xB6`\n\x83a\x0E\x9FV[\x91Pa\x14\xC1\x82a\x14\x82V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra\x14\xE3\x81a\x14\xAAV[\x90P\x91\x90PV[a_\x1A\x80a\x14\xF7_9_\xF3\xFE`\x80`@R4\x80\x15a\0\x0FW__\xFD[P`\x046\x10a\0\xA7W_5`\xE0\x1C\x80c\xAD6\xE6\xD0\x11a\0oW\x80c\xAD6\xE6\xD0\x14a\x01\x15W\x80c\xC10\x80\x9A\x14a\x01\x1FW\x80c\xCCEf*\x14a\x01)W\x80c\xF2\xFD\xE3\x8B\x14a\x01EW\x80c\xF5\xF2\xD9\xF1\x14a\x01aW\x80c\xFF\xD7@\xDF\x14a\x01kWa\0\xA7V[\x80c0H\xBF\xBA\x14a\0\xABW\x80c@\x99\0\xE8\x14a\0\xB5W\x80cH\x86\xF6,\x14a\0\xD1W\x80cl\x0Ba\xB9\x14a\0\xDBW\x80cuA\x8B\x9D\x14a\0\xF7W[__\xFD[a\0\xB3a\x01\x87V[\0[a\0\xCF`\x04\x806\x03\x81\x01\x90a\0\xCA\x91\x90a9\xE2V[a\x02\xDBV[\0[a\0\xD9a\x03~V[\0[a\0\xF5`\x04\x806\x03\x81\x01\x90a\0\xF0\x91\x90a:+V[a\x08,V[\0[a\0\xFFa\tVV[`@Qa\x01\x0C\x91\x90a?GV[`@Q\x80\x91\x03\x90\xF3[a\x01\x1Da\nXV[\0[a\x01'a\x0B}V[\0[a\x01C`\x04\x806\x03\x81\x01\x90a\x01>\x91\x90a@\x1DV[a\x0C\xD1V[\0[a\x01_`\x04\x806\x03\x81\x01\x90a\x01Z\x91\x90a@\xC5V[a\x10;V[\0[a\x01ia\x11\x0BV[\0[a\x01\x85`\x04\x806\x03\x81\x01\x90a\x01\x80\x91\x90aA\x1AV[a\x12zV[\0[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x02\x15W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x02\x0C\x90aA\x9FV[`@Q\x80\x91\x03\x90\xFD[a\x02\x1F`\ta\x14\x0EV[`\n`\x08\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x02M\x90aA\xEAV[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\x8F\xB9\xCD\x05M\n\x02!\x10\xCC\xED#\x9E\x90\x8B\x83NL\xD2\x19Q\x18V\xD4\xEA\xAE0Q\xD92\xD6\x04`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x02\xD1\x91\x90aB0V[`@Q\x80\x91\x03\x90\xA1V[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x03iW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x03`\x90aA\x9FV[`@Q\x80\x91\x03\x90\xFD[\x80`\x01\x81\x81a\x03x\x91\x90aC\xC4V[\x90PPPV[a\x03\x923`\x05a\x14\xC6\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[`\n`\x08\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x03\xC0\x90aA\xEAV[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\xA7j\x8F\xC1\xA9\x02f\xDD\xEE\x897\xA1\x8E\x12\xF0\x1E\xAD\xE9F\xB3\xB6a\x97\xFF\xF2\x89\xAF\x92w\xC2\xBD%3`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x04F\x92\x91\x90aC\xE1V[`@Q\x80\x91\x03\x90\xA1_`\x05`\x03\x01_\x90T\x90a\x01\0\n\x90\x04`\xFF\x16`\xFF\x16\x11a\x08*W__\x90P[`\x05_\x01\x80T\x90P\x81\x10\x15a\x04\xDBWa\x04\xCE`\x05_\x01\x82\x81T\x81\x10a\x04\x96Wa\x04\x95aD\x08V[[\x90_R` _ \x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02a\x15\xE4\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x80\x80`\x01\x01\x91PPa\x04nV[P__\x90P[`\x05`\x01\x01\x80T\x90P\x81\x10\x15a\x07\x18Wa\x07\x0B`\x05`\x01\x01\x82\x81T\x81\x10a\x05\x0BWa\x05\naD\x08V[[\x90_R` _ \x90`\x03\x02\x01`@Q\x80``\x01`@R\x90\x81_\x82\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01`\x01\x82\x01\x80T\x80` \x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01_\x90[\x82\x82\x10\x15a\x06cW\x83\x82\x90_R` _ \x90`\x02\x02\x01`@Q\x80`@\x01`@R\x90\x81_\x82\x01T\x81R` \x01`\x01\x82\x01\x80Ta\x05\xD4\x90aDbV[\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01\x82\x80Ta\x06\0\x90aDbV[\x80\x15a\x06KW\x80`\x1F\x10a\x06\"Wa\x01\0\x80\x83T\x04\x02\x83R\x91` \x01\x91a\x06KV[\x82\x01\x91\x90_R` _ \x90[\x81T\x81R\x90`\x01\x01\x90` \x01\x80\x83\x11a\x06.W\x82\x90\x03`\x1F\x16\x82\x01\x91[PPPPP\x81RPP\x81R` \x01\x90`\x01\x01\x90a\x05\x9AV[PPPP\x81R` \x01`\x02\x82\x01\x80Ta\x06{\x90aDbV[\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01\x82\x80Ta\x06\xA7\x90aDbV[\x80\x15a\x06\xF2W\x80`\x1F\x10a\x06\xC9Wa\x01\0\x80\x83T\x04\x02\x83R\x91` \x01\x91a\x06\xF2V[\x82\x01\x91\x90_R` _ \x90[\x81T\x81R\x90`\x01\x01\x90` \x01\x80\x83\x11a\x06\xD5W\x82\x90\x03`\x1F\x16\x82\x01\x91[PPPPP\x81RPP`\x02a\x18v\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x80\x80`\x01\x01\x91PPa\x04\xE1V[P`\n_\x81\x81\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x07>\x90aD\x92V[\x91\x90a\x01\0\n\x81T\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPPa\x07o`\x05a\x1B\x03V[`\n`\x08\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x07\x9D\x90aA\xEAV[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\x11\xCEP\x16\x0Ef\x10\x057\xFDK\n\xE2m\xE6mQ\xDA\xB7\x13\xAD\x9213S\xA1\x8C$\xE8\xF6\xDA\xAB`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x08!\x91\x90aB0V[`@Q\x80\x91\x03\x90\xA1[V[a\x08@3`\x02a\x1B\xAC\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x08\x7FW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x08v\x90aE\x0BV[`@Q\x80\x91\x03\x90\xFD[a\x08\x953\x82`\x02a\x1D\x04\x90\x92\x91\x90c\xFF\xFF\xFF\xFF\x16V[`\n`\x08\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x08\xC3\x90aA\xEAV[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7Fj\xDF\xB8\x96\xD3@v\x81\xD0_\xB8t\xD4\xDF\xB7\x06\x8En*6\xF0\x9A\xCD8\xA3\xB7\xD0L\x01t_\xEE3\x82`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\tK\x93\x92\x91\x90aF3V[`@Q\x80\x91\x03\x90\xA1PV[a\t^a7FV[`@Q\x80`\xA0\x01`@R\x80a\ts`\x02a\x1D\x96V[\x81R` \x01a\t\x8F`\x02_\x01`\x05a\x1F\x99\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x81R` \x01`\t`@Q\x80` \x01`@R\x90\x81_\x82\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RPP\x81R` \x01`\n_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RP\x90P\x90V[a\nl3`\x02a\x1B\xAC\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\n\xABW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\n\xA2\x90aE\x0BV[`@Q\x80\x91\x03\x90\xFD[a\n\xBF3`\ta'\0\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[`\n`\x08\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\n\xED\x90aA\xEAV[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\xF9\x10g\xEBB\x0C(\xD3\x12He\xFC\x99nj\xA9\xD5A\xB9\xB4\xFE\xF9\x18\x8C\xB9e\xA6\xCCd\x91c\x8E3`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x0Bs\x92\x91\x90aC\xE1V[`@Q\x80\x91\x03\x90\xA1V[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x0C\x0BW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x0C\x02\x90aA\x9FV[`@Q\x80\x91\x03\x90\xFD[a\x0C\x15`\x05a('V[`\n`\x08\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x0CC\x90aA\xEAV[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\x9C\xE1\x92\xAE\xA5\xFA\xF2\x15\x1B\xBC$l\xD8\x91\x8D.\xBAp/\xA2iQ\xF6\x7F+\xF7\xB3\x81~h\x9D\x98`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x0C\xC7\x91\x90aB0V[`@Q\x80\x91\x03\x90\xA1V[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\r_W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\rV\x90aA\x9FV[`@Q\x80\x91\x03\x90\xFD[a\ri`\ta({V[\x15a\r\xA9W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\r\xA0\x90aF\xB9V[`@Q\x80\x91\x03\x90\xFD[__\x90P[\x84\x84\x90P\x81\x10\x15a\x0E@Wa\r\xF4\x85\x85\x83\x81\x81\x10a\r\xCFWa\r\xCEaD\x08V[[\x90P` \x02\x01` \x81\x01\x90a\r\xE4\x91\x90a@\xC5V[`\x02a\x1B\xAC\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x0E3W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x0E*\x90aG!V[`@Q\x80\x91\x03\x90\xFD[\x80\x80`\x01\x01\x91PPa\r\xAEV[P__\x90P[\x82\x82\x90P\x81\x10\x15a\x0F%Wa\x0E\x8F\x83\x83\x83\x81\x81\x10a\x0EgWa\x0EfaD\x08V[[\x90P` \x02\x81\x01\x90a\x0Ey\x91\x90aGKV[\x80` \x01\x90a\x0E\x88\x91\x90aGrV[\x90Pa(\xD5V[a\x0E\xD8\x83\x83\x83\x81\x81\x10a\x0E\xA5Wa\x0E\xA4aD\x08V[[\x90P` \x02\x81\x01\x90a\x0E\xB7\x91\x90aGKV[_\x01` \x81\x01\x90a\x0E\xC8\x91\x90a@\xC5V[`\x02a\x1B\xAC\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x15a\x0F\x18W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x0F\x0F\x90aH\x1EV[`@Q\x80\x91\x03\x90\xFD[\x80\x80`\x01\x01\x91PPa\x0EFV[Pa\x0FT\x82\x82\x90P\x85\x85\x90Pa\x0F;`\x02a)tV[a\x0FE\x91\x90aH&\x82\x82a=\xB0V[\x91PP` \x83\x01Q\x84\x82\x03` \x86\x01Ra>@\x82\x82a<\xCAV[\x91PP`@\x83\x01Q\x84\x82\x03`@\x86\x01Ra>Z\x82\x82a=\xB0V[\x91PP\x80\x91PP\x92\x91PPV[` \x82\x01_\x82\x01Qa>{_\x85\x01\x82a:\xCBV[PPPPV[_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[a>\x9D\x81a>\x81V[\x82RPPV[_o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[a>\xC7\x81a>\xA3V[\x82RPPV[_`\xA0\x83\x01_\x83\x01Q\x84\x82\x03_\x86\x01Ra>\xE7\x82\x82a==V[\x91PP` \x83\x01Q\x84\x82\x03` \x86\x01Ra?\x01\x82\x82a>\x0CV[\x91PP`@\x83\x01Qa?\x16`@\x86\x01\x82a>gV[P``\x83\x01Qa?)``\x86\x01\x82a>\x94V[P`\x80\x83\x01Qa?<`\x80\x86\x01\x82a>\xBEV[P\x80\x91PP\x92\x91PPV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra?_\x81\x84a>\xCDV[\x90P\x92\x91PPV[__\xFD[__\xFD[__\xFD[__\x83`\x1F\x84\x01\x12a?\x88Wa?\x87a?gV[[\x825\x90Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a?\xA5Wa?\xA4a?kV[[` \x83\x01\x91P\x83` \x82\x02\x83\x01\x11\x15a?\xC1Wa?\xC0a?oV[[\x92P\x92\x90PV[__\x83`\x1F\x84\x01\x12a?\xDDWa?\xDCa?gV[[\x825\x90Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a?\xFAWa?\xF9a?kV[[` \x83\x01\x91P\x83` \x82\x02\x83\x01\x11\x15a@\x16Wa@\x15a?oV[[\x92P\x92\x90PV[____`@\x85\x87\x03\x12\x15a@5Wa@4a9\xB8V[[_\x85\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a@RWa@Qa9\xBCV[[a@^\x87\x82\x88\x01a?sV[\x94P\x94PP` \x85\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a@\x81Wa@\x80a9\xBCV[[a@\x8D\x87\x82\x88\x01a?\xC8V[\x92P\x92PP\x92\x95\x91\x94P\x92PV[a@\xA4\x81a:\xBAV[\x81\x14a@\xAEW__\xFD[PV[_\x815\x90Pa@\xBF\x81a@\x9BV[\x92\x91PPV[_` \x82\x84\x03\x12\x15a@\xDAWa@\xD9a9\xB8V[[_a@\xE7\x84\x82\x85\x01a@\xB1V[\x91PP\x92\x91PPV[a@\xF9\x81a;\x03V[\x81\x14aA\x03W__\xFD[PV[_\x815\x90PaA\x14\x81a@\xF0V[\x92\x91PPV[_` \x82\x84\x03\x12\x15aA/WaA.a9\xB8V[[_aA<\x84\x82\x85\x01aA\x06V[\x91PP\x92\x91PPV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[\x7Fnot the owner\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aA\x89`\r\x83aAEV[\x91PaA\x94\x82aAUV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaA\xB6\x81aA}V[\x90P\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`\x11`\x04R`$_\xFD[_aA\xF4\x82a>\xA3V[\x91Po\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x03aB\x16WaB\x15aA\xBDV[[`\x01\x82\x01\x90P\x91\x90PV[aB*\x81a>\xA3V[\x82RPPV[_` \x82\x01\x90PaBC_\x83\x01\x84aB!V[\x92\x91PPV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R_`\x04R`$_\xFD[_`\xFF\x82\x16\x90P\x91\x90PV[aB\x8A\x81aBuV[\x81\x14aB\x94W__\xFD[PV[_\x815aB\xA3\x81aB\x81V[\x80\x91PP\x91\x90PV[_\x81_\x1B\x90P\x91\x90PV[_`\xFFaB\xC3\x84aB\xACV[\x93P\x80\x19\x83\x16\x92P\x80\x84\x16\x83\x17\x91PP\x92\x91PPV[_\x81\x90P\x91\x90PV[_aB\xFCaB\xF7aB\xF2\x84aBuV[aB\xD9V[aBuV[\x90P\x91\x90PV[_\x81\x90P\x91\x90PV[aC\x15\x82aB\xE2V[aC(aC!\x82aC\x03V[\x83TaB\xB7V[\x82UPPPV[_\x81`\x08\x1B\x90P\x91\x90PV[_a\xFF\0aCH\x84aC/V[\x93P\x80\x19\x83\x16\x92P\x80\x84\x16\x83\x17\x91PP\x92\x91PPV[aCg\x82aB\xE2V[aCzaCs\x82aC\x03V[\x83TaC;V[\x82UPPPV[_\x81\x01_\x83\x01\x80aC\x91\x81aB\x97V[\x90PaC\x9D\x81\x84aC\x0CV[PPP_\x81\x01` \x83\x01\x80aC\xB1\x81aB\x97V[\x90PaC\xBD\x81\x84aC^V[PPPPPV[aC\xCE\x82\x82aC\x81V[PPV[aC\xDB\x81a:\xBAV[\x82RPPV[_`@\x82\x01\x90PaC\xF4_\x83\x01\x85aC\xD2V[aD\x01` \x83\x01\x84aB!V[\x93\x92PPPV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`2`\x04R`$_\xFD[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`\"`\x04R`$_\xFD[_`\x02\x82\x04\x90P`\x01\x82\x16\x80aDyW`\x7F\x82\x16\x91P[` \x82\x10\x81\x03aD\x8CWaD\x8BaD5V[[P\x91\x90PV[_aD\x9C\x82a>\x81V[\x91Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x03aD\xB6WaD\xB5aA\xBDV[[`\x01\x82\x01\x90P\x91\x90PV[\x7Fnot an operator\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aD\xF5`\x0F\x83aAEV[\x91PaE\0\x82aD\xC1V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaE\"\x81aD\xE9V[\x90P\x91\x90PV[_aE7` \x84\x01\x84aA\x06V[\x90P\x92\x91PPV[__\xFD[__\xFD[__\xFD[__\x835`\x01` \x03\x846\x03\x03\x81\x12aEgWaEfaEGV[[\x83\x81\x01\x92P\x825\x91P` \x83\x01\x92Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15aE\x8FWaE\x8EaE?V[[`\x01\x82\x026\x03\x83\x13\x15aE\xA5WaE\xA4aECV[[P\x92P\x92\x90PV[\x82\x81\x837_\x83\x83\x01RPPPV[_aE\xC6\x83\x85a;%V[\x93PaE\xD3\x83\x85\x84aE\xADV[aE\xDC\x83a;CV[\x84\x01\x90P\x93\x92PPPV[_`@\x83\x01aE\xF8_\x84\x01\x84aE)V[aF\x04_\x86\x01\x82a;\x0CV[PaF\x12` \x84\x01\x84aEKV[\x85\x83\x03` \x87\x01RaF%\x83\x82\x84aE\xBBV[\x92PPP\x80\x91PP\x92\x91PPV[_``\x82\x01\x90PaFF_\x83\x01\x86aC\xD2V[\x81\x81\x03` \x83\x01RaFX\x81\x85aE\xE7V[\x90PaFg`@\x83\x01\x84aB!V[\x94\x93PPPPV[\x7Fmaintenance in progress\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aF\xA3`\x17\x83aAEV[\x91PaF\xAE\x82aFoV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaF\xD0\x81aF\x97V[\x90P\x91\x90PV[\x7Funknown operator\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aG\x0B`\x10\x83aAEV[\x91PaG\x16\x82aF\xD7V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaG8\x81aF\xFFV[\x90P\x91\x90PV[__\xFD[__\xFD[__\xFD[_\x825`\x01``\x03\x836\x03\x03\x81\x12aGfWaGeaG?V[[\x80\x83\x01\x91PP\x92\x91PPV[__\x835`\x01` \x03\x846\x03\x03\x81\x12aG\x8EWaG\x8DaG?V[[\x80\x84\x01\x92P\x825\x91Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15aG\xB0WaG\xAFaGCV[[` \x83\x01\x92P` \x82\x026\x03\x83\x13\x15aG\xCCWaG\xCBaGGV[[P\x92P\x92\x90PV[\x7Foperator already exists\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aH\x08`\x17\x83aAEV[\x91PaH\x13\x82aG\xD4V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaH5\x81aG\xFCV[\x90P\x91\x90PV[_aHF\x82a;\x03V[\x91PaHQ\x83a;\x03V[\x92P\x82\x82\x03\x90P\x81\x81\x11\x15aHiWaHhaA\xBDV[[\x92\x91PPV[_aHy\x82a;\x03V[\x91PaH\x84\x83a;\x03V[\x92P\x82\x82\x01\x90P\x80\x82\x11\x15aH\x9CWaH\x9BaA\xBDV[[\x92\x91PPV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[_\x81\x90P\x91\x90PV[_aH\xC9` \x84\x01\x84a@\xB1V[\x90P\x92\x91PPV[_` \x82\x01\x90P\x91\x90PV[_aH\xE8\x83\x85aH\xA2V[\x93PaH\xF3\x82aH\xB2V[\x80_[\x85\x81\x10\x15aI+WaI\x08\x82\x84aH\xBBV[aI\x12\x88\x82a=\x8DV[\x97PaI\x1D\x83aH\xD1V[\x92PP`\x01\x81\x01\x90PaH\xF6V[P\x85\x92PPP\x93\x92PPPV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[_\x81\x90P\x91\x90PV[__\x835`\x01` \x03\x846\x03\x03\x81\x12aImWaIlaEGV[[\x83\x81\x01\x92P\x825\x91P` \x83\x01\x92Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15aI\x95WaI\x94aE?V[[` \x82\x026\x03\x83\x13\x15aI\xABWaI\xAAaECV[[P\x92P\x92\x90PV[_\x81\x90P\x91\x90PV[_`@\x83\x01aI\xCD_\x84\x01\x84aE)V[aI\xD9_\x86\x01\x82a;\x0CV[PaI\xE7` \x84\x01\x84aEKV[\x85\x83\x03` \x87\x01RaI\xFA\x83\x82\x84aE\xBBV[\x92PPP\x80\x91PP\x92\x91PPV[_aJ\x13\x83\x83aI\xBCV[\x90P\x92\x91PPV[_\x825`\x01`@\x03\x836\x03\x03\x81\x12aJ6WaJ5aEGV[[\x82\x81\x01\x91PP\x92\x91PPV[_` \x82\x01\x90P\x91\x90PV[_aJY\x83\x85a:\xE4V[\x93P\x83` \x84\x02\x85\x01aJk\x84aI\xB3V[\x80_[\x87\x81\x10\x15aJ\xAEW\x84\x84\x03\x89RaJ\x85\x82\x84aJ\x1BV[aJ\x8F\x85\x82aJ\x08V[\x94PaJ\x9A\x83aJBV[\x92P` \x8A\x01\x99PP`\x01\x81\x01\x90PaJnV[P\x82\x97P\x87\x94PPPPP\x93\x92PPPV[_``\x83\x01aJ\xD1_\x84\x01\x84aH\xBBV[aJ\xDD_\x86\x01\x82a:\xCBV[PaJ\xEB` \x84\x01\x84aIQV[\x85\x83\x03` \x87\x01RaJ\xFE\x83\x82\x84aJNV[\x92PPPaK\x0F`@\x84\x01\x84aEKV[\x85\x83\x03`@\x87\x01RaK\"\x83\x82\x84aE\xBBV[\x92PPP\x80\x91PP\x92\x91PPV[_aK;\x83\x83aJ\xC0V[\x90P\x92\x91PPV[_\x825`\x01``\x03\x836\x03\x03\x81\x12aK^WaK]aEGV[[\x82\x81\x01\x91PP\x92\x91PPV[_` \x82\x01\x90P\x91\x90PV[_aK\x81\x83\x85aI8V[\x93P\x83` \x84\x02\x85\x01aK\x93\x84aIHV[\x80_[\x87\x81\x10\x15aK\xD6W\x84\x84\x03\x89RaK\xAD\x82\x84aKCV[aK\xB7\x85\x82aK0V[\x94PaK\xC2\x83aKjV[\x92P` \x8A\x01\x99PP`\x01\x81\x01\x90PaK\x96V[P\x82\x97P\x87\x94PPPPP\x93\x92PPPV[_``\x82\x01\x90P\x81\x81\x03_\x83\x01RaL\x01\x81\x87\x89aH\xDDV[\x90P\x81\x81\x03` \x83\x01RaL\x16\x81\x85\x87aKvV[\x90PaL%`@\x83\x01\x84aB!V[\x96\x95PPPPPPV[\x7Fmigration in progress\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aLc`\x15\x83aAEV[\x91PaLn\x82aL/V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaL\x90\x81aLWV[\x90P\x91\x90PV[\x7Ftoo few nodes\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aL\xCB`\r\x83aAEV[\x91PaL\xD6\x82aL\x97V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaL\xF8\x81aL\xBFV[\x90P\x91\x90PV[aM\x08\x81a;\x03V[\x82RPPV[_``\x82\x01\x90PaM!_\x83\x01\x86aC\xD2V[aM.` \x83\x01\x85aL\xFFV[aM;`@\x83\x01\x84aB!V[\x94\x93PPPPV[\x7Fnot under maintenance\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aMw`\x15\x83aAEV[\x91PaM\x82\x82aMCV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaM\xA4\x81aMkV[\x90P\x91\x90PV[\x7Fnot pulling\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aM\xDF`\x0B\x83aAEV[\x91PaM\xEA\x82aM\xABV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaN\x0C\x81aM\xD3V[\x90P\x91\x90PV[_aN\x1D\x82aBuV[\x91P_\x82\x03aN/WaN.aA\xBDV[[`\x01\x82\x03\x90P\x91\x90PV[\x7Finvalid address\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aNn`\x0F\x83aAEV[\x91PaNy\x82aN:V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaN\x9B\x81aNbV[\x90P\x91\x90PV[\x7Foperator doesn't exist\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aN\xD6`\x16\x83aAEV[\x91PaN\xE1\x82aN\xA2V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaO\x03\x81aN\xCAV[\x90P\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`1`\x04R`$_\xFD[\x7Ftoo many operators\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aOk`\x12\x83aAEV[\x91PaOv\x82aO7V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaO\x98\x81aO_V[\x90P\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`A`\x04R`$_\xFD[_\x81\x90P\x81_R` _ \x90P\x91\x90PV[_` `\x1F\x83\x01\x04\x90P\x91\x90PV[_\x82\x82\x1B\x90P\x92\x91PPV[_`\x08\x83\x02aP(\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82aO\xEDV[aP2\x86\x83aO\xEDV[\x95P\x80\x19\x84\x16\x93P\x80\x86\x16\x84\x17\x92PPP\x93\x92PPPV[_aPdaP_aPZ\x84a;\x03V[aB\xD9V[a;\x03V[\x90P\x91\x90PV[_\x81\x90P\x91\x90PV[aP}\x83aPJV[aP\x91aP\x89\x82aPkV[\x84\x84TaO\xF9V[\x82UPPPPV[__\x90P\x90V[aP\xA8aP\x99V[aP\xB3\x81\x84\x84aPtV[PPPV[[\x81\x81\x10\x15aP\xD6WaP\xCB_\x82aP\xA0V[`\x01\x81\x01\x90PaP\xB9V[PPV[`\x1F\x82\x11\x15aQ\x1BWaP\xEC\x81aO\xCCV[aP\xF5\x84aO\xDEV[\x81\x01` \x85\x10\x15aQ\x04W\x81\x90P[aQ\x18aQ\x10\x85aO\xDEV[\x83\x01\x82aP\xB8V[PP[PPPV[_\x82\x82\x1C\x90P\x92\x91PPV[_aQ;_\x19\x84`\x08\x02aQ V[\x19\x80\x83\x16\x91PP\x92\x91PPV[_aQS\x83\x83aQ,V[\x91P\x82`\x02\x02\x82\x17\x90P\x92\x91PPV[aQl\x82a;\x1BV[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15aQ\x85WaQ\x84aO\x9FV[[aQ\x8F\x82TaDbV[aQ\x9A\x82\x82\x85aP\xDAV[_` \x90P`\x1F\x83\x11`\x01\x81\x14aQ\xCBW_\x84\x15aQ\xB9W\x82\x87\x01Q\x90P[aQ\xC3\x85\x82aQHV[\x86UPaR*V[`\x1F\x19\x84\x16aQ\xD9\x86aO\xCCV[_[\x82\x81\x10\x15aR\0W\x84\x89\x01Q\x82U`\x01\x82\x01\x91P` \x85\x01\x94P` \x81\x01\x90PaQ\xDBV[\x86\x83\x10\x15aR\x1DW\x84\x89\x01QaR\x19`\x1F\x89\x16\x82aQ,V[\x83UP[`\x01`\x02\x88\x02\x01\x88UPPP[PPPPPPV[\x7Fnot in progress\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aRf`\x0F\x83aAEV[\x91PaRq\x82aR2V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaR\x93\x81aRZV[\x90P\x91\x90PV[\x7Fdata pull in progress\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aR\xCE`\x15\x83aAEV[\x91PaR\xD9\x82aR\x9AV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaR\xFB\x81aR\xC2V[\x90P\x91\x90PV[__\xFD[aS\x0F\x82a;CV[\x81\x01\x81\x81\x10g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x17\x15aS.WaS-aO\x9FV[[\x80`@RPPPV[_aS@a9\xAFV[\x90PaSL\x82\x82aS\x06V[\x91\x90PV[__\xFD[__\xFD[_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15aSsWaSraO\x9FV[[aS|\x82a;CV[\x90P` \x81\x01\x90P\x91\x90PV[_aS\x9BaS\x96\x84aSYV[aS7V[\x90P\x82\x81R` \x81\x01\x84\x84\x84\x01\x11\x15aS\xB7WaS\xB6aSUV[[aS\xC2\x84\x82\x85aE\xADV[P\x93\x92PPPV[_\x82`\x1F\x83\x01\x12aS\xDEWaS\xDDa?gV[[\x815aS\xEE\x84\x82` \x86\x01aS\x89V[\x91PP\x92\x91PPV[_`@\x82\x84\x03\x12\x15aT\x0CWaT\x0BaS\x02V[[aT\x16`@aS7V[\x90P_aT%\x84\x82\x85\x01aA\x06V[_\x83\x01RP` \x82\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15aTHWaTGaSQV[[aTT\x84\x82\x85\x01aS\xCAV[` \x83\x01RP\x92\x91PPV[_aTk6\x83aS\xF7V[\x90P\x91\x90PV[_aT|\x82a;\x03V[\x91P\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x03aT\xAEWaT\xADaA\xBDV[[`\x01\x82\x01\x90P\x91\x90PV[\x7Ftoo many nodes\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aT\xED`\x0E\x83aAEV[\x91PaT\xF8\x82aT\xB9V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaU\x1A\x81aT\xE1V[\x90P\x91\x90PV[\x7Ftoo few operators\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aUU`\x11\x83aAEV[\x91PaU`\x82aU!V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaU\x82\x81aUIV[\x90P\x91\x90PV[\x7Fmigration already in progress\0\0\0_\x82\x01RPV[_aU\xBD`\x1D\x83aAEV[\x91PaU\xC8\x82aU\x89V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaU\xEA\x81aU\xB1V[\x90P\x91\x90PV[\x7Fnothing to do\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aV%`\r\x83aAEV[\x91PaV0\x82aU\xF1V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaVR\x81aV\x19V[\x90P\x91\x90PV[_aVc\x82aBuV[\x91P`\xFF\x82\x03aVvWaVuaA\xBDV[[`\x01\x82\x01\x90P\x91\x90PV[_\x815aV\x8D\x81a@\x9BV[\x80\x91PP\x91\x90PV[_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFFaV\xB5\x84aB\xACV[\x93P\x80\x19\x83\x16\x92P\x80\x84\x16\x83\x17\x91PP\x92\x91PPV[_aV\xE5aV\xE0aV\xDB\x84a:\x9BV[aB\xD9V[a:\x9BV[\x90P\x91\x90PV[_aV\xF6\x82aV\xCBV[\x90P\x91\x90PV[_aW\x07\x82aV\xECV[\x90P\x91\x90PV[_\x81\x90P\x91\x90PV[aW \x82aV\xFDV[aW3aW,\x82aW\x0EV[\x83TaV\x96V[\x82UPPPV[_\x825`\x01`@\x03\x836\x03\x03\x81\x12aWUWaWTaG?V[[\x80\x83\x01\x91PP\x92\x91PPV[_\x81T\x90P\x91\x90PV[_aWu\x82a;\x03V[\x91PaW\x80\x83a;\x03V[\x92P\x82\x82\x02aW\x8E\x81a;\x03V[\x91P\x82\x82\x04\x84\x14\x83\x15\x17aW\xA5WaW\xA4aA\xBDV[[P\x92\x91PPV[_\x81\x90PaW\xBB\x82`\x02aWkV[\x90P\x91\x90PV[_\x81\x90P\x81_R` _ \x90P\x91\x90PV[aX\x04\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x83` \x03`\x08\x02aQ V[\x81T\x81\x16\x82UPPPV[aX\x18\x81aO\xCCV[aX#\x83\x82TaQHV[\x80\x83U_\x82UPPPPV[` \x84\x10_\x81\x14aX\x89W`\x1F\x84\x11`\x01\x81\x14aXWWaXP\x86\x85aQHV[\x83UaX\x83V[aX`\x83aO\xCCV[aXwaXl\x87aO\xDEV[\x82\x01`\x01\x83\x01aP\xB8V[aX\x81\x87\x85aX\x0FV[P[PaX\xD6V[aX\x92\x82aO\xCCV[aX\x9B\x86aO\xDEV[\x81\x01`\x1F\x87\x16\x80\x15aX\xB5WaX\xB4\x81`\x01\x84\x03aW\xD4V[[aX\xC9aX\xC1\x88aO\xDEV[\x84\x01\x83aP\xB8V[`\x01\x88`\x02\x02\x17\x85UPPP[PPPPPV[h\x01\0\0\0\0\0\0\0\0\x84\x11\x15aX\xF7WaX\xF6aO\x9FV[[` \x83\x10_\x81\x14aY@W` \x85\x10_\x81\x14aY\x1EWaY\x17\x86\x85aQHV[\x83UaY:V[\x83`\xFF\x19\x16\x93P\x83aY/\x84aO\xCCV[U`\x01\x86`\x02\x02\x01\x83U[PaYJV[`\x01\x85`\x02\x02\x01\x82U[PPPPPV[\x80TaY\\\x81aDbV[\x80\x84\x11\x15aYqWaYp\x84\x82\x84\x86aX\xDDV[[\x80\x84\x10\x15aY\x86WaY\x85\x84\x82\x84\x86aX/V[[PPPPV[\x81\x81\x10\x15aY\xA9WaY\x9E_\x82aP\xA0V[`\x01\x81\x01\x90PaY\x8CV[PPV[aY\xB7_\x82aYQV[PV[_\x82\x14aY\xCAWaY\xC9aBIV[[aY\xD3\x81aY\xADV[PPV[aY\xE3__\x83\x01aP\xA0V[aY\xF0_`\x01\x83\x01aY\xBAV[PV[_\x82\x14aZ\x03WaZ\x02aBIV[[aZ\x0C\x81aY\xD7V[PPV[[\x81\x81\x10\x15aZ.WaZ#_\x82aY\xF3V[`\x02\x81\x01\x90PaZ\x11V[PPV[\x81\x83\x10\x15aZkWaZC\x82aW\xACV[aZL\x84aW\xACV[aZU\x83aW\xC2V[\x81\x81\x01\x83\x82\x01aZe\x81\x83aZ\x10V[PPPPP[PPPV[h\x01\0\0\0\0\0\0\0\0\x82\x11\x15aZ\x8AWaZ\x89aO\x9FV[[aZ\x93\x81aWaV[\x82\x82UaZ\xA1\x83\x82\x84aZ2V[PPPV[_\x82\x90P\x92\x91PPV[_\x815aZ\xBC\x81a@\xF0V[\x80\x91PP\x91\x90PV[_\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFFaZ\xF0\x84aB\xACV[\x93P\x80\x19\x83\x16\x92P\x80\x84\x16\x83\x17\x91PP\x92\x91PPV[a[\x0F\x82aPJV[a[\"a[\x1B\x82aPkV[\x83TaZ\xC5V[\x82UPPPV[__\x835`\x01` \x03\x846\x03\x03\x81\x12a[EWa[DaG?V[[\x80\x84\x01\x92P\x825\x91Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15a[gWa[faGCV[[` \x83\x01\x92P`\x01\x82\x026\x03\x83\x13\x15a[\x83Wa[\x82aGGV[[P\x92P\x92\x90PV[_\x82\x90P\x92\x91PPV[a[\x9F\x83\x83a[\x8BV[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a[\xB8Wa[\xB7aO\x9FV[[a[\xC2\x82TaDbV[a[\xCD\x82\x82\x85aP\xDAV[_`\x1F\x83\x11`\x01\x81\x14a[\xFAW_\x84\x15a[\xE8W\x82\x87\x015\x90P[a[\xF2\x85\x82aQHV[\x86UPa\\YV[`\x1F\x19\x84\x16a\\\x08\x86aO\xCCV[_[\x82\x81\x10\x15a\\/W\x84\x89\x015\x82U`\x01\x82\x01\x91P` \x85\x01\x94P` \x81\x01\x90Pa\\\nV[\x86\x83\x10\x15a\\LW\x84\x89\x015a\\H`\x1F\x89\x16\x82aQ,V[\x83UP[`\x01`\x02\x88\x02\x01\x88UPPP[PPPPPPPV[a\\m\x83\x83\x83a[\x95V[PPPV[_\x81\x01_\x83\x01\x80a\\\x82\x81aZ\xB0V[\x90Pa\\\x8E\x81\x84a[\x06V[PPP`\x01\x81\x01` \x83\x01a\\\xA3\x81\x85a[)V[a\\\xAE\x81\x83\x86a\\bV[PPPPPPV[a\\\xC0\x82\x82a\\rV[PPV[a\\\xCE\x83\x83aZ\xA6V[a\\\xD8\x81\x83aZpV[a\\\xE1\x83aI\xB3V[a\\\xEA\x83aW\xC2V[_[\x83\x81\x10\x15a] Wa\\\xFE\x83\x87aW:V[a]\x08\x81\x84a\\\xB6V[` \x84\x01\x93P`\x02\x83\x01\x92PP`\x01\x81\x01\x90Pa\\\xECV[PPPPPPPV[a]4\x83\x83\x83a\\\xC4V[PPPV[_\x81\x01_\x83\x01\x80a]I\x81aV\x81V[\x90Pa]U\x81\x84aW\x17V[PPP`\x01\x81\x01` \x83\x01a]j\x81\x85aGrV[a]u\x81\x83\x86a])V[PPPP`\x02\x81\x01`@\x83\x01a]\x8B\x81\x85a[)V[a]\x96\x81\x83\x86a\\bV[PPPPPPV[a]\xA8\x82\x82a]9V[PPV[\x7Fanother maintenance in progress\0_\x82\x01RPV[_a]\xE0`\x1F\x83aAEV[\x91Pa]\xEB\x82a]\xACV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra^\r\x81a]\xD4V[\x90P\x91\x90PV[\x7Finvalid id\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a^H`\n\x83aAEV[\x91Pa^S\x82a^\x14V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra^u\x81a^\x91\x90a@\x1DV[a\x0C\xD1V[\0[a\x01_`\x04\x806\x03\x81\x01\x90a\x01Z\x91\x90a@\xC5V[a\x10;V[\0[a\x01ia\x11\x0BV[\0[a\x01\x85`\x04\x806\x03\x81\x01\x90a\x01\x80\x91\x90aA\x1AV[a\x12zV[\0[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x02\x15W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x02\x0C\x90aA\x9FV[`@Q\x80\x91\x03\x90\xFD[a\x02\x1F`\ta\x14\x0EV[`\n`\x08\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x02M\x90aA\xEAV[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\x8F\xB9\xCD\x05M\n\x02!\x10\xCC\xED#\x9E\x90\x8B\x83NL\xD2\x19Q\x18V\xD4\xEA\xAE0Q\xD92\xD6\x04`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x02\xD1\x91\x90aB0V[`@Q\x80\x91\x03\x90\xA1V[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x03iW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x03`\x90aA\x9FV[`@Q\x80\x91\x03\x90\xFD[\x80`\x01\x81\x81a\x03x\x91\x90aC\xC4V[\x90PPPV[a\x03\x923`\x05a\x14\xC6\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[`\n`\x08\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x03\xC0\x90aA\xEAV[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\xA7j\x8F\xC1\xA9\x02f\xDD\xEE\x897\xA1\x8E\x12\xF0\x1E\xAD\xE9F\xB3\xB6a\x97\xFF\xF2\x89\xAF\x92w\xC2\xBD%3`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x04F\x92\x91\x90aC\xE1V[`@Q\x80\x91\x03\x90\xA1_`\x05`\x03\x01_\x90T\x90a\x01\0\n\x90\x04`\xFF\x16`\xFF\x16\x11a\x08*W__\x90P[`\x05_\x01\x80T\x90P\x81\x10\x15a\x04\xDBWa\x04\xCE`\x05_\x01\x82\x81T\x81\x10a\x04\x96Wa\x04\x95aD\x08V[[\x90_R` _ \x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02a\x15\xE4\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x80\x80`\x01\x01\x91PPa\x04nV[P__\x90P[`\x05`\x01\x01\x80T\x90P\x81\x10\x15a\x07\x18Wa\x07\x0B`\x05`\x01\x01\x82\x81T\x81\x10a\x05\x0BWa\x05\naD\x08V[[\x90_R` _ \x90`\x03\x02\x01`@Q\x80``\x01`@R\x90\x81_\x82\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01`\x01\x82\x01\x80T\x80` \x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01_\x90[\x82\x82\x10\x15a\x06cW\x83\x82\x90_R` _ \x90`\x02\x02\x01`@Q\x80`@\x01`@R\x90\x81_\x82\x01T\x81R` \x01`\x01\x82\x01\x80Ta\x05\xD4\x90aDbV[\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01\x82\x80Ta\x06\0\x90aDbV[\x80\x15a\x06KW\x80`\x1F\x10a\x06\"Wa\x01\0\x80\x83T\x04\x02\x83R\x91` \x01\x91a\x06KV[\x82\x01\x91\x90_R` _ \x90[\x81T\x81R\x90`\x01\x01\x90` \x01\x80\x83\x11a\x06.W\x82\x90\x03`\x1F\x16\x82\x01\x91[PPPPP\x81RPP\x81R` \x01\x90`\x01\x01\x90a\x05\x9AV[PPPP\x81R` \x01`\x02\x82\x01\x80Ta\x06{\x90aDbV[\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01\x82\x80Ta\x06\xA7\x90aDbV[\x80\x15a\x06\xF2W\x80`\x1F\x10a\x06\xC9Wa\x01\0\x80\x83T\x04\x02\x83R\x91` \x01\x91a\x06\xF2V[\x82\x01\x91\x90_R` _ \x90[\x81T\x81R\x90`\x01\x01\x90` \x01\x80\x83\x11a\x06\xD5W\x82\x90\x03`\x1F\x16\x82\x01\x91[PPPPP\x81RPP`\x02a\x18v\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x80\x80`\x01\x01\x91PPa\x04\xE1V[P`\n_\x81\x81\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x07>\x90aD\x92V[\x91\x90a\x01\0\n\x81T\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPPa\x07o`\x05a\x1B\x03V[`\n`\x08\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x07\x9D\x90aA\xEAV[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\x11\xCEP\x16\x0Ef\x10\x057\xFDK\n\xE2m\xE6mQ\xDA\xB7\x13\xAD\x9213S\xA1\x8C$\xE8\xF6\xDA\xAB`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x08!\x91\x90aB0V[`@Q\x80\x91\x03\x90\xA1[V[a\x08@3`\x02a\x1B\xAC\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x08\x7FW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x08v\x90aE\x0BV[`@Q\x80\x91\x03\x90\xFD[a\x08\x953\x82`\x02a\x1D\x04\x90\x92\x91\x90c\xFF\xFF\xFF\xFF\x16V[`\n`\x08\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x08\xC3\x90aA\xEAV[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7Fj\xDF\xB8\x96\xD3@v\x81\xD0_\xB8t\xD4\xDF\xB7\x06\x8En*6\xF0\x9A\xCD8\xA3\xB7\xD0L\x01t_\xEE3\x82`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\tK\x93\x92\x91\x90aF3V[`@Q\x80\x91\x03\x90\xA1PV[a\t^a7FV[`@Q\x80`\xA0\x01`@R\x80a\ts`\x02a\x1D\x96V[\x81R` \x01a\t\x8F`\x02_\x01`\x05a\x1F\x99\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x81R` \x01`\t`@Q\x80` \x01`@R\x90\x81_\x82\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RPP\x81R` \x01`\n_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RP\x90P\x90V[a\nl3`\x02a\x1B\xAC\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\n\xABW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\n\xA2\x90aE\x0BV[`@Q\x80\x91\x03\x90\xFD[a\n\xBF3`\ta'\0\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[`\n`\x08\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\n\xED\x90aA\xEAV[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\xF9\x10g\xEBB\x0C(\xD3\x12He\xFC\x99nj\xA9\xD5A\xB9\xB4\xFE\xF9\x18\x8C\xB9e\xA6\xCCd\x91c\x8E3`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x0Bs\x92\x91\x90aC\xE1V[`@Q\x80\x91\x03\x90\xA1V[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x0C\x0BW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x0C\x02\x90aA\x9FV[`@Q\x80\x91\x03\x90\xFD[a\x0C\x15`\x05a('V[`\n`\x08\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x0CC\x90aA\xEAV[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\x9C\xE1\x92\xAE\xA5\xFA\xF2\x15\x1B\xBC$l\xD8\x91\x8D.\xBAp/\xA2iQ\xF6\x7F+\xF7\xB3\x81~h\x9D\x98`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x0C\xC7\x91\x90aB0V[`@Q\x80\x91\x03\x90\xA1V[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\r_W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\rV\x90aA\x9FV[`@Q\x80\x91\x03\x90\xFD[a\ri`\ta({V[\x15a\r\xA9W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\r\xA0\x90aF\xB9V[`@Q\x80\x91\x03\x90\xFD[__\x90P[\x84\x84\x90P\x81\x10\x15a\x0E@Wa\r\xF4\x85\x85\x83\x81\x81\x10a\r\xCFWa\r\xCEaD\x08V[[\x90P` \x02\x01` \x81\x01\x90a\r\xE4\x91\x90a@\xC5V[`\x02a\x1B\xAC\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x0E3W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x0E*\x90aG!V[`@Q\x80\x91\x03\x90\xFD[\x80\x80`\x01\x01\x91PPa\r\xAEV[P__\x90P[\x82\x82\x90P\x81\x10\x15a\x0F%Wa\x0E\x8F\x83\x83\x83\x81\x81\x10a\x0EgWa\x0EfaD\x08V[[\x90P` \x02\x81\x01\x90a\x0Ey\x91\x90aGKV[\x80` \x01\x90a\x0E\x88\x91\x90aGrV[\x90Pa(\xD5V[a\x0E\xD8\x83\x83\x83\x81\x81\x10a\x0E\xA5Wa\x0E\xA4aD\x08V[[\x90P` \x02\x81\x01\x90a\x0E\xB7\x91\x90aGKV[_\x01` \x81\x01\x90a\x0E\xC8\x91\x90a@\xC5V[`\x02a\x1B\xAC\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x15a\x0F\x18W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x0F\x0F\x90aH\x1EV[`@Q\x80\x91\x03\x90\xFD[\x80\x80`\x01\x01\x91PPa\x0EFV[Pa\x0FT\x82\x82\x90P\x85\x85\x90Pa\x0F;`\x02a)tV[a\x0FE\x91\x90aH&\x82\x82a=\xB0V[\x91PP` \x83\x01Q\x84\x82\x03` \x86\x01Ra>@\x82\x82a<\xCAV[\x91PP`@\x83\x01Q\x84\x82\x03`@\x86\x01Ra>Z\x82\x82a=\xB0V[\x91PP\x80\x91PP\x92\x91PPV[` \x82\x01_\x82\x01Qa>{_\x85\x01\x82a:\xCBV[PPPPV[_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[a>\x9D\x81a>\x81V[\x82RPPV[_o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[a>\xC7\x81a>\xA3V[\x82RPPV[_`\xA0\x83\x01_\x83\x01Q\x84\x82\x03_\x86\x01Ra>\xE7\x82\x82a==V[\x91PP` \x83\x01Q\x84\x82\x03` \x86\x01Ra?\x01\x82\x82a>\x0CV[\x91PP`@\x83\x01Qa?\x16`@\x86\x01\x82a>gV[P``\x83\x01Qa?)``\x86\x01\x82a>\x94V[P`\x80\x83\x01Qa?<`\x80\x86\x01\x82a>\xBEV[P\x80\x91PP\x92\x91PPV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra?_\x81\x84a>\xCDV[\x90P\x92\x91PPV[__\xFD[__\xFD[__\xFD[__\x83`\x1F\x84\x01\x12a?\x88Wa?\x87a?gV[[\x825\x90Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a?\xA5Wa?\xA4a?kV[[` \x83\x01\x91P\x83` \x82\x02\x83\x01\x11\x15a?\xC1Wa?\xC0a?oV[[\x92P\x92\x90PV[__\x83`\x1F\x84\x01\x12a?\xDDWa?\xDCa?gV[[\x825\x90Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a?\xFAWa?\xF9a?kV[[` \x83\x01\x91P\x83` \x82\x02\x83\x01\x11\x15a@\x16Wa@\x15a?oV[[\x92P\x92\x90PV[____`@\x85\x87\x03\x12\x15a@5Wa@4a9\xB8V[[_\x85\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a@RWa@Qa9\xBCV[[a@^\x87\x82\x88\x01a?sV[\x94P\x94PP` \x85\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a@\x81Wa@\x80a9\xBCV[[a@\x8D\x87\x82\x88\x01a?\xC8V[\x92P\x92PP\x92\x95\x91\x94P\x92PV[a@\xA4\x81a:\xBAV[\x81\x14a@\xAEW__\xFD[PV[_\x815\x90Pa@\xBF\x81a@\x9BV[\x92\x91PPV[_` \x82\x84\x03\x12\x15a@\xDAWa@\xD9a9\xB8V[[_a@\xE7\x84\x82\x85\x01a@\xB1V[\x91PP\x92\x91PPV[a@\xF9\x81a;\x03V[\x81\x14aA\x03W__\xFD[PV[_\x815\x90PaA\x14\x81a@\xF0V[\x92\x91PPV[_` \x82\x84\x03\x12\x15aA/WaA.a9\xB8V[[_aA<\x84\x82\x85\x01aA\x06V[\x91PP\x92\x91PPV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[\x7Fnot the owner\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aA\x89`\r\x83aAEV[\x91PaA\x94\x82aAUV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaA\xB6\x81aA}V[\x90P\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`\x11`\x04R`$_\xFD[_aA\xF4\x82a>\xA3V[\x91Po\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x03aB\x16WaB\x15aA\xBDV[[`\x01\x82\x01\x90P\x91\x90PV[aB*\x81a>\xA3V[\x82RPPV[_` \x82\x01\x90PaBC_\x83\x01\x84aB!V[\x92\x91PPV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R_`\x04R`$_\xFD[_`\xFF\x82\x16\x90P\x91\x90PV[aB\x8A\x81aBuV[\x81\x14aB\x94W__\xFD[PV[_\x815aB\xA3\x81aB\x81V[\x80\x91PP\x91\x90PV[_\x81_\x1B\x90P\x91\x90PV[_`\xFFaB\xC3\x84aB\xACV[\x93P\x80\x19\x83\x16\x92P\x80\x84\x16\x83\x17\x91PP\x92\x91PPV[_\x81\x90P\x91\x90PV[_aB\xFCaB\xF7aB\xF2\x84aBuV[aB\xD9V[aBuV[\x90P\x91\x90PV[_\x81\x90P\x91\x90PV[aC\x15\x82aB\xE2V[aC(aC!\x82aC\x03V[\x83TaB\xB7V[\x82UPPPV[_\x81`\x08\x1B\x90P\x91\x90PV[_a\xFF\0aCH\x84aC/V[\x93P\x80\x19\x83\x16\x92P\x80\x84\x16\x83\x17\x91PP\x92\x91PPV[aCg\x82aB\xE2V[aCzaCs\x82aC\x03V[\x83TaC;V[\x82UPPPV[_\x81\x01_\x83\x01\x80aC\x91\x81aB\x97V[\x90PaC\x9D\x81\x84aC\x0CV[PPP_\x81\x01` \x83\x01\x80aC\xB1\x81aB\x97V[\x90PaC\xBD\x81\x84aC^V[PPPPPV[aC\xCE\x82\x82aC\x81V[PPV[aC\xDB\x81a:\xBAV[\x82RPPV[_`@\x82\x01\x90PaC\xF4_\x83\x01\x85aC\xD2V[aD\x01` \x83\x01\x84aB!V[\x93\x92PPPV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`2`\x04R`$_\xFD[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`\"`\x04R`$_\xFD[_`\x02\x82\x04\x90P`\x01\x82\x16\x80aDyW`\x7F\x82\x16\x91P[` \x82\x10\x81\x03aD\x8CWaD\x8BaD5V[[P\x91\x90PV[_aD\x9C\x82a>\x81V[\x91Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x03aD\xB6WaD\xB5aA\xBDV[[`\x01\x82\x01\x90P\x91\x90PV[\x7Fnot an operator\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aD\xF5`\x0F\x83aAEV[\x91PaE\0\x82aD\xC1V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaE\"\x81aD\xE9V[\x90P\x91\x90PV[_aE7` \x84\x01\x84aA\x06V[\x90P\x92\x91PPV[__\xFD[__\xFD[__\xFD[__\x835`\x01` \x03\x846\x03\x03\x81\x12aEgWaEfaEGV[[\x83\x81\x01\x92P\x825\x91P` \x83\x01\x92Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15aE\x8FWaE\x8EaE?V[[`\x01\x82\x026\x03\x83\x13\x15aE\xA5WaE\xA4aECV[[P\x92P\x92\x90PV[\x82\x81\x837_\x83\x83\x01RPPPV[_aE\xC6\x83\x85a;%V[\x93PaE\xD3\x83\x85\x84aE\xADV[aE\xDC\x83a;CV[\x84\x01\x90P\x93\x92PPPV[_`@\x83\x01aE\xF8_\x84\x01\x84aE)V[aF\x04_\x86\x01\x82a;\x0CV[PaF\x12` \x84\x01\x84aEKV[\x85\x83\x03` \x87\x01RaF%\x83\x82\x84aE\xBBV[\x92PPP\x80\x91PP\x92\x91PPV[_``\x82\x01\x90PaFF_\x83\x01\x86aC\xD2V[\x81\x81\x03` \x83\x01RaFX\x81\x85aE\xE7V[\x90PaFg`@\x83\x01\x84aB!V[\x94\x93PPPPV[\x7Fmaintenance in progress\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aF\xA3`\x17\x83aAEV[\x91PaF\xAE\x82aFoV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaF\xD0\x81aF\x97V[\x90P\x91\x90PV[\x7Funknown operator\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aG\x0B`\x10\x83aAEV[\x91PaG\x16\x82aF\xD7V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaG8\x81aF\xFFV[\x90P\x91\x90PV[__\xFD[__\xFD[__\xFD[_\x825`\x01``\x03\x836\x03\x03\x81\x12aGfWaGeaG?V[[\x80\x83\x01\x91PP\x92\x91PPV[__\x835`\x01` \x03\x846\x03\x03\x81\x12aG\x8EWaG\x8DaG?V[[\x80\x84\x01\x92P\x825\x91Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15aG\xB0WaG\xAFaGCV[[` \x83\x01\x92P` \x82\x026\x03\x83\x13\x15aG\xCCWaG\xCBaGGV[[P\x92P\x92\x90PV[\x7Foperator already exists\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aH\x08`\x17\x83aAEV[\x91PaH\x13\x82aG\xD4V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaH5\x81aG\xFCV[\x90P\x91\x90PV[_aHF\x82a;\x03V[\x91PaHQ\x83a;\x03V[\x92P\x82\x82\x03\x90P\x81\x81\x11\x15aHiWaHhaA\xBDV[[\x92\x91PPV[_aHy\x82a;\x03V[\x91PaH\x84\x83a;\x03V[\x92P\x82\x82\x01\x90P\x80\x82\x11\x15aH\x9CWaH\x9BaA\xBDV[[\x92\x91PPV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[_\x81\x90P\x91\x90PV[_aH\xC9` \x84\x01\x84a@\xB1V[\x90P\x92\x91PPV[_` \x82\x01\x90P\x91\x90PV[_aH\xE8\x83\x85aH\xA2V[\x93PaH\xF3\x82aH\xB2V[\x80_[\x85\x81\x10\x15aI+WaI\x08\x82\x84aH\xBBV[aI\x12\x88\x82a=\x8DV[\x97PaI\x1D\x83aH\xD1V[\x92PP`\x01\x81\x01\x90PaH\xF6V[P\x85\x92PPP\x93\x92PPPV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[_\x81\x90P\x91\x90PV[__\x835`\x01` \x03\x846\x03\x03\x81\x12aImWaIlaEGV[[\x83\x81\x01\x92P\x825\x91P` \x83\x01\x92Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15aI\x95WaI\x94aE?V[[` \x82\x026\x03\x83\x13\x15aI\xABWaI\xAAaECV[[P\x92P\x92\x90PV[_\x81\x90P\x91\x90PV[_`@\x83\x01aI\xCD_\x84\x01\x84aE)V[aI\xD9_\x86\x01\x82a;\x0CV[PaI\xE7` \x84\x01\x84aEKV[\x85\x83\x03` \x87\x01RaI\xFA\x83\x82\x84aE\xBBV[\x92PPP\x80\x91PP\x92\x91PPV[_aJ\x13\x83\x83aI\xBCV[\x90P\x92\x91PPV[_\x825`\x01`@\x03\x836\x03\x03\x81\x12aJ6WaJ5aEGV[[\x82\x81\x01\x91PP\x92\x91PPV[_` \x82\x01\x90P\x91\x90PV[_aJY\x83\x85a:\xE4V[\x93P\x83` \x84\x02\x85\x01aJk\x84aI\xB3V[\x80_[\x87\x81\x10\x15aJ\xAEW\x84\x84\x03\x89RaJ\x85\x82\x84aJ\x1BV[aJ\x8F\x85\x82aJ\x08V[\x94PaJ\x9A\x83aJBV[\x92P` \x8A\x01\x99PP`\x01\x81\x01\x90PaJnV[P\x82\x97P\x87\x94PPPPP\x93\x92PPPV[_``\x83\x01aJ\xD1_\x84\x01\x84aH\xBBV[aJ\xDD_\x86\x01\x82a:\xCBV[PaJ\xEB` \x84\x01\x84aIQV[\x85\x83\x03` \x87\x01RaJ\xFE\x83\x82\x84aJNV[\x92PPPaK\x0F`@\x84\x01\x84aEKV[\x85\x83\x03`@\x87\x01RaK\"\x83\x82\x84aE\xBBV[\x92PPP\x80\x91PP\x92\x91PPV[_aK;\x83\x83aJ\xC0V[\x90P\x92\x91PPV[_\x825`\x01``\x03\x836\x03\x03\x81\x12aK^WaK]aEGV[[\x82\x81\x01\x91PP\x92\x91PPV[_` \x82\x01\x90P\x91\x90PV[_aK\x81\x83\x85aI8V[\x93P\x83` \x84\x02\x85\x01aK\x93\x84aIHV[\x80_[\x87\x81\x10\x15aK\xD6W\x84\x84\x03\x89RaK\xAD\x82\x84aKCV[aK\xB7\x85\x82aK0V[\x94PaK\xC2\x83aKjV[\x92P` \x8A\x01\x99PP`\x01\x81\x01\x90PaK\x96V[P\x82\x97P\x87\x94PPPPP\x93\x92PPPV[_``\x82\x01\x90P\x81\x81\x03_\x83\x01RaL\x01\x81\x87\x89aH\xDDV[\x90P\x81\x81\x03` \x83\x01RaL\x16\x81\x85\x87aKvV[\x90PaL%`@\x83\x01\x84aB!V[\x96\x95PPPPPPV[\x7Fmigration in progress\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aLc`\x15\x83aAEV[\x91PaLn\x82aL/V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaL\x90\x81aLWV[\x90P\x91\x90PV[\x7Ftoo few nodes\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aL\xCB`\r\x83aAEV[\x91PaL\xD6\x82aL\x97V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaL\xF8\x81aL\xBFV[\x90P\x91\x90PV[aM\x08\x81a;\x03V[\x82RPPV[_``\x82\x01\x90PaM!_\x83\x01\x86aC\xD2V[aM.` \x83\x01\x85aL\xFFV[aM;`@\x83\x01\x84aB!V[\x94\x93PPPPV[\x7Fnot under maintenance\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aMw`\x15\x83aAEV[\x91PaM\x82\x82aMCV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaM\xA4\x81aMkV[\x90P\x91\x90PV[\x7Fnot pulling\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aM\xDF`\x0B\x83aAEV[\x91PaM\xEA\x82aM\xABV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaN\x0C\x81aM\xD3V[\x90P\x91\x90PV[_aN\x1D\x82aBuV[\x91P_\x82\x03aN/WaN.aA\xBDV[[`\x01\x82\x03\x90P\x91\x90PV[\x7Finvalid address\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aNn`\x0F\x83aAEV[\x91PaNy\x82aN:V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaN\x9B\x81aNbV[\x90P\x91\x90PV[\x7Foperator doesn't exist\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aN\xD6`\x16\x83aAEV[\x91PaN\xE1\x82aN\xA2V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaO\x03\x81aN\xCAV[\x90P\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`1`\x04R`$_\xFD[\x7Ftoo many operators\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aOk`\x12\x83aAEV[\x91PaOv\x82aO7V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaO\x98\x81aO_V[\x90P\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`A`\x04R`$_\xFD[_\x81\x90P\x81_R` _ \x90P\x91\x90PV[_` `\x1F\x83\x01\x04\x90P\x91\x90PV[_\x82\x82\x1B\x90P\x92\x91PPV[_`\x08\x83\x02aP(\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82aO\xEDV[aP2\x86\x83aO\xEDV[\x95P\x80\x19\x84\x16\x93P\x80\x86\x16\x84\x17\x92PPP\x93\x92PPPV[_aPdaP_aPZ\x84a;\x03V[aB\xD9V[a;\x03V[\x90P\x91\x90PV[_\x81\x90P\x91\x90PV[aP}\x83aPJV[aP\x91aP\x89\x82aPkV[\x84\x84TaO\xF9V[\x82UPPPPV[__\x90P\x90V[aP\xA8aP\x99V[aP\xB3\x81\x84\x84aPtV[PPPV[[\x81\x81\x10\x15aP\xD6WaP\xCB_\x82aP\xA0V[`\x01\x81\x01\x90PaP\xB9V[PPV[`\x1F\x82\x11\x15aQ\x1BWaP\xEC\x81aO\xCCV[aP\xF5\x84aO\xDEV[\x81\x01` \x85\x10\x15aQ\x04W\x81\x90P[aQ\x18aQ\x10\x85aO\xDEV[\x83\x01\x82aP\xB8V[PP[PPPV[_\x82\x82\x1C\x90P\x92\x91PPV[_aQ;_\x19\x84`\x08\x02aQ V[\x19\x80\x83\x16\x91PP\x92\x91PPV[_aQS\x83\x83aQ,V[\x91P\x82`\x02\x02\x82\x17\x90P\x92\x91PPV[aQl\x82a;\x1BV[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15aQ\x85WaQ\x84aO\x9FV[[aQ\x8F\x82TaDbV[aQ\x9A\x82\x82\x85aP\xDAV[_` \x90P`\x1F\x83\x11`\x01\x81\x14aQ\xCBW_\x84\x15aQ\xB9W\x82\x87\x01Q\x90P[aQ\xC3\x85\x82aQHV[\x86UPaR*V[`\x1F\x19\x84\x16aQ\xD9\x86aO\xCCV[_[\x82\x81\x10\x15aR\0W\x84\x89\x01Q\x82U`\x01\x82\x01\x91P` \x85\x01\x94P` \x81\x01\x90PaQ\xDBV[\x86\x83\x10\x15aR\x1DW\x84\x89\x01QaR\x19`\x1F\x89\x16\x82aQ,V[\x83UP[`\x01`\x02\x88\x02\x01\x88UPPP[PPPPPPV[\x7Fnot in progress\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aRf`\x0F\x83aAEV[\x91PaRq\x82aR2V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaR\x93\x81aRZV[\x90P\x91\x90PV[\x7Fdata pull in progress\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aR\xCE`\x15\x83aAEV[\x91PaR\xD9\x82aR\x9AV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaR\xFB\x81aR\xC2V[\x90P\x91\x90PV[__\xFD[aS\x0F\x82a;CV[\x81\x01\x81\x81\x10g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x17\x15aS.WaS-aO\x9FV[[\x80`@RPPPV[_aS@a9\xAFV[\x90PaSL\x82\x82aS\x06V[\x91\x90PV[__\xFD[__\xFD[_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15aSsWaSraO\x9FV[[aS|\x82a;CV[\x90P` \x81\x01\x90P\x91\x90PV[_aS\x9BaS\x96\x84aSYV[aS7V[\x90P\x82\x81R` \x81\x01\x84\x84\x84\x01\x11\x15aS\xB7WaS\xB6aSUV[[aS\xC2\x84\x82\x85aE\xADV[P\x93\x92PPPV[_\x82`\x1F\x83\x01\x12aS\xDEWaS\xDDa?gV[[\x815aS\xEE\x84\x82` \x86\x01aS\x89V[\x91PP\x92\x91PPV[_`@\x82\x84\x03\x12\x15aT\x0CWaT\x0BaS\x02V[[aT\x16`@aS7V[\x90P_aT%\x84\x82\x85\x01aA\x06V[_\x83\x01RP` \x82\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15aTHWaTGaSQV[[aTT\x84\x82\x85\x01aS\xCAV[` \x83\x01RP\x92\x91PPV[_aTk6\x83aS\xF7V[\x90P\x91\x90PV[_aT|\x82a;\x03V[\x91P\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x03aT\xAEWaT\xADaA\xBDV[[`\x01\x82\x01\x90P\x91\x90PV[\x7Ftoo many nodes\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aT\xED`\x0E\x83aAEV[\x91PaT\xF8\x82aT\xB9V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaU\x1A\x81aT\xE1V[\x90P\x91\x90PV[\x7Ftoo few operators\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aUU`\x11\x83aAEV[\x91PaU`\x82aU!V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaU\x82\x81aUIV[\x90P\x91\x90PV[\x7Fmigration already in progress\0\0\0_\x82\x01RPV[_aU\xBD`\x1D\x83aAEV[\x91PaU\xC8\x82aU\x89V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaU\xEA\x81aU\xB1V[\x90P\x91\x90PV[\x7Fnothing to do\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aV%`\r\x83aAEV[\x91PaV0\x82aU\xF1V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaVR\x81aV\x19V[\x90P\x91\x90PV[_aVc\x82aBuV[\x91P`\xFF\x82\x03aVvWaVuaA\xBDV[[`\x01\x82\x01\x90P\x91\x90PV[_\x815aV\x8D\x81a@\x9BV[\x80\x91PP\x91\x90PV[_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFFaV\xB5\x84aB\xACV[\x93P\x80\x19\x83\x16\x92P\x80\x84\x16\x83\x17\x91PP\x92\x91PPV[_aV\xE5aV\xE0aV\xDB\x84a:\x9BV[aB\xD9V[a:\x9BV[\x90P\x91\x90PV[_aV\xF6\x82aV\xCBV[\x90P\x91\x90PV[_aW\x07\x82aV\xECV[\x90P\x91\x90PV[_\x81\x90P\x91\x90PV[aW \x82aV\xFDV[aW3aW,\x82aW\x0EV[\x83TaV\x96V[\x82UPPPV[_\x825`\x01`@\x03\x836\x03\x03\x81\x12aWUWaWTaG?V[[\x80\x83\x01\x91PP\x92\x91PPV[_\x81T\x90P\x91\x90PV[_aWu\x82a;\x03V[\x91PaW\x80\x83a;\x03V[\x92P\x82\x82\x02aW\x8E\x81a;\x03V[\x91P\x82\x82\x04\x84\x14\x83\x15\x17aW\xA5WaW\xA4aA\xBDV[[P\x92\x91PPV[_\x81\x90PaW\xBB\x82`\x02aWkV[\x90P\x91\x90PV[_\x81\x90P\x81_R` _ \x90P\x91\x90PV[aX\x04\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x83` \x03`\x08\x02aQ V[\x81T\x81\x16\x82UPPPV[aX\x18\x81aO\xCCV[aX#\x83\x82TaQHV[\x80\x83U_\x82UPPPPV[` \x84\x10_\x81\x14aX\x89W`\x1F\x84\x11`\x01\x81\x14aXWWaXP\x86\x85aQHV[\x83UaX\x83V[aX`\x83aO\xCCV[aXwaXl\x87aO\xDEV[\x82\x01`\x01\x83\x01aP\xB8V[aX\x81\x87\x85aX\x0FV[P[PaX\xD6V[aX\x92\x82aO\xCCV[aX\x9B\x86aO\xDEV[\x81\x01`\x1F\x87\x16\x80\x15aX\xB5WaX\xB4\x81`\x01\x84\x03aW\xD4V[[aX\xC9aX\xC1\x88aO\xDEV[\x84\x01\x83aP\xB8V[`\x01\x88`\x02\x02\x17\x85UPPP[PPPPPV[h\x01\0\0\0\0\0\0\0\0\x84\x11\x15aX\xF7WaX\xF6aO\x9FV[[` \x83\x10_\x81\x14aY@W` \x85\x10_\x81\x14aY\x1EWaY\x17\x86\x85aQHV[\x83UaY:V[\x83`\xFF\x19\x16\x93P\x83aY/\x84aO\xCCV[U`\x01\x86`\x02\x02\x01\x83U[PaYJV[`\x01\x85`\x02\x02\x01\x82U[PPPPPV[\x80TaY\\\x81aDbV[\x80\x84\x11\x15aYqWaYp\x84\x82\x84\x86aX\xDDV[[\x80\x84\x10\x15aY\x86WaY\x85\x84\x82\x84\x86aX/V[[PPPPV[\x81\x81\x10\x15aY\xA9WaY\x9E_\x82aP\xA0V[`\x01\x81\x01\x90PaY\x8CV[PPV[aY\xB7_\x82aYQV[PV[_\x82\x14aY\xCAWaY\xC9aBIV[[aY\xD3\x81aY\xADV[PPV[aY\xE3__\x83\x01aP\xA0V[aY\xF0_`\x01\x83\x01aY\xBAV[PV[_\x82\x14aZ\x03WaZ\x02aBIV[[aZ\x0C\x81aY\xD7V[PPV[[\x81\x81\x10\x15aZ.WaZ#_\x82aY\xF3V[`\x02\x81\x01\x90PaZ\x11V[PPV[\x81\x83\x10\x15aZkWaZC\x82aW\xACV[aZL\x84aW\xACV[aZU\x83aW\xC2V[\x81\x81\x01\x83\x82\x01aZe\x81\x83aZ\x10V[PPPPP[PPPV[h\x01\0\0\0\0\0\0\0\0\x82\x11\x15aZ\x8AWaZ\x89aO\x9FV[[aZ\x93\x81aWaV[\x82\x82UaZ\xA1\x83\x82\x84aZ2V[PPPV[_\x82\x90P\x92\x91PPV[_\x815aZ\xBC\x81a@\xF0V[\x80\x91PP\x91\x90PV[_\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFFaZ\xF0\x84aB\xACV[\x93P\x80\x19\x83\x16\x92P\x80\x84\x16\x83\x17\x91PP\x92\x91PPV[a[\x0F\x82aPJV[a[\"a[\x1B\x82aPkV[\x83TaZ\xC5V[\x82UPPPV[__\x835`\x01` \x03\x846\x03\x03\x81\x12a[EWa[DaG?V[[\x80\x84\x01\x92P\x825\x91Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15a[gWa[faGCV[[` \x83\x01\x92P`\x01\x82\x026\x03\x83\x13\x15a[\x83Wa[\x82aGGV[[P\x92P\x92\x90PV[_\x82\x90P\x92\x91PPV[a[\x9F\x83\x83a[\x8BV[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a[\xB8Wa[\xB7aO\x9FV[[a[\xC2\x82TaDbV[a[\xCD\x82\x82\x85aP\xDAV[_`\x1F\x83\x11`\x01\x81\x14a[\xFAW_\x84\x15a[\xE8W\x82\x87\x015\x90P[a[\xF2\x85\x82aQHV[\x86UPa\\YV[`\x1F\x19\x84\x16a\\\x08\x86aO\xCCV[_[\x82\x81\x10\x15a\\/W\x84\x89\x015\x82U`\x01\x82\x01\x91P` \x85\x01\x94P` \x81\x01\x90Pa\\\nV[\x86\x83\x10\x15a\\LW\x84\x89\x015a\\H`\x1F\x89\x16\x82aQ,V[\x83UP[`\x01`\x02\x88\x02\x01\x88UPPP[PPPPPPPV[a\\m\x83\x83\x83a[\x95V[PPPV[_\x81\x01_\x83\x01\x80a\\\x82\x81aZ\xB0V[\x90Pa\\\x8E\x81\x84a[\x06V[PPP`\x01\x81\x01` \x83\x01a\\\xA3\x81\x85a[)V[a\\\xAE\x81\x83\x86a\\bV[PPPPPPV[a\\\xC0\x82\x82a\\rV[PPV[a\\\xCE\x83\x83aZ\xA6V[a\\\xD8\x81\x83aZpV[a\\\xE1\x83aI\xB3V[a\\\xEA\x83aW\xC2V[_[\x83\x81\x10\x15a] Wa\\\xFE\x83\x87aW:V[a]\x08\x81\x84a\\\xB6V[` \x84\x01\x93P`\x02\x83\x01\x92PP`\x01\x81\x01\x90Pa\\\xECV[PPPPPPPV[a]4\x83\x83\x83a\\\xC4V[PPPV[_\x81\x01_\x83\x01\x80a]I\x81aV\x81V[\x90Pa]U\x81\x84aW\x17V[PPP`\x01\x81\x01` \x83\x01a]j\x81\x85aGrV[a]u\x81\x83\x86a])V[PPPP`\x02\x81\x01`@\x83\x01a]\x8B\x81\x85a[)V[a]\x96\x81\x83\x86a\\bV[PPPPPPV[a]\xA8\x82\x82a]9V[PPV[\x7Fanother maintenance in progress\0_\x82\x01RPV[_a]\xE0`\x1F\x83aAEV[\x91Pa]\xEB\x82a]\xACV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra^\r\x81a]\xD4V[\x90P\x91\x90PV[\x7Finvalid id\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a^H`\n\x83aAEV[\x91Pa^S\x82a^\x14V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra^u\x81a^::RustType, - #[allow(missing_docs)] - pub migration: ::RustType, - #[allow(missing_docs)] - pub maintenance: ::RustType, - #[allow(missing_docs)] - pub keyspaceVersion: u64, - #[allow(missing_docs)] - pub version: u128, - } - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - #[doc(hidden)] - type UnderlyingSolTuple<'a> = ( - NodeOperatorsView, - MigrationView, - Maintenance, - alloy::sol_types::sol_data::Uint<64>, - alloy::sol_types::sol_data::Uint<128>, - ); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = ( - ::RustType, - ::RustType, - ::RustType, - u64, - u128, - ); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: ClusterView) -> Self { - ( - value.operators, - value.migration, - value.maintenance, - value.keyspaceVersion, - value.version, - ) - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for ClusterView { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self { - operators: tuple.0, - migration: tuple.1, - maintenance: tuple.2, - keyspaceVersion: tuple.3, - version: tuple.4, - } - } - } - #[automatically_derived] - impl alloy_sol_types::SolValue for ClusterView { - type SolType = Self; - } - #[automatically_derived] - impl alloy_sol_types::private::SolTypeValue for ClusterView { - #[inline] - fn stv_to_tokens(&self) -> ::Token<'_> { - ( - ::tokenize(&self.operators), - ::tokenize(&self.migration), - ::tokenize(&self.maintenance), - as alloy_sol_types::SolType>::tokenize( - &self.keyspaceVersion, - ), - as alloy_sol_types::SolType>::tokenize( - &self.version, - ), - ) - } - #[inline] - fn stv_abi_encoded_size(&self) -> usize { - if let Some(size) = ::ENCODED_SIZE { - return size; - } - let tuple = - as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_encoded_size(&tuple) - } - #[inline] - fn stv_eip712_data_word(&self) -> alloy_sol_types::Word { - ::eip712_hash_struct(self) - } - #[inline] - fn stv_abi_encode_packed_to(&self, out: &mut alloy_sol_types::private::Vec) { - let tuple = - as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_encode_packed_to( - &tuple, out, - ) - } - #[inline] - fn stv_abi_packed_encoded_size(&self) -> usize { - if let Some(size) = ::PACKED_ENCODED_SIZE { - return size; - } - let tuple = - as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_packed_encoded_size( - &tuple, - ) - } - } - #[automatically_derived] - impl alloy_sol_types::SolType for ClusterView { - type RustType = Self; - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SOL_NAME: &'static str = ::NAME; - const ENCODED_SIZE: Option = - as alloy_sol_types::SolType>::ENCODED_SIZE; - const PACKED_ENCODED_SIZE: Option = - as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; - #[inline] - fn valid_token(token: &Self::Token<'_>) -> bool { - as alloy_sol_types::SolType>::valid_token(token) - } - #[inline] - fn detokenize(token: Self::Token<'_>) -> Self::RustType { - let tuple = as alloy_sol_types::SolType>::detokenize(token); - >>::from(tuple) - } - } - #[automatically_derived] - impl alloy_sol_types::SolStruct for ClusterView { - const NAME: &'static str = "ClusterView"; - #[inline] - fn eip712_root_type() -> alloy_sol_types::private::Cow<'static, str> { - alloy_sol_types::private::Cow::Borrowed( - "ClusterView(NodeOperatorsView operators,MigrationView migration,Maintenance \ - maintenance,uint64 keyspaceVersion,uint128 version)", - ) - } - #[inline] - fn eip712_components( - ) -> alloy_sol_types::private::Vec> - { - let mut components = alloy_sol_types::private::Vec::with_capacity(3); - components - .push(::eip712_root_type()); - components - .extend(::eip712_components()); - components.push(::eip712_root_type()); - components - .extend(::eip712_components()); - components.push(::eip712_root_type()); - components.extend(::eip712_components()); - components - } - #[inline] - fn eip712_encode_data(&self) -> alloy_sol_types::private::Vec { - [ - ::eip712_data_word( - &self.operators, - ) - .0, - ::eip712_data_word( - &self.migration, - ) - .0, - ::eip712_data_word( - &self.maintenance, - ) - .0, - as alloy_sol_types::SolType>::eip712_data_word( - &self.keyspaceVersion, - ) - .0, - as alloy_sol_types::SolType>::eip712_data_word(&self.version) - .0, - ] - .concat() - } - } - #[automatically_derived] - impl alloy_sol_types::EventTopic for ClusterView { - #[inline] - fn topic_preimage_length(rust: &Self::RustType) -> usize { - 0usize - + ::topic_preimage_length( - &rust.operators, - ) - + ::topic_preimage_length( - &rust.migration, - ) - + ::topic_preimage_length( - &rust.maintenance, - ) - + as alloy_sol_types::EventTopic>::topic_preimage_length( - &rust.keyspaceVersion, - ) - + as alloy_sol_types::EventTopic>::topic_preimage_length( - &rust.version, - ) - } - #[inline] - fn encode_topic_preimage( - rust: &Self::RustType, - out: &mut alloy_sol_types::private::Vec, - ) { - out.reserve(::topic_preimage_length(rust)); - ::encode_topic_preimage( - &rust.operators, - out, - ); - ::encode_topic_preimage( - &rust.migration, - out, - ); - ::encode_topic_preimage( - &rust.maintenance, - out, - ); - as alloy_sol_types::EventTopic>::encode_topic_preimage( - &rust.keyspaceVersion, - out, - ); - as alloy_sol_types::EventTopic>::encode_topic_preimage( - &rust.version, - out, - ); - } - #[inline] - fn encode_topic(rust: &Self::RustType) -> alloy_sol_types::abi::token::WordToken { - let mut out = alloy_sol_types::private::Vec::new(); - ::encode_topic_preimage(rust, &mut out); - alloy_sol_types::abi::token::WordToken(alloy_sol_types::private::keccak256(out)) - } - } - }; - /// ```solidity - /// struct Maintenance { address slot; } - /// ``` - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct Maintenance { - #[allow(missing_docs)] - pub slot: alloy::sol_types::private::Address, - } - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - #[doc(hidden)] - type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Address,); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = (alloy::sol_types::private::Address,); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: Maintenance) -> Self { - (value.slot,) - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for Maintenance { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self { slot: tuple.0 } - } - } - #[automatically_derived] - impl alloy_sol_types::SolValue for Maintenance { - type SolType = Self; - } - #[automatically_derived] - impl alloy_sol_types::private::SolTypeValue for Maintenance { - #[inline] - fn stv_to_tokens(&self) -> ::Token<'_> { - ( - ::tokenize( - &self.slot, - ), - ) - } - #[inline] - fn stv_abi_encoded_size(&self) -> usize { - if let Some(size) = ::ENCODED_SIZE { - return size; - } - let tuple = - as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_encoded_size(&tuple) - } - #[inline] - fn stv_eip712_data_word(&self) -> alloy_sol_types::Word { - ::eip712_hash_struct(self) - } - #[inline] - fn stv_abi_encode_packed_to(&self, out: &mut alloy_sol_types::private::Vec) { - let tuple = - as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_encode_packed_to( - &tuple, out, - ) - } - #[inline] - fn stv_abi_packed_encoded_size(&self) -> usize { - if let Some(size) = ::PACKED_ENCODED_SIZE { - return size; - } - let tuple = - as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_packed_encoded_size( - &tuple, - ) - } - } - #[automatically_derived] - impl alloy_sol_types::SolType for Maintenance { - type RustType = Self; - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SOL_NAME: &'static str = ::NAME; - const ENCODED_SIZE: Option = - as alloy_sol_types::SolType>::ENCODED_SIZE; - const PACKED_ENCODED_SIZE: Option = - as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; - #[inline] - fn valid_token(token: &Self::Token<'_>) -> bool { - as alloy_sol_types::SolType>::valid_token(token) - } - #[inline] - fn detokenize(token: Self::Token<'_>) -> Self::RustType { - let tuple = as alloy_sol_types::SolType>::detokenize(token); - >>::from(tuple) - } - } - #[automatically_derived] - impl alloy_sol_types::SolStruct for Maintenance { - const NAME: &'static str = "Maintenance"; - #[inline] - fn eip712_root_type() -> alloy_sol_types::private::Cow<'static, str> { - alloy_sol_types::private::Cow::Borrowed("Maintenance(address slot)") - } - #[inline] - fn eip712_components( - ) -> alloy_sol_types::private::Vec> - { - alloy_sol_types::private::Vec::new() - } - #[inline] - fn eip712_encode_type() -> alloy_sol_types::private::Cow<'static, str> { - ::eip712_root_type() - } - #[inline] - fn eip712_encode_data(&self) -> alloy_sol_types::private::Vec { - ::eip712_data_word( - &self.slot, - ) - .0 - .to_vec() - } - } - #[automatically_derived] - impl alloy_sol_types::EventTopic for Maintenance { - #[inline] - fn topic_preimage_length(rust: &Self::RustType) -> usize { - 0usize - + ::topic_preimage_length( - &rust.slot, - ) - } - #[inline] - fn encode_topic_preimage( - rust: &Self::RustType, - out: &mut alloy_sol_types::private::Vec, - ) { - out.reserve(::topic_preimage_length(rust)); - ::encode_topic_preimage( - &rust.slot, - out, - ); - } - #[inline] - fn encode_topic(rust: &Self::RustType) -> alloy_sol_types::abi::token::WordToken { - let mut out = alloy_sol_types::private::Vec::new(); - ::encode_topic_preimage(rust, &mut out); - alloy_sol_types::abi::token::WordToken(alloy_sol_types::private::keccak256(out)) - } - } - }; - /// ```solidity - /// struct MigrationView { address[] operatorsToRemove; NodeOperatorView[] operatorsToAdd; address[] pullingOperators; } - /// ``` - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct MigrationView { - #[allow(missing_docs)] - pub operatorsToRemove: alloy::sol_types::private::Vec, - #[allow(missing_docs)] - pub operatorsToAdd: alloy::sol_types::private::Vec< - ::RustType, - >, - #[allow(missing_docs)] - pub pullingOperators: alloy::sol_types::private::Vec, - } - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - #[doc(hidden)] - type UnderlyingSolTuple<'a> = ( - alloy::sol_types::sol_data::Array, - alloy::sol_types::sol_data::Array, - alloy::sol_types::sol_data::Array, - ); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = ( - alloy::sol_types::private::Vec, - alloy::sol_types::private::Vec< - ::RustType, - >, - alloy::sol_types::private::Vec, - ); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: MigrationView) -> Self { - ( - value.operatorsToRemove, - value.operatorsToAdd, - value.pullingOperators, - ) - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for MigrationView { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self { - operatorsToRemove: tuple.0, - operatorsToAdd: tuple.1, - pullingOperators: tuple.2, - } - } - } - #[automatically_derived] - impl alloy_sol_types::SolValue for MigrationView { - type SolType = Self; - } - #[automatically_derived] - impl alloy_sol_types::private::SolTypeValue for MigrationView { - #[inline] - fn stv_to_tokens(&self) -> ::Token<'_> { - ( - as alloy_sol_types::SolType>::tokenize(&self.operatorsToRemove), - as alloy_sol_types::SolType>::tokenize(&self.operatorsToAdd), - as alloy_sol_types::SolType>::tokenize(&self.pullingOperators), - ) - } - #[inline] - fn stv_abi_encoded_size(&self) -> usize { - if let Some(size) = ::ENCODED_SIZE { - return size; - } - let tuple = - as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_encoded_size(&tuple) - } - #[inline] - fn stv_eip712_data_word(&self) -> alloy_sol_types::Word { - ::eip712_hash_struct(self) - } - #[inline] - fn stv_abi_encode_packed_to(&self, out: &mut alloy_sol_types::private::Vec) { - let tuple = - as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_encode_packed_to( - &tuple, out, - ) - } - #[inline] - fn stv_abi_packed_encoded_size(&self) -> usize { - if let Some(size) = ::PACKED_ENCODED_SIZE { - return size; - } - let tuple = - as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_packed_encoded_size( - &tuple, - ) - } - } - #[automatically_derived] - impl alloy_sol_types::SolType for MigrationView { - type RustType = Self; - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SOL_NAME: &'static str = ::NAME; - const ENCODED_SIZE: Option = - as alloy_sol_types::SolType>::ENCODED_SIZE; - const PACKED_ENCODED_SIZE: Option = - as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; - #[inline] - fn valid_token(token: &Self::Token<'_>) -> bool { - as alloy_sol_types::SolType>::valid_token(token) - } - #[inline] - fn detokenize(token: Self::Token<'_>) -> Self::RustType { - let tuple = as alloy_sol_types::SolType>::detokenize(token); - >>::from(tuple) - } - } - #[automatically_derived] - impl alloy_sol_types::SolStruct for MigrationView { - const NAME: &'static str = "MigrationView"; - #[inline] - fn eip712_root_type() -> alloy_sol_types::private::Cow<'static, str> { - alloy_sol_types::private::Cow::Borrowed( - "MigrationView(address[] operatorsToRemove,NodeOperatorView[] \ - operatorsToAdd,address[] pullingOperators)", - ) - } - #[inline] - fn eip712_components( - ) -> alloy_sol_types::private::Vec> - { - let mut components = alloy_sol_types::private::Vec::with_capacity(1); - components - .push(::eip712_root_type()); - components - .extend(::eip712_components()); - components - } - #[inline] - fn eip712_encode_data(&self) -> alloy_sol_types::private::Vec { - [ - as alloy_sol_types::SolType>::eip712_data_word( - &self.operatorsToRemove, - ) - .0, - as alloy_sol_types::SolType>::eip712_data_word( - &self.operatorsToAdd, - ) - .0, - as alloy_sol_types::SolType>::eip712_data_word( - &self.pullingOperators, - ) - .0, - ] - .concat() - } - } - #[automatically_derived] - impl alloy_sol_types::EventTopic for MigrationView { - #[inline] - fn topic_preimage_length(rust: &Self::RustType) -> usize { - 0usize - + as alloy_sol_types::EventTopic>::topic_preimage_length( - &rust.operatorsToRemove, - ) - + as alloy_sol_types::EventTopic>::topic_preimage_length( - &rust.operatorsToAdd, - ) - + as alloy_sol_types::EventTopic>::topic_preimage_length( - &rust.pullingOperators, - ) - } - #[inline] - fn encode_topic_preimage( - rust: &Self::RustType, - out: &mut alloy_sol_types::private::Vec, - ) { - out.reserve(::topic_preimage_length(rust)); - as alloy_sol_types::EventTopic>::encode_topic_preimage( - &rust.operatorsToRemove, - out, - ); - as alloy_sol_types::EventTopic>::encode_topic_preimage( - &rust.operatorsToAdd, - out, - ); - as alloy_sol_types::EventTopic>::encode_topic_preimage( - &rust.pullingOperators, - out, - ); - } - #[inline] - fn encode_topic(rust: &Self::RustType) -> alloy_sol_types::abi::token::WordToken { - let mut out = alloy_sol_types::private::Vec::new(); - ::encode_topic_preimage(rust, &mut out); - alloy_sol_types::abi::token::WordToken(alloy_sol_types::private::keccak256(out)) - } - } - }; - /// ```solidity - /// struct Node { uint256 id; bytes data; } - /// ``` - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct Node { - #[allow(missing_docs)] - pub id: alloy::sol_types::private::primitives::aliases::U256, - #[allow(missing_docs)] - pub data: alloy::sol_types::private::Bytes, - } - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - #[doc(hidden)] - type UnderlyingSolTuple<'a> = ( - alloy::sol_types::sol_data::Uint<256>, - alloy::sol_types::sol_data::Bytes, - ); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = ( - alloy::sol_types::private::primitives::aliases::U256, - alloy::sol_types::private::Bytes, - ); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: Node) -> Self { - (value.id, value.data) - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for Node { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self { - id: tuple.0, - data: tuple.1, - } - } - } - #[automatically_derived] - impl alloy_sol_types::SolValue for Node { - type SolType = Self; - } - #[automatically_derived] - impl alloy_sol_types::private::SolTypeValue for Node { - #[inline] - fn stv_to_tokens(&self) -> ::Token<'_> { - ( - as alloy_sol_types::SolType>::tokenize( - &self.id, - ), - ::tokenize( - &self.data, - ), - ) - } - #[inline] - fn stv_abi_encoded_size(&self) -> usize { - if let Some(size) = ::ENCODED_SIZE { - return size; - } - let tuple = - as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_encoded_size(&tuple) - } - #[inline] - fn stv_eip712_data_word(&self) -> alloy_sol_types::Word { - ::eip712_hash_struct(self) - } - #[inline] - fn stv_abi_encode_packed_to(&self, out: &mut alloy_sol_types::private::Vec) { - let tuple = - as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_encode_packed_to( - &tuple, out, - ) - } - #[inline] - fn stv_abi_packed_encoded_size(&self) -> usize { - if let Some(size) = ::PACKED_ENCODED_SIZE { - return size; - } - let tuple = - as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_packed_encoded_size( - &tuple, - ) - } - } - #[automatically_derived] - impl alloy_sol_types::SolType for Node { - type RustType = Self; - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SOL_NAME: &'static str = ::NAME; - const ENCODED_SIZE: Option = - as alloy_sol_types::SolType>::ENCODED_SIZE; - const PACKED_ENCODED_SIZE: Option = - as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; - #[inline] - fn valid_token(token: &Self::Token<'_>) -> bool { - as alloy_sol_types::SolType>::valid_token(token) - } - #[inline] - fn detokenize(token: Self::Token<'_>) -> Self::RustType { - let tuple = as alloy_sol_types::SolType>::detokenize(token); - >>::from(tuple) - } - } - #[automatically_derived] - impl alloy_sol_types::SolStruct for Node { - const NAME: &'static str = "Node"; - #[inline] - fn eip712_root_type() -> alloy_sol_types::private::Cow<'static, str> { - alloy_sol_types::private::Cow::Borrowed("Node(uint256 id,bytes data)") - } - #[inline] - fn eip712_components( - ) -> alloy_sol_types::private::Vec> - { - alloy_sol_types::private::Vec::new() - } - #[inline] - fn eip712_encode_type() -> alloy_sol_types::private::Cow<'static, str> { - ::eip712_root_type() - } - #[inline] - fn eip712_encode_data(&self) -> alloy_sol_types::private::Vec { - [ - as alloy_sol_types::SolType>::eip712_data_word(&self.id) - .0, - ::eip712_data_word( - &self.data, - ) - .0, - ] - .concat() - } - } - #[automatically_derived] - impl alloy_sol_types::EventTopic for Node { - #[inline] - fn topic_preimage_length(rust: &Self::RustType) -> usize { - 0usize - + as alloy_sol_types::EventTopic>::topic_preimage_length(&rust.id) - + ::topic_preimage_length( - &rust.data, - ) - } - #[inline] - fn encode_topic_preimage( - rust: &Self::RustType, - out: &mut alloy_sol_types::private::Vec, - ) { - out.reserve(::topic_preimage_length(rust)); - as alloy_sol_types::EventTopic>::encode_topic_preimage(&rust.id, out); - ::encode_topic_preimage( - &rust.data, - out, - ); - } - #[inline] - fn encode_topic(rust: &Self::RustType) -> alloy_sol_types::abi::token::WordToken { - let mut out = alloy_sol_types::private::Vec::new(); - ::encode_topic_preimage(rust, &mut out); - alloy_sol_types::abi::token::WordToken(alloy_sol_types::private::keccak256(out)) - } - } - }; - /// ```solidity - /// struct NodeOperatorView { address addr; Node[] nodes; bytes data; } - /// ``` - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct NodeOperatorView { - #[allow(missing_docs)] - pub addr: alloy::sol_types::private::Address, - #[allow(missing_docs)] - pub nodes: alloy::sol_types::private::Vec<::RustType>, - #[allow(missing_docs)] - pub data: alloy::sol_types::private::Bytes, - } - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - #[doc(hidden)] - type UnderlyingSolTuple<'a> = ( - alloy::sol_types::sol_data::Address, - alloy::sol_types::sol_data::Array, - alloy::sol_types::sol_data::Bytes, - ); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = ( - alloy::sol_types::private::Address, - alloy::sol_types::private::Vec<::RustType>, - alloy::sol_types::private::Bytes, - ); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: NodeOperatorView) -> Self { - (value.addr, value.nodes, value.data) - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for NodeOperatorView { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self { - addr: tuple.0, - nodes: tuple.1, - data: tuple.2, - } - } - } - #[automatically_derived] - impl alloy_sol_types::SolValue for NodeOperatorView { - type SolType = Self; - } - #[automatically_derived] - impl alloy_sol_types::private::SolTypeValue for NodeOperatorView { - #[inline] - fn stv_to_tokens(&self) -> ::Token<'_> { - ( - ::tokenize( - &self.addr, - ), - as alloy_sol_types::SolType>::tokenize( - &self.nodes, - ), - ::tokenize( - &self.data, - ), - ) - } - #[inline] - fn stv_abi_encoded_size(&self) -> usize { - if let Some(size) = ::ENCODED_SIZE { - return size; - } - let tuple = - as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_encoded_size(&tuple) - } - #[inline] - fn stv_eip712_data_word(&self) -> alloy_sol_types::Word { - ::eip712_hash_struct(self) - } - #[inline] - fn stv_abi_encode_packed_to(&self, out: &mut alloy_sol_types::private::Vec) { - let tuple = - as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_encode_packed_to( - &tuple, out, - ) - } - #[inline] - fn stv_abi_packed_encoded_size(&self) -> usize { - if let Some(size) = ::PACKED_ENCODED_SIZE { - return size; - } - let tuple = - as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_packed_encoded_size( - &tuple, - ) - } - } - #[automatically_derived] - impl alloy_sol_types::SolType for NodeOperatorView { - type RustType = Self; - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SOL_NAME: &'static str = ::NAME; - const ENCODED_SIZE: Option = - as alloy_sol_types::SolType>::ENCODED_SIZE; - const PACKED_ENCODED_SIZE: Option = - as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; - #[inline] - fn valid_token(token: &Self::Token<'_>) -> bool { - as alloy_sol_types::SolType>::valid_token(token) - } - #[inline] - fn detokenize(token: Self::Token<'_>) -> Self::RustType { - let tuple = as alloy_sol_types::SolType>::detokenize(token); - >>::from(tuple) - } - } - #[automatically_derived] - impl alloy_sol_types::SolStruct for NodeOperatorView { - const NAME: &'static str = "NodeOperatorView"; - #[inline] - fn eip712_root_type() -> alloy_sol_types::private::Cow<'static, str> { - alloy_sol_types::private::Cow::Borrowed( - "NodeOperatorView(address addr,Node[] nodes,bytes data)", - ) - } - #[inline] - fn eip712_components( - ) -> alloy_sol_types::private::Vec> - { - let mut components = alloy_sol_types::private::Vec::with_capacity(1); - components.push(::eip712_root_type()); - components.extend(::eip712_components()); - components - } - #[inline] - fn eip712_encode_data(&self) -> alloy_sol_types::private::Vec { - [ - ::eip712_data_word( - &self.addr, - ) - .0, - as alloy_sol_types::SolType>::eip712_data_word(&self.nodes) - .0, - ::eip712_data_word( - &self.data, - ) - .0, - ] - .concat() - } - } - #[automatically_derived] - impl alloy_sol_types::EventTopic for NodeOperatorView { - #[inline] - fn topic_preimage_length(rust: &Self::RustType) -> usize { - 0usize - + ::topic_preimage_length( - &rust.addr, - ) - + as alloy_sol_types::EventTopic>::topic_preimage_length(&rust.nodes) - + ::topic_preimage_length( - &rust.data, - ) - } - #[inline] - fn encode_topic_preimage( - rust: &Self::RustType, - out: &mut alloy_sol_types::private::Vec, - ) { - out.reserve(::topic_preimage_length(rust)); - ::encode_topic_preimage( - &rust.addr, - out, - ); - as alloy_sol_types::EventTopic>::encode_topic_preimage( - &rust.nodes, - out, - ); - ::encode_topic_preimage( - &rust.data, - out, - ); - } - #[inline] - fn encode_topic(rust: &Self::RustType) -> alloy_sol_types::abi::token::WordToken { - let mut out = alloy_sol_types::private::Vec::new(); - ::encode_topic_preimage(rust, &mut out); - alloy_sol_types::abi::token::WordToken(alloy_sol_types::private::keccak256(out)) - } - } - }; - /// ```solidity - /// struct NodeOperatorsView { NodeOperatorView[] slots; } - /// ``` - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct NodeOperatorsView { - #[allow(missing_docs)] - pub slots: alloy::sol_types::private::Vec< - ::RustType, - >, - } - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - #[doc(hidden)] - type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Array,); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = ( - alloy::sol_types::private::Vec< - ::RustType, - >, - ); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: NodeOperatorsView) -> Self { - (value.slots,) - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for NodeOperatorsView { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self { slots: tuple.0 } - } - } - #[automatically_derived] - impl alloy_sol_types::SolValue for NodeOperatorsView { - type SolType = Self; - } - #[automatically_derived] - impl alloy_sol_types::private::SolTypeValue for NodeOperatorsView { - #[inline] - fn stv_to_tokens(&self) -> ::Token<'_> { - ( - as alloy_sol_types::SolType>::tokenize(&self.slots), - ) - } - #[inline] - fn stv_abi_encoded_size(&self) -> usize { - if let Some(size) = ::ENCODED_SIZE { - return size; - } - let tuple = - as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_encoded_size(&tuple) - } - #[inline] - fn stv_eip712_data_word(&self) -> alloy_sol_types::Word { - ::eip712_hash_struct(self) - } - #[inline] - fn stv_abi_encode_packed_to(&self, out: &mut alloy_sol_types::private::Vec) { - let tuple = - as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_encode_packed_to( - &tuple, out, - ) - } - #[inline] - fn stv_abi_packed_encoded_size(&self) -> usize { - if let Some(size) = ::PACKED_ENCODED_SIZE { - return size; - } - let tuple = - as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_packed_encoded_size( - &tuple, - ) - } - } - #[automatically_derived] - impl alloy_sol_types::SolType for NodeOperatorsView { - type RustType = Self; - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SOL_NAME: &'static str = ::NAME; - const ENCODED_SIZE: Option = - as alloy_sol_types::SolType>::ENCODED_SIZE; - const PACKED_ENCODED_SIZE: Option = - as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; - #[inline] - fn valid_token(token: &Self::Token<'_>) -> bool { - as alloy_sol_types::SolType>::valid_token(token) - } - #[inline] - fn detokenize(token: Self::Token<'_>) -> Self::RustType { - let tuple = as alloy_sol_types::SolType>::detokenize(token); - >>::from(tuple) - } - } - #[automatically_derived] - impl alloy_sol_types::SolStruct for NodeOperatorsView { - const NAME: &'static str = "NodeOperatorsView"; - #[inline] - fn eip712_root_type() -> alloy_sol_types::private::Cow<'static, str> { - alloy_sol_types::private::Cow::Borrowed( - "NodeOperatorsView(NodeOperatorView[] slots)", - ) - } - #[inline] - fn eip712_components( - ) -> alloy_sol_types::private::Vec> - { - let mut components = alloy_sol_types::private::Vec::with_capacity(1); - components - .push(::eip712_root_type()); - components - .extend(::eip712_components()); - components - } - #[inline] - fn eip712_encode_data(&self) -> alloy_sol_types::private::Vec { - as alloy_sol_types::SolType>::eip712_data_word(&self.slots) - .0 - .to_vec() - } - } - #[automatically_derived] - impl alloy_sol_types::EventTopic for NodeOperatorsView { - #[inline] - fn topic_preimage_length(rust: &Self::RustType) -> usize { - 0usize - + as alloy_sol_types::EventTopic>::topic_preimage_length(&rust.slots) - } - #[inline] - fn encode_topic_preimage( - rust: &Self::RustType, - out: &mut alloy_sol_types::private::Vec, - ) { - out.reserve(::topic_preimage_length(rust)); - as alloy_sol_types::EventTopic>::encode_topic_preimage( - &rust.slots, - out, - ); - } - #[inline] - fn encode_topic(rust: &Self::RustType) -> alloy_sol_types::abi::token::WordToken { - let mut out = alloy_sol_types::private::Vec::new(); - ::encode_topic_preimage(rust, &mut out); - alloy_sol_types::abi::token::WordToken(alloy_sol_types::private::keccak256(out)) - } - } - }; - /// ```solidity - /// struct Settings { uint8 minOperators; uint8 minNodes; } - /// ``` - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct Settings { - #[allow(missing_docs)] - pub minOperators: u8, - #[allow(missing_docs)] - pub minNodes: u8, - } - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - #[doc(hidden)] - type UnderlyingSolTuple<'a> = ( - alloy::sol_types::sol_data::Uint<8>, - alloy::sol_types::sol_data::Uint<8>, - ); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = (u8, u8); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: Settings) -> Self { - (value.minOperators, value.minNodes) - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for Settings { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self { - minOperators: tuple.0, - minNodes: tuple.1, - } - } - } - #[automatically_derived] - impl alloy_sol_types::SolValue for Settings { - type SolType = Self; - } - #[automatically_derived] - impl alloy_sol_types::private::SolTypeValue for Settings { - #[inline] - fn stv_to_tokens(&self) -> ::Token<'_> { - ( - as alloy_sol_types::SolType>::tokenize( - &self.minOperators, - ), - as alloy_sol_types::SolType>::tokenize( - &self.minNodes, - ), - ) - } - #[inline] - fn stv_abi_encoded_size(&self) -> usize { - if let Some(size) = ::ENCODED_SIZE { - return size; - } - let tuple = - as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_encoded_size(&tuple) - } - #[inline] - fn stv_eip712_data_word(&self) -> alloy_sol_types::Word { - ::eip712_hash_struct(self) - } - #[inline] - fn stv_abi_encode_packed_to(&self, out: &mut alloy_sol_types::private::Vec) { - let tuple = - as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_encode_packed_to( - &tuple, out, - ) - } - #[inline] - fn stv_abi_packed_encoded_size(&self) -> usize { - if let Some(size) = ::PACKED_ENCODED_SIZE { - return size; - } - let tuple = - as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_packed_encoded_size( - &tuple, - ) - } - } - #[automatically_derived] - impl alloy_sol_types::SolType for Settings { - type RustType = Self; - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SOL_NAME: &'static str = ::NAME; - const ENCODED_SIZE: Option = - as alloy_sol_types::SolType>::ENCODED_SIZE; - const PACKED_ENCODED_SIZE: Option = - as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; - #[inline] - fn valid_token(token: &Self::Token<'_>) -> bool { - as alloy_sol_types::SolType>::valid_token(token) - } - #[inline] - fn detokenize(token: Self::Token<'_>) -> Self::RustType { - let tuple = as alloy_sol_types::SolType>::detokenize(token); - >>::from(tuple) - } - } - #[automatically_derived] - impl alloy_sol_types::SolStruct for Settings { - const NAME: &'static str = "Settings"; - #[inline] - fn eip712_root_type() -> alloy_sol_types::private::Cow<'static, str> { - alloy_sol_types::private::Cow::Borrowed( - "Settings(uint8 minOperators,uint8 minNodes)", - ) - } - #[inline] - fn eip712_components( - ) -> alloy_sol_types::private::Vec> - { - alloy_sol_types::private::Vec::new() - } - #[inline] - fn eip712_encode_type() -> alloy_sol_types::private::Cow<'static, str> { - ::eip712_root_type() - } - #[inline] - fn eip712_encode_data(&self) -> alloy_sol_types::private::Vec { - [ - as alloy_sol_types::SolType>::eip712_data_word(&self.minOperators) - .0, - as alloy_sol_types::SolType>::eip712_data_word(&self.minNodes) - .0, - ] - .concat() - } - } - #[automatically_derived] - impl alloy_sol_types::EventTopic for Settings { - #[inline] - fn topic_preimage_length(rust: &Self::RustType) -> usize { - 0usize - + as alloy_sol_types::EventTopic>::topic_preimage_length( - &rust.minOperators, - ) - + as alloy_sol_types::EventTopic>::topic_preimage_length( - &rust.minNodes, - ) - } - #[inline] - fn encode_topic_preimage( - rust: &Self::RustType, - out: &mut alloy_sol_types::private::Vec, - ) { - out.reserve(::topic_preimage_length(rust)); - as alloy_sol_types::EventTopic>::encode_topic_preimage( - &rust.minOperators, - out, - ); - as alloy_sol_types::EventTopic>::encode_topic_preimage( - &rust.minNodes, - out, - ); - } - #[inline] - fn encode_topic(rust: &Self::RustType) -> alloy_sol_types::abi::token::WordToken { - let mut out = alloy_sol_types::private::Vec::new(); - ::encode_topic_preimage(rust, &mut out); - alloy_sol_types::abi::token::WordToken(alloy_sol_types::private::keccak256(out)) - } - } - }; - /// Event with signature `MaintenanceAborted(uint128)` and selector - /// `0x8fb9cd054d0a022110cced239e908b834e4cd219511856d4eaae3051d932d604`. - /// ```solidity - /// event MaintenanceAborted(uint128 version); - /// ``` - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - #[derive(Clone)] - pub struct MaintenanceAborted { - #[allow(missing_docs)] - pub version: u128, - } - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - #[automatically_derived] - impl alloy_sol_types::SolEvent for MaintenanceAborted { - type DataTuple<'a> = (alloy::sol_types::sol_data::Uint<128>,); - type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); - const SIGNATURE: &'static str = "MaintenanceAborted(uint128)"; - const SIGNATURE_HASH: alloy_sol_types::private::B256 = - alloy_sol_types::private::B256::new([ - 143u8, 185u8, 205u8, 5u8, 77u8, 10u8, 2u8, 33u8, 16u8, 204u8, 237u8, 35u8, - 158u8, 144u8, 139u8, 131u8, 78u8, 76u8, 210u8, 25u8, 81u8, 24u8, 86u8, 212u8, - 234u8, 174u8, 48u8, 81u8, 217u8, 50u8, 214u8, 4u8, - ]); - const ANONYMOUS: bool = false; - #[allow(unused_variables)] - #[inline] - fn new( - topics: ::RustType, - data: as alloy_sol_types::SolType>::RustType, - ) -> Self { - Self { version: data.0 } - } - #[inline] - fn check_signature( - topics: &::RustType, - ) -> alloy_sol_types::Result<()> { - if topics.0 != Self::SIGNATURE_HASH { - return Err(alloy_sol_types::Error::invalid_event_signature_hash( - Self::SIGNATURE, - topics.0, - Self::SIGNATURE_HASH, - )); - } - Ok(()) - } - #[inline] - fn tokenize_body(&self) -> Self::DataToken<'_> { - ( - as alloy_sol_types::SolType>::tokenize( - &self.version, - ), - ) - } - #[inline] - fn topics(&self) -> ::RustType { - (Self::SIGNATURE_HASH.into(),) - } - #[inline] - fn encode_topics_raw( - &self, - out: &mut [alloy_sol_types::abi::token::WordToken], - ) -> alloy_sol_types::Result<()> { - if out.len() < ::COUNT { - return Err(alloy_sol_types::Error::Overrun); - } - out[0usize] = alloy_sol_types::abi::token::WordToken(Self::SIGNATURE_HASH); - Ok(()) - } - } - #[automatically_derived] - impl alloy_sol_types::private::IntoLogData for MaintenanceAborted { - fn to_log_data(&self) -> alloy_sol_types::private::LogData { - From::from(self) - } - fn into_log_data(self) -> alloy_sol_types::private::LogData { - From::from(&self) - } - } - #[automatically_derived] - impl From<&MaintenanceAborted> for alloy_sol_types::private::LogData { - #[inline] - fn from(this: &MaintenanceAborted) -> alloy_sol_types::private::LogData { - alloy_sol_types::SolEvent::encode_log_data(this) - } - } - }; - /// Event with signature `MaintenanceCompleted(address,uint128)` and - /// selector `0xf91067eb420c28d3124865fc996e6aa9d541b9b4fef9188cb965a6cc6491638e`. - /// ```solidity - /// event MaintenanceCompleted(address operator, uint128 version); - /// ``` - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - #[derive(Clone)] - pub struct MaintenanceCompleted { - #[allow(missing_docs)] - pub operator: alloy::sol_types::private::Address, - #[allow(missing_docs)] - pub version: u128, - } - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - #[automatically_derived] - impl alloy_sol_types::SolEvent for MaintenanceCompleted { - type DataTuple<'a> = ( - alloy::sol_types::sol_data::Address, - alloy::sol_types::sol_data::Uint<128>, - ); - type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); - const SIGNATURE: &'static str = "MaintenanceCompleted(address,uint128)"; - const SIGNATURE_HASH: alloy_sol_types::private::B256 = - alloy_sol_types::private::B256::new([ - 249u8, 16u8, 103u8, 235u8, 66u8, 12u8, 40u8, 211u8, 18u8, 72u8, 101u8, 252u8, - 153u8, 110u8, 106u8, 169u8, 213u8, 65u8, 185u8, 180u8, 254u8, 249u8, 24u8, - 140u8, 185u8, 101u8, 166u8, 204u8, 100u8, 145u8, 99u8, 142u8, - ]); - const ANONYMOUS: bool = false; - #[allow(unused_variables)] - #[inline] - fn new( - topics: ::RustType, - data: as alloy_sol_types::SolType>::RustType, - ) -> Self { - Self { - operator: data.0, - version: data.1, - } - } - #[inline] - fn check_signature( - topics: &::RustType, - ) -> alloy_sol_types::Result<()> { - if topics.0 != Self::SIGNATURE_HASH { - return Err(alloy_sol_types::Error::invalid_event_signature_hash( - Self::SIGNATURE, - topics.0, - Self::SIGNATURE_HASH, - )); - } - Ok(()) - } - #[inline] - fn tokenize_body(&self) -> Self::DataToken<'_> { - ( - ::tokenize( - &self.operator, - ), - as alloy_sol_types::SolType>::tokenize( - &self.version, - ), - ) - } - #[inline] - fn topics(&self) -> ::RustType { - (Self::SIGNATURE_HASH.into(),) - } - #[inline] - fn encode_topics_raw( - &self, - out: &mut [alloy_sol_types::abi::token::WordToken], - ) -> alloy_sol_types::Result<()> { - if out.len() < ::COUNT { - return Err(alloy_sol_types::Error::Overrun); - } - out[0usize] = alloy_sol_types::abi::token::WordToken(Self::SIGNATURE_HASH); - Ok(()) - } - } - #[automatically_derived] - impl alloy_sol_types::private::IntoLogData for MaintenanceCompleted { - fn to_log_data(&self) -> alloy_sol_types::private::LogData { - From::from(self) - } - fn into_log_data(self) -> alloy_sol_types::private::LogData { - From::from(&self) - } - } - #[automatically_derived] - impl From<&MaintenanceCompleted> for alloy_sol_types::private::LogData { - #[inline] - fn from(this: &MaintenanceCompleted) -> alloy_sol_types::private::LogData { - alloy_sol_types::SolEvent::encode_log_data(this) - } - } - }; - /// Event with signature `MaintenanceStarted(address,uint128)` and selector - /// `0xbc2748cf02f7a1291525e866efc76ab3b96d32d7afcbb26c53daec617b38b479`. - /// ```solidity - /// event MaintenanceStarted(address operator, uint128 version); - /// ``` - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - #[derive(Clone)] - pub struct MaintenanceStarted { - #[allow(missing_docs)] - pub operator: alloy::sol_types::private::Address, - #[allow(missing_docs)] - pub version: u128, - } - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - #[automatically_derived] - impl alloy_sol_types::SolEvent for MaintenanceStarted { - type DataTuple<'a> = ( - alloy::sol_types::sol_data::Address, - alloy::sol_types::sol_data::Uint<128>, - ); - type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); - const SIGNATURE: &'static str = "MaintenanceStarted(address,uint128)"; - const SIGNATURE_HASH: alloy_sol_types::private::B256 = - alloy_sol_types::private::B256::new([ - 188u8, 39u8, 72u8, 207u8, 2u8, 247u8, 161u8, 41u8, 21u8, 37u8, 232u8, 102u8, - 239u8, 199u8, 106u8, 179u8, 185u8, 109u8, 50u8, 215u8, 175u8, 203u8, 178u8, - 108u8, 83u8, 218u8, 236u8, 97u8, 123u8, 56u8, 180u8, 121u8, - ]); - const ANONYMOUS: bool = false; - #[allow(unused_variables)] - #[inline] - fn new( - topics: ::RustType, - data: as alloy_sol_types::SolType>::RustType, - ) -> Self { - Self { - operator: data.0, - version: data.1, - } - } - #[inline] - fn check_signature( - topics: &::RustType, - ) -> alloy_sol_types::Result<()> { - if topics.0 != Self::SIGNATURE_HASH { - return Err(alloy_sol_types::Error::invalid_event_signature_hash( - Self::SIGNATURE, - topics.0, - Self::SIGNATURE_HASH, - )); - } - Ok(()) - } - #[inline] - fn tokenize_body(&self) -> Self::DataToken<'_> { - ( - ::tokenize( - &self.operator, - ), - as alloy_sol_types::SolType>::tokenize( - &self.version, - ), - ) - } - #[inline] - fn topics(&self) -> ::RustType { - (Self::SIGNATURE_HASH.into(),) - } - #[inline] - fn encode_topics_raw( - &self, - out: &mut [alloy_sol_types::abi::token::WordToken], - ) -> alloy_sol_types::Result<()> { - if out.len() < ::COUNT { - return Err(alloy_sol_types::Error::Overrun); - } - out[0usize] = alloy_sol_types::abi::token::WordToken(Self::SIGNATURE_HASH); - Ok(()) - } - } - #[automatically_derived] - impl alloy_sol_types::private::IntoLogData for MaintenanceStarted { - fn to_log_data(&self) -> alloy_sol_types::private::LogData { - From::from(self) - } - fn into_log_data(self) -> alloy_sol_types::private::LogData { - From::from(&self) - } - } - #[automatically_derived] - impl From<&MaintenanceStarted> for alloy_sol_types::private::LogData { - #[inline] - fn from(this: &MaintenanceStarted) -> alloy_sol_types::private::LogData { - alloy_sol_types::SolEvent::encode_log_data(this) - } - } - }; - /// Event with signature `MigrationAborted(uint128)` and selector - /// `0x9ce192aea5faf2151bbc246cd8918d2eba702fa26951f67f2bf7b3817e689d98`. - /// ```solidity - /// event MigrationAborted(uint128 version); - /// ``` - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - #[derive(Clone)] - pub struct MigrationAborted { - #[allow(missing_docs)] - pub version: u128, - } - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - #[automatically_derived] - impl alloy_sol_types::SolEvent for MigrationAborted { - type DataTuple<'a> = (alloy::sol_types::sol_data::Uint<128>,); - type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); - const SIGNATURE: &'static str = "MigrationAborted(uint128)"; - const SIGNATURE_HASH: alloy_sol_types::private::B256 = - alloy_sol_types::private::B256::new([ - 156u8, 225u8, 146u8, 174u8, 165u8, 250u8, 242u8, 21u8, 27u8, 188u8, 36u8, - 108u8, 216u8, 145u8, 141u8, 46u8, 186u8, 112u8, 47u8, 162u8, 105u8, 81u8, - 246u8, 127u8, 43u8, 247u8, 179u8, 129u8, 126u8, 104u8, 157u8, 152u8, - ]); - const ANONYMOUS: bool = false; - #[allow(unused_variables)] - #[inline] - fn new( - topics: ::RustType, - data: as alloy_sol_types::SolType>::RustType, - ) -> Self { - Self { version: data.0 } - } - #[inline] - fn check_signature( - topics: &::RustType, - ) -> alloy_sol_types::Result<()> { - if topics.0 != Self::SIGNATURE_HASH { - return Err(alloy_sol_types::Error::invalid_event_signature_hash( - Self::SIGNATURE, - topics.0, - Self::SIGNATURE_HASH, - )); - } - Ok(()) - } - #[inline] - fn tokenize_body(&self) -> Self::DataToken<'_> { - ( - as alloy_sol_types::SolType>::tokenize( - &self.version, - ), - ) - } - #[inline] - fn topics(&self) -> ::RustType { - (Self::SIGNATURE_HASH.into(),) - } - #[inline] - fn encode_topics_raw( - &self, - out: &mut [alloy_sol_types::abi::token::WordToken], - ) -> alloy_sol_types::Result<()> { - if out.len() < ::COUNT { - return Err(alloy_sol_types::Error::Overrun); - } - out[0usize] = alloy_sol_types::abi::token::WordToken(Self::SIGNATURE_HASH); - Ok(()) - } - } - #[automatically_derived] - impl alloy_sol_types::private::IntoLogData for MigrationAborted { - fn to_log_data(&self) -> alloy_sol_types::private::LogData { - From::from(self) - } - fn into_log_data(self) -> alloy_sol_types::private::LogData { - From::from(&self) - } - } - #[automatically_derived] - impl From<&MigrationAborted> for alloy_sol_types::private::LogData { - #[inline] - fn from(this: &MigrationAborted) -> alloy_sol_types::private::LogData { - alloy_sol_types::SolEvent::encode_log_data(this) - } - } - }; - /// Event with signature `MigrationCompleted(uint128)` and selector - /// `0x11ce50160e66100537fd4b0ae26de66d51dab713ad92313353a18c24e8f6daab`. - /// ```solidity - /// event MigrationCompleted(uint128 version); - /// ``` - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - #[derive(Clone)] - pub struct MigrationCompleted { - #[allow(missing_docs)] - pub version: u128, - } - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - #[automatically_derived] - impl alloy_sol_types::SolEvent for MigrationCompleted { - type DataTuple<'a> = (alloy::sol_types::sol_data::Uint<128>,); - type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); - const SIGNATURE: &'static str = "MigrationCompleted(uint128)"; - const SIGNATURE_HASH: alloy_sol_types::private::B256 = - alloy_sol_types::private::B256::new([ - 17u8, 206u8, 80u8, 22u8, 14u8, 102u8, 16u8, 5u8, 55u8, 253u8, 75u8, 10u8, - 226u8, 109u8, 230u8, 109u8, 81u8, 218u8, 183u8, 19u8, 173u8, 146u8, 49u8, 51u8, - 83u8, 161u8, 140u8, 36u8, 232u8, 246u8, 218u8, 171u8, - ]); - const ANONYMOUS: bool = false; - #[allow(unused_variables)] - #[inline] - fn new( - topics: ::RustType, - data: as alloy_sol_types::SolType>::RustType, - ) -> Self { - Self { version: data.0 } - } - #[inline] - fn check_signature( - topics: &::RustType, - ) -> alloy_sol_types::Result<()> { - if topics.0 != Self::SIGNATURE_HASH { - return Err(alloy_sol_types::Error::invalid_event_signature_hash( - Self::SIGNATURE, - topics.0, - Self::SIGNATURE_HASH, - )); - } - Ok(()) - } - #[inline] - fn tokenize_body(&self) -> Self::DataToken<'_> { - ( - as alloy_sol_types::SolType>::tokenize( - &self.version, - ), - ) - } - #[inline] - fn topics(&self) -> ::RustType { - (Self::SIGNATURE_HASH.into(),) - } - #[inline] - fn encode_topics_raw( - &self, - out: &mut [alloy_sol_types::abi::token::WordToken], - ) -> alloy_sol_types::Result<()> { - if out.len() < ::COUNT { - return Err(alloy_sol_types::Error::Overrun); - } - out[0usize] = alloy_sol_types::abi::token::WordToken(Self::SIGNATURE_HASH); - Ok(()) - } - } - #[automatically_derived] - impl alloy_sol_types::private::IntoLogData for MigrationCompleted { - fn to_log_data(&self) -> alloy_sol_types::private::LogData { - From::from(self) - } - fn into_log_data(self) -> alloy_sol_types::private::LogData { - From::from(&self) - } - } - #[automatically_derived] - impl From<&MigrationCompleted> for alloy_sol_types::private::LogData { - #[inline] - fn from(this: &MigrationCompleted) -> alloy_sol_types::private::LogData { - alloy_sol_types::SolEvent::encode_log_data(this) - } - } - }; - /// Event with signature `MigrationDataPullCompleted(address,uint128)` and - /// selector `0xa76a8fc1a90266ddee8937a18e12f01eade946b3b66197fff289af9277c2bd25`. - /// ```solidity - /// event MigrationDataPullCompleted(address operator, uint128 version); - /// ``` - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - #[derive(Clone)] - pub struct MigrationDataPullCompleted { - #[allow(missing_docs)] - pub operator: alloy::sol_types::private::Address, - #[allow(missing_docs)] - pub version: u128, - } - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - #[automatically_derived] - impl alloy_sol_types::SolEvent for MigrationDataPullCompleted { - type DataTuple<'a> = ( - alloy::sol_types::sol_data::Address, - alloy::sol_types::sol_data::Uint<128>, - ); - type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); - const SIGNATURE: &'static str = "MigrationDataPullCompleted(address,uint128)"; - const SIGNATURE_HASH: alloy_sol_types::private::B256 = - alloy_sol_types::private::B256::new([ - 167u8, 106u8, 143u8, 193u8, 169u8, 2u8, 102u8, 221u8, 238u8, 137u8, 55u8, - 161u8, 142u8, 18u8, 240u8, 30u8, 173u8, 233u8, 70u8, 179u8, 182u8, 97u8, 151u8, - 255u8, 242u8, 137u8, 175u8, 146u8, 119u8, 194u8, 189u8, 37u8, - ]); - const ANONYMOUS: bool = false; - #[allow(unused_variables)] - #[inline] - fn new( - topics: ::RustType, - data: as alloy_sol_types::SolType>::RustType, - ) -> Self { - Self { - operator: data.0, - version: data.1, - } - } - #[inline] - fn check_signature( - topics: &::RustType, - ) -> alloy_sol_types::Result<()> { - if topics.0 != Self::SIGNATURE_HASH { - return Err(alloy_sol_types::Error::invalid_event_signature_hash( - Self::SIGNATURE, - topics.0, - Self::SIGNATURE_HASH, - )); - } - Ok(()) - } - #[inline] - fn tokenize_body(&self) -> Self::DataToken<'_> { - ( - ::tokenize( - &self.operator, - ), - as alloy_sol_types::SolType>::tokenize( - &self.version, - ), - ) - } - #[inline] - fn topics(&self) -> ::RustType { - (Self::SIGNATURE_HASH.into(),) - } - #[inline] - fn encode_topics_raw( - &self, - out: &mut [alloy_sol_types::abi::token::WordToken], - ) -> alloy_sol_types::Result<()> { - if out.len() < ::COUNT { - return Err(alloy_sol_types::Error::Overrun); - } - out[0usize] = alloy_sol_types::abi::token::WordToken(Self::SIGNATURE_HASH); - Ok(()) - } - } - #[automatically_derived] - impl alloy_sol_types::private::IntoLogData for MigrationDataPullCompleted { - fn to_log_data(&self) -> alloy_sol_types::private::LogData { - From::from(self) - } - fn into_log_data(self) -> alloy_sol_types::private::LogData { - From::from(&self) - } - } - #[automatically_derived] - impl From<&MigrationDataPullCompleted> for alloy_sol_types::private::LogData { - #[inline] - fn from(this: &MigrationDataPullCompleted) -> alloy_sol_types::private::LogData { - alloy_sol_types::SolEvent::encode_log_data(this) - } - } - }; - /// Event with signature - /// `MigrationStarted(address[],(address,(uint256,bytes)[],bytes)[], - /// uint128)` and selector - /// `0x7e05e40117b6e18ab284c04a3508c3826422dc84a65e9c236a8248774416f8ac`. - /// ```solidity - /// event MigrationStarted(address[] operatorsToRemove, NodeOperatorView[] operatorsToAdd, uint128 version); - /// ``` - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - #[derive(Clone)] - pub struct MigrationStarted { - #[allow(missing_docs)] - pub operatorsToRemove: alloy::sol_types::private::Vec, - #[allow(missing_docs)] - pub operatorsToAdd: alloy::sol_types::private::Vec< - ::RustType, - >, - #[allow(missing_docs)] - pub version: u128, - } - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - #[automatically_derived] - impl alloy_sol_types::SolEvent for MigrationStarted { - type DataTuple<'a> = ( - alloy::sol_types::sol_data::Array, - alloy::sol_types::sol_data::Array, - alloy::sol_types::sol_data::Uint<128>, - ); - type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); - const SIGNATURE: &'static str = - "MigrationStarted(address[],(address,(uint256,bytes)[],bytes)[],uint128)"; - const SIGNATURE_HASH: alloy_sol_types::private::B256 = - alloy_sol_types::private::B256::new([ - 126u8, 5u8, 228u8, 1u8, 23u8, 182u8, 225u8, 138u8, 178u8, 132u8, 192u8, 74u8, - 53u8, 8u8, 195u8, 130u8, 100u8, 34u8, 220u8, 132u8, 166u8, 94u8, 156u8, 35u8, - 106u8, 130u8, 72u8, 119u8, 68u8, 22u8, 248u8, 172u8, - ]); - const ANONYMOUS: bool = false; - #[allow(unused_variables)] - #[inline] - fn new( - topics: ::RustType, - data: as alloy_sol_types::SolType>::RustType, - ) -> Self { - Self { - operatorsToRemove: data.0, - operatorsToAdd: data.1, - version: data.2, - } - } - #[inline] - fn check_signature( - topics: &::RustType, - ) -> alloy_sol_types::Result<()> { - if topics.0 != Self::SIGNATURE_HASH { - return Err(alloy_sol_types::Error::invalid_event_signature_hash( - Self::SIGNATURE, - topics.0, - Self::SIGNATURE_HASH, - )); - } - Ok(()) - } - #[inline] - fn tokenize_body(&self) -> Self::DataToken<'_> { - ( - as alloy_sol_types::SolType>::tokenize(&self.operatorsToRemove), - as alloy_sol_types::SolType>::tokenize(&self.operatorsToAdd), - as alloy_sol_types::SolType>::tokenize(&self.version), - ) - } - #[inline] - fn topics(&self) -> ::RustType { - (Self::SIGNATURE_HASH.into(),) - } - #[inline] - fn encode_topics_raw( - &self, - out: &mut [alloy_sol_types::abi::token::WordToken], - ) -> alloy_sol_types::Result<()> { - if out.len() < ::COUNT { - return Err(alloy_sol_types::Error::Overrun); - } - out[0usize] = alloy_sol_types::abi::token::WordToken(Self::SIGNATURE_HASH); - Ok(()) - } - } - #[automatically_derived] - impl alloy_sol_types::private::IntoLogData for MigrationStarted { - fn to_log_data(&self) -> alloy_sol_types::private::LogData { - From::from(self) - } - fn into_log_data(self) -> alloy_sol_types::private::LogData { - From::from(&self) - } - } - #[automatically_derived] - impl From<&MigrationStarted> for alloy_sol_types::private::LogData { - #[inline] - fn from(this: &MigrationStarted) -> alloy_sol_types::private::LogData { - alloy_sol_types::SolEvent::encode_log_data(this) - } - } - }; - /// Event with signature `NodeRemoved(address,uint256,uint128)` and selector - /// `0xbd184de79f134b0f3da466d278f5417cbcb1450d72f1bd1a1b84f18b1bcd03ca`. - /// ```solidity - /// event NodeRemoved(address operator, uint256 id, uint128 version); - /// ``` - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - #[derive(Clone)] - pub struct NodeRemoved { - #[allow(missing_docs)] - pub operator: alloy::sol_types::private::Address, - #[allow(missing_docs)] - pub id: alloy::sol_types::private::primitives::aliases::U256, - #[allow(missing_docs)] - pub version: u128, - } - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - #[automatically_derived] - impl alloy_sol_types::SolEvent for NodeRemoved { - type DataTuple<'a> = ( - alloy::sol_types::sol_data::Address, - alloy::sol_types::sol_data::Uint<256>, - alloy::sol_types::sol_data::Uint<128>, - ); - type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); - const SIGNATURE: &'static str = "NodeRemoved(address,uint256,uint128)"; - const SIGNATURE_HASH: alloy_sol_types::private::B256 = - alloy_sol_types::private::B256::new([ - 189u8, 24u8, 77u8, 231u8, 159u8, 19u8, 75u8, 15u8, 61u8, 164u8, 102u8, 210u8, - 120u8, 245u8, 65u8, 124u8, 188u8, 177u8, 69u8, 13u8, 114u8, 241u8, 189u8, 26u8, - 27u8, 132u8, 241u8, 139u8, 27u8, 205u8, 3u8, 202u8, - ]); - const ANONYMOUS: bool = false; - #[allow(unused_variables)] - #[inline] - fn new( - topics: ::RustType, - data: as alloy_sol_types::SolType>::RustType, - ) -> Self { - Self { - operator: data.0, - id: data.1, - version: data.2, - } - } - #[inline] - fn check_signature( - topics: &::RustType, - ) -> alloy_sol_types::Result<()> { - if topics.0 != Self::SIGNATURE_HASH { - return Err(alloy_sol_types::Error::invalid_event_signature_hash( - Self::SIGNATURE, - topics.0, - Self::SIGNATURE_HASH, - )); - } - Ok(()) - } - #[inline] - fn tokenize_body(&self) -> Self::DataToken<'_> { - ( - ::tokenize( - &self.operator, - ), - as alloy_sol_types::SolType>::tokenize( - &self.id, - ), - as alloy_sol_types::SolType>::tokenize( - &self.version, - ), - ) - } - #[inline] - fn topics(&self) -> ::RustType { - (Self::SIGNATURE_HASH.into(),) - } - #[inline] - fn encode_topics_raw( - &self, - out: &mut [alloy_sol_types::abi::token::WordToken], - ) -> alloy_sol_types::Result<()> { - if out.len() < ::COUNT { - return Err(alloy_sol_types::Error::Overrun); - } - out[0usize] = alloy_sol_types::abi::token::WordToken(Self::SIGNATURE_HASH); - Ok(()) - } - } - #[automatically_derived] - impl alloy_sol_types::private::IntoLogData for NodeRemoved { - fn to_log_data(&self) -> alloy_sol_types::private::LogData { - From::from(self) - } - fn into_log_data(self) -> alloy_sol_types::private::LogData { - From::from(&self) - } - } - #[automatically_derived] - impl From<&NodeRemoved> for alloy_sol_types::private::LogData { - #[inline] - fn from(this: &NodeRemoved) -> alloy_sol_types::private::LogData { - alloy_sol_types::SolEvent::encode_log_data(this) - } - } - }; - /// Event with signature `NodeSet(address,(uint256,bytes),uint128)` and - /// selector `0x6adfb896d3407681d05fb874d4dfb7068e6e2a36f09acd38a3b7d04c01745fee`. - /// ```solidity - /// event NodeSet(address operator, Node node, uint128 version); - /// ``` - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - #[derive(Clone)] - pub struct NodeSet { - #[allow(missing_docs)] - pub operator: alloy::sol_types::private::Address, - #[allow(missing_docs)] - pub node: ::RustType, - #[allow(missing_docs)] - pub version: u128, - } - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - #[automatically_derived] - impl alloy_sol_types::SolEvent for NodeSet { - type DataTuple<'a> = ( - alloy::sol_types::sol_data::Address, - Node, - alloy::sol_types::sol_data::Uint<128>, - ); - type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); - const SIGNATURE: &'static str = "NodeSet(address,(uint256,bytes),uint128)"; - const SIGNATURE_HASH: alloy_sol_types::private::B256 = - alloy_sol_types::private::B256::new([ - 106u8, 223u8, 184u8, 150u8, 211u8, 64u8, 118u8, 129u8, 208u8, 95u8, 184u8, - 116u8, 212u8, 223u8, 183u8, 6u8, 142u8, 110u8, 42u8, 54u8, 240u8, 154u8, 205u8, - 56u8, 163u8, 183u8, 208u8, 76u8, 1u8, 116u8, 95u8, 238u8, - ]); - const ANONYMOUS: bool = false; - #[allow(unused_variables)] - #[inline] - fn new( - topics: ::RustType, - data: as alloy_sol_types::SolType>::RustType, - ) -> Self { - Self { - operator: data.0, - node: data.1, - version: data.2, - } - } - #[inline] - fn check_signature( - topics: &::RustType, - ) -> alloy_sol_types::Result<()> { - if topics.0 != Self::SIGNATURE_HASH { - return Err(alloy_sol_types::Error::invalid_event_signature_hash( - Self::SIGNATURE, - topics.0, - Self::SIGNATURE_HASH, - )); - } - Ok(()) - } - #[inline] - fn tokenize_body(&self) -> Self::DataToken<'_> { - ( - ::tokenize( - &self.operator, - ), - ::tokenize(&self.node), - as alloy_sol_types::SolType>::tokenize( - &self.version, - ), - ) - } - #[inline] - fn topics(&self) -> ::RustType { - (Self::SIGNATURE_HASH.into(),) - } - #[inline] - fn encode_topics_raw( - &self, - out: &mut [alloy_sol_types::abi::token::WordToken], - ) -> alloy_sol_types::Result<()> { - if out.len() < ::COUNT { - return Err(alloy_sol_types::Error::Overrun); - } - out[0usize] = alloy_sol_types::abi::token::WordToken(Self::SIGNATURE_HASH); - Ok(()) - } - } - #[automatically_derived] - impl alloy_sol_types::private::IntoLogData for NodeSet { - fn to_log_data(&self) -> alloy_sol_types::private::LogData { - From::from(self) - } - fn into_log_data(self) -> alloy_sol_types::private::LogData { - From::from(&self) - } - } - #[automatically_derived] - impl From<&NodeSet> for alloy_sol_types::private::LogData { - #[inline] - fn from(this: &NodeSet) -> alloy_sol_types::private::LogData { - alloy_sol_types::SolEvent::encode_log_data(this) - } - } - }; - /// Constructor`. - /// ```solidity - /// constructor(Settings initialSettings, NodeOperatorView[] initialOperators); - /// ``` - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct constructorCall { - #[allow(missing_docs)] - pub initialSettings: ::RustType, - #[allow(missing_docs)] - pub initialOperators: alloy::sol_types::private::Vec< - ::RustType, - >, - } - const _: () = { - use alloy::sol_types as alloy_sol_types; - { - #[doc(hidden)] - type UnderlyingSolTuple<'a> = ( - Settings, - alloy::sol_types::sol_data::Array, - ); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = ( - ::RustType, - alloy::sol_types::private::Vec< - ::RustType, - >, - ); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: constructorCall) -> Self { - (value.initialSettings, value.initialOperators) - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for constructorCall { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self { - initialSettings: tuple.0, - initialOperators: tuple.1, - } - } - } - } - #[automatically_derived] - impl alloy_sol_types::SolConstructor for constructorCall { - type Parameters<'a> = ( - Settings, - alloy::sol_types::sol_data::Array, - ); - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - #[inline] - fn new<'a>( - tuple: as alloy_sol_types::SolType>::RustType, - ) -> Self { - tuple.into() - } - #[inline] - fn tokenize(&self) -> Self::Token<'_> { - ( - ::tokenize( - &self.initialSettings, - ), - as alloy_sol_types::SolType>::tokenize(&self.initialOperators), - ) - } - } - }; - /// Function with signature `abortMaintenance()` and selector `0x3048bfba`. - /// ```solidity - /// function abortMaintenance() external; - /// ``` - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct abortMaintenanceCall {} - /// Container type for the return parameters of the - /// [`abortMaintenance()`](abortMaintenanceCall) function. - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct abortMaintenanceReturn {} - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - { - #[doc(hidden)] - type UnderlyingSolTuple<'a> = (); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = (); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: abortMaintenanceCall) -> Self { - () - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for abortMaintenanceCall { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self {} - } - } - } - { - #[doc(hidden)] - type UnderlyingSolTuple<'a> = (); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = (); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: abortMaintenanceReturn) -> Self { - () - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for abortMaintenanceReturn { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self {} - } - } - } - #[automatically_derived] - impl alloy_sol_types::SolCall for abortMaintenanceCall { - type Parameters<'a> = (); - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - type Return = abortMaintenanceReturn; - type ReturnTuple<'a> = (); - type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SIGNATURE: &'static str = "abortMaintenance()"; - const SELECTOR: [u8; 4] = [48u8, 72u8, 191u8, 186u8]; - #[inline] - fn new<'a>( - tuple: as alloy_sol_types::SolType>::RustType, - ) -> Self { - tuple.into() - } - #[inline] - fn tokenize(&self) -> Self::Token<'_> { - () - } - #[inline] - fn abi_decode_returns( - data: &[u8], - validate: bool, - ) -> alloy_sol_types::Result { - as alloy_sol_types::SolType>::abi_decode_sequence( - data, validate, - ) - .map(Into::into) - } - } - }; - /// Function with signature `abortMigration()` and selector `0xc130809a`. - /// ```solidity - /// function abortMigration() external; - /// ``` - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct abortMigrationCall {} - /// Container type for the return parameters of the - /// [`abortMigration()`](abortMigrationCall) function. - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct abortMigrationReturn {} - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - { - #[doc(hidden)] - type UnderlyingSolTuple<'a> = (); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = (); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: abortMigrationCall) -> Self { - () - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for abortMigrationCall { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self {} - } - } - } - { - #[doc(hidden)] - type UnderlyingSolTuple<'a> = (); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = (); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: abortMigrationReturn) -> Self { - () - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for abortMigrationReturn { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self {} - } - } - } - #[automatically_derived] - impl alloy_sol_types::SolCall for abortMigrationCall { - type Parameters<'a> = (); - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - type Return = abortMigrationReturn; - type ReturnTuple<'a> = (); - type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SIGNATURE: &'static str = "abortMigration()"; - const SELECTOR: [u8; 4] = [193u8, 48u8, 128u8, 154u8]; - #[inline] - fn new<'a>( - tuple: as alloy_sol_types::SolType>::RustType, - ) -> Self { - tuple.into() - } - #[inline] - fn tokenize(&self) -> Self::Token<'_> { - () - } - #[inline] - fn abi_decode_returns( - data: &[u8], - validate: bool, - ) -> alloy_sol_types::Result { - as alloy_sol_types::SolType>::abi_decode_sequence( - data, validate, - ) - .map(Into::into) - } - } - }; - /// Function with signature `completeMaintenance()` and selector - /// `0xad36e6d0`. ```solidity - /// function completeMaintenance() external; - /// ``` - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct completeMaintenanceCall {} - /// Container type for the return parameters of the - /// [`completeMaintenance()`](completeMaintenanceCall) function. - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct completeMaintenanceReturn {} - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - { - #[doc(hidden)] - type UnderlyingSolTuple<'a> = (); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = (); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: completeMaintenanceCall) -> Self { - () - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for completeMaintenanceCall { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self {} - } - } - } - { - #[doc(hidden)] - type UnderlyingSolTuple<'a> = (); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = (); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: completeMaintenanceReturn) -> Self { - () - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for completeMaintenanceReturn { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self {} - } - } - } - #[automatically_derived] - impl alloy_sol_types::SolCall for completeMaintenanceCall { - type Parameters<'a> = (); - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - type Return = completeMaintenanceReturn; - type ReturnTuple<'a> = (); - type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SIGNATURE: &'static str = "completeMaintenance()"; - const SELECTOR: [u8; 4] = [173u8, 54u8, 230u8, 208u8]; - #[inline] - fn new<'a>( - tuple: as alloy_sol_types::SolType>::RustType, - ) -> Self { - tuple.into() - } - #[inline] - fn tokenize(&self) -> Self::Token<'_> { - () - } - #[inline] - fn abi_decode_returns( - data: &[u8], - validate: bool, - ) -> alloy_sol_types::Result { - as alloy_sol_types::SolType>::abi_decode_sequence( - data, validate, - ) - .map(Into::into) - } - } - }; - /// Function with signature `completeMigration()` and selector `0x4886f62c`. - /// ```solidity - /// function completeMigration() external; - /// ``` - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct completeMigrationCall {} - /// Container type for the return parameters of the - /// [`completeMigration()`](completeMigrationCall) function. - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct completeMigrationReturn {} - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - { - #[doc(hidden)] - type UnderlyingSolTuple<'a> = (); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = (); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: completeMigrationCall) -> Self { - () - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for completeMigrationCall { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self {} - } - } - } - { - #[doc(hidden)] - type UnderlyingSolTuple<'a> = (); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = (); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: completeMigrationReturn) -> Self { - () - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for completeMigrationReturn { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self {} - } - } - } - #[automatically_derived] - impl alloy_sol_types::SolCall for completeMigrationCall { - type Parameters<'a> = (); - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - type Return = completeMigrationReturn; - type ReturnTuple<'a> = (); - type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SIGNATURE: &'static str = "completeMigration()"; - const SELECTOR: [u8; 4] = [72u8, 134u8, 246u8, 44u8]; - #[inline] - fn new<'a>( - tuple: as alloy_sol_types::SolType>::RustType, - ) -> Self { - tuple.into() - } - #[inline] - fn tokenize(&self) -> Self::Token<'_> { - () - } - #[inline] - fn abi_decode_returns( - data: &[u8], - validate: bool, - ) -> alloy_sol_types::Result { - as alloy_sol_types::SolType>::abi_decode_sequence( - data, validate, - ) - .map(Into::into) - } - } - }; - /// Function with signature `getView()` and selector `0x75418b9d`. - /// ```solidity - /// function getView() external view returns (ClusterView memory); - /// ``` - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct getViewCall {} - /// Container type for the return parameters of the - /// [`getView()`](getViewCall) function. - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct getViewReturn { - #[allow(missing_docs)] - pub _0: ::RustType, - } - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - { - #[doc(hidden)] - type UnderlyingSolTuple<'a> = (); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = (); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: getViewCall) -> Self { - () - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for getViewCall { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self {} - } - } - } - { - #[doc(hidden)] - type UnderlyingSolTuple<'a> = (ClusterView,); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = (::RustType,); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: getViewReturn) -> Self { - (value._0,) - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for getViewReturn { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self { _0: tuple.0 } - } - } - } - #[automatically_derived] - impl alloy_sol_types::SolCall for getViewCall { - type Parameters<'a> = (); - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - type Return = getViewReturn; - type ReturnTuple<'a> = (ClusterView,); - type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SIGNATURE: &'static str = "getView()"; - const SELECTOR: [u8; 4] = [117u8, 65u8, 139u8, 157u8]; - #[inline] - fn new<'a>( - tuple: as alloy_sol_types::SolType>::RustType, - ) -> Self { - tuple.into() - } - #[inline] - fn tokenize(&self) -> Self::Token<'_> { - () - } - #[inline] - fn abi_decode_returns( - data: &[u8], - validate: bool, - ) -> alloy_sol_types::Result { - as alloy_sol_types::SolType>::abi_decode_sequence( - data, validate, - ) - .map(Into::into) - } - } - }; - /// Function with signature `removeNode(uint256)` and selector `0xffd740df`. - /// ```solidity - /// function removeNode(uint256 id) external; - /// ``` - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct removeNodeCall { - #[allow(missing_docs)] - pub id: alloy::sol_types::private::primitives::aliases::U256, - } - /// Container type for the return parameters of the - /// [`removeNode(uint256)`](removeNodeCall) function. - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct removeNodeReturn {} - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - { - #[doc(hidden)] - type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Uint<256>,); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = (alloy::sol_types::private::primitives::aliases::U256,); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: removeNodeCall) -> Self { - (value.id,) - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for removeNodeCall { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self { id: tuple.0 } - } - } - } - { - #[doc(hidden)] - type UnderlyingSolTuple<'a> = (); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = (); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: removeNodeReturn) -> Self { - () - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for removeNodeReturn { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self {} - } - } - } - #[automatically_derived] - impl alloy_sol_types::SolCall for removeNodeCall { - type Parameters<'a> = (alloy::sol_types::sol_data::Uint<256>,); - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - type Return = removeNodeReturn; - type ReturnTuple<'a> = (); - type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SIGNATURE: &'static str = "removeNode(uint256)"; - const SELECTOR: [u8; 4] = [255u8, 215u8, 64u8, 223u8]; - #[inline] - fn new<'a>( - tuple: as alloy_sol_types::SolType>::RustType, - ) -> Self { - tuple.into() - } - #[inline] - fn tokenize(&self) -> Self::Token<'_> { - ( - as alloy_sol_types::SolType>::tokenize( - &self.id, - ), - ) - } - #[inline] - fn abi_decode_returns( - data: &[u8], - validate: bool, - ) -> alloy_sol_types::Result { - as alloy_sol_types::SolType>::abi_decode_sequence( - data, validate, - ) - .map(Into::into) - } - } - }; - /// Function with signature `setNode((uint256,bytes))` and selector - /// `0x6c0b61b9`. ```solidity - /// function setNode(Node memory node) external; - /// ``` - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct setNodeCall { - #[allow(missing_docs)] - pub node: ::RustType, - } - /// Container type for the return parameters of the - /// [`setNode((uint256,bytes))`](setNodeCall) function. - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct setNodeReturn {} - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - { - #[doc(hidden)] - type UnderlyingSolTuple<'a> = (Node,); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = (::RustType,); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: setNodeCall) -> Self { - (value.node,) - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for setNodeCall { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self { node: tuple.0 } - } - } - } - { - #[doc(hidden)] - type UnderlyingSolTuple<'a> = (); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = (); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: setNodeReturn) -> Self { - () - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for setNodeReturn { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self {} - } - } - } - #[automatically_derived] - impl alloy_sol_types::SolCall for setNodeCall { - type Parameters<'a> = (Node,); - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - type Return = setNodeReturn; - type ReturnTuple<'a> = (); - type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SIGNATURE: &'static str = "setNode((uint256,bytes))"; - const SELECTOR: [u8; 4] = [108u8, 11u8, 97u8, 185u8]; - #[inline] - fn new<'a>( - tuple: as alloy_sol_types::SolType>::RustType, - ) -> Self { - tuple.into() - } - #[inline] - fn tokenize(&self) -> Self::Token<'_> { - (::tokenize(&self.node),) - } - #[inline] - fn abi_decode_returns( - data: &[u8], - validate: bool, - ) -> alloy_sol_types::Result { - as alloy_sol_types::SolType>::abi_decode_sequence( - data, validate, - ) - .map(Into::into) - } - } - }; - /// Function with signature `startMaintenance()` and selector `0xf5f2d9f1`. - /// ```solidity - /// function startMaintenance() external; - /// ``` - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct startMaintenanceCall {} - /// Container type for the return parameters of the - /// [`startMaintenance()`](startMaintenanceCall) function. - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct startMaintenanceReturn {} - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - { - #[doc(hidden)] - type UnderlyingSolTuple<'a> = (); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = (); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: startMaintenanceCall) -> Self { - () - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for startMaintenanceCall { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self {} - } - } - } - { - #[doc(hidden)] - type UnderlyingSolTuple<'a> = (); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = (); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: startMaintenanceReturn) -> Self { - () - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for startMaintenanceReturn { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self {} - } - } - } - #[automatically_derived] - impl alloy_sol_types::SolCall for startMaintenanceCall { - type Parameters<'a> = (); - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - type Return = startMaintenanceReturn; - type ReturnTuple<'a> = (); - type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SIGNATURE: &'static str = "startMaintenance()"; - const SELECTOR: [u8; 4] = [245u8, 242u8, 217u8, 241u8]; - #[inline] - fn new<'a>( - tuple: as alloy_sol_types::SolType>::RustType, - ) -> Self { - tuple.into() - } - #[inline] - fn tokenize(&self) -> Self::Token<'_> { - () - } - #[inline] - fn abi_decode_returns( - data: &[u8], - validate: bool, - ) -> alloy_sol_types::Result { - as alloy_sol_types::SolType>::abi_decode_sequence( - data, validate, - ) - .map(Into::into) - } - } - }; - /// Function with signature - /// `startMigration(address[],(address,(uint256,bytes)[],bytes)[])` and - /// selector `0xcc45662a`. ```solidity - /// function startMigration(address[] memory operatorsToRemove, - /// NodeOperatorView[] memory operatorsToAdd) external; ``` - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct startMigrationCall { - #[allow(missing_docs)] - pub operatorsToRemove: alloy::sol_types::private::Vec, - #[allow(missing_docs)] - pub operatorsToAdd: alloy::sol_types::private::Vec< - ::RustType, - >, - } - /// Container type for the return parameters of the - /// [`startMigration(address[],(address,(uint256,bytes)[], - /// bytes)[])`](startMigrationCall) function. - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct startMigrationReturn {} - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - { - #[doc(hidden)] - type UnderlyingSolTuple<'a> = ( - alloy::sol_types::sol_data::Array, - alloy::sol_types::sol_data::Array, - ); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = ( - alloy::sol_types::private::Vec, - alloy::sol_types::private::Vec< - ::RustType, - >, - ); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: startMigrationCall) -> Self { - (value.operatorsToRemove, value.operatorsToAdd) - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for startMigrationCall { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self { - operatorsToRemove: tuple.0, - operatorsToAdd: tuple.1, - } - } - } - } - { - #[doc(hidden)] - type UnderlyingSolTuple<'a> = (); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = (); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: startMigrationReturn) -> Self { - () - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for startMigrationReturn { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self {} - } - } - } - #[automatically_derived] - impl alloy_sol_types::SolCall for startMigrationCall { - type Parameters<'a> = ( - alloy::sol_types::sol_data::Array, - alloy::sol_types::sol_data::Array, - ); - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - type Return = startMigrationReturn; - type ReturnTuple<'a> = (); - type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SIGNATURE: &'static str = - "startMigration(address[],(address,(uint256,bytes)[],bytes)[])"; - const SELECTOR: [u8; 4] = [204u8, 69u8, 102u8, 42u8]; - #[inline] - fn new<'a>( - tuple: as alloy_sol_types::SolType>::RustType, - ) -> Self { - tuple.into() - } - #[inline] - fn tokenize(&self) -> Self::Token<'_> { - ( - as alloy_sol_types::SolType>::tokenize(&self.operatorsToRemove), - as alloy_sol_types::SolType>::tokenize(&self.operatorsToAdd), - ) - } - #[inline] - fn abi_decode_returns( - data: &[u8], - validate: bool, - ) -> alloy_sol_types::Result { - as alloy_sol_types::SolType>::abi_decode_sequence( - data, validate, - ) - .map(Into::into) - } - } - }; - /// Function with signature `transferOwnership(address)` and selector - /// `0xf2fde38b`. ```solidity - /// function transferOwnership(address newOwner) external; - /// ``` - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct transferOwnershipCall { - #[allow(missing_docs)] - pub newOwner: alloy::sol_types::private::Address, - } - /// Container type for the return parameters of the - /// [`transferOwnership(address)`](transferOwnershipCall) function. - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct transferOwnershipReturn {} - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - { - #[doc(hidden)] - type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Address,); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = (alloy::sol_types::private::Address,); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: transferOwnershipCall) -> Self { - (value.newOwner,) - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for transferOwnershipCall { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self { newOwner: tuple.0 } - } - } - } - { - #[doc(hidden)] - type UnderlyingSolTuple<'a> = (); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = (); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: transferOwnershipReturn) -> Self { - () - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for transferOwnershipReturn { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self {} - } - } - } - #[automatically_derived] - impl alloy_sol_types::SolCall for transferOwnershipCall { - type Parameters<'a> = (alloy::sol_types::sol_data::Address,); - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - type Return = transferOwnershipReturn; - type ReturnTuple<'a> = (); - type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SIGNATURE: &'static str = "transferOwnership(address)"; - const SELECTOR: [u8; 4] = [242u8, 253u8, 227u8, 139u8]; - #[inline] - fn new<'a>( - tuple: as alloy_sol_types::SolType>::RustType, - ) -> Self { - tuple.into() - } - #[inline] - fn tokenize(&self) -> Self::Token<'_> { - ( - ::tokenize( - &self.newOwner, - ), - ) - } - #[inline] - fn abi_decode_returns( - data: &[u8], - validate: bool, - ) -> alloy_sol_types::Result { - as alloy_sol_types::SolType>::abi_decode_sequence( - data, validate, - ) - .map(Into::into) - } - } - }; - /// Function with signature `updateSettings((uint8,uint8))` and selector - /// `0x409900e8`. ```solidity - /// function updateSettings(Settings memory newSettings) external; - /// ``` - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct updateSettingsCall { - #[allow(missing_docs)] - pub newSettings: ::RustType, - } - /// Container type for the return parameters of the - /// [`updateSettings((uint8,uint8))`](updateSettingsCall) function. - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct updateSettingsReturn {} - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - { - #[doc(hidden)] - type UnderlyingSolTuple<'a> = (Settings,); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = (::RustType,); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: updateSettingsCall) -> Self { - (value.newSettings,) - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for updateSettingsCall { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self { - newSettings: tuple.0, - } - } - } - } - { - #[doc(hidden)] - type UnderlyingSolTuple<'a> = (); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = (); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: updateSettingsReturn) -> Self { - () - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for updateSettingsReturn { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self {} - } - } - } - #[automatically_derived] - impl alloy_sol_types::SolCall for updateSettingsCall { - type Parameters<'a> = (Settings,); - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - type Return = updateSettingsReturn; - type ReturnTuple<'a> = (); - type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SIGNATURE: &'static str = "updateSettings((uint8,uint8))"; - const SELECTOR: [u8; 4] = [64u8, 153u8, 0u8, 232u8]; - #[inline] - fn new<'a>( - tuple: as alloy_sol_types::SolType>::RustType, - ) -> Self { - tuple.into() - } - #[inline] - fn tokenize(&self) -> Self::Token<'_> { - (::tokenize( - &self.newSettings, - ),) - } - #[inline] - fn abi_decode_returns( - data: &[u8], - validate: bool, - ) -> alloy_sol_types::Result { - as alloy_sol_types::SolType>::abi_decode_sequence( - data, validate, - ) - .map(Into::into) - } - } - }; - /// Container for all the [`Cluster`](self) function calls. - pub enum ClusterCalls { - #[allow(missing_docs)] - abortMaintenance(abortMaintenanceCall), - #[allow(missing_docs)] - abortMigration(abortMigrationCall), - #[allow(missing_docs)] - completeMaintenance(completeMaintenanceCall), - #[allow(missing_docs)] - completeMigration(completeMigrationCall), - #[allow(missing_docs)] - getView(getViewCall), - #[allow(missing_docs)] - removeNode(removeNodeCall), - #[allow(missing_docs)] - setNode(setNodeCall), - #[allow(missing_docs)] - startMaintenance(startMaintenanceCall), - #[allow(missing_docs)] - startMigration(startMigrationCall), - #[allow(missing_docs)] - transferOwnership(transferOwnershipCall), - #[allow(missing_docs)] - updateSettings(updateSettingsCall), - } - #[automatically_derived] - impl ClusterCalls { - /// All the selectors of this enum. - /// - /// Note that the selectors might not be in the same order as the - /// variants. No guarantees are made about the order of the - /// selectors. - /// - /// Prefer using `SolInterface` methods instead. - pub const SELECTORS: &'static [[u8; 4usize]] = &[ - [48u8, 72u8, 191u8, 186u8], - [64u8, 153u8, 0u8, 232u8], - [72u8, 134u8, 246u8, 44u8], - [108u8, 11u8, 97u8, 185u8], - [117u8, 65u8, 139u8, 157u8], - [173u8, 54u8, 230u8, 208u8], - [193u8, 48u8, 128u8, 154u8], - [204u8, 69u8, 102u8, 42u8], - [242u8, 253u8, 227u8, 139u8], - [245u8, 242u8, 217u8, 241u8], - [255u8, 215u8, 64u8, 223u8], - ]; - } - #[automatically_derived] - impl alloy_sol_types::SolInterface for ClusterCalls { - const NAME: &'static str = "ClusterCalls"; - const MIN_DATA_LENGTH: usize = 0usize; - const COUNT: usize = 11usize; - #[inline] - fn selector(&self) -> [u8; 4] { - match self { - Self::abortMaintenance(_) => { - ::SELECTOR - } - Self::abortMigration(_) => { - ::SELECTOR - } - Self::completeMaintenance(_) => { - ::SELECTOR - } - Self::completeMigration(_) => { - ::SELECTOR - } - Self::getView(_) => ::SELECTOR, - Self::removeNode(_) => ::SELECTOR, - Self::setNode(_) => ::SELECTOR, - Self::startMaintenance(_) => { - ::SELECTOR - } - Self::startMigration(_) => { - ::SELECTOR - } - Self::transferOwnership(_) => { - ::SELECTOR - } - Self::updateSettings(_) => { - ::SELECTOR - } - } - } - #[inline] - fn selector_at(i: usize) -> ::core::option::Option<[u8; 4]> { - Self::SELECTORS.get(i).copied() - } - #[inline] - fn valid_selector(selector: [u8; 4]) -> bool { - Self::SELECTORS.binary_search(&selector).is_ok() - } - #[inline] - #[allow(non_snake_case)] - fn abi_decode_raw( - selector: [u8; 4], - data: &[u8], - validate: bool, - ) -> alloy_sol_types::Result { - static DECODE_SHIMS: &[fn(&[u8], bool) -> alloy_sol_types::Result] = &[ - { - fn abortMaintenance( - data: &[u8], - validate: bool, - ) -> alloy_sol_types::Result { - ::abi_decode_raw( - data, validate, - ) - .map(ClusterCalls::abortMaintenance) - } - abortMaintenance - }, - { - fn updateSettings( - data: &[u8], - validate: bool, - ) -> alloy_sol_types::Result { - ::abi_decode_raw( - data, validate, - ) - .map(ClusterCalls::updateSettings) - } - updateSettings - }, - { - fn completeMigration( - data: &[u8], - validate: bool, - ) -> alloy_sol_types::Result { - ::abi_decode_raw( - data, validate, - ) - .map(ClusterCalls::completeMigration) - } - completeMigration - }, - { - fn setNode( - data: &[u8], - validate: bool, - ) -> alloy_sol_types::Result { - ::abi_decode_raw(data, validate) - .map(ClusterCalls::setNode) - } - setNode - }, - { - fn getView( - data: &[u8], - validate: bool, - ) -> alloy_sol_types::Result { - ::abi_decode_raw(data, validate) - .map(ClusterCalls::getView) - } - getView - }, - { - fn completeMaintenance( - data: &[u8], - validate: bool, - ) -> alloy_sol_types::Result { - ::abi_decode_raw( - data, validate, - ) - .map(ClusterCalls::completeMaintenance) - } - completeMaintenance - }, - { - fn abortMigration( - data: &[u8], - validate: bool, - ) -> alloy_sol_types::Result { - ::abi_decode_raw( - data, validate, - ) - .map(ClusterCalls::abortMigration) - } - abortMigration - }, - { - fn startMigration( - data: &[u8], - validate: bool, - ) -> alloy_sol_types::Result { - ::abi_decode_raw( - data, validate, - ) - .map(ClusterCalls::startMigration) - } - startMigration - }, - { - fn transferOwnership( - data: &[u8], - validate: bool, - ) -> alloy_sol_types::Result { - ::abi_decode_raw( - data, validate, - ) - .map(ClusterCalls::transferOwnership) - } - transferOwnership - }, - { - fn startMaintenance( - data: &[u8], - validate: bool, - ) -> alloy_sol_types::Result { - ::abi_decode_raw( - data, validate, - ) - .map(ClusterCalls::startMaintenance) - } - startMaintenance - }, - { - fn removeNode( - data: &[u8], - validate: bool, - ) -> alloy_sol_types::Result { - ::abi_decode_raw(data, validate) - .map(ClusterCalls::removeNode) - } - removeNode - }, - ]; - let Ok(idx) = Self::SELECTORS.binary_search(&selector) else { - return Err(alloy_sol_types::Error::unknown_selector( - ::NAME, - selector, - )); - }; - DECODE_SHIMS[idx](data, validate) - } - #[inline] - fn abi_encoded_size(&self) -> usize { - match self { - Self::abortMaintenance(inner) => { - ::abi_encoded_size(inner) - } - Self::abortMigration(inner) => { - ::abi_encoded_size(inner) - } - Self::completeMaintenance(inner) => { - ::abi_encoded_size(inner) - } - Self::completeMigration(inner) => { - ::abi_encoded_size(inner) - } - Self::getView(inner) => { - ::abi_encoded_size(inner) - } - Self::removeNode(inner) => { - ::abi_encoded_size(inner) - } - Self::setNode(inner) => { - ::abi_encoded_size(inner) - } - Self::startMaintenance(inner) => { - ::abi_encoded_size(inner) - } - Self::startMigration(inner) => { - ::abi_encoded_size(inner) - } - Self::transferOwnership(inner) => { - ::abi_encoded_size(inner) - } - Self::updateSettings(inner) => { - ::abi_encoded_size(inner) - } - } - } - #[inline] - fn abi_encode_raw(&self, out: &mut alloy_sol_types::private::Vec) { - match self { - Self::abortMaintenance(inner) => { - ::abi_encode_raw(inner, out) - } - Self::abortMigration(inner) => { - ::abi_encode_raw(inner, out) - } - Self::completeMaintenance(inner) => { - ::abi_encode_raw( - inner, out, - ) - } - Self::completeMigration(inner) => { - ::abi_encode_raw(inner, out) - } - Self::getView(inner) => { - ::abi_encode_raw(inner, out) - } - Self::removeNode(inner) => { - ::abi_encode_raw(inner, out) - } - Self::setNode(inner) => { - ::abi_encode_raw(inner, out) - } - Self::startMaintenance(inner) => { - ::abi_encode_raw(inner, out) - } - Self::startMigration(inner) => { - ::abi_encode_raw(inner, out) - } - Self::transferOwnership(inner) => { - ::abi_encode_raw(inner, out) - } - Self::updateSettings(inner) => { - ::abi_encode_raw(inner, out) - } - } - } - } - /// Container for all the [`Cluster`](self) events. - pub enum ClusterEvents { - #[allow(missing_docs)] - MaintenanceAborted(MaintenanceAborted), - #[allow(missing_docs)] - MaintenanceCompleted(MaintenanceCompleted), - #[allow(missing_docs)] - MaintenanceStarted(MaintenanceStarted), - #[allow(missing_docs)] - MigrationAborted(MigrationAborted), - #[allow(missing_docs)] - MigrationCompleted(MigrationCompleted), - #[allow(missing_docs)] - MigrationDataPullCompleted(MigrationDataPullCompleted), - #[allow(missing_docs)] - MigrationStarted(MigrationStarted), - #[allow(missing_docs)] - NodeRemoved(NodeRemoved), - #[allow(missing_docs)] - NodeSet(NodeSet), - } - #[automatically_derived] - impl ClusterEvents { - /// All the selectors of this enum. - /// - /// Note that the selectors might not be in the same order as the - /// variants. No guarantees are made about the order of the - /// selectors. - /// - /// Prefer using `SolInterface` methods instead. - pub const SELECTORS: &'static [[u8; 32usize]] = &[ - [ - 17u8, 206u8, 80u8, 22u8, 14u8, 102u8, 16u8, 5u8, 55u8, 253u8, 75u8, 10u8, 226u8, - 109u8, 230u8, 109u8, 81u8, 218u8, 183u8, 19u8, 173u8, 146u8, 49u8, 51u8, 83u8, - 161u8, 140u8, 36u8, 232u8, 246u8, 218u8, 171u8, - ], - [ - 106u8, 223u8, 184u8, 150u8, 211u8, 64u8, 118u8, 129u8, 208u8, 95u8, 184u8, 116u8, - 212u8, 223u8, 183u8, 6u8, 142u8, 110u8, 42u8, 54u8, 240u8, 154u8, 205u8, 56u8, - 163u8, 183u8, 208u8, 76u8, 1u8, 116u8, 95u8, 238u8, - ], - [ - 126u8, 5u8, 228u8, 1u8, 23u8, 182u8, 225u8, 138u8, 178u8, 132u8, 192u8, 74u8, 53u8, - 8u8, 195u8, 130u8, 100u8, 34u8, 220u8, 132u8, 166u8, 94u8, 156u8, 35u8, 106u8, - 130u8, 72u8, 119u8, 68u8, 22u8, 248u8, 172u8, - ], - [ - 143u8, 185u8, 205u8, 5u8, 77u8, 10u8, 2u8, 33u8, 16u8, 204u8, 237u8, 35u8, 158u8, - 144u8, 139u8, 131u8, 78u8, 76u8, 210u8, 25u8, 81u8, 24u8, 86u8, 212u8, 234u8, - 174u8, 48u8, 81u8, 217u8, 50u8, 214u8, 4u8, - ], - [ - 156u8, 225u8, 146u8, 174u8, 165u8, 250u8, 242u8, 21u8, 27u8, 188u8, 36u8, 108u8, - 216u8, 145u8, 141u8, 46u8, 186u8, 112u8, 47u8, 162u8, 105u8, 81u8, 246u8, 127u8, - 43u8, 247u8, 179u8, 129u8, 126u8, 104u8, 157u8, 152u8, - ], - [ - 167u8, 106u8, 143u8, 193u8, 169u8, 2u8, 102u8, 221u8, 238u8, 137u8, 55u8, 161u8, - 142u8, 18u8, 240u8, 30u8, 173u8, 233u8, 70u8, 179u8, 182u8, 97u8, 151u8, 255u8, - 242u8, 137u8, 175u8, 146u8, 119u8, 194u8, 189u8, 37u8, - ], - [ - 188u8, 39u8, 72u8, 207u8, 2u8, 247u8, 161u8, 41u8, 21u8, 37u8, 232u8, 102u8, 239u8, - 199u8, 106u8, 179u8, 185u8, 109u8, 50u8, 215u8, 175u8, 203u8, 178u8, 108u8, 83u8, - 218u8, 236u8, 97u8, 123u8, 56u8, 180u8, 121u8, - ], - [ - 189u8, 24u8, 77u8, 231u8, 159u8, 19u8, 75u8, 15u8, 61u8, 164u8, 102u8, 210u8, - 120u8, 245u8, 65u8, 124u8, 188u8, 177u8, 69u8, 13u8, 114u8, 241u8, 189u8, 26u8, - 27u8, 132u8, 241u8, 139u8, 27u8, 205u8, 3u8, 202u8, - ], - [ - 249u8, 16u8, 103u8, 235u8, 66u8, 12u8, 40u8, 211u8, 18u8, 72u8, 101u8, 252u8, - 153u8, 110u8, 106u8, 169u8, 213u8, 65u8, 185u8, 180u8, 254u8, 249u8, 24u8, 140u8, - 185u8, 101u8, 166u8, 204u8, 100u8, 145u8, 99u8, 142u8, - ], - ]; - } - #[automatically_derived] - impl alloy_sol_types::SolEventInterface for ClusterEvents { - const NAME: &'static str = "ClusterEvents"; - const COUNT: usize = 9usize; - fn decode_raw_log( - topics: &[alloy_sol_types::Word], - data: &[u8], - validate: bool, - ) -> alloy_sol_types::Result { - match topics.first().copied() { - Some(::SIGNATURE_HASH) => { - ::decode_raw_log( - topics, data, validate, - ) - .map(Self::MaintenanceAborted) - } - Some(::SIGNATURE_HASH) => { - ::decode_raw_log( - topics, data, validate, - ) - .map(Self::MaintenanceCompleted) - } - Some(::SIGNATURE_HASH) => { - ::decode_raw_log( - topics, data, validate, - ) - .map(Self::MaintenanceStarted) - } - Some(::SIGNATURE_HASH) => { - ::decode_raw_log( - topics, data, validate, - ) - .map(Self::MigrationAborted) - } - Some(::SIGNATURE_HASH) => { - ::decode_raw_log( - topics, data, validate, - ) - .map(Self::MigrationCompleted) - } - Some(::SIGNATURE_HASH) => { - ::decode_raw_log( - topics, data, validate, - ) - .map(Self::MigrationDataPullCompleted) - } - Some(::SIGNATURE_HASH) => { - ::decode_raw_log( - topics, data, validate, - ) - .map(Self::MigrationStarted) - } - Some(::SIGNATURE_HASH) => { - ::decode_raw_log( - topics, data, validate, - ) - .map(Self::NodeRemoved) - } - Some(::SIGNATURE_HASH) => { - ::decode_raw_log(topics, data, validate) - .map(Self::NodeSet) - } - _ => alloy_sol_types::private::Err(alloy_sol_types::Error::InvalidLog { - name: ::NAME, - log: alloy_sol_types::private::Box::new( - alloy_sol_types::private::LogData::new_unchecked( - topics.to_vec(), - data.to_vec().into(), - ), - ), - }), - } - } - } - #[automatically_derived] - impl alloy_sol_types::private::IntoLogData for ClusterEvents { - fn to_log_data(&self) -> alloy_sol_types::private::LogData { - match self { - Self::MaintenanceAborted(inner) => { - alloy_sol_types::private::IntoLogData::to_log_data(inner) - } - Self::MaintenanceCompleted(inner) => { - alloy_sol_types::private::IntoLogData::to_log_data(inner) - } - Self::MaintenanceStarted(inner) => { - alloy_sol_types::private::IntoLogData::to_log_data(inner) - } - Self::MigrationAborted(inner) => { - alloy_sol_types::private::IntoLogData::to_log_data(inner) - } - Self::MigrationCompleted(inner) => { - alloy_sol_types::private::IntoLogData::to_log_data(inner) - } - Self::MigrationDataPullCompleted(inner) => { - alloy_sol_types::private::IntoLogData::to_log_data(inner) - } - Self::MigrationStarted(inner) => { - alloy_sol_types::private::IntoLogData::to_log_data(inner) - } - Self::NodeRemoved(inner) => { - alloy_sol_types::private::IntoLogData::to_log_data(inner) - } - Self::NodeSet(inner) => alloy_sol_types::private::IntoLogData::to_log_data(inner), - } - } - fn into_log_data(self) -> alloy_sol_types::private::LogData { - match self { - Self::MaintenanceAborted(inner) => { - alloy_sol_types::private::IntoLogData::into_log_data(inner) - } - Self::MaintenanceCompleted(inner) => { - alloy_sol_types::private::IntoLogData::into_log_data(inner) - } - Self::MaintenanceStarted(inner) => { - alloy_sol_types::private::IntoLogData::into_log_data(inner) - } - Self::MigrationAborted(inner) => { - alloy_sol_types::private::IntoLogData::into_log_data(inner) - } - Self::MigrationCompleted(inner) => { - alloy_sol_types::private::IntoLogData::into_log_data(inner) - } - Self::MigrationDataPullCompleted(inner) => { - alloy_sol_types::private::IntoLogData::into_log_data(inner) - } - Self::MigrationStarted(inner) => { - alloy_sol_types::private::IntoLogData::into_log_data(inner) - } - Self::NodeRemoved(inner) => { - alloy_sol_types::private::IntoLogData::into_log_data(inner) - } - Self::NodeSet(inner) => alloy_sol_types::private::IntoLogData::into_log_data(inner), - } - } - } - use alloy::contract as alloy_contract; - /// Creates a new wrapper around an on-chain [`Cluster`](self) contract - /// instance. - /// - /// See the [wrapper's documentation](`ClusterInstance`) for more details. - #[inline] - pub const fn new< - T: alloy_contract::private::Transport + ::core::clone::Clone, - P: alloy_contract::private::Provider, - N: alloy_contract::private::Network, - >( - address: alloy_sol_types::private::Address, - provider: P, - ) -> ClusterInstance { - ClusterInstance::::new(address, provider) - } - /// Deploys this contract using the given `provider` and constructor - /// arguments, if any. - /// - /// Returns a new instance of the contract, if the deployment was - /// successful. - /// - /// For more fine-grained control over the deployment process, use - /// [`deploy_builder`] instead. - #[inline] - pub fn deploy< - T: alloy_contract::private::Transport + ::core::clone::Clone, - P: alloy_contract::private::Provider, - N: alloy_contract::private::Network, - >( - provider: P, - initialSettings: ::RustType, - initialOperators: alloy::sol_types::private::Vec< - ::RustType, - >, - ) -> impl ::core::future::Future>> - { - ClusterInstance::::deploy(provider, initialSettings, initialOperators) - } - /// Creates a `RawCallBuilder` for deploying this contract using the given - /// `provider` and constructor arguments, if any. - /// - /// This is a simple wrapper around creating a `RawCallBuilder` with the - /// data set to the bytecode concatenated with the constructor's - /// ABI-encoded arguments. - #[inline] - pub fn deploy_builder< - T: alloy_contract::private::Transport + ::core::clone::Clone, - P: alloy_contract::private::Provider, - N: alloy_contract::private::Network, - >( - provider: P, - initialSettings: ::RustType, - initialOperators: alloy::sol_types::private::Vec< - ::RustType, - >, - ) -> alloy_contract::RawCallBuilder { - ClusterInstance::::deploy_builder(provider, initialSettings, initialOperators) - } - /// A [`Cluster`](self) instance. - /// - /// Contains type-safe methods for interacting with an on-chain instance of - /// the [`Cluster`](self) contract located at a given `address`, using a - /// given provider `P`. - /// - /// If the contract bytecode is available (see the - /// [`sol!`](alloy_sol_types::sol!) documentation on how to provide it), - /// the `deploy` and `deploy_builder` methods can be used to deploy a - /// new instance of the contract. - /// - /// See the [module-level documentation](self) for all the available - /// methods. - #[derive(Clone)] - pub struct ClusterInstance { - address: alloy_sol_types::private::Address, - provider: P, - _network_transport: ::core::marker::PhantomData<(N, T)>, - } - #[automatically_derived] - impl ::core::fmt::Debug for ClusterInstance { - #[inline] - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { - f.debug_tuple("ClusterInstance") - .field(&self.address) - .finish() - } - } - /// Instantiation and getters/setters. - #[automatically_derived] - impl< - T: alloy_contract::private::Transport + ::core::clone::Clone, - P: alloy_contract::private::Provider, - N: alloy_contract::private::Network, - > ClusterInstance - { - /// Creates a new wrapper around an on-chain [`Cluster`](self) contract - /// instance. - /// - /// See the [wrapper's documentation](`ClusterInstance`) for more - /// details. - #[inline] - pub const fn new(address: alloy_sol_types::private::Address, provider: P) -> Self { - Self { - address, - provider, - _network_transport: ::core::marker::PhantomData, - } - } - /// Deploys this contract using the given `provider` and constructor - /// arguments, if any. - /// - /// Returns a new instance of the contract, if the deployment was - /// successful. - /// - /// For more fine-grained control over the deployment process, use - /// [`deploy_builder`] instead. - #[inline] - pub async fn deploy( - provider: P, - initialSettings: ::RustType, - initialOperators: alloy::sol_types::private::Vec< - ::RustType, - >, - ) -> alloy_contract::Result> { - let call_builder = Self::deploy_builder(provider, initialSettings, initialOperators); - let contract_address = call_builder.deploy().await?; - Ok(Self::new(contract_address, call_builder.provider)) - } - /// Creates a `RawCallBuilder` for deploying this contract using the - /// given `provider` and constructor arguments, if any. - /// - /// This is a simple wrapper around creating a `RawCallBuilder` with the - /// data set to the bytecode concatenated with the constructor's - /// ABI-encoded arguments. - #[inline] - pub fn deploy_builder( - provider: P, - initialSettings: ::RustType, - initialOperators: alloy::sol_types::private::Vec< - ::RustType, - >, - ) -> alloy_contract::RawCallBuilder { - alloy_contract::RawCallBuilder::new_raw_deploy( - provider, - [ - &BYTECODE[..], - &alloy_sol_types::SolConstructor::abi_encode(&constructorCall { - initialSettings, - initialOperators, - })[..], - ] - .concat() - .into(), - ) - } - /// Returns a reference to the address. - #[inline] - pub const fn address(&self) -> &alloy_sol_types::private::Address { - &self.address - } - /// Sets the address. - #[inline] - pub fn set_address(&mut self, address: alloy_sol_types::private::Address) { - self.address = address; - } - /// Sets the address and returns `self`. - pub fn at(mut self, address: alloy_sol_types::private::Address) -> Self { - self.set_address(address); - self - } - /// Returns a reference to the provider. - #[inline] - pub const fn provider(&self) -> &P { - &self.provider - } - } - impl ClusterInstance { - /// Clones the provider and returns a new instance with the cloned - /// provider. - #[inline] - pub fn with_cloned_provider(self) -> ClusterInstance { - ClusterInstance { - address: self.address, - provider: ::core::clone::Clone::clone(&self.provider), - _network_transport: ::core::marker::PhantomData, - } - } - } - /// Function calls. - #[automatically_derived] - impl< - T: alloy_contract::private::Transport + ::core::clone::Clone, - P: alloy_contract::private::Provider, - N: alloy_contract::private::Network, - > ClusterInstance - { - /// Creates a new call builder using this contract instance's provider - /// and address. - /// - /// Note that the call can be any function call, not just those defined - /// in this contract. Prefer using the other methods for - /// building type-safe contract calls. - pub fn call_builder( - &self, - call: &C, - ) -> alloy_contract::SolCallBuilder { - alloy_contract::SolCallBuilder::new_sol(&self.provider, &self.address, call) - } - /// Creates a new call builder for the [`abortMaintenance`] function. - pub fn abortMaintenance( - &self, - ) -> alloy_contract::SolCallBuilder { - self.call_builder(&abortMaintenanceCall {}) - } - /// Creates a new call builder for the [`abortMigration`] function. - pub fn abortMigration( - &self, - ) -> alloy_contract::SolCallBuilder { - self.call_builder(&abortMigrationCall {}) - } - /// Creates a new call builder for the [`completeMaintenance`] function. - pub fn completeMaintenance( - &self, - ) -> alloy_contract::SolCallBuilder { - self.call_builder(&completeMaintenanceCall {}) - } - /// Creates a new call builder for the [`completeMigration`] function. - pub fn completeMigration( - &self, - ) -> alloy_contract::SolCallBuilder { - self.call_builder(&completeMigrationCall {}) - } - /// Creates a new call builder for the [`getView`] function. - pub fn getView(&self) -> alloy_contract::SolCallBuilder { - self.call_builder(&getViewCall {}) - } - /// Creates a new call builder for the [`removeNode`] function. - pub fn removeNode( - &self, - id: alloy::sol_types::private::primitives::aliases::U256, - ) -> alloy_contract::SolCallBuilder { - self.call_builder(&removeNodeCall { id }) - } - /// Creates a new call builder for the [`setNode`] function. - pub fn setNode( - &self, - node: ::RustType, - ) -> alloy_contract::SolCallBuilder { - self.call_builder(&setNodeCall { node }) - } - /// Creates a new call builder for the [`startMaintenance`] function. - pub fn startMaintenance( - &self, - ) -> alloy_contract::SolCallBuilder { - self.call_builder(&startMaintenanceCall {}) - } - /// Creates a new call builder for the [`startMigration`] function. - pub fn startMigration( - &self, - operatorsToRemove: alloy::sol_types::private::Vec, - operatorsToAdd: alloy::sol_types::private::Vec< - ::RustType, - >, - ) -> alloy_contract::SolCallBuilder { - self.call_builder(&startMigrationCall { - operatorsToRemove, - operatorsToAdd, - }) - } - /// Creates a new call builder for the [`transferOwnership`] function. - pub fn transferOwnership( - &self, - newOwner: alloy::sol_types::private::Address, - ) -> alloy_contract::SolCallBuilder { - self.call_builder(&transferOwnershipCall { newOwner }) - } - /// Creates a new call builder for the [`updateSettings`] function. - pub fn updateSettings( - &self, - newSettings: ::RustType, - ) -> alloy_contract::SolCallBuilder { - self.call_builder(&updateSettingsCall { newSettings }) - } - } - /// Event filters. - #[automatically_derived] - impl< - T: alloy_contract::private::Transport + ::core::clone::Clone, - P: alloy_contract::private::Provider, - N: alloy_contract::private::Network, - > ClusterInstance - { - /// Creates a new event filter using this contract instance's provider - /// and address. - /// - /// Note that the type can be any event, not just those defined in this - /// contract. Prefer using the other methods for building - /// type-safe event filters. - pub fn event_filter( - &self, - ) -> alloy_contract::Event { - alloy_contract::Event::new_sol(&self.provider, &self.address) - } - /// Creates a new event filter for the [`MaintenanceAborted`] event. - pub fn MaintenanceAborted_filter( - &self, - ) -> alloy_contract::Event { - self.event_filter::() - } - /// Creates a new event filter for the [`MaintenanceCompleted`] event. - pub fn MaintenanceCompleted_filter( - &self, - ) -> alloy_contract::Event { - self.event_filter::() - } - /// Creates a new event filter for the [`MaintenanceStarted`] event. - pub fn MaintenanceStarted_filter( - &self, - ) -> alloy_contract::Event { - self.event_filter::() - } - /// Creates a new event filter for the [`MigrationAborted`] event. - pub fn MigrationAborted_filter(&self) -> alloy_contract::Event { - self.event_filter::() - } - /// Creates a new event filter for the [`MigrationCompleted`] event. - pub fn MigrationCompleted_filter( - &self, - ) -> alloy_contract::Event { - self.event_filter::() - } - /// Creates a new event filter for the [`MigrationDataPullCompleted`] - /// event. - pub fn MigrationDataPullCompleted_filter( - &self, - ) -> alloy_contract::Event { - self.event_filter::() - } - /// Creates a new event filter for the [`MigrationStarted`] event. - pub fn MigrationStarted_filter(&self) -> alloy_contract::Event { - self.event_filter::() - } - /// Creates a new event filter for the [`NodeRemoved`] event. - pub fn NodeRemoved_filter(&self) -> alloy_contract::Event { - self.event_filter::() - } - /// Creates a new event filter for the [`NodeSet`] event. - pub fn NodeSet_filter(&self) -> alloy_contract::Event { - self.event_filter::() - } - } +#[cfg(feature = "evm")] +pub mod evm; + +/// Public key on a chain hosting the [`SmartContract`]. +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct PublicKey(String); + +pub struct Settings { + pub min_operators: u8, + pub max_operator_data_bytes: u32, } + +pub enum Call { + StartMigration { + operators_to_remove: Vec, + operators_to_add: Vec<(PublicKey, node::Operator)>, + }, + CompleteMigration, + AbortMigration, + + StartMaintenance, + CompleteMaintenance, + AbortMaintenance, + + UpdateNodeOperator(node::Operator), + + UpdateSettings(Settings), + + TransferOwnership(PublicKey), +} + +pub trait SmartContract { + fn call(&self, call: Call) -> impl Future> + Send; +} + +pub struct Error(String); diff --git a/crates/cluster/src/event.rs b/crates/cluster/src/event.rs new file mode 100644 index 00000000..5cc94059 --- /dev/null +++ b/crates/cluster/src/event.rs @@ -0,0 +1,40 @@ +use crate::{NodeOperator, PublicKey}; + +pub struct MigrationStarted { + pub operators_to_remove: Vec, + pub operators_to_add: Vec<(K, NodeOperator)>, + pub version: u128, +} + +pub struct MigrationDataPullCompleted { + pub operator: K, + pub version: u128, +} + +pub struct MigrationCompleted { + pub version: u128, +} + +pub struct MigrationAborted { + pub version: u128, +} + +pub struct MaintenanceStarted { + pub operator: K, + pub version: u8, +} + +pub struct MaintenanceCompleted { + pub operator: K, + pub version: u8, +} + +pub struct MaintenanceAborted { + pub operator: K, + pub version: u8, +} + +pub struct NodeOperatorUpdated { + pub key: K, + pub operator: NodeOperator, +} diff --git a/crates/cluster/src/lib.rs b/crates/cluster/src/lib.rs index a071d3c1..f84994a5 100644 --- a/crates/cluster/src/lib.rs +++ b/crates/cluster/src/lib.rs @@ -1,4 +1,47 @@ -#[rustfmt::skip] +use std::collections::HashSet; + pub mod contract; +pub use contract::SmartContract; + +pub mod node; +pub use node::Node; + +const REPLICATION_FACTOR: usize = 5; + +type Keyspace = sharding::Keyspace; + +/// Read-only view of a WCN cluster. +pub struct View { + /// + pub operators: node::Operators, + + migration: Migration, + maintenance: Maintenance, + + keyspace: Keyspace, + keyspace_version: u64, + + version: u128, +} + +/// Data migration process within a regional WCN cluster. +pub struct Migration { + /// List of [`node::Operator`]s to be removed from the cluster. + pub operators_to_remove: Vec, + + /// List of [`node::Operator`]s to be added to the cluster. + pub operators_to_add: Vec, + + /// List of [`node::Operator`]s still pulling the data. + pub pulling_operators: HashSet, +} -pub struct Cluster {} +/// Maintenance process within a regional WCN cluster. +/// +/// Only a single [`node::Operator`] at a time is allowed to be under +/// maintenance. +pub struct Maintenance { + /// [`node::OperatorId`] of the [`node::Operator`] currently under + /// maintenance (if any). + pub slot: Option, +} diff --git a/crates/cluster/src/node.rs b/crates/cluster/src/node.rs new file mode 100644 index 00000000..6cbfe8ff --- /dev/null +++ b/crates/cluster/src/node.rs @@ -0,0 +1,206 @@ +use { + crate::contract, + libp2p::identity::PeerId, + std::{collections::HashMap, mem, net::SocketAddrV4}, +}; + +/// Globally unique identifier of an [`Operator`]; +pub type OperatorId = contract::PublicKey; + +/// Locally unique identifier of an [`Operator`] within a regional WCN cluster. +/// +/// Refers to a position within the [`Operators`] slot map. +pub type OperatorIdx = u8; + +/// Name of an [`Operator`]. +/// +/// Used for informational purposes only. +/// Expected to be unique within the cluster, but not enforced to. +#[derive(Debug)] +pub struct OperatorName(String); + +impl OperatorName { + /// Maximum allowed length of an [`OperatorName`] (in bytes). + pub const MAX_LENGTH: usize = 32; + + /// Tries to create a new [`OperatorName`] out of the provided [`ToString`]. + /// + /// Returns `None` if the string length exceeds [`Self::MAX_LENGTH`]. + pub fn new(s: impl ToString) -> Option { + let s = s.to_string(); + (s.len() <= Self::MAX_LENGTH).then_some(Self(s)) + } + + /// Returns a reference to the underlying string. + pub fn as_str(&self) -> &str { + &self.0 + } +} + +/// Entity operating a set of WCN nodes within a regional WCN cluster. +#[derive(Debug)] +pub struct Operator { + /// ID of this [`Operator`]. + pub id: OperatorId, + + /// Name of this [`Operator`]. + pub name: OperatorName, + + /// List of [`Node`]s being operated by this [`Operator`]. + pub nodes: Vec, + + /// List of clients of this [`Operator`]. + /// + /// Those clients are allowed to use the WCN network on behalf of this + /// [`Operator`]. + pub clients: Vec, +} + +/// Node within a WCN network. +#[derive(Debug)] +pub struct Node { + /// [`PeerId`] of this [`Node`]. + /// + /// Used for authentication. Multiple nodes managed by the same + /// [`NodeOperator`] are allowed to have the same [`PeerId`]. + pub peer_id: PeerId, + + /// [`SocketAddrV4`] of this [`Node`]. + pub addr: SocketAddrV4, +} + +/// Collection of [`Operator`]s within a regional WCN cluster. +/// +/// Allows to retrieve stored [`Operator`]s using both [`OperatorIdx`]es +/// and [`OperatorId`]s. +/// +/// Guarantees stable ordering on removal -- doesn't shift any elements +/// therefore preserving [`OperatorIdx`] validity. +#[derive(Debug)] +pub struct Operators { + id_to_slot_idx: HashMap, + slots: Vec>, +} + +impl Default for Operators { + fn default() -> Self { + Self { + id_to_slot_idx: HashMap::new(), + slots: Vec::new(), + } + } +} + +impl Operators { + /// Maximum allowed number of slots in this collection. + pub const MAX_SLOTS: usize = u8::MAX as usize + 1; + + // Creates a new empty collection. + pub fn new() -> Self { + Self::default() + } + + /// Tries to create a new collection out of the provided list of existing + /// slots. + /// + /// Returns `None` if the number of slots exceeds [`Self::MAX_SLOTS`]. + pub fn from_slots(slots: Vec>) -> Option { + if slots.len() > Self::MAX_SLOTS { + return None; + } + + let mut key_to_slot_idx = HashMap::new(); + for (idx, value) in slots.iter().enumerate() { + if let Some(v) = value { + key_to_slot_idx.insert(v.id.clone(), idx as u8); + } + } + + Some(Self { + id_to_slot_idx: key_to_slot_idx, + slots, + }) + } + + /// Returns the list of [`Operator] slots. + pub fn slots(&self) -> &[Option] { + &self.slots + } + + /// Gets [`Operator`] by [`OperatorId`]. + pub fn get(&self, id: &OperatorId) -> Option<&Operator> { + self.id_to_slot_idx + .get(id) + .and_then(|&idx| self.slots[idx as usize].as_ref()) + } + + /// Gets [`Operator`] by [`OperatorIdx`]. + pub fn get_by_idx(&self, idx: OperatorIdx) -> Option<&Operator> { + let idx = idx as usize; + if idx >= self.slots.len() { + return None; + } + + self.slots[idx].as_ref() + } + + /// Indicates whether this collection contains the [`Operator`] with the + /// specified [`OperatorId`]. + pub fn contains(&self, id: &OperatorId) -> bool { + self.id_to_slot_idx.contains_key(id) + } + + /// Returns an [`Iterator`] over the [`Operator`] slots in this collection. + pub fn iter(&self) -> impl Iterator { + self.slots + .iter() + .enumerate() + .filter_map(|(idx, n)| n.as_ref().map(|n| (idx as u8, n))) + } + + fn allocate_slot(&mut self) -> Option { + if let Some(idx) = self.slots.iter().position(|n| n.is_none()) { + return Some(idx as u8); + }; + + if self.slots.len() == Self::MAX_SLOTS { + return None; + } + + self.slots.push(None); + Some((self.slots.len() - 1) as u8) + } + + /// Inserts an [`Operator`] into the collection. + pub fn insert( + &mut self, + operator: Operator, + ) -> Result, TooManyOperatorsError> { + let idx = if let Some(idx) = self.id_to_slot_idx.get(&operator.id) { + *idx + } else { + let idx = self.allocate_slot().ok_or(TooManyOperatorsError)?; + let _ = self.id_to_slot_idx.insert(operator.id.clone(), idx); + idx + }; + + let mut operator = Some(operator); + mem::swap(&mut operator, &mut self.slots[idx as usize]); + Ok(operator) + } + + /// Removes the [`Operator`] with the specified [`OperatorId`] from this + /// collection. + pub fn remove(&mut self, id: &OperatorId) -> Option { + if let Some(idx) = self.id_to_slot_idx.remove(id) { + return self.slots[idx as usize].take(); + } + + None + } +} + +/// Error of trying to insert too many elements into [`Operators`] collection. +#[derive(Clone, Debug, thiserror::Error)] +#[error("Maximum number of node operator reached: {}", Operators::MAX_SLOTS)] +pub struct TooManyOperatorsError; diff --git a/crates/cluster/tests/integration.rs b/crates/cluster/tests/integration.rs index 54f94862..da733164 100644 --- a/crates/cluster/tests/integration.rs +++ b/crates/cluster/tests/integration.rs @@ -1,6 +1,31 @@ -use cluster::contract; +use { + alloy::providers::ProviderBuilder, + cluster::contract::{ + self, + Cluster::{NodeOperatorView, Settings}, + }, +}; #[tokio::test] async fn test_suite() { - // cluster::contract::Cluster::deploy(); + let provider = ProviderBuilder::new().on_anvil_with_wallet(); + + let settings = Settings { + minOperators: 5, + minNodes: 1, + }; + + let contract = contract::Cluster::deploy(&provider, settings).await?; + + // // 2. Use Anvil's first default private key + // let wallet: LocalWallet = + // "0x59c6995e998f97a5a0044976f51e2bc4a26b19f3c6d8ff2b67d46e2b4103b3b3" + // .parse::()? + // .with_chain_id(31337); + + // let client = Arc::new(provider.with_signer(wallet)); + + // // 3. Deploy Counter contract + // let deployer = Counter::deploy(client.clone(), ())?; // No constructor + // args let contract = deployer.send().await?; } From aca8a7c81d6896fb3909f1090b920cf8f1117730 Mon Sep 17 00:00:00 2001 From: Github Bot Date: Wed, 14 May 2025 21:22:21 +0000 Subject: [PATCH 14/79] Bump VERSION to 250514.0 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index bdaa0f88..dc325536 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -250513.0 +250514.0 From a244a3637fe2ea3086672f724f23deb18bb2d03b Mon Sep 17 00:00:00 2001 From: Darksome Date: Tue, 20 May 2025 09:33:48 +0000 Subject: [PATCH 15/79] smart contract overhaul --- contracts/remappings.txt | 1 - contracts/src/Cluster.sol | 349 ++++++++++ contracts/src/Cluster/Cluster.sol | 183 ----- contracts/src/Cluster/Maintenance.sol | 29 - contracts/src/Cluster/Migration.sol | 114 ---- contracts/src/Cluster/NodeOperators.sol | 103 --- contracts/src/Cluster/Nodes.sol | 71 -- contracts/test/Suite.sol | 857 +++++++++--------------- 8 files changed, 682 insertions(+), 1025 deletions(-) delete mode 100644 contracts/remappings.txt create mode 100644 contracts/src/Cluster.sol delete mode 100644 contracts/src/Cluster/Cluster.sol delete mode 100644 contracts/src/Cluster/Maintenance.sol delete mode 100644 contracts/src/Cluster/Migration.sol delete mode 100644 contracts/src/Cluster/NodeOperators.sol delete mode 100644 contracts/src/Cluster/Nodes.sol diff --git a/contracts/remappings.txt b/contracts/remappings.txt deleted file mode 100644 index 58a28133..00000000 --- a/contracts/remappings.txt +++ /dev/null @@ -1 +0,0 @@ -forge-std-1.9.7/=dependencies/forge-std-1.9.7/ diff --git a/contracts/src/Cluster.sol b/contracts/src/Cluster.sol new file mode 100644 index 00000000..4da06483 --- /dev/null +++ b/contracts/src/Cluster.sol @@ -0,0 +1,349 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import '../dependencies/openzeppelin-contracts/contracts/utils/math/Math.sol'; + +struct Settings { + uint16 maxOperatorDataBytes; +} + +event MigrationStarted(uint64 id, MigrationPlan plan, uint128 clusterVersion); +event MigrationDataPullCompleted(uint64 id, address operatorAddress, uint128 clusterVersion); +event MigrationCompleted(uint64 id, address operatorAddress, uint128 clusterVersion); +event MigrationAborted(uint64 id, uint128 clusterVersion); + +event MaintenanceStarted(address operatorAddress, uint128 clusterVersion); +event MaintenanceCompleted(address operatorAddress, uint128 clusterVersion); +event MaintenanceAborted(uint128 clusterVersion); + +event NodeOperatorDataUpdated(address operatorAddress, bytes data, uint128 clusterVersion); + +contract Cluster { + using Bitmask for uint256; + + address owner; + + mapping(address => bytes) operatorData; + + Keyspace[2] keyspaces; + uint64 keyspaceVersion; + + Settings settings; + Migration migration; + Maintenance maintenance; + + uint128 version; + + constructor(Settings memory initialSettings, address[] memory initialOperators) { + owner = msg.sender; + settings = initialSettings; + + for (uint256 i = 0; i < initialOperators.length; i++) { + keyspaces[0].operators[i] = initialOperators[i]; + } + keyspaces[0].operatorsBitmask = Bitmask.fill(uint8(initialOperators.length)); + } + + modifier onlyOwner() { + require(msg.sender == owner, "not the owner"); + _; + } + + modifier hasMigration() { + require(isMigrationInProgress(), "no migration"); + _; + } + + modifier noMigration() { + require(!isMigrationInProgress(), "migration in progress"); + _; + } + + modifier hasMaintenance() { + require(isMaintenanceInProgress(), "no maintenance"); + _; + } + + modifier noMaintenance() { + require(!isMaintenanceInProgress(), "maintenance in progress"); + _; + } + + function startMigration(MigrationPlan calldata plan) external onlyOwner noMigration noMaintenance { + migration.id++; + + uint256 prevKeyspaceIdx = keyspaceVersion % 2; + keyspaceVersion++; + uint256 currKeyspaceIdx = keyspaceVersion % 2; + + // NOTE: We are not zeroing out the rest of the buffer, so there might be some junk left. + // The source of truth on whether the value is set or not should be the bitmask! + for (uint256 i = 0; i <= keyspaces[prevKeyspaceIdx].operatorsBitmask.highest1(); i++) { + if (keyspaces[currKeyspaceIdx].operators[i] != keyspaces[prevKeyspaceIdx].operators[i]) { + keyspaces[currKeyspaceIdx].operators[i] = keyspaces[prevKeyspaceIdx].operators[i]; + } + } + + uint256 operatorsBitmask = keyspaces[prevKeyspaceIdx].operatorsBitmask; + + uint8 idx; + address addr; + for (uint256 i = 0; i < plan.slotsToUpdate.length; i++) { + idx = plan.slotsToUpdate[i].idx; + addr = plan.slotsToUpdate[i].operator; + + if (addr == address(0)) { + operatorsBitmask = operatorsBitmask.set0(idx); + } else { + operatorsBitmask = operatorsBitmask.set1(idx); + } + + keyspaces[currKeyspaceIdx].operators[idx] = addr; + } + + keyspaces[currKeyspaceIdx].operatorsBitmask = operatorsBitmask; + keyspaces[currKeyspaceIdx].replicationStrategy = plan.replicationStrategy; + + migration.pullingOperatorsBitmask = operatorsBitmask; + + version++; + emit MigrationStarted(migration.id, plan, version); + } + + function completeMigration(uint64 id, uint8 operatorIdx) external hasMigration { + require(id == migration.id, "wrong migration id"); + require(keyspaces[keyspaceVersion % 2].operators[operatorIdx] == msg.sender, "wrong operator"); + if (migration.pullingOperatorsBitmask.is0(operatorIdx)) { + return; + } + + migration.pullingOperatorsBitmask = migration.pullingOperatorsBitmask.set0(operatorIdx); + + version++; + if (migration.pullingOperatorsBitmask == 0) { + emit MigrationCompleted(migration.id, msg.sender, version); + } else { + emit MigrationDataPullCompleted(migration.id, msg.sender, version); + } + } + + function abortMigration() external onlyOwner hasMigration { + keyspaceVersion--; + migration.pullingOperatorsBitmask = 0; + + version++; + emit MigrationAborted(migration.id, version); + } + + function startMaintenance(uint8 operatorIdx) external noMigration noMaintenance { + require(keyspaces[keyspaceVersion % 2].operators[operatorIdx] == msg.sender, "wrong operator"); + + maintenance.slot = msg.sender; + + version++; + emit MaintenanceStarted(msg.sender, version); + } + + function completeMaintenance() external hasMaintenance { + require(maintenance.slot == msg.sender, "wrong operator"); + + maintenance.slot = address(0); + + version++; + emit MaintenanceCompleted(msg.sender, version); + } + + function abortMaintenance() external onlyOwner hasMaintenance { + maintenance.slot = address(0); + + version++; + emit MaintenanceAborted(version); + } + + function registerNodeOperator(bytes calldata data) external { + validateOperatorDataSize(data.length); + operatorData[msg.sender] = data; + } + + function updateNodeOperatorData(uint8 operatorIdx, bytes calldata data) external { + validateOperatorDataSize(data.length); + + bool inPrimaryKeyspace; + bool inSecondaryKeyspace; + + if (isMigrationInProgress()) { + inPrimaryKeyspace = keyspaces[(keyspaceVersion - 1) % 2].operators[operatorIdx] == msg.sender; + if (!inPrimaryKeyspace) { + inSecondaryKeyspace = keyspaces[keyspaceVersion % 2].operators[operatorIdx] == msg.sender; + } + } else { + inPrimaryKeyspace = keyspaces[keyspaceVersion % 2].operators[operatorIdx] == msg.sender; + } + + require(inPrimaryKeyspace || inSecondaryKeyspace, "wrong operator"); + + operatorData[msg.sender] = data; + version++; + emit NodeOperatorDataUpdated(msg.sender, data, version); + } + + function updateSettings(Settings calldata newSettings) external onlyOwner { + settings = newSettings; + } + + function transferOwnership(address newOwner) external onlyOwner { + owner = newOwner; + } + + function getView() public view returns (ClusterView memory) { + ClusterView memory clusterView; + + uint256 primaryKeyspaceIdx; + + address addr; + uint256 highestSlotIdx; + + if (isMigrationInProgress()) { + clusterView.migration.id = migration.id; + clusterView.migration.pullingOperatorsBitmask = migration.pullingOperatorsBitmask; + + primaryKeyspaceIdx = (keyspaceVersion - 1) % 2; + uint256 secondaryKeyspaceIdx = keyspaceVersion % 2; + + highestSlotIdx = keyspaces[secondaryKeyspaceIdx].operatorsBitmask.highest1(); + clusterView.secondaryKeyspace.operators = new NodeOperator[](highestSlotIdx + 1); + clusterView.secondaryKeyspace.replicationStrategy = keyspaces[secondaryKeyspaceIdx].replicationStrategy; + + for (uint256 i = 0; i <= highestSlotIdx; i++) { + if (keyspaces[secondaryKeyspaceIdx].operatorsBitmask.is0(uint8(i))) { + continue; + } + + addr = keyspaces[secondaryKeyspaceIdx].operators[i]; + clusterView.secondaryKeyspace.operators[i].addr = addr; + + // Populate data only if it won't be present in the primary keyspace view, to optimize the cluster view size. + if (keyspaces[primaryKeyspaceIdx].operatorsBitmask.is0(uint8(i)) || keyspaces[primaryKeyspaceIdx].operators[i] != addr) { + clusterView.secondaryKeyspace.operators[i].data = operatorData[addr]; + } + } + } else { + primaryKeyspaceIdx = keyspaceVersion % 2; + } + + highestSlotIdx = keyspaces[primaryKeyspaceIdx].operatorsBitmask.highest1(); + clusterView.primaryKeyspace.operators = new NodeOperator[](highestSlotIdx + 1); + clusterView.primaryKeyspace.replicationStrategy = keyspaces[primaryKeyspaceIdx].replicationStrategy; + + for (uint256 i = 0; i <= highestSlotIdx; i++) { + if (keyspaces[primaryKeyspaceIdx].operatorsBitmask.is0(uint8(i))) { + continue; + } + + addr = keyspaces[primaryKeyspaceIdx].operators[i]; + clusterView.primaryKeyspace.operators[i].addr = addr; + clusterView.primaryKeyspace.operators[i].data = operatorData[addr]; + } + + clusterView.keyspaceVersion = keyspaceVersion; + clusterView.maintenance.slot = maintenance.slot; + clusterView.version = version; + + return clusterView; + } + + function validateOperatorDataSize(uint256 value) view internal { + require(value > 0, "empty operator data"); + require(value <= settings.maxOperatorDataBytes, "operator data too large"); + } + + function isMigrationInProgress() view internal returns (bool) { + return migration.pullingOperatorsBitmask != 0; + } + + function isMaintenanceInProgress() view internal returns (bool) { + return maintenance.slot != address(0); + } +} + +struct NodeOperator { + address addr; + bytes data; +} + +struct Keyspace { + address[256] operators; + uint256 operatorsBitmask; + + uint8 replicationStrategy; +} + +struct KeyspaceView { + NodeOperator[] operators; + + uint8 replicationStrategy; +} + +struct KeyspaceSlot { + uint8 idx; + address operator; +} + +struct MigrationPlan { + KeyspaceSlot[] slotsToUpdate; + uint8 replicationStrategy; +} + + +struct Migration { + uint64 id; + uint256 pullingOperatorsBitmask; +} + +struct Maintenance { + address slot; +} + +struct ClusterView { + KeyspaceView primaryKeyspace; + KeyspaceView secondaryKeyspace; + uint64 keyspaceVersion; + + Migration migration; + Maintenance maintenance; + + uint128 version; +} + +library Bitmask { + function fill(uint8 n) internal pure returns (uint256) { + return (1 << uint256(n)) - 1; + } + + function set1(uint256 bitmask, uint8 n) internal pure returns (uint256) { + return bitmask | 1 << uint256(n); + } + + function set0(uint256 bitmask, uint8 n) internal pure returns (uint256) { + return bitmask & ~(1 << uint256(n)); + } + + function is1(uint256 bitmask, uint8 n) internal pure returns (bool) { + return (bitmask & (1 << uint256(n))) != 0; + } + + function is0(uint256 bitmask, uint8 n) internal pure returns (bool) { + return (bitmask & (1 << uint256(n))) == 0; + } + + function count1(uint256 bitmask) internal pure returns (uint256 count) { + while (bitmask != 0) { + bitmask &= (bitmask - 1); + count++; + } + } + + function highest1(uint256 bitmask) internal pure returns (uint256) { + return Math.log2(bitmask); + } +} diff --git a/contracts/src/Cluster/Cluster.sol b/contracts/src/Cluster/Cluster.sol deleted file mode 100644 index ba380954..00000000 --- a/contracts/src/Cluster/Cluster.sol +++ /dev/null @@ -1,183 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -import './Nodes.sol'; -import './NodeOperators.sol'; -import './Migration.sol'; -import './Maintenance.sol'; - -struct Settings { - uint8 minOperators; - uint8 minNodes; -} - -struct ClusterView { - NodeOperatorsView operators; - MigrationView migration; - Maintenance maintenance; - - uint64 keyspaceVersion; - uint128 version; -} - - -event MigrationStarted(address[] operatorsToRemove, NodeOperatorView[] operatorsToAdd, uint128 version); -event MigrationDataPullCompleted(address operator, uint128 version); -event MigrationCompleted(uint128 version); -event MigrationAborted(uint128 version); - -event MaintenanceStarted(address operator, uint128 version); -event MaintenanceCompleted(address operator, uint128 version); -event MaintenanceAborted(uint128 version); - -event NodeSet(address operator, Node node, uint128 version); -event NodeRemoved(address operator, uint256 id, uint128 version); - -contract Cluster { - using NodeOperatorsLib for NodeOperators; - using MigrationLib for Migration; - using MaintenanceLib for Maintenance; - - address owner; - - Settings settings; - NodeOperators operators; - Migration migration; - Maintenance maintenance; - - uint64 keyspaceVersion; - uint128 version; - - constructor(Settings memory initialSettings, NodeOperatorView[] memory initialOperators) { - owner = msg.sender; - settings = initialSettings; - - validateOperatorsCount(initialOperators.length); - - for (uint256 i = 0; i < initialOperators.length; i++) { - validateNodesCount(initialOperators[i].nodes.length); - operators.add(initialOperators[i]); - } - } - - modifier onlyOwner() { - require(msg.sender == owner, "not the owner"); - _; - } - - modifier onlyOperator() { - require(operators.exists(msg.sender), "not an operator"); - _; - } - - function startMigration(address[] calldata operatorsToRemove, NodeOperatorView[] calldata operatorsToAdd) external onlyOwner { - require(!maintenance.inProgress(), "maintenance in progress"); - - for (uint256 i = 0; i < operatorsToRemove.length; i++) { - require(operators.exists(operatorsToRemove[i]), "unknown operator"); - } - - for (uint256 i = 0; i < operatorsToAdd.length; i++) { - validateNodesCount(operatorsToAdd[i].nodes.length); - require(!operators.exists(operatorsToAdd[i].addr), "operator already exists"); - } - - validateOperatorsCount((operators.length() - operatorsToRemove.length + operatorsToAdd.length)); - - migration.start(operators.slots, operatorsToRemove, operatorsToAdd); - version++; - emit MigrationStarted(operatorsToRemove, operatorsToAdd, version); - } - - function completeMigration() external { - migration.completeDataPull(msg.sender); - version++; - emit MigrationDataPullCompleted(msg.sender, version); - - if (migration.pullingOperatorsCount > 0) { - return; - } - - for (uint256 i = 0; i < migration.operatorsToRemove.length; i++) { - operators.remove(migration.operatorsToRemove[i]); - } - - for (uint256 i = 0; i < migration.operatorsToAdd.length; i++) { - operators.add(migration.operatorsToAdd[i]); - } - - keyspaceVersion++; - - migration.complete(); - version++; - - emit MigrationCompleted(version); - } - - function abortMigration() external onlyOwner { - migration.abort(); - version++; - emit MigrationAborted(version); - } - - function startMaintenance() external onlyOperator { - require(!migration.inProgress(), "migration in progress"); - - maintenance.start(msg.sender); - version++; - emit MaintenanceStarted(msg.sender, version); - } - - function completeMaintenance() external onlyOperator { - maintenance.complete(msg.sender); - version++; - emit MaintenanceCompleted(msg.sender, version); - } - - function abortMaintenance() external onlyOwner { - maintenance.abort(); - version++; - emit MaintenanceAborted(version); - } - - function setNode(Node calldata node) external onlyOperator { - operators.setNode(msg.sender, node); - version++; - emit NodeSet(msg.sender, node, version); - } - - function removeNode(uint256 id) external onlyOperator { - operators.removeNode(msg.sender, id); - require(operators.nodesCount(msg.sender) >= settings.minNodes, "too few nodes"); - version++; - emit NodeRemoved(msg.sender, id, version); - } - - function updateSettings(Settings calldata newSettings) external onlyOwner { - settings = newSettings; - } - - function transferOwnership(address newOwner) external onlyOwner { - owner = newOwner; - } - - function validateOperatorsCount(uint256 value) view internal { - require(value >= settings.minOperators, "too few operators"); - require(value <= 256, "too many operators"); - } - - function validateNodesCount(uint256 value) view internal { - require(value >= settings.minNodes, "too few nodes"); - require(value <= 256, "too many nodes"); - } - - function getView() public view returns (ClusterView memory) { - return ClusterView({ - operators: operators.getView(), - migration: migration.getView(operators.slots), - maintenance: maintenance, - keyspaceVersion: keyspaceVersion, - version: version - }); - } -} diff --git a/contracts/src/Cluster/Maintenance.sol b/contracts/src/Cluster/Maintenance.sol deleted file mode 100644 index 11c2edea..00000000 --- a/contracts/src/Cluster/Maintenance.sol +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -struct Maintenance { - address slot; -} - -library MaintenanceLib { - function start(Maintenance storage self, address operator) internal { - require(operator != address(0), "invalid address"); - require(self.slot == address(0), "another maintenance in progress"); - self.slot = operator; - } - - function complete(Maintenance storage self, address operator) internal { - require(operator != address(0), "invalid address"); - require(self.slot == operator, "not under maintenance"); - delete self.slot; - } - - function abort(Maintenance storage self) internal { - require(self.slot != address(0), "not under maintenance"); - delete self.slot; - } - - function inProgress(Maintenance storage self) internal view returns (bool) { - return (self.slot != address(0)); - } -} diff --git a/contracts/src/Cluster/Migration.sol b/contracts/src/Cluster/Migration.sol deleted file mode 100644 index 11abd403..00000000 --- a/contracts/src/Cluster/Migration.sol +++ /dev/null @@ -1,114 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -import "./NodeOperators.sol"; - -struct Migration { - address[] operatorsToRemove; - NodeOperatorView[] operatorsToAdd; - - mapping(address => bool) pullingOperators; - uint8 pullingOperatorsCount; -} - -struct MigrationView { - address[] operatorsToRemove; - NodeOperatorView[] operatorsToAdd; - - address[] pullingOperators; -} - -library MigrationLib { - using MigrationLib for Migration; - - function start( - Migration storage self, - NodeOperator[] storage currentOperators, - address[] calldata operatorsToRemove, - NodeOperatorView[] calldata operatorsToAdd - ) internal { - require(!inProgress(self), "migration already in progress"); - require(operatorsToRemove.length > 0 || operatorsToAdd.length > 0, "nothing to do"); - - for (uint256 i = 0; i < currentOperators.length; i++) { - if (currentOperators[i].addr != address(0)) { - self.pullingOperators[currentOperators[i].addr] = true; - self.pullingOperatorsCount++; - } - } - - for (uint256 i = 0; i < operatorsToRemove.length; i++) { - self.operatorsToRemove.push(operatorsToRemove[i]); - self.pullingOperators[operatorsToRemove[i]] = false; - self.pullingOperatorsCount--; - } - - for (uint256 i = 0; i < operatorsToAdd.length; i++) { - self.operatorsToAdd.push(operatorsToAdd[i]); - self.pullingOperators[operatorsToAdd[i].addr] = true; - self.pullingOperatorsCount++; - } - } - - function completeDataPull(Migration storage self, address operator) internal { - require(self.pullingOperators[operator], "not pulling"); - self.pullingOperators[operator] = false; - self.pullingOperatorsCount--; - } - - function complete(Migration storage self) internal { - require(inProgress(self), "not in progress"); - require(self.pullingOperatorsCount == 0, "data pull in progress"); - self.cleanup(); - } - - function abort(Migration storage self) internal { - require(inProgress(self), "not in progress"); - self.cleanup(); - } - - function cleanup(Migration storage self) internal { - delete self.operatorsToRemove; - delete self.operatorsToAdd; - delete self.pullingOperatorsCount; - } - - function inProgress(Migration storage self) internal view returns (bool) { - return (self.operatorsToRemove.length != 0 || self.operatorsToAdd.length != 0); - } - - function getView(Migration storage self, NodeOperator[] storage currentOperators) internal view returns (MigrationView memory) { - address[] memory toRemove = new address[](self.operatorsToRemove.length); - for (uint256 i = 0; i < self.operatorsToRemove.length; i++) { - toRemove[i] = self.operatorsToRemove[i]; - } - - NodeOperatorView[] memory toAdd = new NodeOperatorView[](self.operatorsToAdd.length); - for (uint256 i = 0; i < self.operatorsToAdd.length; i++) { - toAdd[i] = self.operatorsToAdd[i]; - } - - address[] memory pulling = new address[](self.pullingOperatorsCount); - if (self.pullingOperatorsCount > 0) { - uint256 j; - for (uint256 i = 0; i < currentOperators.length; i++) { - if (currentOperators[i].addr != address(0) && self.pullingOperators[currentOperators[i].addr]) { - pulling[j] = currentOperators[i].addr; - j++; - } - } - for (uint256 i = 0; i < self.operatorsToAdd.length; i++) { - if (self.pullingOperators[self.operatorsToAdd[i].addr]) { - pulling[j] = self.operatorsToAdd[i].addr; - j++; - } - } - } - - return MigrationView({ - operatorsToRemove: toRemove, - operatorsToAdd: toAdd, - pullingOperators: pulling - }); - } -} diff --git a/contracts/src/Cluster/NodeOperators.sol b/contracts/src/Cluster/NodeOperators.sol deleted file mode 100644 index 207a92e4..00000000 --- a/contracts/src/Cluster/NodeOperators.sol +++ /dev/null @@ -1,103 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -import './Nodes.sol'; - -struct NodeOperator { - address addr; - Nodes nodes; - bytes data; -} - -struct NodeOperatorView { - address addr; - Node[] nodes; - bytes data; -} - -struct NodeOperators { - NodeOperator[] slots; - mapping(address => uint8) indexes; - uint8[] freeSlotIndexes; -} - -struct NodeOperatorsView { - NodeOperatorView[] slots; -} - -library NodeOperatorsLib { - using NodesLib for Nodes; - using NodeOperatorsLib for NodeOperators; - - function add(NodeOperators storage self, NodeOperatorView memory operator) internal { - require(!exists(self, operator.addr), "operator already exists"); - - uint8 idx; - - if (self.freeSlotIndexes.length > 0) { - idx = self.freeSlotIndexes[self.freeSlotIndexes.length - 1]; - self.freeSlotIndexes.pop(); - } else { - require(self.slots.length < 256, "too many operators"); - idx = uint8(self.slots.length); - self.slots.push(); - } - - self.indexes[operator.addr] = idx; - NodeOperator storage op = self.slots[idx]; - op.addr = operator.addr; - op.data = operator.data; - for (uint256 i = 0; i < operator.nodes.length; i++) { - op.nodes.set(operator.nodes[i]); - } - } - - function remove(NodeOperators storage self, address addr) internal { - require(addr != address(0), "invalid address"); - - uint8 idx = self.indexes[addr]; - require((idx != 0 || self.slots[0].addr == addr), "operator doesn't exist"); - - delete self.indexes[addr]; - delete self.slots[idx]; - self.freeSlotIndexes.push(idx); - } - - function exists(NodeOperators storage self, address addr) internal view returns (bool) { - require(addr != address(0), "invalid address"); - - if (self.slots.length > 0) { - return ((self.indexes[addr] != 0 || self.slots[0].addr == addr)); - } - - return false; - } - - function length(NodeOperators storage self) internal view returns (uint256) { - return self.slots.length - self.freeSlotIndexes.length; - } - - function setNode(NodeOperators storage self, address operator, Node calldata node) internal { - self.slots[self.indexes[operator]].nodes.set(node); - } - - function removeNode(NodeOperators storage self, address operator, uint256 id) internal { - self.slots[self.indexes[operator]].nodes.remove(id); - } - - function nodesCount(NodeOperators storage self, address operator) internal view returns (uint256) { - return self.slots[self.indexes[operator]].nodes.length(); - } - - function getView(NodeOperators storage self) internal view returns (NodeOperatorsView memory) { - NodeOperatorView[] memory slots = new NodeOperatorView[](self.slots.length); - for (uint256 i = 0; i < self.slots.length; i++) { - slots[i] = NodeOperatorView({ - addr: self.slots[i].addr, - nodes: self.slots[i].nodes.getView(), - data: self.slots[i].data - }); - } - return NodeOperatorsView({ slots: slots }); - } -} diff --git a/contracts/src/Cluster/Nodes.sol b/contracts/src/Cluster/Nodes.sol deleted file mode 100644 index 939db40e..00000000 --- a/contracts/src/Cluster/Nodes.sol +++ /dev/null @@ -1,71 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -struct Node { - uint256 id; - bytes data; -} - -struct Nodes { - Node[] slots; - mapping(uint256 => uint8) indexes; - uint8[] freeSlotIndexes; -} - -library NodesLib { - function set(Nodes storage self, Node memory node) internal { - require(node.id != 0, "invalid id"); - - uint8 idx; - - if (self.slots.length > 0) { - idx = self.indexes[node.id]; - if (idx != 0 || self.slots[0].id == node.id) { - self.slots[idx] = node; - return; - } - } - - if (self.freeSlotIndexes.length > 0) { - idx = self.freeSlotIndexes[self.freeSlotIndexes.length - 1]; - self.freeSlotIndexes.pop(); - } else { - require(self.slots.length < 256, "too many nodes"); - idx = uint8(self.slots.length); - self.slots.push(); - } - - self.indexes[node.id] = idx; - self.slots[idx] = node; - } - - function remove(Nodes storage self, uint256 id) internal { - require(id != 0, "invalid id"); - - uint8 idx = self.indexes[id]; - require((idx != 0 || self.slots[0].id == id), "node doesn't exist"); - - delete self.slots[idx]; - self.freeSlotIndexes.push(idx); - } - - function length(Nodes storage self) internal view returns (uint256) { - return self.slots.length - self.freeSlotIndexes.length; - } - - function getView(Nodes storage self) internal view returns (Node[] memory) { - Node[] memory nodes = new Node[](length(self)); - uint256 j; - for (uint256 i = 0; i < self.slots.length; i++) { - if (self.slots[i].id != 0) { - nodes[j] = Node({ - id: self.slots[i].id, - data: self.slots[i].data - }); - j++; - } - } - return nodes; - } -} - diff --git a/contracts/test/Suite.sol b/contracts/test/Suite.sol index 9b279f2b..825203b5 100644 --- a/contracts/test/Suite.sol +++ b/contracts/test/Suite.sol @@ -5,32 +5,19 @@ import "../dependencies/forge-std-1.9.7/src/Test.sol"; import {Vm} from "../dependencies/forge-std-1.9.7/src/Vm.sol"; import "../dependencies/forge-std-1.9.7/src/console.sol"; -import "../src/Cluster/Cluster.sol"; +import "../src/Cluster.sol"; uint256 constant OWNER = 12345; uint256 constant NEW_OWNER = 56789; uint256 constant ANYONE = 9000; - -uint256 constant OPERATOR_A = 1; -uint256 constant OPERATOR_B = 2; -uint256 constant OPERATOR_C = 3; -uint256 constant EXTRA_OPERATOR = 1000; +uint256 constant OPERATOR = 1; bytes constant DEFAULT_OPERATOR_DATA = "Some operator specific data"; - -uint256 constant NODE_A = 1; -uint256 constant NODE_B = 2; -uint256 constant EXTRA_NODE = 1000; - -bytes constant DEFAULT_NODE_DATA = "Some node specific data"; - -uint256 constant MIN_OPERATORS = 3; -uint256 constant MIN_NODES = 1; - -uint256 constant MAX_OPERATORS = 256; -uint256 constant MAX_NODES = 256; +uint16 constant MAX_OPERATOR_DATA_BYTES = 4096; contract ClusterTest is Test { + using Bitmask for uint256; + Cluster cluster; ClusterView clusterView; @@ -38,56 +25,58 @@ contract ClusterTest is Test { newCluster(vm); } - // contructor + function test_bitmask() public pure { + uint256 bitmask; - function test_canNotCreateClusterWithTooFewOperators() public { - expectRevert("too few operators"); - newCluster(vm, MIN_OPERATORS - 1, MIN_NODES); - } + for (uint256 i = 0; i < 256; i++) { + bitmask = Bitmask.fill(uint8(i)); + assertEq(bitmask.count1(), i); - function test_canNotCreateClusterWithTooFewNodes() public { - expectRevert("too few nodes"); - newCluster(vm, MIN_OPERATORS, MIN_NODES - 1); - } + if (i == 0) { + assertEq(bitmask.highest1(), 0); + } else { + assertEq(bitmask.highest1(), i - 1); + assertEq(bitmask.is1(uint8(i - 1)), true); + if (i != 256) { + assertEq(bitmask.is1(uint8(i)), false); + } + } + } - function test_canNotCreateClusterWithTooManyOperators() public { - expectRevert("too many operators"); - newCluster(vm, MAX_OPERATORS + 1, MIN_NODES); - } + bitmask = Bitmask.fill(5); + assertEq(bitmask, 0x1F); - function test_canNotCreateClusterWithTooManyNodes() public { - expectRevert("too many nodes"); - newCluster(vm, MIN_OPERATORS, MAX_NODES + 1); - } + bitmask = bitmask.set1(5); + bitmask = bitmask.set1(6); + bitmask = bitmask.set1(7); + assertEq(bitmask, 0xFF); + assertEq(bitmask.count1(), 8); + assertEq(bitmask.highest1(), 7); - function test_canCreateClusterWithMinNumberOfOperatorsAndNodes() public { - newCluster(vm, MIN_OPERATORS, MIN_NODES); + bitmask = bitmask.set0(5); + assertEq(bitmask, 0xDF); + assertEq(bitmask.count1(), 7); + assertEq(bitmask.highest1(), 7); } - function test_canCreateClusterWithMaxNumberOfOperators() public { - newCluster(vm, MAX_OPERATORS, MIN_NODES); - } + // contructor - function test_canCreateClusterWithMaxNumberOfNodes() public { - newCluster(vm, MIN_OPERATORS, MAX_NODES); + function test_canNotCreateClusterWithTooManyOperators() public { + vm.expectRevert(); + newCluster(vm, 257); } - function test_clusterContainsInitialOperators() public view { - assertOperatorSlotsCount(MIN_OPERATORS); - assertOperatorSlot(0, OPERATOR_A); - assertOperatorSlot(1, OPERATOR_B); - assertOperatorSlot(2, OPERATOR_C); + function test_canCreateClusterWithMaxNumberOfOperators() public { + newCluster(vm, 256); } - function test_clusterContainsInitialNodes() public { - assertNodesCount(OPERATOR_A, MIN_NODES); - assertNode(OPERATOR_A, NODE_A, DEFAULT_NODE_DATA); - - assertNodesCount(OPERATOR_B, MIN_NODES); - assertNode(OPERATOR_B, NODE_A, DEFAULT_NODE_DATA); - - assertNodesCount(OPERATOR_C, MIN_NODES); - assertNode(OPERATOR_C, NODE_A, DEFAULT_NODE_DATA); + function test_clusterContainsInitialOperatorsInPrimaryKeyspace() public view { + assertKeyspaceSlotsCount(clusterView.primaryKeyspace, 5); + assertKeyspaceSlot(clusterView.primaryKeyspace, 0, 1); + assertKeyspaceSlot(clusterView.primaryKeyspace, 1, 2); + assertKeyspaceSlot(clusterView.primaryKeyspace, 2, 3); + assertKeyspaceSlot(clusterView.primaryKeyspace, 3, 4); + assertKeyspaceSlot(clusterView.primaryKeyspace, 4, 5); } function test_clusterInitialVersionIs0() public view { @@ -102,566 +91,464 @@ contract ClusterTest is Test { function test_anyoneCanNotStartMigration() public { expectRevert("not the owner"); - startMigration(ANYONE); + startMigration(ANYONE, newMigration().clear(0)); } function test_operatorCanNotStartMigration() public { expectRevert("not the owner"); - startMigration(OPERATOR_A); + startMigration(OPERATOR, newMigration().clear(0)); } function test_ownerCanStartMigration() public { - startMigration(OWNER); - } - - function test_canNotStartMigrationWithTooManyOperators() public { - expectRevert("too many operators"); - startMigration(OWNER, 0, MAX_OPERATORS - MIN_OPERATORS + 1); - } - - function test_canNotStartMigrationWithTooFewOperators() public { - expectRevert("too few operators"); - startMigration(OWNER, 1, 0); - } - - function test_canStartMigrationWhenAddedOperatorsReplenishRemoved() public { - startMigration(OWNER, MIN_OPERATORS, MIN_OPERATORS); - } - - function test_canNotStartMigrationWithTooManyNodes() public { - expectRevert("too many nodes"); - startMigration(OWNER, newMigration().addOperator(EXTRA_OPERATOR, MAX_NODES + 1)); - } - - function test_canNotStartMigrationWithTooFewNodes() public { - expectRevert("too few nodes"); - startMigration(OWNER, newMigration().addOperator(EXTRA_OPERATOR, MIN_NODES - 1)); + startMigration(OWNER, newMigration().clear(0)); } function test_canNotStartMigrationWhenMaintenanceInProgress() public { - startMaintenance(OPERATOR_A); + startMaintenance(1, 0); expectRevert("maintenance in progress"); - startMigration(OWNER, 0, 1); + startMigration(OWNER, newMigration().clear(0)); } function test_startMigrationBumpsVersion() public { - startMigration(OWNER, 0, 1); + startMigration(OWNER, newMigration().clear(0)); assertVersion(1); } - function test_startMigrationDoesNotBumpKeyspaceVersion() public { - startMigration(OWNER, 0, 1); - assertKeyspaceVersion(0); + function test_startMigrationBumpsKeyspaceVersion() public { + startMigration(OWNER, newMigration().clear(0)); + assertKeyspaceVersion(1); } function test_startMigrationEmitsMigrationStartedEvent() public { - TestMigration memory migration = newMigration(2, 2); + TestMigration memory migration = newMigration().clear(0); vm.expectEmit(); - emit MigrationStarted(migration.operatorsToRemove, migration.operatorsToAdd, 1); + emit MigrationStarted(1, migration.plan, 1); startMigration(OWNER, migration); } - function test_startMigrationUpdatesMigration() public { - newCluster(vm, 5, MIN_NODES); - TestMigration memory migration = newMigration() - .removeOperator(3) - .removeOperator(2) - .addOperator(6) - .addOperator(7) - .addOperator(8); + function test_startMigrationInitializesMigration() public { + startMigration(OWNER, newMigration().set(4, 6).set(5, 7).clear(2)); + assertMigration(1, 5); + assertMigrationPullingOperator(0); + assertMigrationPullingOperator(1); + assertMigrationPullingOperator(3); + assertMigrationPullingOperator(4); + assertMigrationPullingOperator(5); + } - startMigration(OWNER, migration); - assertMigration(migration); - assertMigrationPullingOperatorsCount(5 - 2 + 3); - assertMigrationPullingOperator(0, 1); - assertMigrationPullingOperator(1, 4); - assertMigrationPullingOperator(2, 5); - assertMigrationPullingOperator(3, 6); - assertMigrationPullingOperator(4, 7); - assertMigrationPullingOperator(5, 8); + function test_startMigrationPopulatesSecondaryKeyspace() public { + registerNodeOperator(6, "operator6"); + registerNodeOperator(7, "operator7"); + + startMigration(OWNER, newMigration().set(4, 6).set(5, 7).clear(2)); + assertKeyspaceSlotsCount(clusterView.secondaryKeyspace, 6); + assertKeyspaceSlot(clusterView.secondaryKeyspace, 0, 1, ""); + assertKeyspaceSlot(clusterView.secondaryKeyspace, 1, 2, ""); + assertKeyspaceSlotEmpty(clusterView.secondaryKeyspace, 2); + assertKeyspaceSlot(clusterView.secondaryKeyspace, 3, 4, ""); + assertKeyspaceSlot(clusterView.secondaryKeyspace, 4, 6, "operator6"); + assertKeyspaceSlot(clusterView.secondaryKeyspace, 5, 7, "operator7"); } // completeMigration function test_anyoneCanNotCompleteMigration() public { - startMigration(OWNER, 0, 1); - expectRevert("not pulling"); - completeMigration(ANYONE); + startMigration(OWNER, newMigration().clear(0)); + expectRevert("wrong operator"); + completeMigration(ANYONE, 1, 0); } function test_ownerCanNotCompleteMigration() public { - startMigration(OWNER, 0, 1); - expectRevert("not pulling"); - completeMigration(OWNER); + startMigration(OWNER, newMigration().clear(0)); + expectRevert("wrong operator"); + completeMigration(OWNER, 1, 0); } function test_operatorCanNotCompleteNonExistentMigration() public { - expectRevert("not pulling"); - completeMigration(OPERATOR_A); + expectRevert("no migration"); + completeMigration(OPERATOR, 1, 0); } function test_operatorCanCompleteMigration() public { - startMigration(OWNER, 0, 1); - completeMigration(OPERATOR_A); + startMigration(OWNER, newMigration().clear(1)); + completeMigration(OPERATOR, 1, 0); } - function test_operatorCanNotCompleteMigrationTwice() public { - startMigration(OWNER, 0, 1); - completeMigration(OPERATOR_A); - expectRevert("not pulling"); - completeMigration(OPERATOR_A); + function test_completeMigrationIsIdempotent() public { + startMigration(OWNER, newMigration().clear(1)); + completeMigration(OPERATOR, 1, 0); + completeMigration(OPERATOR, 1, 0); } function test_completeMigrationBumpsVersion() public { - startMigration(OWNER, 0, 1); - completeMigration(OPERATOR_A); + startMigration(OWNER, newMigration().clear(1)); + completeMigration(OPERATOR, 1, 0); assertVersion(2); } - function test_completeMigrationBumpsVersionForEachCompletedPullAndForCompletionItself() public { - startMigration(OWNER, 0, 1); - completeMigration(OPERATOR_A); - completeMigration(OPERATOR_B); - completeMigration(OPERATOR_C); - completeMigration(EXTRA_OPERATOR); - assertVersion(6); - } - - function test_completeMigrationDoesNotUpdateOperatorsIfNotCompleted() public { - startMigration(OWNER, 0, 1); - completeMigration(OPERATOR_A); - assertOperatorSlotsCount(MIN_OPERATORS); - assertOperatorSlot(0, OPERATOR_A); - assertOperatorSlot(1, OPERATOR_B); - assertOperatorSlot(2, OPERATOR_C); + function test_completeMigrationDoesNotUpdatePrimaryKeyspaceIfNotCompleted() public { + startMigration(OWNER, newMigration().set(5, 6)); + completeMigration(OPERATOR, 1, 0); + assertKeyspaceSlotsCount(clusterView.primaryKeyspace, 5); + assertKeyspaceSlot(clusterView.primaryKeyspace, 0, 1); + assertKeyspaceSlot(clusterView.primaryKeyspace, 1, 2); + assertKeyspaceSlot(clusterView.primaryKeyspace, 2, 3); + assertKeyspaceSlot(clusterView.primaryKeyspace, 3, 4); + assertKeyspaceSlot(clusterView.primaryKeyspace, 4, 5); } function test_completeMigrationUpdatesOperatorsIfCompleted() public { - newCluster(vm, 5, MIN_NODES); - TestMigration memory migration = newMigration() - .removeOperator(3) - .removeOperator(4) - .removeOperator(2) - .addOperator(6) - .addOperator(7); - - startMigration(OWNER, migration); - completeMigration(1); - completeMigration(5); - completeMigration(6); - completeMigration(7); - - assertOperatorSlotsCount(5); - assertOperatorSlot(0, 1); - assertOperatorSlot(1, 6); - assertOperatorSlotEmpty(2); - assertOperatorSlot(3, 7); - assertOperatorSlot(4, 5); + registerNodeOperator(6, "operator6"); + startMigration(OWNER, newMigration().set(4, 6)); + completeMigration(1, 1, 0); + completeMigration(2, 1, 1); + completeMigration(3, 1, 2); + completeMigration(4, 1, 3); + completeMigration(6, 1, 4); + assertKeyspaceSlotsCount(clusterView.primaryKeyspace, 5); + assertKeyspaceSlot(clusterView.primaryKeyspace, 0, 1); + assertKeyspaceSlot(clusterView.primaryKeyspace, 1, 2); + assertKeyspaceSlot(clusterView.primaryKeyspace, 2, 3); + assertKeyspaceSlot(clusterView.primaryKeyspace, 3, 4); + assertKeyspaceSlot(clusterView.primaryKeyspace, 4, 6, "operator6"); } function test_completeMigrationDeletesMigrationIfCompleted() public { - startMigration(OWNER, 0, 1); - completeMigration(OPERATOR_A); - completeMigration(OPERATOR_B); - completeMigration(OPERATOR_C); - completeMigration(EXTRA_OPERATOR); + startMigration(OWNER, newMigration().clear(3).clear(4)); + completeMigration(1, 1, 0); + completeMigration(2, 1, 1); + completeMigration(3, 1, 2); assertNoMigration(); } - function test_completeMigrationUpdatesMigrationIfNotCompleted() public { - startMigration(OWNER, 0, 1); - completeMigration(OPERATOR_A); - assertMigrationPullingOperatorsCount(MIN_OPERATORS + 1 - 1); - assertMigrationPullingOperator(0, OPERATOR_B); - assertMigrationPullingOperator(1, OPERATOR_C); - assertMigrationPullingOperator(2, EXTRA_OPERATOR); + function test_completeMigrationRemovesPullingOperatorBitIfNotCompleted() public { + startMigration(OWNER, newMigration().set(2, 10)); + completeMigration(1, 1, 0); + assert(clusterView.migration.pullingOperatorsBitmask.is0(0)); } function test_completeMigrationDoesNotBumpKeyspaceVersionIfNotCompleted() public { - startMigration(OWNER, 0, 1); - completeMigration(OPERATOR_A); - assertKeyspaceVersion(0); + startMigration(OWNER, newMigration().set(2, 10)); + completeMigration(1, 1, 0); + assertKeyspaceVersion(1); } - function test_completeMigrationBumpKeyspaceVersionIfCompleted() public { - startMigration(OWNER, 0, 1); - completeMigration(OPERATOR_A); - completeMigration(OPERATOR_B); - completeMigration(OPERATOR_C); - completeMigration(EXTRA_OPERATOR); + function test_completeMigrationDoesNotBumpKeyspaceVersionIfCompleted() public { + startMigration(OWNER, newMigration().clear(3).clear(4)); + completeMigration(1, 1, 0); + completeMigration(2, 1, 1); + completeMigration(3, 1, 2); assertKeyspaceVersion(1); } function test_completeMigrationEmitsMigrationDataPullCompletedEventIfNotCompleted() public { - startMigration(OWNER, 0, 1); + startMigration(OWNER, newMigration().set(2, 10)); vm.expectEmit(); - emit MigrationDataPullCompleted(vm.addr(OPERATOR_A), 2); - completeMigration(OPERATOR_A); + emit MigrationDataPullCompleted(1, vm.addr(1), 2); + completeMigration(1, 1, 0); } function test_completeMigrationEmitsMigrationCompletedEventIfCompleted() public { - startMigration(OWNER, 0, 1); - completeMigration(OPERATOR_A); - completeMigration(OPERATOR_B); - completeMigration(OPERATOR_C); + startMigration(OWNER, newMigration().clear(3).clear(4)); + completeMigration(1, 1, 0); + completeMigration(2, 1, 1); vm.expectEmit(); - emit MigrationDataPullCompleted(vm.addr(EXTRA_OPERATOR), 5); - emit MigrationCompleted(6); - completeMigration(EXTRA_OPERATOR); + emit MigrationCompleted(1, vm.addr(3), 4); + completeMigration(3, 1, 2); } // abortMigration function test_anyoneCanNotAbortMigration() public { - startMigration(OWNER, 0, 1); + startMigration(OWNER, newMigration().clear(0)); expectRevert("not the owner"); abortMigration(ANYONE); } function test_operatorCanNotAbortMigration() public { - startMigration(OWNER, 0, 1); + startMigration(OWNER, newMigration().clear(0)); expectRevert("not the owner"); - abortMigration(OPERATOR_A); + abortMigration(OPERATOR); } function test_ownerCanAbortMigration() public { - startMigration(OWNER, 0, 1); + startMigration(OWNER, newMigration().clear(0)); abortMigration(OWNER); } function test_canNotAbortNonExistentMigration() public { - expectRevert("not in progress"); + expectRevert("no migration"); abortMigration(OWNER); } function test_abortMigrationBumpsVersion() public { - startMigration(OWNER, 0, 1); + startMigration(OWNER, newMigration().clear(0)); abortMigration(OWNER); assertVersion(2); } - function test_abortMigrationDoesNotBumpKeyspaceVersion() public { - startMigration(OWNER, 0, 1); + function test_abortMigrationRevertsKeyspaceVersion() public { + startMigration(OWNER, newMigration().clear(0)); abortMigration(OWNER); assertKeyspaceVersion(0); } - function test_abortMigrationDoesNotUpdateOperators() public { - startMigration(OWNER, 0, 1); + function test_abortMigrationDoesNotUpdatePrimaryKeyspace() public { + startMigration(OWNER, newMigration().clear(0)); abortMigration(OWNER); - assertOperatorSlotsCount(MIN_OPERATORS); - assertOperatorSlot(0, OPERATOR_A); - assertOperatorSlot(1, OPERATOR_B); - assertOperatorSlot(2, OPERATOR_C); + assertKeyspaceSlotsCount(clusterView.primaryKeyspace, 5); + assertKeyspaceSlot(clusterView.primaryKeyspace, 0, 1); + assertKeyspaceSlot(clusterView.primaryKeyspace, 1, 2); + assertKeyspaceSlot(clusterView.primaryKeyspace, 2, 3); + assertKeyspaceSlot(clusterView.primaryKeyspace, 3, 4); + assertKeyspaceSlot(clusterView.primaryKeyspace, 4, 5); } function test_abortMigrationDeletesMigration() public { - startMigration(OWNER, 0, 1); + startMigration(OWNER, newMigration().clear(0)); abortMigration(OWNER); assertNoMigration(); } function test_abortMigrationEmitsMigrationAbortedEvent() public { - startMigration(OWNER, 0, 1); + startMigration(OWNER, newMigration().clear(0)); vm.expectEmit(); - emit MigrationAborted(2); + emit MigrationAborted(1, 2); abortMigration(OWNER); } // startMaintenance function test_anyoneCanNotStartMaintenance() public { - expectRevert("not an operator"); - startMaintenance(ANYONE); + expectRevert("wrong operator"); + startMaintenance(ANYONE, 0); } function test_ownerCanNotStartMaintenance() public { - expectRevert("not an operator"); - startMaintenance(OWNER); + expectRevert("wrong operator"); + startMaintenance(OWNER, 0); } function test_operatorCanStartMaintenance() public { - startMaintenance(OPERATOR_A); + startMaintenance(OPERATOR, 0); } function test_canNotStartMoreThanOneMaintenance() public { - startMaintenance(OPERATOR_A); - expectRevert("another maintenance in progress"); - startMaintenance(OPERATOR_B); - } - - function test_canNotStartMaintenanceTwice() public { - startMaintenance(OPERATOR_A); - expectRevert("another maintenance in progress"); - startMaintenance(OPERATOR_A); + startMaintenance(1, 0); + expectRevert("maintenance in progress"); + startMaintenance(2, 1); } function test_operatorCanNotStartMaintenanceWhenMigrationInProgress() public { - startMigration(OWNER, 0, 1); + startMigration(OWNER, newMigration().clear(1)); expectRevert("migration in progress"); - startMaintenance(OPERATOR_A); + startMaintenance(1, 0); } function test_startMaintenanceBumpsVersion() public { - startMaintenance(OPERATOR_A); + startMaintenance(1, 0); assertVersion(1); } function test_startMaintenanceDoesNotBumpKeyspaceVersion() public { - startMaintenance(OPERATOR_A); + startMaintenance(1, 0); assertKeyspaceVersion(0); } function test_startMaintenanceUpdatesMaintenance() public { - startMaintenance(OPERATOR_A); - assertMaintenance(OPERATOR_A); + startMaintenance(1, 0); + assertMaintenance(1); } function test_startMaintenanceEmitsMaintenanceStartedEvent() public { vm.expectEmit(); - emit MaintenanceStarted(vm.addr(OPERATOR_A), 1); - startMaintenance(OPERATOR_A); + emit MaintenanceStarted(vm.addr(1), 1); + startMaintenance(1, 0); } // completeMaintenance function test_anyoneCanNotCompleteMaintenance() public { - expectRevert("not an operator"); - startMaintenance(ANYONE); + startMaintenance(1, 0); + expectRevert("wrong operator"); + completeMaintenance(ANYONE); } function test_anotherOperatorCanNotCompleteMaintenance() public { - startMaintenance(OPERATOR_A); - expectRevert("not under maintenance"); - completeMaintenance(OPERATOR_B); + startMaintenance(2, 1); + expectRevert("wrong operator"); + completeMaintenance(OPERATOR); } function test_ownerCanNotCompleteMaintenance() public { - startMaintenance(OPERATOR_A); - expectRevert("not an operator"); + startMaintenance(1, 0); + expectRevert("wrong operator"); completeMaintenance(OWNER); } function test_sameOperatorCanCompleteMaintenance() public { - startMaintenance(OPERATOR_A); - completeMaintenance(OPERATOR_A); + startMaintenance(1, 0); + completeMaintenance(OPERATOR); } function test_canNotCompleteNonExistentMaintenance() public { - expectRevert("not under maintenance"); - completeMaintenance(OPERATOR_A); + expectRevert("no maintenance"); + completeMaintenance(OPERATOR); } function test_completeMaintenanceBumpsVersion() public { - startMaintenance(OPERATOR_A); - completeMaintenance(OPERATOR_A); + startMaintenance(1, 0); + completeMaintenance(1); assertVersion(2); } function test_completeMaintenanceDoesNotBumpKeyspaceVersion() public { - startMaintenance(OPERATOR_A); - completeMaintenance(OPERATOR_A); + startMaintenance(1, 0); + completeMaintenance(1); assertKeyspaceVersion(0); } function test_completeMaintenanceDeletesMaintenance() public { - startMaintenance(OPERATOR_A); - completeMaintenance(OPERATOR_A); + startMaintenance(1, 0); + completeMaintenance(1); assertNoMaintenance(); } function test_completeMaintenanceEmitsMaintenanceCompletedEvent() public { - startMaintenance(OPERATOR_A); + startMaintenance(1, 0); vm.expectEmit(); - emit MaintenanceCompleted(vm.addr(OPERATOR_A), 2); - completeMaintenance(OPERATOR_A); + emit MaintenanceCompleted(vm.addr(1), 2); + completeMaintenance(1); } // abortMaintenance function test_anyoneCanNotAbortMaintenance() public { - startMaintenance(OPERATOR_A); + startMaintenance(1, 0); expectRevert("not the owner"); abortMaintenance(ANYONE); } function test_operatorCanNotAbortMaintenance() public { - startMaintenance(OPERATOR_A); + startMaintenance(1, 0); expectRevert("not the owner"); - abortMaintenance(OPERATOR_B); + abortMaintenance(OPERATOR); } function test_ownerCanAbortMaintenance() public { - startMaintenance(OPERATOR_A); + startMaintenance(1, 0); abortMaintenance(OWNER); } function test_canNotAbortNonExistentMaintenance() public { - expectRevert("not under maintenance"); + expectRevert("no maintenance"); abortMaintenance(OWNER); } function test_abortMaintenanceBumpsVersion() public { - startMaintenance(OPERATOR_A); + startMaintenance(1, 0); abortMaintenance(OWNER); assertVersion(2); } function test_abortMaintenanceDoesNotBumpKeyspaceVersion() public { - startMaintenance(OPERATOR_A); + startMaintenance(1, 0); abortMaintenance(OWNER); assertKeyspaceVersion(0); } function test_abortMaintenanceDeletesMaintenance() public { - startMaintenance(OPERATOR_A); + startMaintenance(1, 0); abortMaintenance(OWNER); assertNoMaintenance(); } function test_abortMaintenanceEmitsMaintenanceAbortedEvent() public { - startMaintenance(OPERATOR_A); + startMaintenance(1, 0); vm.expectEmit(); emit MaintenanceAborted(2); abortMaintenance(OWNER); } - // setNode + // registerNodeOperator - function test_anyoneCanNotSetNode() public { - expectRevert("not an operator"); - setNode(ANYONE, NODE_A, "data"); - } - - function test_ownerCanNotSetNode() public { - expectRevert("not an operator"); - setNode(OWNER, NODE_A, "data"); - } - - function test_operatorCanSetNode() public { - setNode(OPERATOR_A, NODE_A, "data"); - } - - function test_canSetSameNode() public { - setNode(OPERATOR_A, NODE_A, "data"); - setNode(OPERATOR_A, NODE_A, "data"); - } - - function test_canNotSetNewNodeWhenTooManyNodes() public { - newCluster(vm, MIN_OPERATORS, MAX_NODES); - expectRevert("too many nodes"); - setNode(OPERATOR_A, EXTRA_NODE, "data"); - } - - function test_setNodeWithNewIdDoesNotOverwriteExistingOnes() public { - assertNodesCount(OPERATOR_A, 1); - assertNode(OPERATOR_A, NODE_A, DEFAULT_NODE_DATA); - setNode(OPERATOR_A, EXTRA_NODE, "data"); - assertNodesCount(OPERATOR_A, 2); - assertNode(OPERATOR_A, EXTRA_NODE, "data"); - } - - function test_setNodeWithSameIdOverwritesExistingOne() public { - setNode(OPERATOR_A, NODE_A, "data"); - assertNodesCount(OPERATOR_A, 1); - assertNode(OPERATOR_A, NODE_A, "data"); + function test_anyoneCanRegisterNodeOperator() public { + registerNodeOperator(ANYONE, "anyone"); } - function test_setNodeBumpsVersion() public { - setNode(OPERATOR_A, NODE_A, "data"); - assertVersion(1); + function test_registerNodeOperatorDoesNotBumpVersion() public { + registerNodeOperator(ANYONE, "anyone"); + assertVersion(0); } - function test_setNodeDoesNotBumpKeyspaceVersion() public { - setNode(OPERATOR_A, NODE_A, "data"); + function test_registerNodeOperatorDoesNotBumpKeyspaceVersion() public { + registerNodeOperator(ANYONE, "anyone"); assertKeyspaceVersion(0); } - function test_setNodeEmitsNodeSetEvent() public { - vm.expectEmit(); - emit NodeSet(vm.addr(OPERATOR_A), Node({ id: NODE_A, data: "NodeSet data"}), 1); - setNode(OPERATOR_A, NODE_A, "NodeSet data"); - } - - // removeNode - - function test_anyoneCanNotRemoveNode() public { - expectRevert("not an operator"); - removeNode(ANYONE, NODE_A); + function test_registerNodeOperatorDoesNotEmitEvents() public { + vm.recordLogs(); + registerNodeOperator(ANYONE, "anyone"); + assertEq(vm.getRecordedLogs().length, 0); } - function test_ownerCanNotRemoveNode() public { - expectRevert("not an operator"); - removeNode(OWNER, NODE_A); - } + // updateNodeOperatorData - function test_operatorCanRemoveNode() public { - setNode(OPERATOR_A, EXTRA_NODE, "data"); - removeNode(OPERATOR_A, NODE_A); + function test_anyoneCanNotUpdateNodeOperatorData() public { + expectRevert("wrong operator"); + updateNodeOperatorData(ANYONE, 0, "new data"); } - function test_canNotRemoveNonExistentNode() public { - expectRevert("node doesn't exist"); - removeNode(OPERATOR_A, EXTRA_NODE); + function test_ownerCanNotUpdateNodeOperatorData() public { + expectRevert("wrong operator"); + updateNodeOperatorData(OWNER, 0, "new data"); } - function test_canNotRemoveNodeWhenTooFewNodes() public { - expectRevert("too few nodes"); - removeNode(OPERATOR_A, NODE_A); + function test_operatorCanUpdateNodeOperatorData() public { + updateNodeOperatorData(OPERATOR, 0, "new data"); } - function test_removeNodeBumpsVersion() public { - setNode(OPERATOR_A, EXTRA_NODE, "data"); - removeNode(OPERATOR_A, NODE_A); - assertVersion(2); + function test_updateNodeOperatorDataDoesUpdateTheData() public { + updateNodeOperatorData(OPERATOR, 0, "new data"); + assertKeyspaceSlot(clusterView.primaryKeyspace, 0, OPERATOR, "new data"); } - function test_removeNodeDoesRemoveTheNode() public { - setNode(OPERATOR_A, EXTRA_NODE, "data"); - removeNode(OPERATOR_A, NODE_A); - assertNodesCount(OPERATOR_A, 1); - assertNode(OPERATOR_A, EXTRA_NODE, "data"); + function test_updateNodeOperatorDataBumpsVersion() public { + updateNodeOperatorData(OPERATOR, 0, "new data"); + assertVersion(1); } - function test_removeNodeDoesNotBumpKeyspaceVersion() public { - setNode(OPERATOR_A, EXTRA_NODE, "data"); - removeNode(OPERATOR_A, NODE_A); + function test_updateNodeOperatorDataDoesNotBumpKeyspaceVersion() public { + updateNodeOperatorData(OPERATOR, 0, "new data"); assertKeyspaceVersion(0); } - function test_removeNodeEmitsNodeRemovedEvent() public { - setNode(OPERATOR_A, EXTRA_NODE, "data"); + function test_updateNodeOperatorDataEmitsEventNodeOperatorDataUpdated() public { vm.expectEmit(); - emit NodeRemoved(vm.addr(OPERATOR_A), NODE_A, 2); - removeNode(OPERATOR_A, NODE_A); + emit NodeOperatorDataUpdated(vm.addr(OPERATOR), "new data", 1); + updateNodeOperatorData(OPERATOR, 0, "new data"); } - + // updateSettings function test_anyoneCanNotUpdateSettings() public { expectRevert("not the owner"); - updateSettings(ANYONE, Settings({ minOperators: 5, minNodes: 2 })); + updateSettings(ANYONE, Settings({ maxOperatorDataBytes: 100 })); } function test_operatorCanNotUpdateSettings() public { expectRevert("not the owner"); - updateSettings(OPERATOR_A, Settings({ minOperators: 5, minNodes: 2 })); + updateSettings(OPERATOR, Settings({ maxOperatorDataBytes: 100 })); } function test_ownerCanUpdateSettings() public { - updateSettings(OWNER, Settings({ minOperators: 5, minNodes: 2 })); - } - - function test_updateSettingsCorrectlyUpdatesMinOperators() public { - newCluster(vm, 5, MIN_NODES); - updateSettings(OWNER, Settings({ minOperators: 3, minNodes: uint8(MIN_NODES) })); - startMigration(OWNER, 1, 0); + updateSettings(OWNER, Settings({ maxOperatorDataBytes: 100 })); } - function test_updateSettingsCorrectlyUpdatesMinNodes() public { - newCluster(vm, MIN_OPERATORS, 2); - updateSettings(OWNER, Settings({ minOperators: uint8(MIN_OPERATORS), minNodes: 1 })); - removeNode(OPERATOR_A, NODE_A); + function test_updateSettingsUpdatesMaxOperatorDataBytes() public { + updateSettings(OWNER, Settings({ maxOperatorDataBytes: 5 })); + expectRevert("operator data too large"); + registerNodeOperator(10, "123456"); } // transferOwnership @@ -673,7 +560,7 @@ contract ClusterTest is Test { function test_operatorCanNotTransferOwnership() public { expectRevert("not the owner"); - transferOwnership(OPERATOR_A, OPERATOR_A); + transferOwnership(OPERATOR, OPERATOR); } function test_ownerCanTransferOwnership() public { @@ -682,44 +569,48 @@ contract ClusterTest is Test { function test_transferOwnershipChangesOwner() public { transferOwnership(OWNER, NEW_OWNER); - startMigration(NEW_OWNER, 0, 1); + startMigration(NEW_OWNER, newMigration().clear(0)); } // full lifecycle function test_fullClusterLifecycle() public { - newCluster(vm, Settings({ minOperators: 5, minNodes: 1 }), 9, 1); - setNode(OPERATOR_A, EXTRA_NODE, "A"); - startMaintenance(OPERATOR_B); - setNode(OPERATOR_C, EXTRA_NODE, "C"); - completeMaintenance(OPERATOR_B); - startMigration(OWNER, newMigration().addOperator(10).addOperator(11).addOperator(12)); - removeNode(OPERATOR_A, NODE_A); - for (uint256 i = 1; i <= 12; i++) { - completeMigration(i); + updateNodeOperatorData(1, 0, "operator1"); + startMaintenance(2, 1); + updateNodeOperatorData(3, 2, "operator3"); + completeMaintenance(2); + + registerNodeOperator(6, "operator6"); + registerNodeOperator(7, "operator7"); + registerNodeOperator(8, "operator8"); + startMigration(OWNER, newMigration().set(5, 6).set(6, 7).set(7, 8)); + updateNodeOperatorData(1, 0, "operator1'"); + for (uint256 i = 0; i < 8; i++) { + completeMigration(i + 1, 1, uint8(i)); } - removeNode(OPERATOR_C, NODE_A); - startMaintenance(11); - setNode(11, NODE_A, "11"); + updateNodeOperatorData(3, 2, "operator3'"); + startMaintenance(7, 6); + updateNodeOperatorData(7, 6, "operator8"); abortMaintenance(OWNER); - startMigration(OWNER, newMigration().removeOperator(11)); - for (uint256 i = 1; i <= 12; i++) { - if (i != 11) { - completeMigration(i); + startMigration(OWNER, newMigration().clear(6)); + for (uint256 i = 0; i < 8; i++) { + if (i != 6) { + completeMigration(i + 1, 2, uint8(i)); } } - startMigration(OWNER, newMigration().addOperator(13)); - for (uint256 i = 1; i <= 12; i++) { - if (i != 11) { - completeMigration(i); + registerNodeOperator(9, "operator9"); + startMigration(OWNER, newMigration().set(6, 9)); + for (uint256 i = 0; i < 8; i++) { + if (i != 6) { + completeMigration(i + 1, 3, uint8(i)); } } abortMigration(OWNER); transferOwnership(OWNER, NEW_OWNER); - updateSettings(NEW_OWNER, Settings({ minOperators: 7, minNodes: 1 })); + updateSettings(NEW_OWNER, Settings({ maxOperatorDataBytes: 1024 })); assertKeyspaceVersion(2); } @@ -727,23 +618,19 @@ contract ClusterTest is Test { // internal function newCluster(Vm vm) internal { - newCluster(vm, Settings({ minOperators: uint8(MIN_OPERATORS), minNodes: uint8(MIN_NODES) })); + newCluster(vm, 5); } - function newCluster(Vm vm, Settings memory settings) internal { - newCluster(vm, settings, settings.minOperators, settings.minNodes); + function newCluster(Vm vm, uint256 operatorsCount) internal { + newCluster(vm, Settings({ maxOperatorDataBytes: MAX_OPERATOR_DATA_BYTES }), operatorsCount); } - function newCluster(Vm vm, uint256 operatorsCount, uint256 nodesCount) internal { - newCluster(vm, Settings({ minOperators: uint8(MIN_OPERATORS), minNodes: uint8(MIN_NODES) }), operatorsCount, nodesCount); - } - - function newCluster(Vm vm, Settings memory settings, uint256 operatorsCount, uint256 nodesCount) internal { + function newCluster(Vm vm, Settings memory settings, uint256 operatorsCount) internal { setCaller(OWNER); - NodeOperatorView[] memory operators = new NodeOperatorView[](operatorsCount); + address[] memory operators = new address[](operatorsCount); for (uint256 i = 0; i < operatorsCount; i++) { - operators[i] = newNodeOperator(vm.addr(i + 1), nodesCount); + operators[i] = vm.addr(i + 1); } cluster = new Cluster(settings, operators); @@ -752,6 +639,10 @@ contract ClusterTest is Test { return; } + for (uint256 i = 0; i < operatorsCount; i++) { + registerNodeOperator(i + 1); + } + updateClusterView(); } @@ -768,84 +659,43 @@ contract ClusterTest is Test { } function assertVersion(uint128 expectedVersion) internal view { - assertEq(cluster.getView().version, expectedVersion); + assertEq(clusterView.version, expectedVersion); } function assertKeyspaceVersion(uint64 expectedVersion) internal view { - assertEq(cluster.getView().keyspaceVersion, expectedVersion); - } - - function assertOperatorSlotsCount(uint256 count) internal view { - assertEq(clusterView.operators.slots.length, count); + assertEq(clusterView.keyspaceVersion, expectedVersion); } - function assertOperatorSlot(uint256 index, uint256 privateKey) internal view { - assertEq(clusterView.operators.slots[index].addr, vm.addr(privateKey)); + function assertKeyspaceSlotsCount(KeyspaceView storage keyspace, uint256 count) internal view { + assertEq(keyspace.operators.length, count); } - function assertOperatorSlotEmpty(uint256 index) internal view { - assertEq(clusterView.operators.slots[index].addr, address(0)); + function assertKeyspaceSlot(KeyspaceView storage keyspace, uint256 index, uint256 privateKey) internal view { + assertKeyspaceSlot(keyspace, index, privateKey, DEFAULT_OPERATOR_DATA); } - function assertNodesCount(uint256 operator, uint256 count) internal { - address addr = vm.addr(operator); - - for (uint256 i = 0; i < clusterView.operators.slots.length; i++) { - if (clusterView.operators.slots[i].addr == addr) { - assertEq(clusterView.operators.slots[i].nodes.length, count); - return; - } - } - - fail(); + function assertKeyspaceSlot(KeyspaceView storage keyspace, uint256 index, uint256 privateKey, bytes memory data) internal view { + assertEq(keyspace.operators[index].addr, vm.addr(privateKey)); + assertEq(keyspace.operators[index].data, data); } - function assertNode(uint256 operator, uint256 id, bytes memory data) internal { - address addr = vm.addr(operator); - - for (uint256 i = 0; i < clusterView.operators.slots.length; i++) { - if (clusterView.operators.slots[i].addr == addr) { - for (uint256 j = 0; j < clusterView.operators.slots[i].nodes.length; j++) { - if (clusterView.operators.slots[i].nodes[j].id == id) { - assertEq(clusterView.operators.slots[i].nodes[j].data, data); - return; - } - } - fail(); - } - } - - fail(); + function assertKeyspaceSlotEmpty(KeyspaceView storage keyspace, uint256 index) internal view { + assertEq(keyspace.operators[index].addr, address(0)); + assertEq(keyspace.operators[index].data, new bytes(0)); } - function assertMigration(TestMigration memory migration) internal view { - assertEq(clusterView.migration.operatorsToRemove.length, migration.operatorsToRemove.length); - for (uint256 i = 0; i < clusterView.migration.operatorsToRemove.length; i++) { - assertEq(clusterView.migration.operatorsToRemove[i], migration.operatorsToRemove[i]); - } - - assertEq(clusterView.migration.operatorsToAdd.length, migration.operatorsToAdd.length); - for (uint256 i = 0; i < clusterView.migration.operatorsToAdd.length; i++) { - assertEq(clusterView.migration.operatorsToAdd[i].addr, migration.operatorsToAdd[i].addr); - assertEq(clusterView.migration.operatorsToAdd[i].data, migration.operatorsToAdd[i].data); - for (uint256 j = 0; j < clusterView.migration.operatorsToAdd[i].nodes.length; j++) { - assertEq(clusterView.migration.operatorsToAdd[i].nodes[j].id, migration.operatorsToAdd[i].nodes[j].id); - assertEq(clusterView.migration.operatorsToAdd[i].nodes[j].data, migration.operatorsToAdd[i].nodes[j].data); - } - } + function assertMigration(uint64 id, uint256 pullingOperatorsCount) internal view { + assertEq(clusterView.migration.id, id); + assertEq(clusterView.migration.pullingOperatorsBitmask.count1(), pullingOperatorsCount); } function assertNoMigration() internal view { - TestMigration memory migration; - assertMigration(migration); - } - - function assertMigrationPullingOperatorsCount(uint256 count) internal view { - assertEq(clusterView.migration.pullingOperators.length, count); + assertEq(clusterView.migration.id, 0); + assertEq(clusterView.migration.pullingOperatorsBitmask, 0); } - function assertMigrationPullingOperator(uint256 idx, uint256 operator) internal view { - assertEq(clusterView.migration.pullingOperators[idx], vm.addr(operator)); + function assertMigrationPullingOperator(uint8 idx) internal view { + assert(clusterView.migration.pullingOperatorsBitmask.is1(idx)); } function assertMaintenance(uint256 operator) internal view { @@ -859,56 +709,22 @@ contract ClusterTest is Test { function newMigration() internal pure returns (TestMigration memory) { return TestMigration({ vm: vm, - operatorsToRemove: new address[](0), - operatorsToAdd: new NodeOperatorView[](0) + plan: MigrationPlan({ + slotsToUpdate: new KeyspaceSlot[](0), + replicationStrategy: 0 + }) }); } - function newMigration(uint256 toRemove, uint256 toAdd) internal view returns (TestMigration memory) { - TestMigration memory migration = TestMigration({ - vm: vm, - operatorsToRemove: new address[](toRemove), - operatorsToAdd: new NodeOperatorView[](toAdd) - }); - - uint256 j; - for (uint256 i = 0; i < clusterView.operators.slots.length; i++) { - if (toRemove == 0) { - break; - } - - if (clusterView.operators.slots[i].addr != address(0)) { - migration.operatorsToRemove[j] = clusterView.operators.slots[i].addr; - j++; - toRemove--; - } - } - require(toRemove == 0); - - for (uint256 i = 0; i < toAdd; i++) { - migration.operatorsToAdd[i] = newNodeOperator(vm.addr(EXTRA_OPERATOR + i), MIN_NODES); - } - - return migration; - } - - function startMigration(uint256 caller) internal { - startMigration(caller, 0, 1); - } - - function startMigration(uint256 caller, uint256 toRemove, uint256 toAdd) internal { - startMigration(caller, newMigration(toRemove, toAdd)); - } - function startMigration(uint256 caller, TestMigration memory migration) internal { setCaller(caller); - cluster.startMigration(migration.operatorsToRemove, migration.operatorsToAdd); + cluster.startMigration(migration.plan); updateClusterView(); } - function completeMigration(uint256 caller) internal { + function completeMigration(uint256 caller, uint64 id, uint8 operatorIdx) internal { setCaller(caller); - cluster.completeMigration(); + cluster.completeMigration(id, operatorIdx); updateClusterView(); } @@ -918,9 +734,9 @@ contract ClusterTest is Test { updateClusterView(); } - function startMaintenance(uint256 caller) internal { + function startMaintenance(uint256 caller, uint8 operatorIdx) internal { setCaller(caller); - cluster.startMaintenance(); + cluster.startMaintenance(operatorIdx); updateClusterView(); } @@ -936,15 +752,19 @@ contract ClusterTest is Test { updateClusterView(); } - function setNode(uint256 caller, uint256 id, bytes memory data) internal { + function registerNodeOperator(uint256 caller) internal { + registerNodeOperator(caller, DEFAULT_OPERATOR_DATA); + } + + function registerNodeOperator(uint256 caller, bytes memory data) internal { setCaller(caller); - cluster.setNode(Node({ id: id, data: data })); + cluster.registerNodeOperator(data); updateClusterView(); } - function removeNode(uint256 caller, uint256 id) internal { + function updateNodeOperatorData(uint256 caller, uint8 idx, bytes memory data) internal { setCaller(caller); - cluster.removeNode(id); + cluster.updateNodeOperatorData(idx, data); updateClusterView(); } @@ -962,49 +782,38 @@ contract ClusterTest is Test { struct TestMigration { Vm vm; - address[] operatorsToRemove; - NodeOperatorView[] operatorsToAdd; + MigrationPlan plan; } library TestMigrationLib { - function addOperator(TestMigration memory self, uint256 privateKey) internal pure returns (TestMigration memory) { - return addOperator(self, privateKey, MIN_NODES); + function set(TestMigration memory self, uint8 idx, uint256 privateKey) internal pure returns (TestMigration memory) { + TestMigrationLib.setSlot(self, idx, KeyspaceSlot({ idx: idx, operator: self.vm.addr(privateKey) })); + return self; } - function addOperator(TestMigration memory self, uint256 privateKey, uint256 nodesCount) internal pure returns (TestMigration memory) { - NodeOperatorView[] memory operators = new NodeOperatorView[](self.operatorsToAdd.length + 1); - for (uint256 i = 0; i < self.operatorsToAdd.length; i++) { - operators[i] = self.operatorsToAdd[i]; - } - operators[operators.length - 1] = newNodeOperator(self.vm.addr(privateKey), nodesCount); - - self.operatorsToAdd = operators; + function clear(TestMigration memory self, uint8 idx) internal pure returns (TestMigration memory) { + TestMigrationLib.setSlot(self, idx, KeyspaceSlot({ idx: idx, operator: address(0) })); return self; } - function removeOperator(TestMigration memory self, uint256 privateKey) internal pure returns (TestMigration memory) { - address[] memory operators = new address[](self.operatorsToRemove.length + 1); - for (uint256 i = 0; i < self.operatorsToRemove.length; i++) { - operators[i] = self.operatorsToRemove[i]; + function setSlot(TestMigration memory self, uint8 idx, KeyspaceSlot memory slot) internal pure returns (TestMigration memory) { + KeyspaceSlot[] memory slotsToUpdate = new KeyspaceSlot[](self.plan.slotsToUpdate.length + 1); + for (uint256 i = 0; i < self.plan.slotsToUpdate.length; i++) { + slotsToUpdate[i] = self.plan.slotsToUpdate[i]; } - operators[operators.length - 1] = self.vm.addr(privateKey); - self.operatorsToRemove = operators; + slotsToUpdate[self.plan.slotsToUpdate.length] = slot; + self.plan.slotsToUpdate = slotsToUpdate; + return self; } } using TestMigrationLib for TestMigration; -function newNodeOperator(address addr, uint256 nodesCount) pure returns (NodeOperatorView memory) { - Node[] memory nodes = new Node[](nodesCount); - for (uint256 i = 0; i < nodesCount; i++) { - nodes[i] = Node({ id: i + 1 , data: DEFAULT_NODE_DATA }); - } - - return NodeOperatorView({ +function newNodeOperator(address addr, bytes memory operatorData) pure returns (NodeOperator memory) { + return NodeOperator({ addr: addr, - nodes: nodes, - data: DEFAULT_OPERATOR_DATA + data: operatorData }); } From de63784248201676eaaa1fc5cee2d89aa1251c3f Mon Sep 17 00:00:00 2001 From: Darksome Date: Tue, 20 May 2025 09:38:08 +0000 Subject: [PATCH 16/79] regenerate bindings --- .../cluster/src/contract/evm/bindings/mod.rs | 2939 +++++++++-------- 1 file changed, 1470 insertions(+), 1469 deletions(-) diff --git a/crates/cluster/src/contract/evm/bindings/mod.rs b/crates/cluster/src/contract/evm/bindings/mod.rs index 4059c590..b551880d 100644 --- a/crates/cluster/src/contract/evm/bindings/mod.rs +++ b/crates/cluster/src/contract/evm/bindings/mod.rs @@ -9,59 +9,61 @@ Generated by the following Solidity interface... ```solidity interface Cluster { struct ClusterView { - NodeOperatorsView operators; - MigrationView migration; - Maintenance maintenance; + KeyspaceView primaryKeyspace; + KeyspaceView secondaryKeyspace; uint64 keyspaceVersion; + Migration migration; + Maintenance maintenance; uint128 version; } + struct KeyspaceSlot { + uint8 idx; + address operator; + } + struct KeyspaceView { + NodeOperator[] operators; + uint8 replicationStrategy; + } struct Maintenance { address slot; } - struct MigrationView { - address[] operatorsToRemove; - NodeOperatorView[] operatorsToAdd; - address[] pullingOperators; + struct Migration { + uint64 id; + uint256 pullingOperatorsBitmask; } - struct Node { - uint256 id; - bytes data; + struct MigrationPlan { + KeyspaceSlot[] slotsToUpdate; + uint8 replicationStrategy; } - struct NodeOperatorView { + struct NodeOperator { address addr; - Node[] nodes; bytes data; } - struct NodeOperatorsView { - NodeOperatorView[] slots; - } struct Settings { - uint8 minOperators; - uint8 minNodes; + uint16 maxOperatorDataBytes; } - event MaintenanceAborted(uint128 version); - event MaintenanceCompleted(address operator, uint128 version); - event MaintenanceStarted(address operator, uint128 version); - event MigrationAborted(uint128 version); - event MigrationCompleted(uint128 version); - event MigrationDataPullCompleted(address operator, uint128 version); - event MigrationStarted(address[] operatorsToRemove, NodeOperatorView[] operatorsToAdd, uint128 version); - event NodeRemoved(address operator, uint256 id, uint128 version); - event NodeSet(address operator, Node node, uint128 version); + event MaintenanceAborted(uint128 clusterVersion); + event MaintenanceCompleted(address operatorAddress, uint128 clusterVersion); + event MaintenanceStarted(address operatorAddress, uint128 clusterVersion); + event MigrationAborted(uint64 id, uint128 clusterVersion); + event MigrationCompleted(uint64 id, address operatorAddress, uint128 clusterVersion); + event MigrationDataPullCompleted(uint64 id, address operatorAddress, uint128 clusterVersion); + event MigrationStarted(uint64 id, MigrationPlan plan, uint128 clusterVersion); + event NodeOperatorDataUpdated(address operatorAddress, bytes data, uint128 clusterVersion); - constructor(Settings initialSettings, NodeOperatorView[] initialOperators); + constructor(Settings initialSettings, address[] initialOperators); function abortMaintenance() external; function abortMigration() external; function completeMaintenance() external; - function completeMigration() external; + function completeMigration(uint64 id, uint8 operatorIdx) external; function getView() external view returns (ClusterView memory); - function removeNode(uint256 id) external; - function setNode(Node memory node) external; - function startMaintenance() external; - function startMigration(address[] memory operatorsToRemove, NodeOperatorView[] memory operatorsToAdd) external; + function registerNodeOperator(bytes memory data) external; + function startMaintenance(uint8 operatorIdx) external; + function startMigration(MigrationPlan memory plan) external; function transferOwnership(address newOwner) external; + function updateNodeOperatorData(uint8 operatorIdx, bytes memory data) external; function updateSettings(Settings memory newSettings) external; } ``` @@ -78,50 +80,16 @@ interface Cluster { "internalType": "struct Settings", "components": [ { - "name": "minOperators", - "type": "uint8", - "internalType": "uint8" - }, - { - "name": "minNodes", - "type": "uint8", - "internalType": "uint8" + "name": "maxOperatorDataBytes", + "type": "uint16", + "internalType": "uint16" } ] }, { "name": "initialOperators", - "type": "tuple[]", - "internalType": "struct NodeOperatorView[]", - "components": [ - { - "name": "addr", - "type": "address", - "internalType": "address" - }, - { - "name": "nodes", - "type": "tuple[]", - "internalType": "struct Node[]", - "components": [ - { - "name": "id", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "data", - "type": "bytes", - "internalType": "bytes" - } - ] - }, - { - "name": "data", - "type": "bytes", - "internalType": "bytes" - } - ] + "type": "address[]", + "internalType": "address[]" } ], "stateMutability": "nonpayable" @@ -150,7 +118,18 @@ interface Cluster { { "type": "function", "name": "completeMigration", - "inputs": [], + "inputs": [ + { + "name": "id", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "operatorIdx", + "type": "uint8", + "internalType": "uint8" + } + ], "outputs": [], "stateMutability": "nonpayable" }, @@ -165,83 +144,49 @@ interface Cluster { "internalType": "struct ClusterView", "components": [ { - "name": "operators", + "name": "primaryKeyspace", "type": "tuple", - "internalType": "struct NodeOperatorsView", + "internalType": "struct KeyspaceView", "components": [ { - "name": "slots", + "name": "operators", "type": "tuple[]", - "internalType": "struct NodeOperatorView[]", + "internalType": "struct NodeOperator[]", "components": [ { "name": "addr", "type": "address", "internalType": "address" }, - { - "name": "nodes", - "type": "tuple[]", - "internalType": "struct Node[]", - "components": [ - { - "name": "id", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "data", - "type": "bytes", - "internalType": "bytes" - } - ] - }, { "name": "data", "type": "bytes", "internalType": "bytes" } ] + }, + { + "name": "replicationStrategy", + "type": "uint8", + "internalType": "uint8" } ] }, { - "name": "migration", + "name": "secondaryKeyspace", "type": "tuple", - "internalType": "struct MigrationView", + "internalType": "struct KeyspaceView", "components": [ { - "name": "operatorsToRemove", - "type": "address[]", - "internalType": "address[]" - }, - { - "name": "operatorsToAdd", + "name": "operators", "type": "tuple[]", - "internalType": "struct NodeOperatorView[]", + "internalType": "struct NodeOperator[]", "components": [ { "name": "addr", "type": "address", "internalType": "address" }, - { - "name": "nodes", - "type": "tuple[]", - "internalType": "struct Node[]", - "components": [ - { - "name": "id", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "data", - "type": "bytes", - "internalType": "bytes" - } - ] - }, { "name": "data", "type": "bytes", @@ -250,9 +195,31 @@ interface Cluster { ] }, { - "name": "pullingOperators", - "type": "address[]", - "internalType": "address[]" + "name": "replicationStrategy", + "type": "uint8", + "internalType": "uint8" + } + ] + }, + { + "name": "keyspaceVersion", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "migration", + "type": "tuple", + "internalType": "struct Migration", + "components": [ + { + "name": "id", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "pullingOperatorsBitmask", + "type": "uint256", + "internalType": "uint256" } ] }, @@ -268,11 +235,6 @@ interface Cluster { } ] }, - { - "name": "keyspaceVersion", - "type": "uint64", - "internalType": "uint64" - }, { "name": "version", "type": "uint128", @@ -285,12 +247,12 @@ interface Cluster { }, { "type": "function", - "name": "removeNode", + "name": "registerNodeOperator", "inputs": [ { - "name": "id", - "type": "uint256", - "internalType": "uint256" + "name": "data", + "type": "bytes", + "internalType": "bytes" } ], "outputs": [], @@ -298,76 +260,47 @@ interface Cluster { }, { "type": "function", - "name": "setNode", + "name": "startMaintenance", "inputs": [ { - "name": "node", - "type": "tuple", - "internalType": "struct Node", - "components": [ - { - "name": "id", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "data", - "type": "bytes", - "internalType": "bytes" - } - ] + "name": "operatorIdx", + "type": "uint8", + "internalType": "uint8" } ], "outputs": [], "stateMutability": "nonpayable" }, - { - "type": "function", - "name": "startMaintenance", - "inputs": [], - "outputs": [], - "stateMutability": "nonpayable" - }, { "type": "function", "name": "startMigration", "inputs": [ { - "name": "operatorsToRemove", - "type": "address[]", - "internalType": "address[]" - }, - { - "name": "operatorsToAdd", - "type": "tuple[]", - "internalType": "struct NodeOperatorView[]", + "name": "plan", + "type": "tuple", + "internalType": "struct MigrationPlan", "components": [ { - "name": "addr", - "type": "address", - "internalType": "address" - }, - { - "name": "nodes", + "name": "slotsToUpdate", "type": "tuple[]", - "internalType": "struct Node[]", + "internalType": "struct KeyspaceSlot[]", "components": [ { - "name": "id", - "type": "uint256", - "internalType": "uint256" + "name": "idx", + "type": "uint8", + "internalType": "uint8" }, { - "name": "data", - "type": "bytes", - "internalType": "bytes" + "name": "operator", + "type": "address", + "internalType": "address" } ] }, { - "name": "data", - "type": "bytes", - "internalType": "bytes" + "name": "replicationStrategy", + "type": "uint8", + "internalType": "uint8" } ] } @@ -388,6 +321,24 @@ interface Cluster { "outputs": [], "stateMutability": "nonpayable" }, + { + "type": "function", + "name": "updateNodeOperatorData", + "inputs": [ + { + "name": "operatorIdx", + "type": "uint8", + "internalType": "uint8" + }, + { + "name": "data", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, { "type": "function", "name": "updateSettings", @@ -398,14 +349,9 @@ interface Cluster { "internalType": "struct Settings", "components": [ { - "name": "minOperators", - "type": "uint8", - "internalType": "uint8" - }, - { - "name": "minNodes", - "type": "uint8", - "internalType": "uint8" + "name": "maxOperatorDataBytes", + "type": "uint16", + "internalType": "uint16" } ] } @@ -418,7 +364,7 @@ interface Cluster { "name": "MaintenanceAborted", "inputs": [ { - "name": "version", + "name": "clusterVersion", "type": "uint128", "indexed": false, "internalType": "uint128" @@ -431,13 +377,13 @@ interface Cluster { "name": "MaintenanceCompleted", "inputs": [ { - "name": "operator", + "name": "operatorAddress", "type": "address", "indexed": false, "internalType": "address" }, { - "name": "version", + "name": "clusterVersion", "type": "uint128", "indexed": false, "internalType": "uint128" @@ -450,13 +396,13 @@ interface Cluster { "name": "MaintenanceStarted", "inputs": [ { - "name": "operator", + "name": "operatorAddress", "type": "address", "indexed": false, "internalType": "address" }, { - "name": "version", + "name": "clusterVersion", "type": "uint128", "indexed": false, "internalType": "uint128" @@ -469,7 +415,13 @@ interface Cluster { "name": "MigrationAborted", "inputs": [ { - "name": "version", + "name": "id", + "type": "uint64", + "indexed": false, + "internalType": "uint64" + }, + { + "name": "clusterVersion", "type": "uint128", "indexed": false, "internalType": "uint128" @@ -482,7 +434,19 @@ interface Cluster { "name": "MigrationCompleted", "inputs": [ { - "name": "version", + "name": "id", + "type": "uint64", + "indexed": false, + "internalType": "uint64" + }, + { + "name": "operatorAddress", + "type": "address", + "indexed": false, + "internalType": "address" + }, + { + "name": "clusterVersion", "type": "uint128", "indexed": false, "internalType": "uint128" @@ -495,13 +459,19 @@ interface Cluster { "name": "MigrationDataPullCompleted", "inputs": [ { - "name": "operator", + "name": "id", + "type": "uint64", + "indexed": false, + "internalType": "uint64" + }, + { + "name": "operatorAddress", "type": "address", "indexed": false, "internalType": "address" }, { - "name": "version", + "name": "clusterVersion", "type": "uint128", "indexed": false, "internalType": "uint128" @@ -514,73 +484,43 @@ interface Cluster { "name": "MigrationStarted", "inputs": [ { - "name": "operatorsToRemove", - "type": "address[]", + "name": "id", + "type": "uint64", "indexed": false, - "internalType": "address[]" + "internalType": "uint64" }, { - "name": "operatorsToAdd", - "type": "tuple[]", + "name": "plan", + "type": "tuple", "indexed": false, - "internalType": "struct NodeOperatorView[]", + "internalType": "struct MigrationPlan", "components": [ { - "name": "addr", - "type": "address", - "internalType": "address" - }, - { - "name": "nodes", + "name": "slotsToUpdate", "type": "tuple[]", - "internalType": "struct Node[]", + "internalType": "struct KeyspaceSlot[]", "components": [ { - "name": "id", - "type": "uint256", - "internalType": "uint256" + "name": "idx", + "type": "uint8", + "internalType": "uint8" }, { - "name": "data", - "type": "bytes", - "internalType": "bytes" + "name": "operator", + "type": "address", + "internalType": "address" } ] }, { - "name": "data", - "type": "bytes", - "internalType": "bytes" + "name": "replicationStrategy", + "type": "uint8", + "internalType": "uint8" } ] }, { - "name": "version", - "type": "uint128", - "indexed": false, - "internalType": "uint128" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "NodeRemoved", - "inputs": [ - { - "name": "operator", - "type": "address", - "indexed": false, - "internalType": "address" - }, - { - "name": "id", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - }, - { - "name": "version", + "name": "clusterVersion", "type": "uint128", "indexed": false, "internalType": "uint128" @@ -590,34 +530,22 @@ interface Cluster { }, { "type": "event", - "name": "NodeSet", + "name": "NodeOperatorDataUpdated", "inputs": [ { - "name": "operator", + "name": "operatorAddress", "type": "address", "indexed": false, "internalType": "address" }, { - "name": "node", - "type": "tuple", + "name": "data", + "type": "bytes", "indexed": false, - "internalType": "struct Node", - "components": [ - { - "name": "id", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "data", - "type": "bytes", - "internalType": "bytes" - } - ] + "internalType": "bytes" }, { - "name": "version", + "name": "clusterVersion", "type": "uint128", "indexed": false, "internalType": "uint128" @@ -640,38 +568,40 @@ pub mod Cluster { /// The creation / init bytecode of the contract. /// /// ```text - ///0x608060405234801561000f575f5ffd5b5060405161741138038061741183398181016040528101906100319190610e18565b335f5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508160015f820151815f015f6101000a81548160ff021916908360ff1602179055506020820151815f0160016101000a81548160ff021916908360ff1602179055509050506100c4815161014360201b60201c565b5f5f90505b815181101561013b576101008282815181106100e8576100e7610e72565b5b602002602001015160200151516101e160201b60201c565b61012e82828151811061011657610115610e72565b5b6020026020010151600261028060201b90919060201c565b80806001019150506100c9565b5050506114ea565b60015f015f9054906101000a900460ff1660ff16811015610199576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161019090610ef9565b60405180910390fd5b6101008111156101de576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101d590610f61565b60405180910390fd5b50565b60015f0160019054906101000a900460ff1660ff16811015610238576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161022f90610fc9565b60405180910390fd5b61010081111561027d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161027490611031565b60405180910390fd5b50565b61029382825f015161051360201b60201c565b156102d3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102ca90611099565b60405180910390fd5b5f5f8360020180549050111561036d5782600201600184600201805490506102fb91906110e4565b8154811061030c5761030b610e72565b5b905f5260205f2090602091828204019190069054906101000a900460ff169050826002018054806103405761033f611117565b5b600190038181905f5260205f2090602091828204019190066101000a81549060ff021916905590556103de565b610100835f0180549050106103b7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103ae90610f61565b60405180910390fd5b825f01805490509050825f0160018160018154018082558091505003905f5260205f209050505b80836001015f845f015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908360ff1602179055505f835f018260ff168154811061045157610450610e72565b5b905f5260205f2090600502019050825f0151815f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555082604001518160040190816104b8919061134b565b505f5f90505b83602001515181101561050c576104ff846020015182815181106104e5576104e4610e72565b5b60200260200101518360010161066b60201b90919060201c565b80806001019150506104be565b5050505050565b5f5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610582576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161057990611464565b60405180910390fd5b5f835f01805490501115610661575f836001015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1660ff1614158061065a57508173ffffffffffffffffffffffffffffffffffffffff16835f015f8154811061061457610613610e72565b5b905f5260205f2090600502015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b9050610665565b5f90505b92915050565b5f815f0151036106b0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106a7906114cc565b60405180910390fd5b5f5f835f0180549050111561076d57826001015f835f015181526020019081526020015f205f9054906101000a900460ff1690505f8160ff1614158061071b5750815f0151835f015f8154811061070a57610709610e72565b5b905f5260205f2090600202015f0154145b1561076c5781835f018260ff168154811061073957610738610e72565b5b905f5260205f2090600202015f820151815f01556020820151816001019081610762919061134b565b50905050506108ed565b5b5f8360020180549050111561080657826002016001846002018054905061079491906110e4565b815481106107a5576107a4610e72565b5b905f5260205f2090602091828204019190069054906101000a900460ff169050826002018054806107d9576107d8611117565b5b600190038181905f5260205f2090602091828204019190066101000a81549060ff02191690559055610877565b610100835f018054905010610850576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161084790611031565b60405180910390fd5b825f01805490509050825f0160018160018154018082558091505003905f5260205f209050505b80836001015f845f015181526020019081526020015f205f6101000a81548160ff021916908360ff16021790555081835f018260ff16815481106108be576108bd610e72565b5b905f5260205f2090600202015f820151815f015560208201518160010190816108e7919061134b565b50905050505b5050565b5f604051905090565b5f5ffd5b5f5ffd5b5f5ffd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b61094c82610906565b810181811067ffffffffffffffff8211171561096b5761096a610916565b5b80604052505050565b5f61097d6108f1565b90506109898282610943565b919050565b5f5ffd5b5f60ff82169050919050565b6109a781610992565b81146109b1575f5ffd5b50565b5f815190506109c28161099e565b92915050565b5f604082840312156109dd576109dc610902565b5b6109e76040610974565b90505f6109f6848285016109b4565b5f830152506020610a09848285016109b4565b60208301525092915050565b5f5ffd5b5f67ffffffffffffffff821115610a3357610a32610916565b5b602082029050602081019050919050565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f610a7182610a48565b9050919050565b610a8181610a67565b8114610a8b575f5ffd5b50565b5f81519050610a9c81610a78565b92915050565b5f67ffffffffffffffff821115610abc57610abb610916565b5b602082029050602081019050919050565b5f819050919050565b610adf81610acd565b8114610ae9575f5ffd5b50565b5f81519050610afa81610ad6565b92915050565b5f5ffd5b5f67ffffffffffffffff821115610b1e57610b1d610916565b5b610b2782610906565b9050602081019050919050565b8281835e5f83830152505050565b5f610b54610b4f84610b04565b610974565b905082815260208101848484011115610b7057610b6f610b00565b5b610b7b848285610b34565b509392505050565b5f82601f830112610b9757610b96610a15565b5b8151610ba7848260208601610b42565b91505092915050565b5f60408284031215610bc557610bc4610902565b5b610bcf6040610974565b90505f610bde84828501610aec565b5f83015250602082015167ffffffffffffffff811115610c0157610c0061098e565b5b610c0d84828501610b83565b60208301525092915050565b5f610c2b610c2684610aa2565b610974565b90508083825260208201905060208402830185811115610c4e57610c4d610a44565b5b835b81811015610c9557805167ffffffffffffffff811115610c7357610c72610a15565b5b808601610c808982610bb0565b85526020850194505050602081019050610c50565b5050509392505050565b5f82601f830112610cb357610cb2610a15565b5b8151610cc3848260208601610c19565b91505092915050565b5f60608284031215610ce157610ce0610902565b5b610ceb6060610974565b90505f610cfa84828501610a8e565b5f83015250602082015167ffffffffffffffff811115610d1d57610d1c61098e565b5b610d2984828501610c9f565b602083015250604082015167ffffffffffffffff811115610d4d57610d4c61098e565b5b610d5984828501610b83565b60408301525092915050565b5f610d77610d7284610a19565b610974565b90508083825260208201905060208402830185811115610d9a57610d99610a44565b5b835b81811015610de157805167ffffffffffffffff811115610dbf57610dbe610a15565b5b808601610dcc8982610ccc565b85526020850194505050602081019050610d9c565b5050509392505050565b5f82601f830112610dff57610dfe610a15565b5b8151610e0f848260208601610d65565b91505092915050565b5f5f60608385031215610e2e57610e2d6108fa565b5b5f610e3b858286016109c8565b925050604083015167ffffffffffffffff811115610e5c57610e5b6108fe565b5b610e6885828601610deb565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f82825260208201905092915050565b7f746f6f20666577206f70657261746f72730000000000000000000000000000005f82015250565b5f610ee3601183610e9f565b9150610eee82610eaf565b602082019050919050565b5f6020820190508181035f830152610f1081610ed7565b9050919050565b7f746f6f206d616e79206f70657261746f727300000000000000000000000000005f82015250565b5f610f4b601283610e9f565b9150610f5682610f17565b602082019050919050565b5f6020820190508181035f830152610f7881610f3f565b9050919050565b7f746f6f20666577206e6f646573000000000000000000000000000000000000005f82015250565b5f610fb3600d83610e9f565b9150610fbe82610f7f565b602082019050919050565b5f6020820190508181035f830152610fe081610fa7565b9050919050565b7f746f6f206d616e79206e6f6465730000000000000000000000000000000000005f82015250565b5f61101b600e83610e9f565b915061102682610fe7565b602082019050919050565b5f6020820190508181035f8301526110488161100f565b9050919050565b7f6f70657261746f7220616c7265616479206578697374730000000000000000005f82015250565b5f611083601783610e9f565b915061108e8261104f565b602082019050919050565b5f6020820190508181035f8301526110b081611077565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6110ee82610acd565b91506110f983610acd565b9250828203905081811115611111576111106110b7565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffd5b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061119257607f821691505b6020821081036111a5576111a461114e565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026112077fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826111cc565b61121186836111cc565b95508019841693508086168417925050509392505050565b5f819050919050565b5f61124c61124761124284610acd565b611229565b610acd565b9050919050565b5f819050919050565b61126583611232565b61127961127182611253565b8484546111d8565b825550505050565b5f5f905090565b611290611281565b61129b81848461125c565b505050565b5b818110156112be576112b35f82611288565b6001810190506112a1565b5050565b601f821115611303576112d4816111ab565b6112dd846111bd565b810160208510156112ec578190505b6113006112f8856111bd565b8301826112a0565b50505b505050565b5f82821c905092915050565b5f6113235f1984600802611308565b1980831691505092915050565b5f61133b8383611314565b9150826002028217905092915050565b61135482611144565b67ffffffffffffffff81111561136d5761136c610916565b5b611377825461117b565b6113828282856112c2565b5f60209050601f8311600181146113b3575f84156113a1578287015190505b6113ab8582611330565b865550611412565b601f1984166113c1866111ab565b5f5b828110156113e8578489015182556001820191506020850194506020810190506113c3565b868310156114055784890151611401601f891682611314565b8355505b6001600288020188555050505b505050505050565b7f696e76616c6964206164647265737300000000000000000000000000000000005f82015250565b5f61144e600f83610e9f565b91506114598261141a565b602082019050919050565b5f6020820190508181035f83015261147b81611442565b9050919050565b7f696e76616c6964206964000000000000000000000000000000000000000000005f82015250565b5f6114b6600a83610e9f565b91506114c182611482565b602082019050919050565b5f6020820190508181035f8301526114e3816114aa565b9050919050565b615f1a806114f75f395ff3fe608060405234801561000f575f5ffd5b50600436106100a7575f3560e01c8063ad36e6d01161006f578063ad36e6d014610115578063c130809a1461011f578063cc45662a14610129578063f2fde38b14610145578063f5f2d9f114610161578063ffd740df1461016b576100a7565b80633048bfba146100ab578063409900e8146100b55780634886f62c146100d15780636c0b61b9146100db57806375418b9d146100f7575b5f5ffd5b6100b3610187565b005b6100cf60048036038101906100ca91906139e2565b6102db565b005b6100d961037e565b005b6100f560048036038101906100f09190613a2b565b61082c565b005b6100ff610956565b60405161010c9190613f47565b60405180910390f35b61011d610a58565b005b610127610b7d565b005b610143600480360381019061013e919061401d565b610cd1565b005b61015f600480360381019061015a91906140c5565b61103b565b005b61016961110b565b005b6101856004803603810190610180919061411a565b61127a565b005b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610215576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161020c9061419f565b60405180910390fd5b61021f600961140e565b600a600881819054906101000a90046fffffffffffffffffffffffffffffffff168092919061024d906141ea565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507f8fb9cd054d0a022110cced239e908b834e4cd219511856d4eaae3051d932d604600a60089054906101000a90046fffffffffffffffffffffffffffffffff166040516102d19190614230565b60405180910390a1565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610369576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103609061419f565b60405180910390fd5b806001818161037891906143c4565b90505050565b6103923360056114c690919063ffffffff16565b600a600881819054906101000a90046fffffffffffffffffffffffffffffffff16809291906103c0906141ea565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507fa76a8fc1a90266ddee8937a18e12f01eade946b3b66197fff289af9277c2bd2533600a60089054906101000a90046fffffffffffffffffffffffffffffffff166040516104469291906143e1565b60405180910390a15f60056003015f9054906101000a900460ff1660ff161161082a575f5f90505b60055f01805490508110156104db576104ce60055f01828154811061049657610495614408565b5b905f5260205f20015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660026115e490919063ffffffff16565b808060010191505061046e565b505f5f90505b6005600101805490508110156107185761070b6005600101828154811061050b5761050a614408565b5b905f5260205f2090600302016040518060600160405290815f82015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160018201805480602002602001604051908101604052809291908181526020015f905b82821015610663578382905f5260205f2090600202016040518060400160405290815f82015481526020016001820180546105d490614462565b80601f016020809104026020016040519081016040528092919081815260200182805461060090614462565b801561064b5780601f106106225761010080835404028352916020019161064b565b820191905f5260205f20905b81548152906001019060200180831161062e57829003601f168201915b5050505050815250508152602001906001019061059a565b50505050815260200160028201805461067b90614462565b80601f01602080910402602001604051908101604052809291908181526020018280546106a790614462565b80156106f25780601f106106c9576101008083540402835291602001916106f2565b820191905f5260205f20905b8154815290600101906020018083116106d557829003601f168201915b505050505081525050600261187690919063ffffffff16565b80806001019150506104e1565b50600a5f81819054906101000a900467ffffffffffffffff168092919061073e90614492565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055505061076f6005611b03565b600a600881819054906101000a90046fffffffffffffffffffffffffffffffff168092919061079d906141ea565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507f11ce50160e66100537fd4b0ae26de66d51dab713ad92313353a18c24e8f6daab600a60089054906101000a90046fffffffffffffffffffffffffffffffff166040516108219190614230565b60405180910390a15b565b610840336002611bac90919063ffffffff16565b61087f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108769061450b565b60405180910390fd5b61089533826002611d049092919063ffffffff16565b600a600881819054906101000a90046fffffffffffffffffffffffffffffffff16809291906108c3906141ea565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507f6adfb896d3407681d05fb874d4dfb7068e6e2a36f09acd38a3b7d04c01745fee3382600a60089054906101000a90046fffffffffffffffffffffffffffffffff1660405161094b93929190614633565b60405180910390a150565b61095e613746565b6040518060a001604052806109736002611d96565b815260200161098f60025f016005611f9990919063ffffffff16565b815260200160096040518060200160405290815f82015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815250508152602001600a5f9054906101000a900467ffffffffffffffff1667ffffffffffffffff168152602001600a60089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff16815250905090565b610a6c336002611bac90919063ffffffff16565b610aab576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610aa29061450b565b60405180910390fd5b610abf33600961270090919063ffffffff16565b600a600881819054906101000a90046fffffffffffffffffffffffffffffffff1680929190610aed906141ea565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507ff91067eb420c28d3124865fc996e6aa9d541b9b4fef9188cb965a6cc6491638e33600a60089054906101000a90046fffffffffffffffffffffffffffffffff16604051610b739291906143e1565b60405180910390a1565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610c0b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c029061419f565b60405180910390fd5b610c156005612827565b600a600881819054906101000a90046fffffffffffffffffffffffffffffffff1680929190610c43906141ea565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507f9ce192aea5faf2151bbc246cd8918d2eba702fa26951f67f2bf7b3817e689d98600a60089054906101000a90046fffffffffffffffffffffffffffffffff16604051610cc79190614230565b60405180910390a1565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610d5f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d569061419f565b60405180910390fd5b610d69600961287b565b15610da9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610da0906146b9565b60405180910390fd5b5f5f90505b84849050811015610e4057610df4858583818110610dcf57610dce614408565b5b9050602002016020810190610de491906140c5565b6002611bac90919063ffffffff16565b610e33576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e2a90614721565b60405180910390fd5b8080600101915050610dae565b505f5f90505b82829050811015610f2557610e8f838383818110610e6757610e66614408565b5b9050602002810190610e79919061474b565b8060200190610e889190614772565b90506128d5565b610ed8838383818110610ea557610ea4614408565b5b9050602002810190610eb7919061474b565b5f016020810190610ec891906140c5565b6002611bac90919063ffffffff16565b15610f18576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f0f9061481e565b60405180910390fd5b8080600101915050610e46565b50610f548282905085859050610f3b6002612974565b610f45919061483c565b610f4f919061486f565b612995565b610f7360025f01858585856005612a339095949392919063ffffffff16565b600a600881819054906101000a90046fffffffffffffffffffffffffffffffff1680929190610fa1906141ea565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507f7e05e40117b6e18ab284c04a3508c3826422dc84a65e9c236a8248774416f8ac84848484600a60089054906101000a90046fffffffffffffffffffffffffffffffff1660405161102d959493929190614be8565b60405180910390a150505050565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146110c9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110c09061419f565b60405180910390fd5b805f5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b61111f336002611bac90919063ffffffff16565b61115e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111559061450b565b60405180910390fd5b6111686005612ed5565b156111a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161119f90614c79565b60405180910390fd5b6111bc336009612ef990919063ffffffff16565b600a600881819054906101000a90046fffffffffffffffffffffffffffffffff16809291906111ea906141ea565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507fbc2748cf02f7a1291525e866efc76ab3b96d32d7afcbb26c53daec617b38b47933600a60089054906101000a90046fffffffffffffffffffffffffffffffff166040516112709291906143e1565b60405180910390a1565b61128e336002611bac90919063ffffffff16565b6112cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112c49061450b565b60405180910390fd5b6112e33382600261303c9092919063ffffffff16565b60015f0160019054906101000a900460ff1660ff1661130c3360026130c590919063ffffffff16565b101561134d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161134490614ce1565b60405180910390fd5b600a600881819054906101000a90046fffffffffffffffffffffffffffffffff168092919061137b906141ea565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507fbd184de79f134b0f3da466d278f5417cbcb1450d72f1bd1a1b84f18b1bcd03ca3382600a60089054906101000a90046fffffffffffffffffffffffffffffffff1660405161140393929190614d0e565b60405180910390a150565b5f73ffffffffffffffffffffffffffffffffffffffff16815f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff160361149e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161149590614d8d565b60405180910390fd5b805f015f6101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905550565b816002015f8273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16611551576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161154890614df5565b60405180910390fd5b5f826002015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908315150217905550816003015f81819054906101000a900460ff16809291906115c790614e13565b91906101000a81548160ff021916908360ff160217905550505050565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611652576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161164990614e84565b60405180910390fd5b5f826001015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1690505f8160ff1614158061172057508173ffffffffffffffffffffffffffffffffffffffff16835f015f815481106116da576116d9614408565b5b905f5260205f2090600502015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b61175f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161175690614eec565b60405180910390fd5b826001015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81549060ff0219169055825f018160ff16815481106117c5576117c4614408565b5b905f5260205f2090600502015f5f82015f6101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600182015f5f82015f61180a91906137a1565b600282015f61181991906137c2565b5050600482015f61182a91906137e7565b50508260020181908060018154018082558091505060019003905f5260205f2090602091828204019190069091909190916101000a81548160ff021916908360ff160217905550505050565b61188382825f0151611bac565b156118c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118ba9061481e565b60405180910390fd5b5f5f8360020180549050111561195d5782600201600184600201805490506118eb919061483c565b815481106118fc576118fb614408565b5b905f5260205f2090602091828204019190069054906101000a900460ff169050826002018054806119305761192f614f0a565b5b600190038181905f5260205f2090602091828204019190066101000a81549060ff021916905590556119ce565b610100835f0180549050106119a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161199e90614f81565b60405180910390fd5b825f01805490509050825f0160018160018154018082558091505003905f5260205f209050505b80836001015f845f015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908360ff1602179055505f835f018260ff1681548110611a4157611a40614408565b5b905f5260205f2090600502019050825f0151815f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508260400151816004019081611aa89190615163565b505f5f90505b836020015151811015611afc57611aef84602001518281518110611ad557611ad4614408565b5b60200260200101518360010161314890919063ffffffff16565b8080600101915050611aae565b5050505050565b611b0c81612ed5565b611b4b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b429061527c565b60405180910390fd5b5f816003015f9054906101000a900460ff1660ff1614611ba0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b97906152e4565b60405180910390fd5b611ba9816133ce565b50565b5f5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611c1b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c1290614e84565b60405180910390fd5b5f835f01805490501115611cfa575f836001015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1660ff16141580611cf357508173ffffffffffffffffffffffffffffffffffffffff16835f015f81548110611cad57611cac614408565b5b905f5260205f2090600502015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b9050611cfe565b5f90505b92915050565b611d9181611d1190615460565b845f01856001015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1660ff1681548110611d7457611d73614408565b5b905f5260205f20906005020160010161314890919063ffffffff16565b505050565b611d9e613824565b5f825f018054905067ffffffffffffffff811115611dbf57611dbe614f9f565b5b604051908082528060200260200182016040528015611df857816020015b611de5613837565b815260200190600190039081611ddd5790505b5090505f5f90505b835f0180549050811015611f81576040518060600160405280855f018381548110611e2e57611e2d614408565b5b905f5260205f2090600502015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001611ea3865f018481548110611e8f57611e8e614408565b5b905f5260205f209060050201600101613401565b8152602001855f018381548110611ebd57611ebc614408565b5b905f5260205f2090600502016004018054611ed790614462565b80601f0160208091040260200160405190810160405280929190818152602001828054611f0390614462565b8015611f4e5780601f10611f2557610100808354040283529160200191611f4e565b820191905f5260205f20905b815481529060010190602001808311611f3157829003601f168201915b5050505050815250828281518110611f6957611f68614408565b5b60200260200101819052508080600101915050611e00565b50604051806020016040528082815250915050919050565b611fa161386d565b5f835f018054905067ffffffffffffffff811115611fc257611fc1614f9f565b5b604051908082528060200260200182016040528015611ff05781602001602082028036833780820191505090505b5090505f5f90505b845f018054905081101561209d57845f01818154811061201b5761201a614408565b5b905f5260205f20015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682828151811061205657612055614408565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508080600101915050611ff8565b505f846001018054905067ffffffffffffffff8111156120c0576120bf614f9f565b5b6040519080825280602002602001820160405280156120f957816020015b6120e6613837565b8152602001906001900390816120de5790505b5090505f5f90505b85600101805490508110156123415785600101818154811061212657612125614408565b5b905f5260205f2090600302016040518060600160405290815f82015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160018201805480602002602001604051908101604052809291908181526020015f905b8282101561227e578382905f5260205f2090600202016040518060400160405290815f82015481526020016001820180546121ef90614462565b80601f016020809104026020016040519081016040528092919081815260200182805461221b90614462565b80156122665780601f1061223d57610100808354040283529160200191612266565b820191905f5260205f20905b81548152906001019060200180831161224957829003601f168201915b505050505081525050815260200190600101906121b5565b50505050815260200160028201805461229690614462565b80601f01602080910402602001604051908101604052809291908181526020018280546122c290614462565b801561230d5780601f106122e45761010080835404028352916020019161230d565b820191905f5260205f20905b8154815290600101906020018083116122f057829003601f168201915b50505050508152505082828151811061232957612328614408565b5b60200260200101819052508080600101915050612101565b505f856003015f9054906101000a900460ff1660ff1667ffffffffffffffff8111156123705761236f614f9f565b5b60405190808252806020026020018201604052801561239e5781602001602082028036833780820191505090505b5090505f866003015f9054906101000a900460ff1660ff1611156126da575f5f5f90505b8680549050811015612581575f73ffffffffffffffffffffffffffffffffffffffff168782815481106123f8576123f7614408565b5b905f5260205f2090600502015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141580156124d25750876002015f88838154811061245d5761245c614408565b5b905f5260205f2090600502015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff165b15612574578681815481106124ea576124e9614408565b5b905f5260205f2090600502015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683838151811061252b5761252a614408565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050818061257090615472565b9250505b80806001019150506123c2565b505f5f90505b87600101805490508110156126d757876002015f8960010183815481106125b1576125b0614408565b5b905f5260205f2090600302015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16156126ca578760010181815481106126405761263f614408565b5b905f5260205f2090600302015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683838151811061268157612680614408565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505081806126c690615472565b9250505b8080600101915050612587565b50505b604051806060016040528084815260200183815260200182815250935050505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361276e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161276590614e84565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16825f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146127fe576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127f590614d8d565b60405180910390fd5b815f015f6101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690555050565b61283081612ed5565b61286f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016128669061527c565b60405180910390fd5b612878816133ce565b50565b5f5f73ffffffffffffffffffffffffffffffffffffffff16825f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614159050919050565b60015f0160019054906101000a900460ff1660ff1681101561292c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161292390614ce1565b60405180910390fd5b610100811115612971576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161296890615503565b60405180910390fd5b50565b5f8160020180549050825f018054905061298e919061483c565b9050919050565b60015f015f9054906101000a900460ff1660ff168110156129eb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129e29061556b565b60405180910390fd5b610100811115612a30576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a2790614f81565b60405180910390fd5b50565b612a3c86612ed5565b15612a7c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a73906155d3565b60405180910390fd5b5f848490501180612a8f57505f82829050115b612ace576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612ac59061563b565b60405180910390fd5b5f5f90505b8580549050811015612c30575f73ffffffffffffffffffffffffffffffffffffffff16868281548110612b0957612b08614408565b5b905f5260205f2090600502015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612c23576001876002015f888481548110612b6c57612b6b614408565b5b905f5260205f2090600502015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908315150217905550866003015f81819054906101000a900460ff1680929190612c0990615659565b91906101000a81548160ff021916908360ff160217905550505b8080600101915050612ad3565b505f5f90505b84849050811015612d8c57865f01858583818110612c5757612c56614408565b5b9050602002016020810190612c6c91906140c5565b908060018154018082558091505060019003905f5260205f20015f9091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505f876002015f878785818110612ce257612ce1614408565b5b9050602002016020810190612cf791906140c5565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908315150217905550866003015f81819054906101000a900460ff1680929190612d6690614e13565b91906101000a81548160ff021916908360ff160217905550508080600101915050612c36565b505f5f90505b82829050811015612ecc5786600101838383818110612db457612db3614408565b5b9050602002810190612dc6919061474b565b908060018154018082558091505060019003905f5260205f2090600302015f909190919091508181612df89190615d9e565b50506001876002015f858585818110612e1457612e13614408565b5b9050602002810190612e26919061474b565b5f016020810190612e3791906140c5565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908315150217905550866003015f81819054906101000a900460ff1680929190612ea690615659565b91906101000a81548160ff021916908360ff160217905550508080600101915050612d92565b50505050505050565b5f5f825f0180549050141580612ef257505f826001018054905014155b9050919050565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612f67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612f5e90614e84565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff16825f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612ff7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612fee90615df6565b60405180910390fd5b80825f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b6130c081845f01856001015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1660ff16815481106130a3576130a2614408565b5b905f5260205f2090600502016001016135c790919063ffffffff16565b505050565b5f613140835f01846001015f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1660ff168154811061312c5761312b614408565b5b905f5260205f209060050201600101613725565b905092915050565b5f815f01510361318d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161318490615e5e565b60405180910390fd5b5f5f835f0180549050111561324a57826001015f835f015181526020019081526020015f205f9054906101000a900460ff1690505f8160ff161415806131f85750815f0151835f015f815481106131e7576131e6614408565b5b905f5260205f2090600202015f0154145b156132495781835f018260ff168154811061321657613215614408565b5b905f5260205f2090600202015f820151815f0155602082015181600101908161323f9190615163565b50905050506133ca565b5b5f836002018054905011156132e3578260020160018460020180549050613271919061483c565b8154811061328257613281614408565b5b905f5260205f2090602091828204019190069054906101000a900460ff169050826002018054806132b6576132b5614f0a565b5b600190038181905f5260205f2090602091828204019190066101000a81549060ff02191690559055613354565b610100835f01805490501061332d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161332490615503565b60405180910390fd5b825f01805490509050825f0160018160018154018082558091505003905f5260205f209050505b80836001015f845f015181526020019081526020015f205f6101000a81548160ff021916908360ff16021790555081835f018260ff168154811061339b5761339a614408565b5b905f5260205f2090600202015f820151815f015560208201518160010190816133c49190615163565b50905050505b5050565b805f015f6133dc919061388e565b806001015f6133eb91906138ac565b806003015f6101000a81549060ff021916905550565b60605f61340d83613725565b67ffffffffffffffff81111561342657613425614f9f565b5b60405190808252806020026020018201604052801561345f57816020015b61344c6138cd565b8152602001906001900390816134445790505b5090505f5f5f90505b845f01805490508110156135bc575f855f01828154811061348c5761348b614408565b5b905f5260205f2090600202015f0154146135af576040518060400160405280865f0183815481106134c0576134bf614408565b5b905f5260205f2090600202015f01548152602001865f0183815481106134e9576134e8614408565b5b905f5260205f209060020201600101805461350390614462565b80601f016020809104026020016040519081016040528092919081815260200182805461352f90614462565b801561357a5780601f106135515761010080835404028352916020019161357a565b820191905f5260205f20905b81548152906001019060200180831161355d57829003601f168201915b505050505081525083838151811061359557613594614408565b5b602002602001018190525081806135ab90615472565b9250505b8080600101915050613468565b508192505050919050565b5f8103613609576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161360090615e5e565b60405180910390fd5b5f826001015f8381526020019081526020015f205f9054906101000a900460ff1690505f8160ff16141580613660575081835f015f8154811061364f5761364e614408565b5b905f5260205f2090600202015f0154145b61369f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161369690615ec6565b60405180910390fd5b825f018160ff16815481106136b7576136b6614408565b5b905f5260205f2090600202015f5f82015f9055600182015f6136d991906137e7565b50508260020181908060018154018082558091505060019003905f5260205f2090602091828204019190069091909190916101000a81548160ff021916908360ff160217905550505050565b5f8160020180549050825f018054905061373f919061483c565b9050919050565b6040518060a00160405280613759613824565b815260200161376661386d565b81526020016137736138e6565b81526020015f67ffffffffffffffff1681526020015f6fffffffffffffffffffffffffffffffff1681525090565b5080545f8255600202905f5260205f20908101906137bf919061390e565b50565b5080545f8255601f0160209004905f5260205f20908101906137e4919061393a565b50565b5080546137f390614462565b5f825580601f106138045750613821565b601f0160209004905f5260205f2090810190613820919061393a565b5b50565b6040518060200160405280606081525090565b60405180606001604052805f73ffffffffffffffffffffffffffffffffffffffff16815260200160608152602001606081525090565b60405180606001604052806060815260200160608152602001606081525090565b5080545f8255905f5260205f20908101906138a9919061393a565b50565b5080545f8255600302905f5260205f20908101906138ca9190613955565b50565b60405180604001604052805f8152602001606081525090565b60405180602001604052805f73ffffffffffffffffffffffffffffffffffffffff1681525090565b5b80821115613936575f5f82015f9055600182015f61392d91906137e7565b5060020161390f565b5090565b5b80821115613951575f815f90555060010161393b565b5090565b5b808211156139ab575f5f82015f6101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600182015f61399391906137a1565b600282015f6139a291906137e7565b50600301613956565b5090565b5f604051905090565b5f5ffd5b5f5ffd5b5f5ffd5b5f604082840312156139d9576139d86139c0565b5b81905092915050565b5f604082840312156139f7576139f66139b8565b5b5f613a04848285016139c4565b91505092915050565b5f60408284031215613a2257613a216139c0565b5b81905092915050565b5f60208284031215613a4057613a3f6139b8565b5b5f82013567ffffffffffffffff811115613a5d57613a5c6139bc565b5b613a6984828501613a0d565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f613ac482613a9b565b9050919050565b613ad481613aba565b82525050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f819050919050565b613b1581613b03565b82525050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f613b5d82613b1b565b613b678185613b25565b9350613b77818560208601613b35565b613b8081613b43565b840191505092915050565b5f604083015f830151613ba05f860182613b0c565b5060208301518482036020860152613bb88282613b53565b9150508091505092915050565b5f613bd08383613b8b565b905092915050565b5f602082019050919050565b5f613bee82613ada565b613bf88185613ae4565b935083602082028501613c0a85613af4565b805f5b85811015613c455784840389528151613c268582613bc5565b9450613c3183613bd8565b925060208a01995050600181019050613c0d565b50829750879550505050505092915050565b5f606083015f830151613c6c5f860182613acb565b5060208301518482036020860152613c848282613be4565b91505060408301518482036040860152613c9e8282613b53565b9150508091505092915050565b5f613cb68383613c57565b905092915050565b5f602082019050919050565b5f613cd482613a72565b613cde8185613a7c565b935083602082028501613cf085613a8c565b805f5b85811015613d2b5784840389528151613d0c8582613cab565b9450613d1783613cbe565b925060208a01995050600181019050613cf3565b50829750879550505050505092915050565b5f602083015f8301518482035f860152613d578282613cca565b9150508091505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f613d988383613acb565b60208301905092915050565b5f602082019050919050565b5f613dba82613d64565b613dc48185613d6e565b9350613dcf83613d7e565b805f5b83811015613dff578151613de68882613d8d565b9750613df183613da4565b925050600181019050613dd2565b5085935050505092915050565b5f606083015f8301518482035f860152613e268282613db0565b91505060208301518482036020860152613e408282613cca565b91505060408301518482036040860152613e5a8282613db0565b9150508091505092915050565b602082015f820151613e7b5f850182613acb565b50505050565b5f67ffffffffffffffff82169050919050565b613e9d81613e81565b82525050565b5f6fffffffffffffffffffffffffffffffff82169050919050565b613ec781613ea3565b82525050565b5f60a083015f8301518482035f860152613ee78282613d3d565b91505060208301518482036020860152613f018282613e0c565b9150506040830151613f166040860182613e67565b506060830151613f296060860182613e94565b506080830151613f3c6080860182613ebe565b508091505092915050565b5f6020820190508181035f830152613f5f8184613ecd565b905092915050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f83601f840112613f8857613f87613f67565b5b8235905067ffffffffffffffff811115613fa557613fa4613f6b565b5b602083019150836020820283011115613fc157613fc0613f6f565b5b9250929050565b5f5f83601f840112613fdd57613fdc613f67565b5b8235905067ffffffffffffffff811115613ffa57613ff9613f6b565b5b60208301915083602082028301111561401657614015613f6f565b5b9250929050565b5f5f5f5f60408587031215614035576140346139b8565b5b5f85013567ffffffffffffffff811115614052576140516139bc565b5b61405e87828801613f73565b9450945050602085013567ffffffffffffffff811115614081576140806139bc565b5b61408d87828801613fc8565b925092505092959194509250565b6140a481613aba565b81146140ae575f5ffd5b50565b5f813590506140bf8161409b565b92915050565b5f602082840312156140da576140d96139b8565b5b5f6140e7848285016140b1565b91505092915050565b6140f981613b03565b8114614103575f5ffd5b50565b5f81359050614114816140f0565b92915050565b5f6020828403121561412f5761412e6139b8565b5b5f61413c84828501614106565b91505092915050565b5f82825260208201905092915050565b7f6e6f7420746865206f776e6572000000000000000000000000000000000000005f82015250565b5f614189600d83614145565b915061419482614155565b602082019050919050565b5f6020820190508181035f8301526141b68161417d565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6141f482613ea3565b91506fffffffffffffffffffffffffffffffff8203614216576142156141bd565b5b600182019050919050565b61422a81613ea3565b82525050565b5f6020820190506142435f830184614221565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b5f60ff82169050919050565b61428a81614275565b8114614294575f5ffd5b50565b5f81356142a381614281565b80915050919050565b5f815f1b9050919050565b5f60ff6142c3846142ac565b9350801983169250808416831791505092915050565b5f819050919050565b5f6142fc6142f76142f284614275565b6142d9565b614275565b9050919050565b5f819050919050565b614315826142e2565b61432861432182614303565b83546142b7565b8255505050565b5f8160081b9050919050565b5f61ff006143488461432f565b9350801983169250808416831791505092915050565b614367826142e2565b61437a61437382614303565b835461433b565b8255505050565b5f81015f83018061439181614297565b905061439d818461430c565b5050505f810160208301806143b181614297565b90506143bd818461435e565b5050505050565b6143ce8282614381565b5050565b6143db81613aba565b82525050565b5f6040820190506143f45f8301856143d2565b6144016020830184614221565b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061447957607f821691505b60208210810361448c5761448b614435565b5b50919050565b5f61449c82613e81565b915067ffffffffffffffff82036144b6576144b56141bd565b5b600182019050919050565b7f6e6f7420616e206f70657261746f7200000000000000000000000000000000005f82015250565b5f6144f5600f83614145565b9150614500826144c1565b602082019050919050565b5f6020820190508181035f830152614522816144e9565b9050919050565b5f6145376020840184614106565b905092915050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f8335600160200384360303811261456757614566614547565b5b83810192508235915060208301925067ffffffffffffffff82111561458f5761458e61453f565b5b6001820236038313156145a5576145a4614543565b5b509250929050565b828183375f83830152505050565b5f6145c68385613b25565b93506145d38385846145ad565b6145dc83613b43565b840190509392505050565b5f604083016145f85f840184614529565b6146045f860182613b0c565b50614612602084018461454b565b85830360208701526146258382846145bb565b925050508091505092915050565b5f6060820190506146465f8301866143d2565b818103602083015261465881856145e7565b90506146676040830184614221565b949350505050565b7f6d61696e74656e616e636520696e2070726f67726573730000000000000000005f82015250565b5f6146a3601783614145565b91506146ae8261466f565b602082019050919050565b5f6020820190508181035f8301526146d081614697565b9050919050565b7f756e6b6e6f776e206f70657261746f72000000000000000000000000000000005f82015250565b5f61470b601083614145565b9150614716826146d7565b602082019050919050565b5f6020820190508181035f830152614738816146ff565b9050919050565b5f5ffd5b5f5ffd5b5f5ffd5b5f823560016060038336030381126147665761476561473f565b5b80830191505092915050565b5f5f8335600160200384360303811261478e5761478d61473f565b5b80840192508235915067ffffffffffffffff8211156147b0576147af614743565b5b6020830192506020820236038313156147cc576147cb614747565b5b509250929050565b7f6f70657261746f7220616c7265616479206578697374730000000000000000005f82015250565b5f614808601783614145565b9150614813826147d4565b602082019050919050565b5f6020820190508181035f830152614835816147fc565b9050919050565b5f61484682613b03565b915061485183613b03565b9250828203905081811115614869576148686141bd565b5b92915050565b5f61487982613b03565b915061488483613b03565b925082820190508082111561489c5761489b6141bd565b5b92915050565b5f82825260208201905092915050565b5f819050919050565b5f6148c960208401846140b1565b905092915050565b5f602082019050919050565b5f6148e883856148a2565b93506148f3826148b2565b805f5b8581101561492b5761490882846148bb565b6149128882613d8d565b975061491d836148d1565b9250506001810190506148f6565b5085925050509392505050565b5f82825260208201905092915050565b5f819050919050565b5f5f8335600160200384360303811261496d5761496c614547565b5b83810192508235915060208301925067ffffffffffffffff8211156149955761499461453f565b5b6020820236038313156149ab576149aa614543565b5b509250929050565b5f819050919050565b5f604083016149cd5f840184614529565b6149d95f860182613b0c565b506149e7602084018461454b565b85830360208701526149fa8382846145bb565b925050508091505092915050565b5f614a1383836149bc565b905092915050565b5f82356001604003833603038112614a3657614a35614547565b5b82810191505092915050565b5f602082019050919050565b5f614a598385613ae4565b935083602084028501614a6b846149b3565b805f5b87811015614aae578484038952614a858284614a1b565b614a8f8582614a08565b9450614a9a83614a42565b925060208a01995050600181019050614a6e565b50829750879450505050509392505050565b5f60608301614ad15f8401846148bb565b614add5f860182613acb565b50614aeb6020840184614951565b8583036020870152614afe838284614a4e565b92505050614b0f604084018461454b565b8583036040870152614b228382846145bb565b925050508091505092915050565b5f614b3b8383614ac0565b905092915050565b5f82356001606003833603038112614b5e57614b5d614547565b5b82810191505092915050565b5f602082019050919050565b5f614b818385614938565b935083602084028501614b9384614948565b805f5b87811015614bd6578484038952614bad8284614b43565b614bb78582614b30565b9450614bc283614b6a565b925060208a01995050600181019050614b96565b50829750879450505050509392505050565b5f6060820190508181035f830152614c018187896148dd565b90508181036020830152614c16818587614b76565b9050614c256040830184614221565b9695505050505050565b7f6d6967726174696f6e20696e2070726f677265737300000000000000000000005f82015250565b5f614c63601583614145565b9150614c6e82614c2f565b602082019050919050565b5f6020820190508181035f830152614c9081614c57565b9050919050565b7f746f6f20666577206e6f646573000000000000000000000000000000000000005f82015250565b5f614ccb600d83614145565b9150614cd682614c97565b602082019050919050565b5f6020820190508181035f830152614cf881614cbf565b9050919050565b614d0881613b03565b82525050565b5f606082019050614d215f8301866143d2565b614d2e6020830185614cff565b614d3b6040830184614221565b949350505050565b7f6e6f7420756e646572206d61696e74656e616e636500000000000000000000005f82015250565b5f614d77601583614145565b9150614d8282614d43565b602082019050919050565b5f6020820190508181035f830152614da481614d6b565b9050919050565b7f6e6f742070756c6c696e670000000000000000000000000000000000000000005f82015250565b5f614ddf600b83614145565b9150614dea82614dab565b602082019050919050565b5f6020820190508181035f830152614e0c81614dd3565b9050919050565b5f614e1d82614275565b91505f8203614e2f57614e2e6141bd565b5b600182039050919050565b7f696e76616c6964206164647265737300000000000000000000000000000000005f82015250565b5f614e6e600f83614145565b9150614e7982614e3a565b602082019050919050565b5f6020820190508181035f830152614e9b81614e62565b9050919050565b7f6f70657261746f7220646f65736e2774206578697374000000000000000000005f82015250565b5f614ed6601683614145565b9150614ee182614ea2565b602082019050919050565b5f6020820190508181035f830152614f0381614eca565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffd5b7f746f6f206d616e79206f70657261746f727300000000000000000000000000005f82015250565b5f614f6b601283614145565b9150614f7682614f37565b602082019050919050565b5f6020820190508181035f830152614f9881614f5f565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026150287fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82614fed565b6150328683614fed565b95508019841693508086168417925050509392505050565b5f61506461505f61505a84613b03565b6142d9565b613b03565b9050919050565b5f819050919050565b61507d8361504a565b6150916150898261506b565b848454614ff9565b825550505050565b5f5f905090565b6150a8615099565b6150b3818484615074565b505050565b5b818110156150d6576150cb5f826150a0565b6001810190506150b9565b5050565b601f82111561511b576150ec81614fcc565b6150f584614fde565b81016020851015615104578190505b61511861511085614fde565b8301826150b8565b50505b505050565b5f82821c905092915050565b5f61513b5f1984600802615120565b1980831691505092915050565b5f615153838361512c565b9150826002028217905092915050565b61516c82613b1b565b67ffffffffffffffff81111561518557615184614f9f565b5b61518f8254614462565b61519a8282856150da565b5f60209050601f8311600181146151cb575f84156151b9578287015190505b6151c38582615148565b86555061522a565b601f1984166151d986614fcc565b5f5b82811015615200578489015182556001820191506020850194506020810190506151db565b8683101561521d5784890151615219601f89168261512c565b8355505b6001600288020188555050505b505050505050565b7f6e6f7420696e2070726f677265737300000000000000000000000000000000005f82015250565b5f615266600f83614145565b915061527182615232565b602082019050919050565b5f6020820190508181035f8301526152938161525a565b9050919050565b7f646174612070756c6c20696e2070726f677265737300000000000000000000005f82015250565b5f6152ce601583614145565b91506152d98261529a565b602082019050919050565b5f6020820190508181035f8301526152fb816152c2565b9050919050565b5f5ffd5b61530f82613b43565b810181811067ffffffffffffffff8211171561532e5761532d614f9f565b5b80604052505050565b5f6153406139af565b905061534c8282615306565b919050565b5f5ffd5b5f5ffd5b5f67ffffffffffffffff82111561537357615372614f9f565b5b61537c82613b43565b9050602081019050919050565b5f61539b61539684615359565b615337565b9050828152602081018484840111156153b7576153b6615355565b5b6153c28482856145ad565b509392505050565b5f82601f8301126153de576153dd613f67565b5b81356153ee848260208601615389565b91505092915050565b5f6040828403121561540c5761540b615302565b5b6154166040615337565b90505f61542584828501614106565b5f83015250602082013567ffffffffffffffff81111561544857615447615351565b5b615454848285016153ca565b60208301525092915050565b5f61546b36836153f7565b9050919050565b5f61547c82613b03565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036154ae576154ad6141bd565b5b600182019050919050565b7f746f6f206d616e79206e6f6465730000000000000000000000000000000000005f82015250565b5f6154ed600e83614145565b91506154f8826154b9565b602082019050919050565b5f6020820190508181035f83015261551a816154e1565b9050919050565b7f746f6f20666577206f70657261746f72730000000000000000000000000000005f82015250565b5f615555601183614145565b915061556082615521565b602082019050919050565b5f6020820190508181035f83015261558281615549565b9050919050565b7f6d6967726174696f6e20616c726561647920696e2070726f67726573730000005f82015250565b5f6155bd601d83614145565b91506155c882615589565b602082019050919050565b5f6020820190508181035f8301526155ea816155b1565b9050919050565b7f6e6f7468696e6720746f20646f000000000000000000000000000000000000005f82015250565b5f615625600d83614145565b9150615630826155f1565b602082019050919050565b5f6020820190508181035f83015261565281615619565b9050919050565b5f61566382614275565b915060ff8203615676576156756141bd565b5b600182019050919050565b5f813561568d8161409b565b80915050919050565b5f73ffffffffffffffffffffffffffffffffffffffff6156b5846142ac565b9350801983169250808416831791505092915050565b5f6156e56156e06156db84613a9b565b6142d9565b613a9b565b9050919050565b5f6156f6826156cb565b9050919050565b5f615707826156ec565b9050919050565b5f819050919050565b615720826156fd565b61573361572c8261570e565b8354615696565b8255505050565b5f823560016040038336030381126157555761575461473f565b5b80830191505092915050565b5f81549050919050565b5f61577582613b03565b915061578083613b03565b925082820261578e81613b03565b915082820484148315176157a5576157a46141bd565b5b5092915050565b5f8190506157bb82600261576b565b9050919050565b5f819050815f5260205f209050919050565b6158047fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83602003600802615120565b815481168255505050565b61581881614fcc565b615823838254615148565b8083555f825550505050565b602084105f811461588957601f841160018114615857576158508685615148565b8355615883565b61586083614fcc565b61587761586c87614fde565b8201600183016150b8565b615881878561580f565b505b506158d6565b61589282614fcc565b61589b86614fde565b8101601f871680156158b5576158b481600184036157d4565b5b6158c96158c188614fde565b8401836150b8565b6001886002021785555050505b5050505050565b680100000000000000008411156158f7576158f6614f9f565b5b602083105f811461594057602085105f811461591e576159178685615148565b835561593a565b8360ff191693508361592f84614fcc565b556001866002020183555b5061594a565b6001856002020182555b5050505050565b805461595c81614462565b8084111561597157615970848284866158dd565b5b80841015615986576159858482848661582f565b5b50505050565b818110156159a95761599e5f826150a0565b60018101905061598c565b5050565b6159b75f82615951565b50565b5f82146159ca576159c9614249565b5b6159d3816159ad565b5050565b6159e35f5f83016150a0565b6159f05f600183016159ba565b50565b5f8214615a0357615a02614249565b5b615a0c816159d7565b5050565b5b81811015615a2e57615a235f826159f3565b600281019050615a11565b5050565b81831015615a6b57615a43826157ac565b615a4c846157ac565b615a55836157c2565b818101838201615a658183615a10565b50505050505b505050565b68010000000000000000821115615a8a57615a89614f9f565b5b615a9381615761565b828255615aa1838284615a32565b505050565b5f82905092915050565b5f8135615abc816140f0565b80915050919050565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff615af0846142ac565b9350801983169250808416831791505092915050565b615b0f8261504a565b615b22615b1b8261506b565b8354615ac5565b8255505050565b5f5f83356001602003843603038112615b4557615b4461473f565b5b80840192508235915067ffffffffffffffff821115615b6757615b66614743565b5b602083019250600182023603831315615b8357615b82614747565b5b509250929050565b5f82905092915050565b615b9f8383615b8b565b67ffffffffffffffff811115615bb857615bb7614f9f565b5b615bc28254614462565b615bcd8282856150da565b5f601f831160018114615bfa575f8415615be8578287013590505b615bf28582615148565b865550615c59565b601f198416615c0886614fcc565b5f5b82811015615c2f57848901358255600182019150602085019450602081019050615c0a565b86831015615c4c5784890135615c48601f89168261512c565b8355505b6001600288020188555050505b50505050505050565b615c6d838383615b95565b505050565b5f81015f830180615c8281615ab0565b9050615c8e8184615b06565b5050506001810160208301615ca38185615b29565b615cae818386615c62565b505050505050565b615cc08282615c72565b5050565b615cce8383615aa6565b615cd88183615a70565b615ce1836149b3565b615cea836157c2565b5f5b83811015615d2057615cfe838761573a565b615d088184615cb6565b60208401935060028301925050600181019050615cec565b50505050505050565b615d34838383615cc4565b505050565b5f81015f830180615d4981615681565b9050615d558184615717565b5050506001810160208301615d6a8185614772565b615d75818386615d29565b505050506002810160408301615d8b8185615b29565b615d96818386615c62565b505050505050565b615da88282615d39565b5050565b7f616e6f74686572206d61696e74656e616e636520696e2070726f6772657373005f82015250565b5f615de0601f83614145565b9150615deb82615dac565b602082019050919050565b5f6020820190508181035f830152615e0d81615dd4565b9050919050565b7f696e76616c6964206964000000000000000000000000000000000000000000005f82015250565b5f615e48600a83614145565b9150615e5382615e14565b602082019050919050565b5f6020820190508181035f830152615e7581615e3c565b9050919050565b7f6e6f646520646f65736e277420657869737400000000000000000000000000005f82015250565b5f615eb0601283614145565b9150615ebb82615e7c565b602082019050919050565b5f6020820190508181035f830152615edd81615ea4565b905091905056fea26469706673582212205ec0504f700c355842dfb4a4d399a8e48b0ca02d4766027c3ae5b1d4f339375864736f6c634300081c0033 + ///0x608060405234801561000f575f5ffd5b50604051613d0f380380613d0f833981810160405281019061003191906103bd565b335f5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550816102075f820151815f015f6101000a81548161ffff021916908361ffff1602179055509050505f5f90505b8151811015610139578181815181106100b8576100b7610417565b5b602002602001015160025f600281106100d4576100d3610417565b5b61010202015f018261010081106100ee576100ed610417565b5b015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808060010191505061009c565b5061014a815161017260201b60201c565b60025f6002811061015e5761015d610417565b5b6101020201610100018190555050506104ad565b5f60018260ff166001901b610187919061047a565b9050919050565b5f604051905090565b5f5ffd5b5f5ffd5b5f5ffd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6101e9826101a3565b810181811067ffffffffffffffff82111715610208576102076101b3565b5b80604052505050565b5f61021a61018e565b905061022682826101e0565b919050565b5f61ffff82169050919050565b6102418161022b565b811461024b575f5ffd5b50565b5f8151905061025c81610238565b92915050565b5f602082840312156102775761027661019f565b5b6102816020610211565b90505f6102908482850161024e565b5f8301525092915050565b5f5ffd5b5f67ffffffffffffffff8211156102b9576102b86101b3565b5b602082029050602081019050919050565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6102f7826102ce565b9050919050565b610307816102ed565b8114610311575f5ffd5b50565b5f81519050610322816102fe565b92915050565b5f61033a6103358461029f565b610211565b9050808382526020820190506020840283018581111561035d5761035c6102ca565b5b835b8181101561038657806103728882610314565b84526020840193505060208101905061035f565b5050509392505050565b5f82601f8301126103a4576103a361029b565b5b81516103b4848260208601610328565b91505092915050565b5f5f604083850312156103d3576103d2610197565b5b5f6103e085828601610262565b925050602083015167ffffffffffffffff8111156104015761040061019b565b5b61040d85828601610390565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f819050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61048482610444565b915061048f83610444565b92508282039050818111156104a7576104a661044d565b5b92915050565b613855806104ba5f395ff3fe608060405234801561000f575f5ffd5b50600436106100a7575f3560e01c8063ad36e6d01161006f578063ad36e6d014610127578063c130809a14610131578063cdbfc62d1461013b578063dd3fd26914610157578063f019b15414610173578063f2fde38b1461018f576100a7565b80633048bfba146100ab57806355a47d0a146100b557806365706f9c146100d157806375418b9d146100ed5780638b5252d61461010b575b5f5ffd5b6100b36101ab565b005b6100cf60048036038101906100ca919061251f565b61037f565b005b6100eb60048036038101906100e6919061257f565b6106bd565b005b6100f5610761565b60405161010291906128bc565b60405180910390f35b6101256004803603810190610120919061293d565b610f8f565b005b61012f610fec565b005b6101396111c6565b005b610155600480360381019061015091906129a6565b6113c9565b005b610171600480360381019061016c91906129ed565b611a99565b005b61018d60048036038101906101889190612a18565b611d15565b005b6101a960048036038101906101a49190612a9f565b6120ab565b005b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610239576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161023090612b24565b60405180910390fd5b61024161217b565b610280576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161027790612b8c565b60405180910390fd5b5f61020a5f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff16809291906102f190612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507f8fb9cd054d0a022110cced239e908b834e4cd219511856d4eaae3051d932d60461020b5f9054906101000a90046fffffffffffffffffffffffffffffffff166040516103759190612c1d565b60405180910390a1565b6103876121d5565b6103c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103bd90612c80565b60405180910390fd5b6102085f015f9054906101000a900467ffffffffffffffff1667ffffffffffffffff168267ffffffffffffffff1614610434576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042b90612ce8565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff166002806102065f9054906101000a900467ffffffffffffffff1661046f9190612d33565b67ffffffffffffffff166002811061048a57610489612d63565b5b61010202015f018260ff1661010081106104a7576104a6612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461051e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161051590612dda565b60405180910390fd5b61053781610208600101546121e590919063ffffffff16565b6106b95761055481610208600101546121fa90919063ffffffff16565b6102086001018190555061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff168092919061058c90612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550505f6102086001015403610646577f01269879535f40ee8957e15e160bf1866c5e2728ff0cbc583d848821e2639b4e6102085f015f9054906101000a900467ffffffffffffffff163361020b5f9054906101000a90046fffffffffffffffffffffffffffffffff1660405161063993929190612e16565b60405180910390a16106b8565b7faf5e90e72015f43138f66b4cd08bd1dfa2839030104f22a00af843fe847c6d196102085f015f9054906101000a900467ffffffffffffffff163361020b5f9054906101000a90046fffffffffffffffffffffffffffffffff166040516106af93929190612e16565b60405180910390a15b5b5050565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461074b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161074290612b24565b60405180910390fd5b80610207818161075b9190612f2a565b90505050565b6107696123a7565b6107716123a7565b5f5f5f61077c6121d5565b15610bb9576102085f015f9054906101000a900467ffffffffffffffff1684606001515f019067ffffffffffffffff16908167ffffffffffffffff16815250506102086001015484606001516020018181525050600260016102065f9054906101000a900467ffffffffffffffff166107f59190612f38565b6107ff9190612d33565b67ffffffffffffffff1692505f60026102065f9054906101000a900467ffffffffffffffff1661082f9190612d33565b67ffffffffffffffff1690506108616002826002811061085257610851612d63565b5b6101020201610100015461220e565b91506001826108709190612f73565b67ffffffffffffffff81111561088957610888612fa6565b5b6040519080825280602002602001820160405280156108c257816020015b6108af61240f565b8152602001906001900390816108a75790505b5085602001515f0181905250600281600281106108e2576108e1612d63565b5b6101020201610101015f9054906101000a900460ff1685602001516020019060ff16908160ff16815250505f5f90505b828111610bb257610949816002846002811061093157610930612d63565b5b610102020161010001546121e590919063ffffffff16565b610b9f576002826002811061096157610960612d63565b5b61010202015f0181610100811061097b5761097a612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1693508386602001515f015182815181106109b9576109b8612d63565b5b60200260200101515f019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050610a268160028760028110610a0e57610a0d612d63565b5b610102020161010001546121e590919063ffffffff16565b80610aab57508373ffffffffffffffffffffffffffffffffffffffff1660028660028110610a5757610a56612d63565b5b61010202015f01826101008110610a7157610a70612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b15610b9e5760015f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f208054610af890613000565b80601f0160208091040260200160405190810160405280929190818152602001828054610b2490613000565b8015610b6f5780601f10610b4657610100808354040283529160200191610b6f565b820191905f5260205f20905b815481529060010190602001808311610b5257829003601f168201915b505050505086602001515f01518281518110610b8e57610b8d612d63565b5b6020026020010151602001819052505b5b8080610baa90613030565b915050610912565b5050610be9565b60026102065f9054906101000a900467ffffffffffffffff16610bdc9190612d33565b67ffffffffffffffff1692505b610c0f60028460028110610c0057610bff612d63565b5b6101020201610100015461220e565b9050600181610c1e9190612f73565b67ffffffffffffffff811115610c3757610c36612fa6565b5b604051908082528060200260200182016040528015610c7057816020015b610c5d61240f565b815260200190600190039081610c555790505b50845f01515f018190525060028360028110610c8f57610c8e612d63565b5b6101020201610101015f9054906101000a900460ff16845f01516020019060ff16908160ff16815250505f5f90505b818111610ea157610cf58160028660028110610cdd57610cdc612d63565b5b610102020161010001546121e590919063ffffffff16565b610e8e5760028460028110610d0d57610d0c612d63565b5b61010202015f01816101008110610d2757610d26612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16925082855f01515f01518281518110610d6457610d63612d63565b5b60200260200101515f019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f208054610de990613000565b80601f0160208091040260200160405190810160405280929190818152602001828054610e1590613000565b8015610e605780601f10610e3757610100808354040283529160200191610e60565b820191905f5260205f20905b815481529060010190602001808311610e4357829003601f168201915b5050505050855f01515f01518281518110610e7e57610e7d612d63565b5b6020026020010151602001819052505b8080610e9990613030565b915050610cbe565b506102065f9054906101000a900467ffffffffffffffff16846040019067ffffffffffffffff16908167ffffffffffffffff168152505061020a5f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684608001515f019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505061020b5f9054906101000a90046fffffffffffffffffffffffffffffffff168460a001906fffffffffffffffffffffffffffffffff1690816fffffffffffffffffffffffffffffffff16815250508394505050505090565b610f9b8282905061221f565b818160015f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f209182610fe7929190613218565b505050565b610ff461217b565b611033576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161102a90612b8c565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff1661020a5f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146110c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110bc90612dda565b60405180910390fd5b5f61020a5f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff168092919061113690612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507ff91067eb420c28d3124865fc996e6aa9d541b9b4fef9188cb965a6cc6491638e3361020b5f9054906101000a90046fffffffffffffffffffffffffffffffff166040516111bc9291906132e5565b60405180910390a1565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611254576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161124b90612b24565b60405180910390fd5b61125c6121d5565b61129b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161129290612c80565b60405180910390fd5b6102065f81819054906101000a900467ffffffffffffffff16809291906112c19061330c565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550505f6102086001018190555061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff168092919061132190612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507ff73240422246f63ed633ef3ce0726b8ab8fb69d46c8a4e5ecb0b2922668674a16102085f015f9054906101000a900467ffffffffffffffff1661020b5f9054906101000a90046fffffffffffffffffffffffffffffffff166040516113bf929190613333565b60405180910390a1565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611457576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161144e90612b24565b60405180910390fd5b61145f6121d5565b1561149f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611496906133a4565b60405180910390fd5b6114a761217b565b156114e7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114de9061340c565b60405180910390fd5b6102085f015f81819054906101000a900467ffffffffffffffff168092919061150f9061342a565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550505f60026102065f9054906101000a900467ffffffffffffffff1661155a9190612d33565b67ffffffffffffffff1690506102065f81819054906101000a900467ffffffffffffffff168092919061158c9061342a565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550505f60026102065f9054906101000a900467ffffffffffffffff166115d79190612d33565b67ffffffffffffffff1690505f5f90505b61160e600284600281106115ff576115fe612d63565b5b6101020201610100015461220e565b81116117b2576002836002811061162857611627612d63565b5b61010202015f0181610100811061164257611641612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166002836002811061168d5761168c612d63565b5b61010202015f018261010081106116a7576116a6612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461179f57600283600281106116f7576116f6612d63565b5b61010202015f0181610100811061171157611710612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff166002836002811061174657611745612d63565b5b61010202015f018261010081106117605761175f612d63565b5b015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b80806117aa90613030565b9150506115e8565b505f600283600281106117c8576117c7612d63565b5b6101020201610100015490505f5f5f5f90505b86805f01906117ea9190613465565b90508110156119465786805f01906118029190613465565b8281811061181357611812612d63565b5b9050604002015f01602081019061182a91906129ed565b925086805f019061183b9190613465565b8281811061184c5761184b612d63565b5b90506040020160200160208101906118649190612a9f565b91505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036118b3576118ac83856121fa90919063ffffffff16565b93506118c9565b6118c683856122bd90919063ffffffff16565b93505b81600286600281106118de576118dd612d63565b5b61010202015f018460ff1661010081106118fb576118fa612d63565b5b015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080806001019150506117db565b50826002856002811061195c5761195b612d63565b5b6101020201610100018190555085602001602081019061197c91906129ed565b600285600281106119905761198f612d63565b5b6101020201610101015f6101000a81548160ff021916908360ff160217905550826102086001018190555061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff16809291906119e990612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507f78dad2bc0b47c688ed84f3fee79abc18e6c9822db05a79ca19dff54533c7470d6102085f015f9054906101000a900467ffffffffffffffff168761020b5f9054906101000a90046fffffffffffffffffffffffffffffffff16604051611a899392919061368b565b60405180910390a1505050505050565b611aa16121d5565b15611ae1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ad8906133a4565b60405180910390fd5b611ae961217b565b15611b29576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b209061340c565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff166002806102065f9054906101000a900467ffffffffffffffff16611b649190612d33565b67ffffffffffffffff1660028110611b7f57611b7e612d63565b5b61010202015f018260ff166101008110611b9c57611b9b612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611c13576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c0a90612dda565b60405180910390fd5b3361020a5f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff1680929190611c8490612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507fbc2748cf02f7a1291525e866efc76ab3b96d32d7afcbb26c53daec617b38b4793361020b5f9054906101000a90046fffffffffffffffffffffffffffffffff16604051611d0a9291906132e5565b60405180910390a150565b611d218282905061221f565b5f5f611d2b6121d5565b15611ea1573373ffffffffffffffffffffffffffffffffffffffff1660028060016102065f9054906101000a900467ffffffffffffffff16611d6d9190612f38565b611d779190612d33565b67ffffffffffffffff1660028110611d9257611d91612d63565b5b61010202015f018660ff166101008110611daf57611dae612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614915081611e9c573373ffffffffffffffffffffffffffffffffffffffff166002806102065f9054906101000a900467ffffffffffffffff16611e299190612d33565b67ffffffffffffffff1660028110611e4457611e43612d63565b5b61010202015f018660ff166101008110611e6157611e60612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161490505b611f4f565b3373ffffffffffffffffffffffffffffffffffffffff166002806102065f9054906101000a900467ffffffffffffffff16611edc9190612d33565b67ffffffffffffffff1660028110611ef757611ef6612d63565b5b61010202015f018660ff166101008110611f1457611f13612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161491505b8180611f585750805b611f97576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f8e90612dda565b60405180910390fd5b838360015f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f209182611fe3929190613218565b5061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff168092919061201290612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507f125181ec21882dec51a2392905dff3a82cbd0262f18b5c0c035488671b40afb233858561020b5f9054906101000a90046fffffffffffffffffffffffffffffffff1660405161209c9493929190613711565b60405180910390a15050505050565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612139576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161213090612b24565b60405180910390fd5b805f5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b5f5f73ffffffffffffffffffffffffffffffffffffffff1661020a5f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415905090565b5f5f610208600101541415905090565b5f5f8260ff166001901b841614905092915050565b5f8160ff166001901b198316905092915050565b5f612218826122d0565b9050919050565b5f8111612261576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161225890613799565b60405180910390fd5b6102075f015f9054906101000a900461ffff1661ffff168111156122ba576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122b190613801565b60405180910390fd5b50565b5f8160ff166001901b8317905092915050565b5f60076122ee6fffffffffffffffffffffffffffffffff841161239c565b901b9050600661230a67ffffffffffffffff8385901c1161239c565b901b81179050600561232463ffffffff8385901c1161239c565b901b81179050600461233c61ffff8385901c1161239c565b901b81179050600361235360ff8385901c1161239c565b901b81179050600261236a600f8385901c1161239c565b901b811790507d01010202020203030303030303030000000000000000000000000000000082821c1a81179050919050565b5f8115159050919050565b6040518060c001604052806123ba61243e565b81526020016123c761243e565b81526020015f67ffffffffffffffff1681526020016123e461245a565b81526020016123f161247c565b81526020015f6fffffffffffffffffffffffffffffffff1681525090565b60405180604001604052805f73ffffffffffffffffffffffffffffffffffffffff168152602001606081525090565b6040518060400160405280606081526020015f60ff1681525090565b60405180604001604052805f67ffffffffffffffff1681526020015f81525090565b60405180602001604052805f73ffffffffffffffffffffffffffffffffffffffff1681525090565b5f5ffd5b5f5ffd5b5f67ffffffffffffffff82169050919050565b6124c8816124ac565b81146124d2575f5ffd5b50565b5f813590506124e3816124bf565b92915050565b5f60ff82169050919050565b6124fe816124e9565b8114612508575f5ffd5b50565b5f81359050612519816124f5565b92915050565b5f5f60408385031215612535576125346124a4565b5b5f612542858286016124d5565b92505060206125538582860161250b565b9150509250929050565b5f5ffd5b5f602082840312156125765761257561255d565b5b81905092915050565b5f60208284031215612594576125936124a4565b5b5f6125a184828501612561565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6125fc826125d3565b9050919050565b61260c816125f2565b82525050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61265482612612565b61265e818561261c565b935061266e81856020860161262c565b6126778161263a565b840191505092915050565b5f604083015f8301516126975f860182612603565b50602083015184820360208601526126af828261264a565b9150508091505092915050565b5f6126c78383612682565b905092915050565b5f602082019050919050565b5f6126e5826125aa565b6126ef81856125b4565b935083602082028501612701856125c4565b805f5b8581101561273c578484038952815161271d85826126bc565b9450612728836126cf565b925060208a01995050600181019050612704565b50829750879550505050505092915050565b612757816124e9565b82525050565b5f604083015f8301518482035f86015261277782826126db565b915050602083015161278c602086018261274e565b508091505092915050565b6127a0816124ac565b82525050565b5f819050919050565b6127b8816127a6565b82525050565b604082015f8201516127d25f850182612797565b5060208201516127e560208501826127af565b50505050565b602082015f8201516127ff5f850182612603565b50505050565b5f6fffffffffffffffffffffffffffffffff82169050919050565b61282981612805565b82525050565b5f60e083015f8301518482035f860152612849828261275d565b91505060208301518482036020860152612863828261275d565b91505060408301516128786040860182612797565b50606083015161288b60608601826127be565b50608083015161289e60a08601826127eb565b5060a08301516128b160c0860182612820565b508091505092915050565b5f6020820190508181035f8301526128d4818461282f565b905092915050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f83601f8401126128fd576128fc6128dc565b5b8235905067ffffffffffffffff81111561291a576129196128e0565b5b602083019150836001820283011115612936576129356128e4565b5b9250929050565b5f5f60208385031215612953576129526124a4565b5b5f83013567ffffffffffffffff8111156129705761296f6124a8565b5b61297c858286016128e8565b92509250509250929050565b5f6040828403121561299d5761299c61255d565b5b81905092915050565b5f602082840312156129bb576129ba6124a4565b5b5f82013567ffffffffffffffff8111156129d8576129d76124a8565b5b6129e484828501612988565b91505092915050565b5f60208284031215612a0257612a016124a4565b5b5f612a0f8482850161250b565b91505092915050565b5f5f5f60408486031215612a2f57612a2e6124a4565b5b5f612a3c8682870161250b565b935050602084013567ffffffffffffffff811115612a5d57612a5c6124a8565b5b612a69868287016128e8565b92509250509250925092565b612a7e816125f2565b8114612a88575f5ffd5b50565b5f81359050612a9981612a75565b92915050565b5f60208284031215612ab457612ab36124a4565b5b5f612ac184828501612a8b565b91505092915050565b5f82825260208201905092915050565b7f6e6f7420746865206f776e6572000000000000000000000000000000000000005f82015250565b5f612b0e600d83612aca565b9150612b1982612ada565b602082019050919050565b5f6020820190508181035f830152612b3b81612b02565b9050919050565b7f6e6f206d61696e74656e616e63650000000000000000000000000000000000005f82015250565b5f612b76600e83612aca565b9150612b8182612b42565b602082019050919050565b5f6020820190508181035f830152612ba381612b6a565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f612be182612805565b91506fffffffffffffffffffffffffffffffff8203612c0357612c02612baa565b5b600182019050919050565b612c1781612805565b82525050565b5f602082019050612c305f830184612c0e565b92915050565b7f6e6f206d6967726174696f6e00000000000000000000000000000000000000005f82015250565b5f612c6a600c83612aca565b9150612c7582612c36565b602082019050919050565b5f6020820190508181035f830152612c9781612c5e565b9050919050565b7f77726f6e67206d6967726174696f6e20696400000000000000000000000000005f82015250565b5f612cd2601283612aca565b9150612cdd82612c9e565b602082019050919050565b5f6020820190508181035f830152612cff81612cc6565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f612d3d826124ac565b9150612d48836124ac565b925082612d5857612d57612d06565b5b828206905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f77726f6e67206f70657261746f720000000000000000000000000000000000005f82015250565b5f612dc4600e83612aca565b9150612dcf82612d90565b602082019050919050565b5f6020820190508181035f830152612df181612db8565b9050919050565b612e01816124ac565b82525050565b612e10816125f2565b82525050565b5f606082019050612e295f830186612df8565b612e366020830185612e07565b612e436040830184612c0e565b949350505050565b5f61ffff82169050919050565b612e6181612e4b565b8114612e6b575f5ffd5b50565b5f8135612e7a81612e58565b80915050919050565b5f815f1b9050919050565b5f61ffff612e9b84612e83565b9350801983169250808416831791505092915050565b5f819050919050565b5f612ed4612ecf612eca84612e4b565b612eb1565b612e4b565b9050919050565b5f819050919050565b612eed82612eba565b612f00612ef982612edb565b8354612e8e565b8255505050565b5f81015f830180612f1781612e6e565b9050612f238184612ee4565b5050505050565b612f348282612f07565b5050565b5f612f42826124ac565b9150612f4d836124ac565b9250828203905067ffffffffffffffff811115612f6d57612f6c612baa565b5b92915050565b5f612f7d826127a6565b9150612f88836127a6565b9250828201905080821115612fa057612f9f612baa565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061301757607f821691505b60208210810361302a57613029612fd3565b5b50919050565b5f61303a826127a6565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361306c5761306b612baa565b5b600182019050919050565b5f82905092915050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026130dd7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826130a2565b6130e786836130a2565b95508019841693508086168417925050509392505050565b5f61311961311461310f846127a6565b612eb1565b6127a6565b9050919050565b5f819050919050565b613132836130ff565b61314661313e82613120565b8484546130ae565b825550505050565b5f5f905090565b61315d61314e565b613168818484613129565b505050565b5b8181101561318b576131805f82613155565b60018101905061316e565b5050565b601f8211156131d0576131a181613081565b6131aa84613093565b810160208510156131b9578190505b6131cd6131c585613093565b83018261316d565b50505b505050565b5f82821c905092915050565b5f6131f05f19846008026131d5565b1980831691505092915050565b5f61320883836131e1565b9150826002028217905092915050565b6132228383613077565b67ffffffffffffffff81111561323b5761323a612fa6565b5b6132458254613000565b61325082828561318f565b5f601f83116001811461327d575f841561326b578287013590505b61327585826131fd565b8655506132dc565b601f19841661328b86613081565b5f5b828110156132b25784890135825560018201915060208501945060208101905061328d565b868310156132cf57848901356132cb601f8916826131e1565b8355505b6001600288020188555050505b50505050505050565b5f6040820190506132f85f830185612e07565b6133056020830184612c0e565b9392505050565b5f613316826124ac565b91505f820361332857613327612baa565b5b600182039050919050565b5f6040820190506133465f830185612df8565b6133536020830184612c0e565b9392505050565b7f6d6967726174696f6e20696e2070726f677265737300000000000000000000005f82015250565b5f61338e601583612aca565b91506133998261335a565b602082019050919050565b5f6020820190508181035f8301526133bb81613382565b9050919050565b7f6d61696e74656e616e636520696e2070726f67726573730000000000000000005f82015250565b5f6133f6601783612aca565b9150613401826133c2565b602082019050919050565b5f6020820190508181035f830152613423816133ea565b9050919050565b5f613434826124ac565b915067ffffffffffffffff820361344e5761344d612baa565b5b600182019050919050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f8335600160200384360303811261348157613480613459565b5b80840192508235915067ffffffffffffffff8211156134a3576134a261345d565b5b6020830192506040820236038313156134bf576134be613461565b5b509250929050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f833560016020038436030381126134ef576134ee6134cf565b5b83810192508235915060208301925067ffffffffffffffff821115613517576135166134c7565b5b60408202360383131561352d5761352c6134cb565b5b509250929050565b5f82825260208201905092915050565b5f819050919050565b5f61355c602084018461250b565b905092915050565b5f6135726020840184612a8b565b905092915050565b6040820161358a5f83018361354e565b6135965f85018261274e565b506135a46020830183613564565b6135b16020850182612603565b50505050565b5f6135c2838361357a565b60408301905092915050565b5f82905092915050565b5f604082019050919050565b5f6135ef8385613535565b93506135fa82613545565b805f5b858110156136325761360f82846135ce565b61361988826135b7565b9750613624836135d8565b9250506001810190506135fd565b5085925050509392505050565b5f604083016136505f8401846134d3565b8583035f8701526136628382846135e4565b92505050613673602084018461354e565b613680602086018261274e565b508091505092915050565b5f60608201905061369e5f830186612df8565b81810360208301526136b0818561363f565b90506136bf6040830184612c0e565b949350505050565b5f82825260208201905092915050565b828183375f83830152505050565b5f6136f083856136c7565b93506136fd8385846136d7565b6137068361263a565b840190509392505050565b5f6060820190506137245f830187612e07565b81810360208301526137378185876136e5565b90506137466040830184612c0e565b95945050505050565b7f656d707479206f70657261746f722064617461000000000000000000000000005f82015250565b5f613783601383612aca565b915061378e8261374f565b602082019050919050565b5f6020820190508181035f8301526137b081613777565b9050919050565b7f6f70657261746f72206461746120746f6f206c617267650000000000000000005f82015250565b5f6137eb601783612aca565b91506137f6826137b7565b602082019050919050565b5f6020820190508181035f830152613818816137df565b905091905056fea26469706673582212205070bfb78cba4fb204ce3a9ae24b5f710c62732176365ee8389cdab18c3c2d7164736f6c634300081c0033 /// ``` #[rustfmt::skip] #[allow(clippy::all)] pub static BYTECODE: alloy_sol_types::private::Bytes = alloy_sol_types::private::Bytes::from_static( - b"`\x80`@R4\x80\x15a\0\x0FW__\xFD[P`@Qat\x118\x03\x80at\x11\x839\x81\x81\x01`@R\x81\x01\x90a\x001\x91\x90a\x0E\x18V[3__a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UP\x81`\x01_\x82\x01Q\x81_\x01_a\x01\0\n\x81T\x81`\xFF\x02\x19\x16\x90\x83`\xFF\x16\x02\x17\x90UP` \x82\x01Q\x81_\x01`\x01a\x01\0\n\x81T\x81`\xFF\x02\x19\x16\x90\x83`\xFF\x16\x02\x17\x90UP\x90PPa\0\xC4\x81Qa\x01C` \x1B` \x1CV[__\x90P[\x81Q\x81\x10\x15a\x01;Wa\x01\0\x82\x82\x81Q\x81\x10a\0\xE8Wa\0\xE7a\x0ErV[[` \x02` \x01\x01Q` \x01QQa\x01\xE1` \x1B` \x1CV[a\x01.\x82\x82\x81Q\x81\x10a\x01\x16Wa\x01\x15a\x0ErV[[` \x02` \x01\x01Q`\x02a\x02\x80` \x1B\x90\x91\x90` \x1CV[\x80\x80`\x01\x01\x91PPa\0\xC9V[PPPa\x14\xEAV[`\x01_\x01_\x90T\x90a\x01\0\n\x90\x04`\xFF\x16`\xFF\x16\x81\x10\x15a\x01\x99W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x01\x90\x90a\x0E\xF9V[`@Q\x80\x91\x03\x90\xFD[a\x01\0\x81\x11\x15a\x01\xDEW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x01\xD5\x90a\x0FaV[`@Q\x80\x91\x03\x90\xFD[PV[`\x01_\x01`\x01\x90T\x90a\x01\0\n\x90\x04`\xFF\x16`\xFF\x16\x81\x10\x15a\x028W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x02/\x90a\x0F\xC9V[`@Q\x80\x91\x03\x90\xFD[a\x01\0\x81\x11\x15a\x02}W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x02t\x90a\x101V[`@Q\x80\x91\x03\x90\xFD[PV[a\x02\x93\x82\x82_\x01Qa\x05\x13` \x1B` \x1CV[\x15a\x02\xD3W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x02\xCA\x90a\x10\x99V[`@Q\x80\x91\x03\x90\xFD[__\x83`\x02\x01\x80T\x90P\x11\x15a\x03mW\x82`\x02\x01`\x01\x84`\x02\x01\x80T\x90Pa\x02\xFB\x91\x90a\x10\xE4V[\x81T\x81\x10a\x03\x0CWa\x03\x0Ba\x0ErV[[\x90_R` _ \x90` \x91\x82\x82\x04\x01\x91\x90\x06\x90T\x90a\x01\0\n\x90\x04`\xFF\x16\x90P\x82`\x02\x01\x80T\x80a\x03@Wa\x03?a\x11\x17V[[`\x01\x90\x03\x81\x81\x90_R` _ \x90` \x91\x82\x82\x04\x01\x91\x90\x06a\x01\0\n\x81T\x90`\xFF\x02\x19\x16\x90U\x90Ua\x03\xDEV[a\x01\0\x83_\x01\x80T\x90P\x10a\x03\xB7W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x03\xAE\x90a\x0FaV[`@Q\x80\x91\x03\x90\xFD[\x82_\x01\x80T\x90P\x90P\x82_\x01`\x01\x81`\x01\x81T\x01\x80\x82U\x80\x91PP\x03\x90_R` _ \x90PP[\x80\x83`\x01\x01_\x84_\x01Qs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ _a\x01\0\n\x81T\x81`\xFF\x02\x19\x16\x90\x83`\xFF\x16\x02\x17\x90UP_\x83_\x01\x82`\xFF\x16\x81T\x81\x10a\x04QWa\x04Pa\x0ErV[[\x90_R` _ \x90`\x05\x02\x01\x90P\x82_\x01Q\x81_\x01_a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UP\x82`@\x01Q\x81`\x04\x01\x90\x81a\x04\xB8\x91\x90a\x13KV[P__\x90P[\x83` \x01QQ\x81\x10\x15a\x05\x0CWa\x04\xFF\x84` \x01Q\x82\x81Q\x81\x10a\x04\xE5Wa\x04\xE4a\x0ErV[[` \x02` \x01\x01Q\x83`\x01\x01a\x06k` \x1B\x90\x91\x90` \x1CV[\x80\x80`\x01\x01\x91PPa\x04\xBEV[PPPPPV[__s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x82s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x03a\x05\x82W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x05y\x90a\x14dV[`@Q\x80\x91\x03\x90\xFD[_\x83_\x01\x80T\x90P\x11\x15a\x06aW_\x83`\x01\x01_\x84s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ _\x90T\x90a\x01\0\n\x90\x04`\xFF\x16`\xFF\x16\x14\x15\x80a\x06ZWP\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x83_\x01_\x81T\x81\x10a\x06\x14Wa\x06\x13a\x0ErV[[\x90_R` _ \x90`\x05\x02\x01_\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14[\x90Pa\x06eV[_\x90P[\x92\x91PPV[_\x81_\x01Q\x03a\x06\xB0W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x06\xA7\x90a\x14\xCCV[`@Q\x80\x91\x03\x90\xFD[__\x83_\x01\x80T\x90P\x11\x15a\x07mW\x82`\x01\x01_\x83_\x01Q\x81R` \x01\x90\x81R` \x01_ _\x90T\x90a\x01\0\n\x90\x04`\xFF\x16\x90P_\x81`\xFF\x16\x14\x15\x80a\x07\x1BWP\x81_\x01Q\x83_\x01_\x81T\x81\x10a\x07\nWa\x07\ta\x0ErV[[\x90_R` _ \x90`\x02\x02\x01_\x01T\x14[\x15a\x07lW\x81\x83_\x01\x82`\xFF\x16\x81T\x81\x10a\x079Wa\x078a\x0ErV[[\x90_R` _ \x90`\x02\x02\x01_\x82\x01Q\x81_\x01U` \x82\x01Q\x81`\x01\x01\x90\x81a\x07b\x91\x90a\x13KV[P\x90PPPa\x08\xEDV[[_\x83`\x02\x01\x80T\x90P\x11\x15a\x08\x06W\x82`\x02\x01`\x01\x84`\x02\x01\x80T\x90Pa\x07\x94\x91\x90a\x10\xE4V[\x81T\x81\x10a\x07\xA5Wa\x07\xA4a\x0ErV[[\x90_R` _ \x90` \x91\x82\x82\x04\x01\x91\x90\x06\x90T\x90a\x01\0\n\x90\x04`\xFF\x16\x90P\x82`\x02\x01\x80T\x80a\x07\xD9Wa\x07\xD8a\x11\x17V[[`\x01\x90\x03\x81\x81\x90_R` _ \x90` \x91\x82\x82\x04\x01\x91\x90\x06a\x01\0\n\x81T\x90`\xFF\x02\x19\x16\x90U\x90Ua\x08wV[a\x01\0\x83_\x01\x80T\x90P\x10a\x08PW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x08G\x90a\x101V[`@Q\x80\x91\x03\x90\xFD[\x82_\x01\x80T\x90P\x90P\x82_\x01`\x01\x81`\x01\x81T\x01\x80\x82U\x80\x91PP\x03\x90_R` _ \x90PP[\x80\x83`\x01\x01_\x84_\x01Q\x81R` \x01\x90\x81R` \x01_ _a\x01\0\n\x81T\x81`\xFF\x02\x19\x16\x90\x83`\xFF\x16\x02\x17\x90UP\x81\x83_\x01\x82`\xFF\x16\x81T\x81\x10a\x08\xBEWa\x08\xBDa\x0ErV[[\x90_R` _ \x90`\x02\x02\x01_\x82\x01Q\x81_\x01U` \x82\x01Q\x81`\x01\x01\x90\x81a\x08\xE7\x91\x90a\x13KV[P\x90PPP[PPV[_`@Q\x90P\x90V[__\xFD[__\xFD[__\xFD[_`\x1F\x19`\x1F\x83\x01\x16\x90P\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`A`\x04R`$_\xFD[a\tL\x82a\t\x06V[\x81\x01\x81\x81\x10g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x17\x15a\tkWa\tja\t\x16V[[\x80`@RPPPV[_a\t}a\x08\xF1V[\x90Pa\t\x89\x82\x82a\tCV[\x91\x90PV[__\xFD[_`\xFF\x82\x16\x90P\x91\x90PV[a\t\xA7\x81a\t\x92V[\x81\x14a\t\xB1W__\xFD[PV[_\x81Q\x90Pa\t\xC2\x81a\t\x9EV[\x92\x91PPV[_`@\x82\x84\x03\x12\x15a\t\xDDWa\t\xDCa\t\x02V[[a\t\xE7`@a\ttV[\x90P_a\t\xF6\x84\x82\x85\x01a\t\xB4V[_\x83\x01RP` a\n\t\x84\x82\x85\x01a\t\xB4V[` \x83\x01RP\x92\x91PPV[__\xFD[_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15a\n3Wa\n2a\t\x16V[[` \x82\x02\x90P` \x81\x01\x90P\x91\x90PV[__\xFD[_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[_a\nq\x82a\nHV[\x90P\x91\x90PV[a\n\x81\x81a\ngV[\x81\x14a\n\x8BW__\xFD[PV[_\x81Q\x90Pa\n\x9C\x81a\nxV[\x92\x91PPV[_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15a\n\xBCWa\n\xBBa\t\x16V[[` \x82\x02\x90P` \x81\x01\x90P\x91\x90PV[_\x81\x90P\x91\x90PV[a\n\xDF\x81a\n\xCDV[\x81\x14a\n\xE9W__\xFD[PV[_\x81Q\x90Pa\n\xFA\x81a\n\xD6V[\x92\x91PPV[__\xFD[_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15a\x0B\x1EWa\x0B\x1Da\t\x16V[[a\x0B'\x82a\t\x06V[\x90P` \x81\x01\x90P\x91\x90PV[\x82\x81\x83^_\x83\x83\x01RPPPV[_a\x0BTa\x0BO\x84a\x0B\x04V[a\ttV[\x90P\x82\x81R` \x81\x01\x84\x84\x84\x01\x11\x15a\x0BpWa\x0Boa\x0B\0V[[a\x0B{\x84\x82\x85a\x0B4V[P\x93\x92PPPV[_\x82`\x1F\x83\x01\x12a\x0B\x97Wa\x0B\x96a\n\x15V[[\x81Qa\x0B\xA7\x84\x82` \x86\x01a\x0BBV[\x91PP\x92\x91PPV[_`@\x82\x84\x03\x12\x15a\x0B\xC5Wa\x0B\xC4a\t\x02V[[a\x0B\xCF`@a\ttV[\x90P_a\x0B\xDE\x84\x82\x85\x01a\n\xECV[_\x83\x01RP` \x82\x01Qg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x0C\x01Wa\x0C\0a\t\x8EV[[a\x0C\r\x84\x82\x85\x01a\x0B\x83V[` \x83\x01RP\x92\x91PPV[_a\x0C+a\x0C&\x84a\n\xA2V[a\ttV[\x90P\x80\x83\x82R` \x82\x01\x90P` \x84\x02\x83\x01\x85\x81\x11\x15a\x0CNWa\x0CMa\nDV[[\x83[\x81\x81\x10\x15a\x0C\x95W\x80Qg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x0CsWa\x0Cra\n\x15V[[\x80\x86\x01a\x0C\x80\x89\x82a\x0B\xB0V[\x85R` \x85\x01\x94PPP` \x81\x01\x90Pa\x0CPV[PPP\x93\x92PPPV[_\x82`\x1F\x83\x01\x12a\x0C\xB3Wa\x0C\xB2a\n\x15V[[\x81Qa\x0C\xC3\x84\x82` \x86\x01a\x0C\x19V[\x91PP\x92\x91PPV[_``\x82\x84\x03\x12\x15a\x0C\xE1Wa\x0C\xE0a\t\x02V[[a\x0C\xEB``a\ttV[\x90P_a\x0C\xFA\x84\x82\x85\x01a\n\x8EV[_\x83\x01RP` \x82\x01Qg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\r\x1DWa\r\x1Ca\t\x8EV[[a\r)\x84\x82\x85\x01a\x0C\x9FV[` \x83\x01RP`@\x82\x01Qg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\rMWa\rLa\t\x8EV[[a\rY\x84\x82\x85\x01a\x0B\x83V[`@\x83\x01RP\x92\x91PPV[_a\rwa\rr\x84a\n\x19V[a\ttV[\x90P\x80\x83\x82R` \x82\x01\x90P` \x84\x02\x83\x01\x85\x81\x11\x15a\r\x9AWa\r\x99a\nDV[[\x83[\x81\x81\x10\x15a\r\xE1W\x80Qg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\r\xBFWa\r\xBEa\n\x15V[[\x80\x86\x01a\r\xCC\x89\x82a\x0C\xCCV[\x85R` \x85\x01\x94PPP` \x81\x01\x90Pa\r\x9CV[PPP\x93\x92PPPV[_\x82`\x1F\x83\x01\x12a\r\xFFWa\r\xFEa\n\x15V[[\x81Qa\x0E\x0F\x84\x82` \x86\x01a\reV[\x91PP\x92\x91PPV[__``\x83\x85\x03\x12\x15a\x0E.Wa\x0E-a\x08\xFAV[[_a\x0E;\x85\x82\x86\x01a\t\xC8V[\x92PP`@\x83\x01Qg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x0E\\Wa\x0E[a\x08\xFEV[[a\x0Eh\x85\x82\x86\x01a\r\xEBV[\x91PP\x92P\x92\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`2`\x04R`$_\xFD[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[\x7Ftoo few operators\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a\x0E\xE3`\x11\x83a\x0E\x9FV[\x91Pa\x0E\xEE\x82a\x0E\xAFV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra\x0F\x10\x81a\x0E\xD7V[\x90P\x91\x90PV[\x7Ftoo many operators\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a\x0FK`\x12\x83a\x0E\x9FV[\x91Pa\x0FV\x82a\x0F\x17V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra\x0Fx\x81a\x0F?V[\x90P\x91\x90PV[\x7Ftoo few nodes\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a\x0F\xB3`\r\x83a\x0E\x9FV[\x91Pa\x0F\xBE\x82a\x0F\x7FV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra\x0F\xE0\x81a\x0F\xA7V[\x90P\x91\x90PV[\x7Ftoo many nodes\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a\x10\x1B`\x0E\x83a\x0E\x9FV[\x91Pa\x10&\x82a\x0F\xE7V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra\x10H\x81a\x10\x0FV[\x90P\x91\x90PV[\x7Foperator already exists\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a\x10\x83`\x17\x83a\x0E\x9FV[\x91Pa\x10\x8E\x82a\x10OV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra\x10\xB0\x81a\x10wV[\x90P\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`\x11`\x04R`$_\xFD[_a\x10\xEE\x82a\n\xCDV[\x91Pa\x10\xF9\x83a\n\xCDV[\x92P\x82\x82\x03\x90P\x81\x81\x11\x15a\x11\x11Wa\x11\x10a\x10\xB7V[[\x92\x91PPV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`1`\x04R`$_\xFD[_\x81Q\x90P\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`\"`\x04R`$_\xFD[_`\x02\x82\x04\x90P`\x01\x82\x16\x80a\x11\x92W`\x7F\x82\x16\x91P[` \x82\x10\x81\x03a\x11\xA5Wa\x11\xA4a\x11NV[[P\x91\x90PV[_\x81\x90P\x81_R` _ \x90P\x91\x90PV[_` `\x1F\x83\x01\x04\x90P\x91\x90PV[_\x82\x82\x1B\x90P\x92\x91PPV[_`\x08\x83\x02a\x12\x07\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82a\x11\xCCV[a\x12\x11\x86\x83a\x11\xCCV[\x95P\x80\x19\x84\x16\x93P\x80\x86\x16\x84\x17\x92PPP\x93\x92PPPV[_\x81\x90P\x91\x90PV[_a\x12La\x12Ga\x12B\x84a\n\xCDV[a\x12)V[a\n\xCDV[\x90P\x91\x90PV[_\x81\x90P\x91\x90PV[a\x12e\x83a\x122V[a\x12ya\x12q\x82a\x12SV[\x84\x84Ta\x11\xD8V[\x82UPPPPV[__\x90P\x90V[a\x12\x90a\x12\x81V[a\x12\x9B\x81\x84\x84a\x12\\V[PPPV[[\x81\x81\x10\x15a\x12\xBEWa\x12\xB3_\x82a\x12\x88V[`\x01\x81\x01\x90Pa\x12\xA1V[PPV[`\x1F\x82\x11\x15a\x13\x03Wa\x12\xD4\x81a\x11\xABV[a\x12\xDD\x84a\x11\xBDV[\x81\x01` \x85\x10\x15a\x12\xECW\x81\x90P[a\x13\0a\x12\xF8\x85a\x11\xBDV[\x83\x01\x82a\x12\xA0V[PP[PPPV[_\x82\x82\x1C\x90P\x92\x91PPV[_a\x13#_\x19\x84`\x08\x02a\x13\x08V[\x19\x80\x83\x16\x91PP\x92\x91PPV[_a\x13;\x83\x83a\x13\x14V[\x91P\x82`\x02\x02\x82\x17\x90P\x92\x91PPV[a\x13T\x82a\x11DV[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x13mWa\x13la\t\x16V[[a\x13w\x82Ta\x11{V[a\x13\x82\x82\x82\x85a\x12\xC2V[_` \x90P`\x1F\x83\x11`\x01\x81\x14a\x13\xB3W_\x84\x15a\x13\xA1W\x82\x87\x01Q\x90P[a\x13\xAB\x85\x82a\x130V[\x86UPa\x14\x12V[`\x1F\x19\x84\x16a\x13\xC1\x86a\x11\xABV[_[\x82\x81\x10\x15a\x13\xE8W\x84\x89\x01Q\x82U`\x01\x82\x01\x91P` \x85\x01\x94P` \x81\x01\x90Pa\x13\xC3V[\x86\x83\x10\x15a\x14\x05W\x84\x89\x01Qa\x14\x01`\x1F\x89\x16\x82a\x13\x14V[\x83UP[`\x01`\x02\x88\x02\x01\x88UPPP[PPPPPPV[\x7Finvalid address\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a\x14N`\x0F\x83a\x0E\x9FV[\x91Pa\x14Y\x82a\x14\x1AV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra\x14{\x81a\x14BV[\x90P\x91\x90PV[\x7Finvalid id\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a\x14\xB6`\n\x83a\x0E\x9FV[\x91Pa\x14\xC1\x82a\x14\x82V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra\x14\xE3\x81a\x14\xAAV[\x90P\x91\x90PV[a_\x1A\x80a\x14\xF7_9_\xF3\xFE`\x80`@R4\x80\x15a\0\x0FW__\xFD[P`\x046\x10a\0\xA7W_5`\xE0\x1C\x80c\xAD6\xE6\xD0\x11a\0oW\x80c\xAD6\xE6\xD0\x14a\x01\x15W\x80c\xC10\x80\x9A\x14a\x01\x1FW\x80c\xCCEf*\x14a\x01)W\x80c\xF2\xFD\xE3\x8B\x14a\x01EW\x80c\xF5\xF2\xD9\xF1\x14a\x01aW\x80c\xFF\xD7@\xDF\x14a\x01kWa\0\xA7V[\x80c0H\xBF\xBA\x14a\0\xABW\x80c@\x99\0\xE8\x14a\0\xB5W\x80cH\x86\xF6,\x14a\0\xD1W\x80cl\x0Ba\xB9\x14a\0\xDBW\x80cuA\x8B\x9D\x14a\0\xF7W[__\xFD[a\0\xB3a\x01\x87V[\0[a\0\xCF`\x04\x806\x03\x81\x01\x90a\0\xCA\x91\x90a9\xE2V[a\x02\xDBV[\0[a\0\xD9a\x03~V[\0[a\0\xF5`\x04\x806\x03\x81\x01\x90a\0\xF0\x91\x90a:+V[a\x08,V[\0[a\0\xFFa\tVV[`@Qa\x01\x0C\x91\x90a?GV[`@Q\x80\x91\x03\x90\xF3[a\x01\x1Da\nXV[\0[a\x01'a\x0B}V[\0[a\x01C`\x04\x806\x03\x81\x01\x90a\x01>\x91\x90a@\x1DV[a\x0C\xD1V[\0[a\x01_`\x04\x806\x03\x81\x01\x90a\x01Z\x91\x90a@\xC5V[a\x10;V[\0[a\x01ia\x11\x0BV[\0[a\x01\x85`\x04\x806\x03\x81\x01\x90a\x01\x80\x91\x90aA\x1AV[a\x12zV[\0[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x02\x15W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x02\x0C\x90aA\x9FV[`@Q\x80\x91\x03\x90\xFD[a\x02\x1F`\ta\x14\x0EV[`\n`\x08\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x02M\x90aA\xEAV[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\x8F\xB9\xCD\x05M\n\x02!\x10\xCC\xED#\x9E\x90\x8B\x83NL\xD2\x19Q\x18V\xD4\xEA\xAE0Q\xD92\xD6\x04`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x02\xD1\x91\x90aB0V[`@Q\x80\x91\x03\x90\xA1V[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x03iW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x03`\x90aA\x9FV[`@Q\x80\x91\x03\x90\xFD[\x80`\x01\x81\x81a\x03x\x91\x90aC\xC4V[\x90PPPV[a\x03\x923`\x05a\x14\xC6\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[`\n`\x08\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x03\xC0\x90aA\xEAV[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\xA7j\x8F\xC1\xA9\x02f\xDD\xEE\x897\xA1\x8E\x12\xF0\x1E\xAD\xE9F\xB3\xB6a\x97\xFF\xF2\x89\xAF\x92w\xC2\xBD%3`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x04F\x92\x91\x90aC\xE1V[`@Q\x80\x91\x03\x90\xA1_`\x05`\x03\x01_\x90T\x90a\x01\0\n\x90\x04`\xFF\x16`\xFF\x16\x11a\x08*W__\x90P[`\x05_\x01\x80T\x90P\x81\x10\x15a\x04\xDBWa\x04\xCE`\x05_\x01\x82\x81T\x81\x10a\x04\x96Wa\x04\x95aD\x08V[[\x90_R` _ \x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02a\x15\xE4\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x80\x80`\x01\x01\x91PPa\x04nV[P__\x90P[`\x05`\x01\x01\x80T\x90P\x81\x10\x15a\x07\x18Wa\x07\x0B`\x05`\x01\x01\x82\x81T\x81\x10a\x05\x0BWa\x05\naD\x08V[[\x90_R` _ \x90`\x03\x02\x01`@Q\x80``\x01`@R\x90\x81_\x82\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01`\x01\x82\x01\x80T\x80` \x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01_\x90[\x82\x82\x10\x15a\x06cW\x83\x82\x90_R` _ \x90`\x02\x02\x01`@Q\x80`@\x01`@R\x90\x81_\x82\x01T\x81R` \x01`\x01\x82\x01\x80Ta\x05\xD4\x90aDbV[\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01\x82\x80Ta\x06\0\x90aDbV[\x80\x15a\x06KW\x80`\x1F\x10a\x06\"Wa\x01\0\x80\x83T\x04\x02\x83R\x91` \x01\x91a\x06KV[\x82\x01\x91\x90_R` _ \x90[\x81T\x81R\x90`\x01\x01\x90` \x01\x80\x83\x11a\x06.W\x82\x90\x03`\x1F\x16\x82\x01\x91[PPPPP\x81RPP\x81R` \x01\x90`\x01\x01\x90a\x05\x9AV[PPPP\x81R` \x01`\x02\x82\x01\x80Ta\x06{\x90aDbV[\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01\x82\x80Ta\x06\xA7\x90aDbV[\x80\x15a\x06\xF2W\x80`\x1F\x10a\x06\xC9Wa\x01\0\x80\x83T\x04\x02\x83R\x91` \x01\x91a\x06\xF2V[\x82\x01\x91\x90_R` _ \x90[\x81T\x81R\x90`\x01\x01\x90` \x01\x80\x83\x11a\x06\xD5W\x82\x90\x03`\x1F\x16\x82\x01\x91[PPPPP\x81RPP`\x02a\x18v\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x80\x80`\x01\x01\x91PPa\x04\xE1V[P`\n_\x81\x81\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x07>\x90aD\x92V[\x91\x90a\x01\0\n\x81T\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPPa\x07o`\x05a\x1B\x03V[`\n`\x08\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x07\x9D\x90aA\xEAV[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\x11\xCEP\x16\x0Ef\x10\x057\xFDK\n\xE2m\xE6mQ\xDA\xB7\x13\xAD\x9213S\xA1\x8C$\xE8\xF6\xDA\xAB`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x08!\x91\x90aB0V[`@Q\x80\x91\x03\x90\xA1[V[a\x08@3`\x02a\x1B\xAC\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x08\x7FW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x08v\x90aE\x0BV[`@Q\x80\x91\x03\x90\xFD[a\x08\x953\x82`\x02a\x1D\x04\x90\x92\x91\x90c\xFF\xFF\xFF\xFF\x16V[`\n`\x08\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x08\xC3\x90aA\xEAV[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7Fj\xDF\xB8\x96\xD3@v\x81\xD0_\xB8t\xD4\xDF\xB7\x06\x8En*6\xF0\x9A\xCD8\xA3\xB7\xD0L\x01t_\xEE3\x82`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\tK\x93\x92\x91\x90aF3V[`@Q\x80\x91\x03\x90\xA1PV[a\t^a7FV[`@Q\x80`\xA0\x01`@R\x80a\ts`\x02a\x1D\x96V[\x81R` \x01a\t\x8F`\x02_\x01`\x05a\x1F\x99\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x81R` \x01`\t`@Q\x80` \x01`@R\x90\x81_\x82\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RPP\x81R` \x01`\n_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RP\x90P\x90V[a\nl3`\x02a\x1B\xAC\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\n\xABW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\n\xA2\x90aE\x0BV[`@Q\x80\x91\x03\x90\xFD[a\n\xBF3`\ta'\0\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[`\n`\x08\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\n\xED\x90aA\xEAV[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\xF9\x10g\xEBB\x0C(\xD3\x12He\xFC\x99nj\xA9\xD5A\xB9\xB4\xFE\xF9\x18\x8C\xB9e\xA6\xCCd\x91c\x8E3`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x0Bs\x92\x91\x90aC\xE1V[`@Q\x80\x91\x03\x90\xA1V[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x0C\x0BW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x0C\x02\x90aA\x9FV[`@Q\x80\x91\x03\x90\xFD[a\x0C\x15`\x05a('V[`\n`\x08\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x0CC\x90aA\xEAV[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\x9C\xE1\x92\xAE\xA5\xFA\xF2\x15\x1B\xBC$l\xD8\x91\x8D.\xBAp/\xA2iQ\xF6\x7F+\xF7\xB3\x81~h\x9D\x98`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x0C\xC7\x91\x90aB0V[`@Q\x80\x91\x03\x90\xA1V[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\r_W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\rV\x90aA\x9FV[`@Q\x80\x91\x03\x90\xFD[a\ri`\ta({V[\x15a\r\xA9W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\r\xA0\x90aF\xB9V[`@Q\x80\x91\x03\x90\xFD[__\x90P[\x84\x84\x90P\x81\x10\x15a\x0E@Wa\r\xF4\x85\x85\x83\x81\x81\x10a\r\xCFWa\r\xCEaD\x08V[[\x90P` \x02\x01` \x81\x01\x90a\r\xE4\x91\x90a@\xC5V[`\x02a\x1B\xAC\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x0E3W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x0E*\x90aG!V[`@Q\x80\x91\x03\x90\xFD[\x80\x80`\x01\x01\x91PPa\r\xAEV[P__\x90P[\x82\x82\x90P\x81\x10\x15a\x0F%Wa\x0E\x8F\x83\x83\x83\x81\x81\x10a\x0EgWa\x0EfaD\x08V[[\x90P` \x02\x81\x01\x90a\x0Ey\x91\x90aGKV[\x80` \x01\x90a\x0E\x88\x91\x90aGrV[\x90Pa(\xD5V[a\x0E\xD8\x83\x83\x83\x81\x81\x10a\x0E\xA5Wa\x0E\xA4aD\x08V[[\x90P` \x02\x81\x01\x90a\x0E\xB7\x91\x90aGKV[_\x01` \x81\x01\x90a\x0E\xC8\x91\x90a@\xC5V[`\x02a\x1B\xAC\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x15a\x0F\x18W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x0F\x0F\x90aH\x1EV[`@Q\x80\x91\x03\x90\xFD[\x80\x80`\x01\x01\x91PPa\x0EFV[Pa\x0FT\x82\x82\x90P\x85\x85\x90Pa\x0F;`\x02a)tV[a\x0FE\x91\x90aH&\x82\x82a=\xB0V[\x91PP` \x83\x01Q\x84\x82\x03` \x86\x01Ra>@\x82\x82a<\xCAV[\x91PP`@\x83\x01Q\x84\x82\x03`@\x86\x01Ra>Z\x82\x82a=\xB0V[\x91PP\x80\x91PP\x92\x91PPV[` \x82\x01_\x82\x01Qa>{_\x85\x01\x82a:\xCBV[PPPPV[_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[a>\x9D\x81a>\x81V[\x82RPPV[_o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[a>\xC7\x81a>\xA3V[\x82RPPV[_`\xA0\x83\x01_\x83\x01Q\x84\x82\x03_\x86\x01Ra>\xE7\x82\x82a==V[\x91PP` \x83\x01Q\x84\x82\x03` \x86\x01Ra?\x01\x82\x82a>\x0CV[\x91PP`@\x83\x01Qa?\x16`@\x86\x01\x82a>gV[P``\x83\x01Qa?)``\x86\x01\x82a>\x94V[P`\x80\x83\x01Qa?<`\x80\x86\x01\x82a>\xBEV[P\x80\x91PP\x92\x91PPV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra?_\x81\x84a>\xCDV[\x90P\x92\x91PPV[__\xFD[__\xFD[__\xFD[__\x83`\x1F\x84\x01\x12a?\x88Wa?\x87a?gV[[\x825\x90Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a?\xA5Wa?\xA4a?kV[[` \x83\x01\x91P\x83` \x82\x02\x83\x01\x11\x15a?\xC1Wa?\xC0a?oV[[\x92P\x92\x90PV[__\x83`\x1F\x84\x01\x12a?\xDDWa?\xDCa?gV[[\x825\x90Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a?\xFAWa?\xF9a?kV[[` \x83\x01\x91P\x83` \x82\x02\x83\x01\x11\x15a@\x16Wa@\x15a?oV[[\x92P\x92\x90PV[____`@\x85\x87\x03\x12\x15a@5Wa@4a9\xB8V[[_\x85\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a@RWa@Qa9\xBCV[[a@^\x87\x82\x88\x01a?sV[\x94P\x94PP` \x85\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a@\x81Wa@\x80a9\xBCV[[a@\x8D\x87\x82\x88\x01a?\xC8V[\x92P\x92PP\x92\x95\x91\x94P\x92PV[a@\xA4\x81a:\xBAV[\x81\x14a@\xAEW__\xFD[PV[_\x815\x90Pa@\xBF\x81a@\x9BV[\x92\x91PPV[_` \x82\x84\x03\x12\x15a@\xDAWa@\xD9a9\xB8V[[_a@\xE7\x84\x82\x85\x01a@\xB1V[\x91PP\x92\x91PPV[a@\xF9\x81a;\x03V[\x81\x14aA\x03W__\xFD[PV[_\x815\x90PaA\x14\x81a@\xF0V[\x92\x91PPV[_` \x82\x84\x03\x12\x15aA/WaA.a9\xB8V[[_aA<\x84\x82\x85\x01aA\x06V[\x91PP\x92\x91PPV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[\x7Fnot the owner\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aA\x89`\r\x83aAEV[\x91PaA\x94\x82aAUV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaA\xB6\x81aA}V[\x90P\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`\x11`\x04R`$_\xFD[_aA\xF4\x82a>\xA3V[\x91Po\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x03aB\x16WaB\x15aA\xBDV[[`\x01\x82\x01\x90P\x91\x90PV[aB*\x81a>\xA3V[\x82RPPV[_` \x82\x01\x90PaBC_\x83\x01\x84aB!V[\x92\x91PPV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R_`\x04R`$_\xFD[_`\xFF\x82\x16\x90P\x91\x90PV[aB\x8A\x81aBuV[\x81\x14aB\x94W__\xFD[PV[_\x815aB\xA3\x81aB\x81V[\x80\x91PP\x91\x90PV[_\x81_\x1B\x90P\x91\x90PV[_`\xFFaB\xC3\x84aB\xACV[\x93P\x80\x19\x83\x16\x92P\x80\x84\x16\x83\x17\x91PP\x92\x91PPV[_\x81\x90P\x91\x90PV[_aB\xFCaB\xF7aB\xF2\x84aBuV[aB\xD9V[aBuV[\x90P\x91\x90PV[_\x81\x90P\x91\x90PV[aC\x15\x82aB\xE2V[aC(aC!\x82aC\x03V[\x83TaB\xB7V[\x82UPPPV[_\x81`\x08\x1B\x90P\x91\x90PV[_a\xFF\0aCH\x84aC/V[\x93P\x80\x19\x83\x16\x92P\x80\x84\x16\x83\x17\x91PP\x92\x91PPV[aCg\x82aB\xE2V[aCzaCs\x82aC\x03V[\x83TaC;V[\x82UPPPV[_\x81\x01_\x83\x01\x80aC\x91\x81aB\x97V[\x90PaC\x9D\x81\x84aC\x0CV[PPP_\x81\x01` \x83\x01\x80aC\xB1\x81aB\x97V[\x90PaC\xBD\x81\x84aC^V[PPPPPV[aC\xCE\x82\x82aC\x81V[PPV[aC\xDB\x81a:\xBAV[\x82RPPV[_`@\x82\x01\x90PaC\xF4_\x83\x01\x85aC\xD2V[aD\x01` \x83\x01\x84aB!V[\x93\x92PPPV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`2`\x04R`$_\xFD[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`\"`\x04R`$_\xFD[_`\x02\x82\x04\x90P`\x01\x82\x16\x80aDyW`\x7F\x82\x16\x91P[` \x82\x10\x81\x03aD\x8CWaD\x8BaD5V[[P\x91\x90PV[_aD\x9C\x82a>\x81V[\x91Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x03aD\xB6WaD\xB5aA\xBDV[[`\x01\x82\x01\x90P\x91\x90PV[\x7Fnot an operator\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aD\xF5`\x0F\x83aAEV[\x91PaE\0\x82aD\xC1V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaE\"\x81aD\xE9V[\x90P\x91\x90PV[_aE7` \x84\x01\x84aA\x06V[\x90P\x92\x91PPV[__\xFD[__\xFD[__\xFD[__\x835`\x01` \x03\x846\x03\x03\x81\x12aEgWaEfaEGV[[\x83\x81\x01\x92P\x825\x91P` \x83\x01\x92Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15aE\x8FWaE\x8EaE?V[[`\x01\x82\x026\x03\x83\x13\x15aE\xA5WaE\xA4aECV[[P\x92P\x92\x90PV[\x82\x81\x837_\x83\x83\x01RPPPV[_aE\xC6\x83\x85a;%V[\x93PaE\xD3\x83\x85\x84aE\xADV[aE\xDC\x83a;CV[\x84\x01\x90P\x93\x92PPPV[_`@\x83\x01aE\xF8_\x84\x01\x84aE)V[aF\x04_\x86\x01\x82a;\x0CV[PaF\x12` \x84\x01\x84aEKV[\x85\x83\x03` \x87\x01RaF%\x83\x82\x84aE\xBBV[\x92PPP\x80\x91PP\x92\x91PPV[_``\x82\x01\x90PaFF_\x83\x01\x86aC\xD2V[\x81\x81\x03` \x83\x01RaFX\x81\x85aE\xE7V[\x90PaFg`@\x83\x01\x84aB!V[\x94\x93PPPPV[\x7Fmaintenance in progress\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aF\xA3`\x17\x83aAEV[\x91PaF\xAE\x82aFoV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaF\xD0\x81aF\x97V[\x90P\x91\x90PV[\x7Funknown operator\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aG\x0B`\x10\x83aAEV[\x91PaG\x16\x82aF\xD7V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaG8\x81aF\xFFV[\x90P\x91\x90PV[__\xFD[__\xFD[__\xFD[_\x825`\x01``\x03\x836\x03\x03\x81\x12aGfWaGeaG?V[[\x80\x83\x01\x91PP\x92\x91PPV[__\x835`\x01` \x03\x846\x03\x03\x81\x12aG\x8EWaG\x8DaG?V[[\x80\x84\x01\x92P\x825\x91Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15aG\xB0WaG\xAFaGCV[[` \x83\x01\x92P` \x82\x026\x03\x83\x13\x15aG\xCCWaG\xCBaGGV[[P\x92P\x92\x90PV[\x7Foperator already exists\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aH\x08`\x17\x83aAEV[\x91PaH\x13\x82aG\xD4V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaH5\x81aG\xFCV[\x90P\x91\x90PV[_aHF\x82a;\x03V[\x91PaHQ\x83a;\x03V[\x92P\x82\x82\x03\x90P\x81\x81\x11\x15aHiWaHhaA\xBDV[[\x92\x91PPV[_aHy\x82a;\x03V[\x91PaH\x84\x83a;\x03V[\x92P\x82\x82\x01\x90P\x80\x82\x11\x15aH\x9CWaH\x9BaA\xBDV[[\x92\x91PPV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[_\x81\x90P\x91\x90PV[_aH\xC9` \x84\x01\x84a@\xB1V[\x90P\x92\x91PPV[_` \x82\x01\x90P\x91\x90PV[_aH\xE8\x83\x85aH\xA2V[\x93PaH\xF3\x82aH\xB2V[\x80_[\x85\x81\x10\x15aI+WaI\x08\x82\x84aH\xBBV[aI\x12\x88\x82a=\x8DV[\x97PaI\x1D\x83aH\xD1V[\x92PP`\x01\x81\x01\x90PaH\xF6V[P\x85\x92PPP\x93\x92PPPV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[_\x81\x90P\x91\x90PV[__\x835`\x01` \x03\x846\x03\x03\x81\x12aImWaIlaEGV[[\x83\x81\x01\x92P\x825\x91P` \x83\x01\x92Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15aI\x95WaI\x94aE?V[[` \x82\x026\x03\x83\x13\x15aI\xABWaI\xAAaECV[[P\x92P\x92\x90PV[_\x81\x90P\x91\x90PV[_`@\x83\x01aI\xCD_\x84\x01\x84aE)V[aI\xD9_\x86\x01\x82a;\x0CV[PaI\xE7` \x84\x01\x84aEKV[\x85\x83\x03` \x87\x01RaI\xFA\x83\x82\x84aE\xBBV[\x92PPP\x80\x91PP\x92\x91PPV[_aJ\x13\x83\x83aI\xBCV[\x90P\x92\x91PPV[_\x825`\x01`@\x03\x836\x03\x03\x81\x12aJ6WaJ5aEGV[[\x82\x81\x01\x91PP\x92\x91PPV[_` \x82\x01\x90P\x91\x90PV[_aJY\x83\x85a:\xE4V[\x93P\x83` \x84\x02\x85\x01aJk\x84aI\xB3V[\x80_[\x87\x81\x10\x15aJ\xAEW\x84\x84\x03\x89RaJ\x85\x82\x84aJ\x1BV[aJ\x8F\x85\x82aJ\x08V[\x94PaJ\x9A\x83aJBV[\x92P` \x8A\x01\x99PP`\x01\x81\x01\x90PaJnV[P\x82\x97P\x87\x94PPPPP\x93\x92PPPV[_``\x83\x01aJ\xD1_\x84\x01\x84aH\xBBV[aJ\xDD_\x86\x01\x82a:\xCBV[PaJ\xEB` \x84\x01\x84aIQV[\x85\x83\x03` \x87\x01RaJ\xFE\x83\x82\x84aJNV[\x92PPPaK\x0F`@\x84\x01\x84aEKV[\x85\x83\x03`@\x87\x01RaK\"\x83\x82\x84aE\xBBV[\x92PPP\x80\x91PP\x92\x91PPV[_aK;\x83\x83aJ\xC0V[\x90P\x92\x91PPV[_\x825`\x01``\x03\x836\x03\x03\x81\x12aK^WaK]aEGV[[\x82\x81\x01\x91PP\x92\x91PPV[_` \x82\x01\x90P\x91\x90PV[_aK\x81\x83\x85aI8V[\x93P\x83` \x84\x02\x85\x01aK\x93\x84aIHV[\x80_[\x87\x81\x10\x15aK\xD6W\x84\x84\x03\x89RaK\xAD\x82\x84aKCV[aK\xB7\x85\x82aK0V[\x94PaK\xC2\x83aKjV[\x92P` \x8A\x01\x99PP`\x01\x81\x01\x90PaK\x96V[P\x82\x97P\x87\x94PPPPP\x93\x92PPPV[_``\x82\x01\x90P\x81\x81\x03_\x83\x01RaL\x01\x81\x87\x89aH\xDDV[\x90P\x81\x81\x03` \x83\x01RaL\x16\x81\x85\x87aKvV[\x90PaL%`@\x83\x01\x84aB!V[\x96\x95PPPPPPV[\x7Fmigration in progress\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aLc`\x15\x83aAEV[\x91PaLn\x82aL/V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaL\x90\x81aLWV[\x90P\x91\x90PV[\x7Ftoo few nodes\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aL\xCB`\r\x83aAEV[\x91PaL\xD6\x82aL\x97V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaL\xF8\x81aL\xBFV[\x90P\x91\x90PV[aM\x08\x81a;\x03V[\x82RPPV[_``\x82\x01\x90PaM!_\x83\x01\x86aC\xD2V[aM.` \x83\x01\x85aL\xFFV[aM;`@\x83\x01\x84aB!V[\x94\x93PPPPV[\x7Fnot under maintenance\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aMw`\x15\x83aAEV[\x91PaM\x82\x82aMCV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaM\xA4\x81aMkV[\x90P\x91\x90PV[\x7Fnot pulling\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aM\xDF`\x0B\x83aAEV[\x91PaM\xEA\x82aM\xABV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaN\x0C\x81aM\xD3V[\x90P\x91\x90PV[_aN\x1D\x82aBuV[\x91P_\x82\x03aN/WaN.aA\xBDV[[`\x01\x82\x03\x90P\x91\x90PV[\x7Finvalid address\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aNn`\x0F\x83aAEV[\x91PaNy\x82aN:V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaN\x9B\x81aNbV[\x90P\x91\x90PV[\x7Foperator doesn't exist\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aN\xD6`\x16\x83aAEV[\x91PaN\xE1\x82aN\xA2V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaO\x03\x81aN\xCAV[\x90P\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`1`\x04R`$_\xFD[\x7Ftoo many operators\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aOk`\x12\x83aAEV[\x91PaOv\x82aO7V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaO\x98\x81aO_V[\x90P\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`A`\x04R`$_\xFD[_\x81\x90P\x81_R` _ \x90P\x91\x90PV[_` `\x1F\x83\x01\x04\x90P\x91\x90PV[_\x82\x82\x1B\x90P\x92\x91PPV[_`\x08\x83\x02aP(\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82aO\xEDV[aP2\x86\x83aO\xEDV[\x95P\x80\x19\x84\x16\x93P\x80\x86\x16\x84\x17\x92PPP\x93\x92PPPV[_aPdaP_aPZ\x84a;\x03V[aB\xD9V[a;\x03V[\x90P\x91\x90PV[_\x81\x90P\x91\x90PV[aP}\x83aPJV[aP\x91aP\x89\x82aPkV[\x84\x84TaO\xF9V[\x82UPPPPV[__\x90P\x90V[aP\xA8aP\x99V[aP\xB3\x81\x84\x84aPtV[PPPV[[\x81\x81\x10\x15aP\xD6WaP\xCB_\x82aP\xA0V[`\x01\x81\x01\x90PaP\xB9V[PPV[`\x1F\x82\x11\x15aQ\x1BWaP\xEC\x81aO\xCCV[aP\xF5\x84aO\xDEV[\x81\x01` \x85\x10\x15aQ\x04W\x81\x90P[aQ\x18aQ\x10\x85aO\xDEV[\x83\x01\x82aP\xB8V[PP[PPPV[_\x82\x82\x1C\x90P\x92\x91PPV[_aQ;_\x19\x84`\x08\x02aQ V[\x19\x80\x83\x16\x91PP\x92\x91PPV[_aQS\x83\x83aQ,V[\x91P\x82`\x02\x02\x82\x17\x90P\x92\x91PPV[aQl\x82a;\x1BV[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15aQ\x85WaQ\x84aO\x9FV[[aQ\x8F\x82TaDbV[aQ\x9A\x82\x82\x85aP\xDAV[_` \x90P`\x1F\x83\x11`\x01\x81\x14aQ\xCBW_\x84\x15aQ\xB9W\x82\x87\x01Q\x90P[aQ\xC3\x85\x82aQHV[\x86UPaR*V[`\x1F\x19\x84\x16aQ\xD9\x86aO\xCCV[_[\x82\x81\x10\x15aR\0W\x84\x89\x01Q\x82U`\x01\x82\x01\x91P` \x85\x01\x94P` \x81\x01\x90PaQ\xDBV[\x86\x83\x10\x15aR\x1DW\x84\x89\x01QaR\x19`\x1F\x89\x16\x82aQ,V[\x83UP[`\x01`\x02\x88\x02\x01\x88UPPP[PPPPPPV[\x7Fnot in progress\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aRf`\x0F\x83aAEV[\x91PaRq\x82aR2V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaR\x93\x81aRZV[\x90P\x91\x90PV[\x7Fdata pull in progress\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aR\xCE`\x15\x83aAEV[\x91PaR\xD9\x82aR\x9AV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaR\xFB\x81aR\xC2V[\x90P\x91\x90PV[__\xFD[aS\x0F\x82a;CV[\x81\x01\x81\x81\x10g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x17\x15aS.WaS-aO\x9FV[[\x80`@RPPPV[_aS@a9\xAFV[\x90PaSL\x82\x82aS\x06V[\x91\x90PV[__\xFD[__\xFD[_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15aSsWaSraO\x9FV[[aS|\x82a;CV[\x90P` \x81\x01\x90P\x91\x90PV[_aS\x9BaS\x96\x84aSYV[aS7V[\x90P\x82\x81R` \x81\x01\x84\x84\x84\x01\x11\x15aS\xB7WaS\xB6aSUV[[aS\xC2\x84\x82\x85aE\xADV[P\x93\x92PPPV[_\x82`\x1F\x83\x01\x12aS\xDEWaS\xDDa?gV[[\x815aS\xEE\x84\x82` \x86\x01aS\x89V[\x91PP\x92\x91PPV[_`@\x82\x84\x03\x12\x15aT\x0CWaT\x0BaS\x02V[[aT\x16`@aS7V[\x90P_aT%\x84\x82\x85\x01aA\x06V[_\x83\x01RP` \x82\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15aTHWaTGaSQV[[aTT\x84\x82\x85\x01aS\xCAV[` \x83\x01RP\x92\x91PPV[_aTk6\x83aS\xF7V[\x90P\x91\x90PV[_aT|\x82a;\x03V[\x91P\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x03aT\xAEWaT\xADaA\xBDV[[`\x01\x82\x01\x90P\x91\x90PV[\x7Ftoo many nodes\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aT\xED`\x0E\x83aAEV[\x91PaT\xF8\x82aT\xB9V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaU\x1A\x81aT\xE1V[\x90P\x91\x90PV[\x7Ftoo few operators\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aUU`\x11\x83aAEV[\x91PaU`\x82aU!V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaU\x82\x81aUIV[\x90P\x91\x90PV[\x7Fmigration already in progress\0\0\0_\x82\x01RPV[_aU\xBD`\x1D\x83aAEV[\x91PaU\xC8\x82aU\x89V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaU\xEA\x81aU\xB1V[\x90P\x91\x90PV[\x7Fnothing to do\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aV%`\r\x83aAEV[\x91PaV0\x82aU\xF1V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaVR\x81aV\x19V[\x90P\x91\x90PV[_aVc\x82aBuV[\x91P`\xFF\x82\x03aVvWaVuaA\xBDV[[`\x01\x82\x01\x90P\x91\x90PV[_\x815aV\x8D\x81a@\x9BV[\x80\x91PP\x91\x90PV[_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFFaV\xB5\x84aB\xACV[\x93P\x80\x19\x83\x16\x92P\x80\x84\x16\x83\x17\x91PP\x92\x91PPV[_aV\xE5aV\xE0aV\xDB\x84a:\x9BV[aB\xD9V[a:\x9BV[\x90P\x91\x90PV[_aV\xF6\x82aV\xCBV[\x90P\x91\x90PV[_aW\x07\x82aV\xECV[\x90P\x91\x90PV[_\x81\x90P\x91\x90PV[aW \x82aV\xFDV[aW3aW,\x82aW\x0EV[\x83TaV\x96V[\x82UPPPV[_\x825`\x01`@\x03\x836\x03\x03\x81\x12aWUWaWTaG?V[[\x80\x83\x01\x91PP\x92\x91PPV[_\x81T\x90P\x91\x90PV[_aWu\x82a;\x03V[\x91PaW\x80\x83a;\x03V[\x92P\x82\x82\x02aW\x8E\x81a;\x03V[\x91P\x82\x82\x04\x84\x14\x83\x15\x17aW\xA5WaW\xA4aA\xBDV[[P\x92\x91PPV[_\x81\x90PaW\xBB\x82`\x02aWkV[\x90P\x91\x90PV[_\x81\x90P\x81_R` _ \x90P\x91\x90PV[aX\x04\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x83` \x03`\x08\x02aQ V[\x81T\x81\x16\x82UPPPV[aX\x18\x81aO\xCCV[aX#\x83\x82TaQHV[\x80\x83U_\x82UPPPPV[` \x84\x10_\x81\x14aX\x89W`\x1F\x84\x11`\x01\x81\x14aXWWaXP\x86\x85aQHV[\x83UaX\x83V[aX`\x83aO\xCCV[aXwaXl\x87aO\xDEV[\x82\x01`\x01\x83\x01aP\xB8V[aX\x81\x87\x85aX\x0FV[P[PaX\xD6V[aX\x92\x82aO\xCCV[aX\x9B\x86aO\xDEV[\x81\x01`\x1F\x87\x16\x80\x15aX\xB5WaX\xB4\x81`\x01\x84\x03aW\xD4V[[aX\xC9aX\xC1\x88aO\xDEV[\x84\x01\x83aP\xB8V[`\x01\x88`\x02\x02\x17\x85UPPP[PPPPPV[h\x01\0\0\0\0\0\0\0\0\x84\x11\x15aX\xF7WaX\xF6aO\x9FV[[` \x83\x10_\x81\x14aY@W` \x85\x10_\x81\x14aY\x1EWaY\x17\x86\x85aQHV[\x83UaY:V[\x83`\xFF\x19\x16\x93P\x83aY/\x84aO\xCCV[U`\x01\x86`\x02\x02\x01\x83U[PaYJV[`\x01\x85`\x02\x02\x01\x82U[PPPPPV[\x80TaY\\\x81aDbV[\x80\x84\x11\x15aYqWaYp\x84\x82\x84\x86aX\xDDV[[\x80\x84\x10\x15aY\x86WaY\x85\x84\x82\x84\x86aX/V[[PPPPV[\x81\x81\x10\x15aY\xA9WaY\x9E_\x82aP\xA0V[`\x01\x81\x01\x90PaY\x8CV[PPV[aY\xB7_\x82aYQV[PV[_\x82\x14aY\xCAWaY\xC9aBIV[[aY\xD3\x81aY\xADV[PPV[aY\xE3__\x83\x01aP\xA0V[aY\xF0_`\x01\x83\x01aY\xBAV[PV[_\x82\x14aZ\x03WaZ\x02aBIV[[aZ\x0C\x81aY\xD7V[PPV[[\x81\x81\x10\x15aZ.WaZ#_\x82aY\xF3V[`\x02\x81\x01\x90PaZ\x11V[PPV[\x81\x83\x10\x15aZkWaZC\x82aW\xACV[aZL\x84aW\xACV[aZU\x83aW\xC2V[\x81\x81\x01\x83\x82\x01aZe\x81\x83aZ\x10V[PPPPP[PPPV[h\x01\0\0\0\0\0\0\0\0\x82\x11\x15aZ\x8AWaZ\x89aO\x9FV[[aZ\x93\x81aWaV[\x82\x82UaZ\xA1\x83\x82\x84aZ2V[PPPV[_\x82\x90P\x92\x91PPV[_\x815aZ\xBC\x81a@\xF0V[\x80\x91PP\x91\x90PV[_\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFFaZ\xF0\x84aB\xACV[\x93P\x80\x19\x83\x16\x92P\x80\x84\x16\x83\x17\x91PP\x92\x91PPV[a[\x0F\x82aPJV[a[\"a[\x1B\x82aPkV[\x83TaZ\xC5V[\x82UPPPV[__\x835`\x01` \x03\x846\x03\x03\x81\x12a[EWa[DaG?V[[\x80\x84\x01\x92P\x825\x91Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15a[gWa[faGCV[[` \x83\x01\x92P`\x01\x82\x026\x03\x83\x13\x15a[\x83Wa[\x82aGGV[[P\x92P\x92\x90PV[_\x82\x90P\x92\x91PPV[a[\x9F\x83\x83a[\x8BV[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a[\xB8Wa[\xB7aO\x9FV[[a[\xC2\x82TaDbV[a[\xCD\x82\x82\x85aP\xDAV[_`\x1F\x83\x11`\x01\x81\x14a[\xFAW_\x84\x15a[\xE8W\x82\x87\x015\x90P[a[\xF2\x85\x82aQHV[\x86UPa\\YV[`\x1F\x19\x84\x16a\\\x08\x86aO\xCCV[_[\x82\x81\x10\x15a\\/W\x84\x89\x015\x82U`\x01\x82\x01\x91P` \x85\x01\x94P` \x81\x01\x90Pa\\\nV[\x86\x83\x10\x15a\\LW\x84\x89\x015a\\H`\x1F\x89\x16\x82aQ,V[\x83UP[`\x01`\x02\x88\x02\x01\x88UPPP[PPPPPPPV[a\\m\x83\x83\x83a[\x95V[PPPV[_\x81\x01_\x83\x01\x80a\\\x82\x81aZ\xB0V[\x90Pa\\\x8E\x81\x84a[\x06V[PPP`\x01\x81\x01` \x83\x01a\\\xA3\x81\x85a[)V[a\\\xAE\x81\x83\x86a\\bV[PPPPPPV[a\\\xC0\x82\x82a\\rV[PPV[a\\\xCE\x83\x83aZ\xA6V[a\\\xD8\x81\x83aZpV[a\\\xE1\x83aI\xB3V[a\\\xEA\x83aW\xC2V[_[\x83\x81\x10\x15a] Wa\\\xFE\x83\x87aW:V[a]\x08\x81\x84a\\\xB6V[` \x84\x01\x93P`\x02\x83\x01\x92PP`\x01\x81\x01\x90Pa\\\xECV[PPPPPPPV[a]4\x83\x83\x83a\\\xC4V[PPPV[_\x81\x01_\x83\x01\x80a]I\x81aV\x81V[\x90Pa]U\x81\x84aW\x17V[PPP`\x01\x81\x01` \x83\x01a]j\x81\x85aGrV[a]u\x81\x83\x86a])V[PPPP`\x02\x81\x01`@\x83\x01a]\x8B\x81\x85a[)V[a]\x96\x81\x83\x86a\\bV[PPPPPPV[a]\xA8\x82\x82a]9V[PPV[\x7Fanother maintenance in progress\0_\x82\x01RPV[_a]\xE0`\x1F\x83aAEV[\x91Pa]\xEB\x82a]\xACV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra^\r\x81a]\xD4V[\x90P\x91\x90PV[\x7Finvalid id\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a^H`\n\x83aAEV[\x91Pa^S\x82a^\x14V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra^u\x81a^\xD63\xEF<\xE0rk\x8A\xB8\xFBi\xD4l\x8AN^\xCB\x0B)\"f\x86t\xA1a\x02\x08_\x01_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x13\xBF\x92\x91\x90a33V[`@Q\x80\x91\x03\x90\xA1V[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x14WW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x14N\x90a+$V[`@Q\x80\x91\x03\x90\xFD[a\x14_a!\xD5V[\x15a\x14\x9FW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x14\x96\x90a3\xA4V[`@Q\x80\x91\x03\x90\xFD[a\x14\xA7a!{V[\x15a\x14\xE7W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x14\xDE\x90a4\x0CV[`@Q\x80\x91\x03\x90\xFD[a\x02\x08_\x01_\x81\x81\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x15\x0F\x90a4*V[\x91\x90a\x01\0\n\x81T\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP_`\x02a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x15Z\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90Pa\x02\x06_\x81\x81\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x15\x8C\x90a4*V[\x91\x90a\x01\0\n\x81T\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP_`\x02a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x15\xD7\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90P__\x90P[a\x16\x0E`\x02\x84`\x02\x81\x10a\x15\xFFWa\x15\xFEa-cV[[a\x01\x02\x02\x01a\x01\0\x01Ta\"\x0EV[\x81\x11a\x17\xB2W`\x02\x83`\x02\x81\x10a\x16(Wa\x16'a-cV[[a\x01\x02\x02\x01_\x01\x81a\x01\0\x81\x10a\x16BWa\x16Aa-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x83`\x02\x81\x10a\x16\x8DWa\x16\x8Ca-cV[[a\x01\x02\x02\x01_\x01\x82a\x01\0\x81\x10a\x16\xA7Wa\x16\xA6a-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x17\x9FW`\x02\x83`\x02\x81\x10a\x16\xF7Wa\x16\xF6a-cV[[a\x01\x02\x02\x01_\x01\x81a\x01\0\x81\x10a\x17\x11Wa\x17\x10a-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x83`\x02\x81\x10a\x17FWa\x17Ea-cV[[a\x01\x02\x02\x01_\x01\x82a\x01\0\x81\x10a\x17`Wa\x17_a-cV[[\x01_a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UP[\x80\x80a\x17\xAA\x90a00V[\x91PPa\x15\xE8V[P_`\x02\x83`\x02\x81\x10a\x17\xC8Wa\x17\xC7a-cV[[a\x01\x02\x02\x01a\x01\0\x01T\x90P____\x90P[\x86\x80_\x01\x90a\x17\xEA\x91\x90a4eV[\x90P\x81\x10\x15a\x19FW\x86\x80_\x01\x90a\x18\x02\x91\x90a4eV[\x82\x81\x81\x10a\x18\x13Wa\x18\x12a-cV[[\x90P`@\x02\x01_\x01` \x81\x01\x90a\x18*\x91\x90a)\xEDV[\x92P\x86\x80_\x01\x90a\x18;\x91\x90a4eV[\x82\x81\x81\x10a\x18LWa\x18Ka-cV[[\x90P`@\x02\x01` \x01` \x81\x01\x90a\x18d\x91\x90a*\x9FV[\x91P_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x82s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x03a\x18\xB3Wa\x18\xAC\x83\x85a!\xFA\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x93Pa\x18\xC9V[a\x18\xC6\x83\x85a\"\xBD\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x93P[\x81`\x02\x86`\x02\x81\x10a\x18\xDEWa\x18\xDDa-cV[[a\x01\x02\x02\x01_\x01\x84`\xFF\x16a\x01\0\x81\x10a\x18\xFBWa\x18\xFAa-cV[[\x01_a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UP\x80\x80`\x01\x01\x91PPa\x17\xDBV[P\x82`\x02\x85`\x02\x81\x10a\x19\\Wa\x19[a-cV[[a\x01\x02\x02\x01a\x01\0\x01\x81\x90UP\x85` \x01` \x81\x01\x90a\x19|\x91\x90a)\xEDV[`\x02\x85`\x02\x81\x10a\x19\x90Wa\x19\x8Fa-cV[[a\x01\x02\x02\x01a\x01\x01\x01_a\x01\0\n\x81T\x81`\xFF\x02\x19\x16\x90\x83`\xFF\x16\x02\x17\x90UP\x82a\x02\x08`\x01\x01\x81\x90UPa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x19\xE9\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7Fx\xDA\xD2\xBC\x0BG\xC6\x88\xED\x84\xF3\xFE\xE7\x9A\xBC\x18\xE6\xC9\x82-\xB0Zy\xCA\x19\xDF\xF5E3\xC7G\ra\x02\x08_\x01_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x87a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x1A\x89\x93\x92\x91\x90a6\x8BV[`@Q\x80\x91\x03\x90\xA1PPPPPPV[a\x1A\xA1a!\xD5V[\x15a\x1A\xE1W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x1A\xD8\x90a3\xA4V[`@Q\x80\x91\x03\x90\xFD[a\x1A\xE9a!{V[\x15a\x1B)W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x1B \x90a4\x0CV[`@Q\x80\x91\x03\x90\xFD[3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x80a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x1Bd\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x81\x10a\x1B\x7FWa\x1B~a-cV[[a\x01\x02\x02\x01_\x01\x82`\xFF\x16a\x01\0\x81\x10a\x1B\x9CWa\x1B\x9Ba-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x1C\x13W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x1C\n\x90a-\xDAV[`@Q\x80\x91\x03\x90\xFD[3a\x02\n_\x01_a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x1C\x84\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\xBC'H\xCF\x02\xF7\xA1)\x15%\xE8f\xEF\xC7j\xB3\xB9m2\xD7\xAF\xCB\xB2lS\xDA\xECa{8\xB4y3a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x1D\n\x92\x91\x90a2\xE5V[`@Q\x80\x91\x03\x90\xA1PV[a\x1D!\x82\x82\x90Pa\"\x1FV[__a\x1D+a!\xD5V[\x15a\x1E\xA1W3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x80`\x01a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x1Dm\x91\x90a/8V[a\x1Dw\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x81\x10a\x1D\x92Wa\x1D\x91a-cV[[a\x01\x02\x02\x01_\x01\x86`\xFF\x16a\x01\0\x81\x10a\x1D\xAFWa\x1D\xAEa-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14\x91P\x81a\x1E\x9CW3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x80a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x1E)\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x81\x10a\x1EDWa\x1ECa-cV[[a\x01\x02\x02\x01_\x01\x86`\xFF\x16a\x01\0\x81\x10a\x1EaWa\x1E`a-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14\x90P[a\x1FOV[3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x80a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x1E\xDC\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x81\x10a\x1E\xF7Wa\x1E\xF6a-cV[[a\x01\x02\x02\x01_\x01\x86`\xFF\x16a\x01\0\x81\x10a\x1F\x14Wa\x1F\x13a-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14\x91P[\x81\x80a\x1FXWP\x80[a\x1F\x97W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x1F\x8E\x90a-\xDAV[`@Q\x80\x91\x03\x90\xFD[\x83\x83`\x01_3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ \x91\x82a\x1F\xE3\x92\x91\x90a2\x18V[Pa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a \x12\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\x12Q\x81\xEC!\x88-\xECQ\xA29)\x05\xDF\xF3\xA8,\xBD\x02b\xF1\x8B\\\x0C\x03T\x88g\x1B@\xAF\xB23\x85\x85a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa \x9C\x94\x93\x92\x91\x90a7\x11V[`@Q\x80\x91\x03\x90\xA1PPPPPV[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a!9W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a!0\x90a+$V[`@Q\x80\x91\x03\x90\xFD[\x80__a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPPV[__s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x02\n_\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14\x15\x90P\x90V[__a\x02\x08`\x01\x01T\x14\x15\x90P\x90V[__\x82`\xFF\x16`\x01\x90\x1B\x84\x16\x14\x90P\x92\x91PPV[_\x81`\xFF\x16`\x01\x90\x1B\x19\x83\x16\x90P\x92\x91PPV[_a\"\x18\x82a\"\xD0V[\x90P\x91\x90PV[_\x81\x11a\"aW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\"X\x90a7\x99V[`@Q\x80\x91\x03\x90\xFD[a\x02\x07_\x01_\x90T\x90a\x01\0\n\x90\x04a\xFF\xFF\x16a\xFF\xFF\x16\x81\x11\x15a\"\xBAW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\"\xB1\x90a8\x01V[`@Q\x80\x91\x03\x90\xFD[PV[_\x81`\xFF\x16`\x01\x90\x1B\x83\x17\x90P\x92\x91PPV[_`\x07a\"\xEEo\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x84\x11a#\x9CV[\x90\x1B\x90P`\x06a#\ng\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x83\x85\x90\x1C\x11a#\x9CV[\x90\x1B\x81\x17\x90P`\x05a#$c\xFF\xFF\xFF\xFF\x83\x85\x90\x1C\x11a#\x9CV[\x90\x1B\x81\x17\x90P`\x04a#V[\x81R` \x01a#\xC7a$>V[\x81R` \x01_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01a#\xE4a$ZV[\x81R` \x01a#\xF1a$|V[\x81R` \x01_o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RP\x90V[`@Q\x80`@\x01`@R\x80_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01``\x81RP\x90V[`@Q\x80`@\x01`@R\x80``\x81R` \x01_`\xFF\x16\x81RP\x90V[`@Q\x80`@\x01`@R\x80_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01_\x81RP\x90V[`@Q\x80` \x01`@R\x80_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RP\x90V[__\xFD[__\xFD[_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[a$\xC8\x81a$\xACV[\x81\x14a$\xD2W__\xFD[PV[_\x815\x90Pa$\xE3\x81a$\xBFV[\x92\x91PPV[_`\xFF\x82\x16\x90P\x91\x90PV[a$\xFE\x81a$\xE9V[\x81\x14a%\x08W__\xFD[PV[_\x815\x90Pa%\x19\x81a$\xF5V[\x92\x91PPV[__`@\x83\x85\x03\x12\x15a%5Wa%4a$\xA4V[[_a%B\x85\x82\x86\x01a$\xD5V[\x92PP` a%S\x85\x82\x86\x01a%\x0BV[\x91PP\x92P\x92\x90PV[__\xFD[_` \x82\x84\x03\x12\x15a%vWa%ua%]V[[\x81\x90P\x92\x91PPV[_` \x82\x84\x03\x12\x15a%\x94Wa%\x93a$\xA4V[[_a%\xA1\x84\x82\x85\x01a%aV[\x91PP\x92\x91PPV[_\x81Q\x90P\x91\x90PV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[_\x81\x90P` \x82\x01\x90P\x91\x90PV[_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[_a%\xFC\x82a%\xD3V[\x90P\x91\x90PV[a&\x0C\x81a%\xF2V[\x82RPPV[_\x81Q\x90P\x91\x90PV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[\x82\x81\x83^_\x83\x83\x01RPPPV[_`\x1F\x19`\x1F\x83\x01\x16\x90P\x91\x90PV[_a&T\x82a&\x12V[a&^\x81\x85a&\x1CV[\x93Pa&n\x81\x85` \x86\x01a&,V[a&w\x81a&:V[\x84\x01\x91PP\x92\x91PPV[_`@\x83\x01_\x83\x01Qa&\x97_\x86\x01\x82a&\x03V[P` \x83\x01Q\x84\x82\x03` \x86\x01Ra&\xAF\x82\x82a&JV[\x91PP\x80\x91PP\x92\x91PPV[_a&\xC7\x83\x83a&\x82V[\x90P\x92\x91PPV[_` \x82\x01\x90P\x91\x90PV[_a&\xE5\x82a%\xAAV[a&\xEF\x81\x85a%\xB4V[\x93P\x83` \x82\x02\x85\x01a'\x01\x85a%\xC4V[\x80_[\x85\x81\x10\x15a'\x82a1 V[\x84\x84Ta0\xAEV[\x82UPPPPV[__\x90P\x90V[a1]a1NV[a1h\x81\x84\x84a1)V[PPPV[[\x81\x81\x10\x15a1\x8BWa1\x80_\x82a1UV[`\x01\x81\x01\x90Pa1nV[PPV[`\x1F\x82\x11\x15a1\xD0Wa1\xA1\x81a0\x81V[a1\xAA\x84a0\x93V[\x81\x01` \x85\x10\x15a1\xB9W\x81\x90P[a1\xCDa1\xC5\x85a0\x93V[\x83\x01\x82a1mV[PP[PPPV[_\x82\x82\x1C\x90P\x92\x91PPV[_a1\xF0_\x19\x84`\x08\x02a1\xD5V[\x19\x80\x83\x16\x91PP\x92\x91PPV[_a2\x08\x83\x83a1\xE1V[\x91P\x82`\x02\x02\x82\x17\x90P\x92\x91PPV[a2\"\x83\x83a0wV[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a2;Wa2:a/\xA6V[[a2E\x82Ta0\0V[a2P\x82\x82\x85a1\x8FV[_`\x1F\x83\x11`\x01\x81\x14a2}W_\x84\x15a2kW\x82\x87\x015\x90P[a2u\x85\x82a1\xFDV[\x86UPa2\xDCV[`\x1F\x19\x84\x16a2\x8B\x86a0\x81V[_[\x82\x81\x10\x15a2\xB2W\x84\x89\x015\x82U`\x01\x82\x01\x91P` \x85\x01\x94P` \x81\x01\x90Pa2\x8DV[\x86\x83\x10\x15a2\xCFW\x84\x89\x015a2\xCB`\x1F\x89\x16\x82a1\xE1V[\x83UP[`\x01`\x02\x88\x02\x01\x88UPPP[PPPPPPPV[_`@\x82\x01\x90Pa2\xF8_\x83\x01\x85a.\x07V[a3\x05` \x83\x01\x84a,\x0EV[\x93\x92PPPV[_a3\x16\x82a$\xACV[\x91P_\x82\x03a3(Wa3'a+\xAAV[[`\x01\x82\x03\x90P\x91\x90PV[_`@\x82\x01\x90Pa3F_\x83\x01\x85a-\xF8V[a3S` \x83\x01\x84a,\x0EV[\x93\x92PPPV[\x7Fmigration in progress\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a3\x8E`\x15\x83a*\xCAV[\x91Pa3\x99\x82a3ZV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra3\xBB\x81a3\x82V[\x90P\x91\x90PV[\x7Fmaintenance in progress\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a3\xF6`\x17\x83a*\xCAV[\x91Pa4\x01\x82a3\xC2V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra4#\x81a3\xEAV[\x90P\x91\x90PV[_a44\x82a$\xACV[\x91Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x03a4NWa4Ma+\xAAV[[`\x01\x82\x01\x90P\x91\x90PV[__\xFD[__\xFD[__\xFD[__\x835`\x01` \x03\x846\x03\x03\x81\x12a4\x81Wa4\x80a4YV[[\x80\x84\x01\x92P\x825\x91Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15a4\xA3Wa4\xA2a4]V[[` \x83\x01\x92P`@\x82\x026\x03\x83\x13\x15a4\xBFWa4\xBEa4aV[[P\x92P\x92\x90PV[__\xFD[__\xFD[__\xFD[__\x835`\x01` \x03\x846\x03\x03\x81\x12a4\xEFWa4\xEEa4\xCFV[[\x83\x81\x01\x92P\x825\x91P` \x83\x01\x92Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15a5\x17Wa5\x16a4\xC7V[[`@\x82\x026\x03\x83\x13\x15a5-Wa5,a4\xCBV[[P\x92P\x92\x90PV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[_\x81\x90P\x91\x90PV[_a5\\` \x84\x01\x84a%\x0BV[\x90P\x92\x91PPV[_a5r` \x84\x01\x84a*\x8BV[\x90P\x92\x91PPV[`@\x82\x01a5\x8A_\x83\x01\x83a5NV[a5\x96_\x85\x01\x82a'NV[Pa5\xA4` \x83\x01\x83a5dV[a5\xB1` \x85\x01\x82a&\x03V[PPPPV[_a5\xC2\x83\x83a5zV[`@\x83\x01\x90P\x92\x91PPV[_\x82\x90P\x92\x91PPV[_`@\x82\x01\x90P\x91\x90PV[_a5\xEF\x83\x85a55V[\x93Pa5\xFA\x82a5EV[\x80_[\x85\x81\x10\x15a62Wa6\x0F\x82\x84a5\xCEV[a6\x19\x88\x82a5\xB7V[\x97Pa6$\x83a5\xD8V[\x92PP`\x01\x81\x01\x90Pa5\xFDV[P\x85\x92PPP\x93\x92PPPV[_`@\x83\x01a6P_\x84\x01\x84a4\xD3V[\x85\x83\x03_\x87\x01Ra6b\x83\x82\x84a5\xE4V[\x92PPPa6s` \x84\x01\x84a5NV[a6\x80` \x86\x01\x82a'NV[P\x80\x91PP\x92\x91PPV[_``\x82\x01\x90Pa6\x9E_\x83\x01\x86a-\xF8V[\x81\x81\x03` \x83\x01Ra6\xB0\x81\x85a6?V[\x90Pa6\xBF`@\x83\x01\x84a,\x0EV[\x94\x93PPPPV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[\x82\x81\x837_\x83\x83\x01RPPPV[_a6\xF0\x83\x85a6\xC7V[\x93Pa6\xFD\x83\x85\x84a6\xD7V[a7\x06\x83a&:V[\x84\x01\x90P\x93\x92PPPV[_``\x82\x01\x90Pa7$_\x83\x01\x87a.\x07V[\x81\x81\x03` \x83\x01Ra77\x81\x85\x87a6\xE5V[\x90Pa7F`@\x83\x01\x84a,\x0EV[\x95\x94PPPPPV[\x7Fempty operator data\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a7\x83`\x13\x83a*\xCAV[\x91Pa7\x8E\x82a7OV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra7\xB0\x81a7wV[\x90P\x91\x90PV[\x7Foperator data too large\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a7\xEB`\x17\x83a*\xCAV[\x91Pa7\xF6\x82a7\xB7V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra8\x18\x81a7\xDFV[\x90P\x91\x90PV\xFE\xA2dipfsX\"\x12 Pp\xBF\xB7\x8C\xBAO\xB2\x04\xCE:\x9A\xE2K_q\x0Cbs!v6^\xE88\x9C\xDA\xB1\x8C<-qdsolcC\0\x08\x1C\x003", ); /// The runtime bytecode of the contract, as deployed on the network. /// /// ```text - ///0x608060405234801561000f575f5ffd5b50600436106100a7575f3560e01c8063ad36e6d01161006f578063ad36e6d014610115578063c130809a1461011f578063cc45662a14610129578063f2fde38b14610145578063f5f2d9f114610161578063ffd740df1461016b576100a7565b80633048bfba146100ab578063409900e8146100b55780634886f62c146100d15780636c0b61b9146100db57806375418b9d146100f7575b5f5ffd5b6100b3610187565b005b6100cf60048036038101906100ca91906139e2565b6102db565b005b6100d961037e565b005b6100f560048036038101906100f09190613a2b565b61082c565b005b6100ff610956565b60405161010c9190613f47565b60405180910390f35b61011d610a58565b005b610127610b7d565b005b610143600480360381019061013e919061401d565b610cd1565b005b61015f600480360381019061015a91906140c5565b61103b565b005b61016961110b565b005b6101856004803603810190610180919061411a565b61127a565b005b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610215576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161020c9061419f565b60405180910390fd5b61021f600961140e565b600a600881819054906101000a90046fffffffffffffffffffffffffffffffff168092919061024d906141ea565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507f8fb9cd054d0a022110cced239e908b834e4cd219511856d4eaae3051d932d604600a60089054906101000a90046fffffffffffffffffffffffffffffffff166040516102d19190614230565b60405180910390a1565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610369576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103609061419f565b60405180910390fd5b806001818161037891906143c4565b90505050565b6103923360056114c690919063ffffffff16565b600a600881819054906101000a90046fffffffffffffffffffffffffffffffff16809291906103c0906141ea565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507fa76a8fc1a90266ddee8937a18e12f01eade946b3b66197fff289af9277c2bd2533600a60089054906101000a90046fffffffffffffffffffffffffffffffff166040516104469291906143e1565b60405180910390a15f60056003015f9054906101000a900460ff1660ff161161082a575f5f90505b60055f01805490508110156104db576104ce60055f01828154811061049657610495614408565b5b905f5260205f20015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660026115e490919063ffffffff16565b808060010191505061046e565b505f5f90505b6005600101805490508110156107185761070b6005600101828154811061050b5761050a614408565b5b905f5260205f2090600302016040518060600160405290815f82015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160018201805480602002602001604051908101604052809291908181526020015f905b82821015610663578382905f5260205f2090600202016040518060400160405290815f82015481526020016001820180546105d490614462565b80601f016020809104026020016040519081016040528092919081815260200182805461060090614462565b801561064b5780601f106106225761010080835404028352916020019161064b565b820191905f5260205f20905b81548152906001019060200180831161062e57829003601f168201915b5050505050815250508152602001906001019061059a565b50505050815260200160028201805461067b90614462565b80601f01602080910402602001604051908101604052809291908181526020018280546106a790614462565b80156106f25780601f106106c9576101008083540402835291602001916106f2565b820191905f5260205f20905b8154815290600101906020018083116106d557829003601f168201915b505050505081525050600261187690919063ffffffff16565b80806001019150506104e1565b50600a5f81819054906101000a900467ffffffffffffffff168092919061073e90614492565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055505061076f6005611b03565b600a600881819054906101000a90046fffffffffffffffffffffffffffffffff168092919061079d906141ea565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507f11ce50160e66100537fd4b0ae26de66d51dab713ad92313353a18c24e8f6daab600a60089054906101000a90046fffffffffffffffffffffffffffffffff166040516108219190614230565b60405180910390a15b565b610840336002611bac90919063ffffffff16565b61087f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108769061450b565b60405180910390fd5b61089533826002611d049092919063ffffffff16565b600a600881819054906101000a90046fffffffffffffffffffffffffffffffff16809291906108c3906141ea565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507f6adfb896d3407681d05fb874d4dfb7068e6e2a36f09acd38a3b7d04c01745fee3382600a60089054906101000a90046fffffffffffffffffffffffffffffffff1660405161094b93929190614633565b60405180910390a150565b61095e613746565b6040518060a001604052806109736002611d96565b815260200161098f60025f016005611f9990919063ffffffff16565b815260200160096040518060200160405290815f82015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815250508152602001600a5f9054906101000a900467ffffffffffffffff1667ffffffffffffffff168152602001600a60089054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff16815250905090565b610a6c336002611bac90919063ffffffff16565b610aab576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610aa29061450b565b60405180910390fd5b610abf33600961270090919063ffffffff16565b600a600881819054906101000a90046fffffffffffffffffffffffffffffffff1680929190610aed906141ea565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507ff91067eb420c28d3124865fc996e6aa9d541b9b4fef9188cb965a6cc6491638e33600a60089054906101000a90046fffffffffffffffffffffffffffffffff16604051610b739291906143e1565b60405180910390a1565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610c0b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c029061419f565b60405180910390fd5b610c156005612827565b600a600881819054906101000a90046fffffffffffffffffffffffffffffffff1680929190610c43906141ea565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507f9ce192aea5faf2151bbc246cd8918d2eba702fa26951f67f2bf7b3817e689d98600a60089054906101000a90046fffffffffffffffffffffffffffffffff16604051610cc79190614230565b60405180910390a1565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610d5f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d569061419f565b60405180910390fd5b610d69600961287b565b15610da9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610da0906146b9565b60405180910390fd5b5f5f90505b84849050811015610e4057610df4858583818110610dcf57610dce614408565b5b9050602002016020810190610de491906140c5565b6002611bac90919063ffffffff16565b610e33576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e2a90614721565b60405180910390fd5b8080600101915050610dae565b505f5f90505b82829050811015610f2557610e8f838383818110610e6757610e66614408565b5b9050602002810190610e79919061474b565b8060200190610e889190614772565b90506128d5565b610ed8838383818110610ea557610ea4614408565b5b9050602002810190610eb7919061474b565b5f016020810190610ec891906140c5565b6002611bac90919063ffffffff16565b15610f18576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f0f9061481e565b60405180910390fd5b8080600101915050610e46565b50610f548282905085859050610f3b6002612974565b610f45919061483c565b610f4f919061486f565b612995565b610f7360025f01858585856005612a339095949392919063ffffffff16565b600a600881819054906101000a90046fffffffffffffffffffffffffffffffff1680929190610fa1906141ea565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507f7e05e40117b6e18ab284c04a3508c3826422dc84a65e9c236a8248774416f8ac84848484600a60089054906101000a90046fffffffffffffffffffffffffffffffff1660405161102d959493929190614be8565b60405180910390a150505050565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146110c9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110c09061419f565b60405180910390fd5b805f5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b61111f336002611bac90919063ffffffff16565b61115e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111559061450b565b60405180910390fd5b6111686005612ed5565b156111a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161119f90614c79565b60405180910390fd5b6111bc336009612ef990919063ffffffff16565b600a600881819054906101000a90046fffffffffffffffffffffffffffffffff16809291906111ea906141ea565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507fbc2748cf02f7a1291525e866efc76ab3b96d32d7afcbb26c53daec617b38b47933600a60089054906101000a90046fffffffffffffffffffffffffffffffff166040516112709291906143e1565b60405180910390a1565b61128e336002611bac90919063ffffffff16565b6112cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112c49061450b565b60405180910390fd5b6112e33382600261303c9092919063ffffffff16565b60015f0160019054906101000a900460ff1660ff1661130c3360026130c590919063ffffffff16565b101561134d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161134490614ce1565b60405180910390fd5b600a600881819054906101000a90046fffffffffffffffffffffffffffffffff168092919061137b906141ea565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507fbd184de79f134b0f3da466d278f5417cbcb1450d72f1bd1a1b84f18b1bcd03ca3382600a60089054906101000a90046fffffffffffffffffffffffffffffffff1660405161140393929190614d0e565b60405180910390a150565b5f73ffffffffffffffffffffffffffffffffffffffff16815f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff160361149e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161149590614d8d565b60405180910390fd5b805f015f6101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905550565b816002015f8273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16611551576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161154890614df5565b60405180910390fd5b5f826002015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908315150217905550816003015f81819054906101000a900460ff16809291906115c790614e13565b91906101000a81548160ff021916908360ff160217905550505050565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611652576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161164990614e84565b60405180910390fd5b5f826001015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1690505f8160ff1614158061172057508173ffffffffffffffffffffffffffffffffffffffff16835f015f815481106116da576116d9614408565b5b905f5260205f2090600502015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b61175f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161175690614eec565b60405180910390fd5b826001015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81549060ff0219169055825f018160ff16815481106117c5576117c4614408565b5b905f5260205f2090600502015f5f82015f6101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600182015f5f82015f61180a91906137a1565b600282015f61181991906137c2565b5050600482015f61182a91906137e7565b50508260020181908060018154018082558091505060019003905f5260205f2090602091828204019190069091909190916101000a81548160ff021916908360ff160217905550505050565b61188382825f0151611bac565b156118c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118ba9061481e565b60405180910390fd5b5f5f8360020180549050111561195d5782600201600184600201805490506118eb919061483c565b815481106118fc576118fb614408565b5b905f5260205f2090602091828204019190069054906101000a900460ff169050826002018054806119305761192f614f0a565b5b600190038181905f5260205f2090602091828204019190066101000a81549060ff021916905590556119ce565b610100835f0180549050106119a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161199e90614f81565b60405180910390fd5b825f01805490509050825f0160018160018154018082558091505003905f5260205f209050505b80836001015f845f015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908360ff1602179055505f835f018260ff1681548110611a4157611a40614408565b5b905f5260205f2090600502019050825f0151815f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508260400151816004019081611aa89190615163565b505f5f90505b836020015151811015611afc57611aef84602001518281518110611ad557611ad4614408565b5b60200260200101518360010161314890919063ffffffff16565b8080600101915050611aae565b5050505050565b611b0c81612ed5565b611b4b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b429061527c565b60405180910390fd5b5f816003015f9054906101000a900460ff1660ff1614611ba0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b97906152e4565b60405180910390fd5b611ba9816133ce565b50565b5f5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611c1b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c1290614e84565b60405180910390fd5b5f835f01805490501115611cfa575f836001015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1660ff16141580611cf357508173ffffffffffffffffffffffffffffffffffffffff16835f015f81548110611cad57611cac614408565b5b905f5260205f2090600502015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b9050611cfe565b5f90505b92915050565b611d9181611d1190615460565b845f01856001015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1660ff1681548110611d7457611d73614408565b5b905f5260205f20906005020160010161314890919063ffffffff16565b505050565b611d9e613824565b5f825f018054905067ffffffffffffffff811115611dbf57611dbe614f9f565b5b604051908082528060200260200182016040528015611df857816020015b611de5613837565b815260200190600190039081611ddd5790505b5090505f5f90505b835f0180549050811015611f81576040518060600160405280855f018381548110611e2e57611e2d614408565b5b905f5260205f2090600502015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001611ea3865f018481548110611e8f57611e8e614408565b5b905f5260205f209060050201600101613401565b8152602001855f018381548110611ebd57611ebc614408565b5b905f5260205f2090600502016004018054611ed790614462565b80601f0160208091040260200160405190810160405280929190818152602001828054611f0390614462565b8015611f4e5780601f10611f2557610100808354040283529160200191611f4e565b820191905f5260205f20905b815481529060010190602001808311611f3157829003601f168201915b5050505050815250828281518110611f6957611f68614408565b5b60200260200101819052508080600101915050611e00565b50604051806020016040528082815250915050919050565b611fa161386d565b5f835f018054905067ffffffffffffffff811115611fc257611fc1614f9f565b5b604051908082528060200260200182016040528015611ff05781602001602082028036833780820191505090505b5090505f5f90505b845f018054905081101561209d57845f01818154811061201b5761201a614408565b5b905f5260205f20015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682828151811061205657612055614408565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508080600101915050611ff8565b505f846001018054905067ffffffffffffffff8111156120c0576120bf614f9f565b5b6040519080825280602002602001820160405280156120f957816020015b6120e6613837565b8152602001906001900390816120de5790505b5090505f5f90505b85600101805490508110156123415785600101818154811061212657612125614408565b5b905f5260205f2090600302016040518060600160405290815f82015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160018201805480602002602001604051908101604052809291908181526020015f905b8282101561227e578382905f5260205f2090600202016040518060400160405290815f82015481526020016001820180546121ef90614462565b80601f016020809104026020016040519081016040528092919081815260200182805461221b90614462565b80156122665780601f1061223d57610100808354040283529160200191612266565b820191905f5260205f20905b81548152906001019060200180831161224957829003601f168201915b505050505081525050815260200190600101906121b5565b50505050815260200160028201805461229690614462565b80601f01602080910402602001604051908101604052809291908181526020018280546122c290614462565b801561230d5780601f106122e45761010080835404028352916020019161230d565b820191905f5260205f20905b8154815290600101906020018083116122f057829003601f168201915b50505050508152505082828151811061232957612328614408565b5b60200260200101819052508080600101915050612101565b505f856003015f9054906101000a900460ff1660ff1667ffffffffffffffff8111156123705761236f614f9f565b5b60405190808252806020026020018201604052801561239e5781602001602082028036833780820191505090505b5090505f866003015f9054906101000a900460ff1660ff1611156126da575f5f5f90505b8680549050811015612581575f73ffffffffffffffffffffffffffffffffffffffff168782815481106123f8576123f7614408565b5b905f5260205f2090600502015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141580156124d25750876002015f88838154811061245d5761245c614408565b5b905f5260205f2090600502015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff165b15612574578681815481106124ea576124e9614408565b5b905f5260205f2090600502015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683838151811061252b5761252a614408565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050818061257090615472565b9250505b80806001019150506123c2565b505f5f90505b87600101805490508110156126d757876002015f8960010183815481106125b1576125b0614408565b5b905f5260205f2090600302015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16156126ca578760010181815481106126405761263f614408565b5b905f5260205f2090600302015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683838151811061268157612680614408565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505081806126c690615472565b9250505b8080600101915050612587565b50505b604051806060016040528084815260200183815260200182815250935050505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361276e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161276590614e84565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16825f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146127fe576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127f590614d8d565b60405180910390fd5b815f015f6101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690555050565b61283081612ed5565b61286f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016128669061527c565b60405180910390fd5b612878816133ce565b50565b5f5f73ffffffffffffffffffffffffffffffffffffffff16825f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614159050919050565b60015f0160019054906101000a900460ff1660ff1681101561292c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161292390614ce1565b60405180910390fd5b610100811115612971576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161296890615503565b60405180910390fd5b50565b5f8160020180549050825f018054905061298e919061483c565b9050919050565b60015f015f9054906101000a900460ff1660ff168110156129eb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129e29061556b565b60405180910390fd5b610100811115612a30576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a2790614f81565b60405180910390fd5b50565b612a3c86612ed5565b15612a7c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a73906155d3565b60405180910390fd5b5f848490501180612a8f57505f82829050115b612ace576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612ac59061563b565b60405180910390fd5b5f5f90505b8580549050811015612c30575f73ffffffffffffffffffffffffffffffffffffffff16868281548110612b0957612b08614408565b5b905f5260205f2090600502015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612c23576001876002015f888481548110612b6c57612b6b614408565b5b905f5260205f2090600502015f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908315150217905550866003015f81819054906101000a900460ff1680929190612c0990615659565b91906101000a81548160ff021916908360ff160217905550505b8080600101915050612ad3565b505f5f90505b84849050811015612d8c57865f01858583818110612c5757612c56614408565b5b9050602002016020810190612c6c91906140c5565b908060018154018082558091505060019003905f5260205f20015f9091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505f876002015f878785818110612ce257612ce1614408565b5b9050602002016020810190612cf791906140c5565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908315150217905550866003015f81819054906101000a900460ff1680929190612d6690614e13565b91906101000a81548160ff021916908360ff160217905550508080600101915050612c36565b505f5f90505b82829050811015612ecc5786600101838383818110612db457612db3614408565b5b9050602002810190612dc6919061474b565b908060018154018082558091505060019003905f5260205f2090600302015f909190919091508181612df89190615d9e565b50506001876002015f858585818110612e1457612e13614408565b5b9050602002810190612e26919061474b565b5f016020810190612e3791906140c5565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908315150217905550866003015f81819054906101000a900460ff1680929190612ea690615659565b91906101000a81548160ff021916908360ff160217905550508080600101915050612d92565b50505050505050565b5f5f825f0180549050141580612ef257505f826001018054905014155b9050919050565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612f67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612f5e90614e84565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff16825f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612ff7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612fee90615df6565b60405180910390fd5b80825f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b6130c081845f01856001015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1660ff16815481106130a3576130a2614408565b5b905f5260205f2090600502016001016135c790919063ffffffff16565b505050565b5f613140835f01846001015f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1660ff168154811061312c5761312b614408565b5b905f5260205f209060050201600101613725565b905092915050565b5f815f01510361318d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161318490615e5e565b60405180910390fd5b5f5f835f0180549050111561324a57826001015f835f015181526020019081526020015f205f9054906101000a900460ff1690505f8160ff161415806131f85750815f0151835f015f815481106131e7576131e6614408565b5b905f5260205f2090600202015f0154145b156132495781835f018260ff168154811061321657613215614408565b5b905f5260205f2090600202015f820151815f0155602082015181600101908161323f9190615163565b50905050506133ca565b5b5f836002018054905011156132e3578260020160018460020180549050613271919061483c565b8154811061328257613281614408565b5b905f5260205f2090602091828204019190069054906101000a900460ff169050826002018054806132b6576132b5614f0a565b5b600190038181905f5260205f2090602091828204019190066101000a81549060ff02191690559055613354565b610100835f01805490501061332d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161332490615503565b60405180910390fd5b825f01805490509050825f0160018160018154018082558091505003905f5260205f209050505b80836001015f845f015181526020019081526020015f205f6101000a81548160ff021916908360ff16021790555081835f018260ff168154811061339b5761339a614408565b5b905f5260205f2090600202015f820151815f015560208201518160010190816133c49190615163565b50905050505b5050565b805f015f6133dc919061388e565b806001015f6133eb91906138ac565b806003015f6101000a81549060ff021916905550565b60605f61340d83613725565b67ffffffffffffffff81111561342657613425614f9f565b5b60405190808252806020026020018201604052801561345f57816020015b61344c6138cd565b8152602001906001900390816134445790505b5090505f5f5f90505b845f01805490508110156135bc575f855f01828154811061348c5761348b614408565b5b905f5260205f2090600202015f0154146135af576040518060400160405280865f0183815481106134c0576134bf614408565b5b905f5260205f2090600202015f01548152602001865f0183815481106134e9576134e8614408565b5b905f5260205f209060020201600101805461350390614462565b80601f016020809104026020016040519081016040528092919081815260200182805461352f90614462565b801561357a5780601f106135515761010080835404028352916020019161357a565b820191905f5260205f20905b81548152906001019060200180831161355d57829003601f168201915b505050505081525083838151811061359557613594614408565b5b602002602001018190525081806135ab90615472565b9250505b8080600101915050613468565b508192505050919050565b5f8103613609576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161360090615e5e565b60405180910390fd5b5f826001015f8381526020019081526020015f205f9054906101000a900460ff1690505f8160ff16141580613660575081835f015f8154811061364f5761364e614408565b5b905f5260205f2090600202015f0154145b61369f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161369690615ec6565b60405180910390fd5b825f018160ff16815481106136b7576136b6614408565b5b905f5260205f2090600202015f5f82015f9055600182015f6136d991906137e7565b50508260020181908060018154018082558091505060019003905f5260205f2090602091828204019190069091909190916101000a81548160ff021916908360ff160217905550505050565b5f8160020180549050825f018054905061373f919061483c565b9050919050565b6040518060a00160405280613759613824565b815260200161376661386d565b81526020016137736138e6565b81526020015f67ffffffffffffffff1681526020015f6fffffffffffffffffffffffffffffffff1681525090565b5080545f8255600202905f5260205f20908101906137bf919061390e565b50565b5080545f8255601f0160209004905f5260205f20908101906137e4919061393a565b50565b5080546137f390614462565b5f825580601f106138045750613821565b601f0160209004905f5260205f2090810190613820919061393a565b5b50565b6040518060200160405280606081525090565b60405180606001604052805f73ffffffffffffffffffffffffffffffffffffffff16815260200160608152602001606081525090565b60405180606001604052806060815260200160608152602001606081525090565b5080545f8255905f5260205f20908101906138a9919061393a565b50565b5080545f8255600302905f5260205f20908101906138ca9190613955565b50565b60405180604001604052805f8152602001606081525090565b60405180602001604052805f73ffffffffffffffffffffffffffffffffffffffff1681525090565b5b80821115613936575f5f82015f9055600182015f61392d91906137e7565b5060020161390f565b5090565b5b80821115613951575f815f90555060010161393b565b5090565b5b808211156139ab575f5f82015f6101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600182015f61399391906137a1565b600282015f6139a291906137e7565b50600301613956565b5090565b5f604051905090565b5f5ffd5b5f5ffd5b5f5ffd5b5f604082840312156139d9576139d86139c0565b5b81905092915050565b5f604082840312156139f7576139f66139b8565b5b5f613a04848285016139c4565b91505092915050565b5f60408284031215613a2257613a216139c0565b5b81905092915050565b5f60208284031215613a4057613a3f6139b8565b5b5f82013567ffffffffffffffff811115613a5d57613a5c6139bc565b5b613a6984828501613a0d565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f613ac482613a9b565b9050919050565b613ad481613aba565b82525050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f819050919050565b613b1581613b03565b82525050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f613b5d82613b1b565b613b678185613b25565b9350613b77818560208601613b35565b613b8081613b43565b840191505092915050565b5f604083015f830151613ba05f860182613b0c565b5060208301518482036020860152613bb88282613b53565b9150508091505092915050565b5f613bd08383613b8b565b905092915050565b5f602082019050919050565b5f613bee82613ada565b613bf88185613ae4565b935083602082028501613c0a85613af4565b805f5b85811015613c455784840389528151613c268582613bc5565b9450613c3183613bd8565b925060208a01995050600181019050613c0d565b50829750879550505050505092915050565b5f606083015f830151613c6c5f860182613acb565b5060208301518482036020860152613c848282613be4565b91505060408301518482036040860152613c9e8282613b53565b9150508091505092915050565b5f613cb68383613c57565b905092915050565b5f602082019050919050565b5f613cd482613a72565b613cde8185613a7c565b935083602082028501613cf085613a8c565b805f5b85811015613d2b5784840389528151613d0c8582613cab565b9450613d1783613cbe565b925060208a01995050600181019050613cf3565b50829750879550505050505092915050565b5f602083015f8301518482035f860152613d578282613cca565b9150508091505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f613d988383613acb565b60208301905092915050565b5f602082019050919050565b5f613dba82613d64565b613dc48185613d6e565b9350613dcf83613d7e565b805f5b83811015613dff578151613de68882613d8d565b9750613df183613da4565b925050600181019050613dd2565b5085935050505092915050565b5f606083015f8301518482035f860152613e268282613db0565b91505060208301518482036020860152613e408282613cca565b91505060408301518482036040860152613e5a8282613db0565b9150508091505092915050565b602082015f820151613e7b5f850182613acb565b50505050565b5f67ffffffffffffffff82169050919050565b613e9d81613e81565b82525050565b5f6fffffffffffffffffffffffffffffffff82169050919050565b613ec781613ea3565b82525050565b5f60a083015f8301518482035f860152613ee78282613d3d565b91505060208301518482036020860152613f018282613e0c565b9150506040830151613f166040860182613e67565b506060830151613f296060860182613e94565b506080830151613f3c6080860182613ebe565b508091505092915050565b5f6020820190508181035f830152613f5f8184613ecd565b905092915050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f83601f840112613f8857613f87613f67565b5b8235905067ffffffffffffffff811115613fa557613fa4613f6b565b5b602083019150836020820283011115613fc157613fc0613f6f565b5b9250929050565b5f5f83601f840112613fdd57613fdc613f67565b5b8235905067ffffffffffffffff811115613ffa57613ff9613f6b565b5b60208301915083602082028301111561401657614015613f6f565b5b9250929050565b5f5f5f5f60408587031215614035576140346139b8565b5b5f85013567ffffffffffffffff811115614052576140516139bc565b5b61405e87828801613f73565b9450945050602085013567ffffffffffffffff811115614081576140806139bc565b5b61408d87828801613fc8565b925092505092959194509250565b6140a481613aba565b81146140ae575f5ffd5b50565b5f813590506140bf8161409b565b92915050565b5f602082840312156140da576140d96139b8565b5b5f6140e7848285016140b1565b91505092915050565b6140f981613b03565b8114614103575f5ffd5b50565b5f81359050614114816140f0565b92915050565b5f6020828403121561412f5761412e6139b8565b5b5f61413c84828501614106565b91505092915050565b5f82825260208201905092915050565b7f6e6f7420746865206f776e6572000000000000000000000000000000000000005f82015250565b5f614189600d83614145565b915061419482614155565b602082019050919050565b5f6020820190508181035f8301526141b68161417d565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6141f482613ea3565b91506fffffffffffffffffffffffffffffffff8203614216576142156141bd565b5b600182019050919050565b61422a81613ea3565b82525050565b5f6020820190506142435f830184614221565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b5f60ff82169050919050565b61428a81614275565b8114614294575f5ffd5b50565b5f81356142a381614281565b80915050919050565b5f815f1b9050919050565b5f60ff6142c3846142ac565b9350801983169250808416831791505092915050565b5f819050919050565b5f6142fc6142f76142f284614275565b6142d9565b614275565b9050919050565b5f819050919050565b614315826142e2565b61432861432182614303565b83546142b7565b8255505050565b5f8160081b9050919050565b5f61ff006143488461432f565b9350801983169250808416831791505092915050565b614367826142e2565b61437a61437382614303565b835461433b565b8255505050565b5f81015f83018061439181614297565b905061439d818461430c565b5050505f810160208301806143b181614297565b90506143bd818461435e565b5050505050565b6143ce8282614381565b5050565b6143db81613aba565b82525050565b5f6040820190506143f45f8301856143d2565b6144016020830184614221565b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061447957607f821691505b60208210810361448c5761448b614435565b5b50919050565b5f61449c82613e81565b915067ffffffffffffffff82036144b6576144b56141bd565b5b600182019050919050565b7f6e6f7420616e206f70657261746f7200000000000000000000000000000000005f82015250565b5f6144f5600f83614145565b9150614500826144c1565b602082019050919050565b5f6020820190508181035f830152614522816144e9565b9050919050565b5f6145376020840184614106565b905092915050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f8335600160200384360303811261456757614566614547565b5b83810192508235915060208301925067ffffffffffffffff82111561458f5761458e61453f565b5b6001820236038313156145a5576145a4614543565b5b509250929050565b828183375f83830152505050565b5f6145c68385613b25565b93506145d38385846145ad565b6145dc83613b43565b840190509392505050565b5f604083016145f85f840184614529565b6146045f860182613b0c565b50614612602084018461454b565b85830360208701526146258382846145bb565b925050508091505092915050565b5f6060820190506146465f8301866143d2565b818103602083015261465881856145e7565b90506146676040830184614221565b949350505050565b7f6d61696e74656e616e636520696e2070726f67726573730000000000000000005f82015250565b5f6146a3601783614145565b91506146ae8261466f565b602082019050919050565b5f6020820190508181035f8301526146d081614697565b9050919050565b7f756e6b6e6f776e206f70657261746f72000000000000000000000000000000005f82015250565b5f61470b601083614145565b9150614716826146d7565b602082019050919050565b5f6020820190508181035f830152614738816146ff565b9050919050565b5f5ffd5b5f5ffd5b5f5ffd5b5f823560016060038336030381126147665761476561473f565b5b80830191505092915050565b5f5f8335600160200384360303811261478e5761478d61473f565b5b80840192508235915067ffffffffffffffff8211156147b0576147af614743565b5b6020830192506020820236038313156147cc576147cb614747565b5b509250929050565b7f6f70657261746f7220616c7265616479206578697374730000000000000000005f82015250565b5f614808601783614145565b9150614813826147d4565b602082019050919050565b5f6020820190508181035f830152614835816147fc565b9050919050565b5f61484682613b03565b915061485183613b03565b9250828203905081811115614869576148686141bd565b5b92915050565b5f61487982613b03565b915061488483613b03565b925082820190508082111561489c5761489b6141bd565b5b92915050565b5f82825260208201905092915050565b5f819050919050565b5f6148c960208401846140b1565b905092915050565b5f602082019050919050565b5f6148e883856148a2565b93506148f3826148b2565b805f5b8581101561492b5761490882846148bb565b6149128882613d8d565b975061491d836148d1565b9250506001810190506148f6565b5085925050509392505050565b5f82825260208201905092915050565b5f819050919050565b5f5f8335600160200384360303811261496d5761496c614547565b5b83810192508235915060208301925067ffffffffffffffff8211156149955761499461453f565b5b6020820236038313156149ab576149aa614543565b5b509250929050565b5f819050919050565b5f604083016149cd5f840184614529565b6149d95f860182613b0c565b506149e7602084018461454b565b85830360208701526149fa8382846145bb565b925050508091505092915050565b5f614a1383836149bc565b905092915050565b5f82356001604003833603038112614a3657614a35614547565b5b82810191505092915050565b5f602082019050919050565b5f614a598385613ae4565b935083602084028501614a6b846149b3565b805f5b87811015614aae578484038952614a858284614a1b565b614a8f8582614a08565b9450614a9a83614a42565b925060208a01995050600181019050614a6e565b50829750879450505050509392505050565b5f60608301614ad15f8401846148bb565b614add5f860182613acb565b50614aeb6020840184614951565b8583036020870152614afe838284614a4e565b92505050614b0f604084018461454b565b8583036040870152614b228382846145bb565b925050508091505092915050565b5f614b3b8383614ac0565b905092915050565b5f82356001606003833603038112614b5e57614b5d614547565b5b82810191505092915050565b5f602082019050919050565b5f614b818385614938565b935083602084028501614b9384614948565b805f5b87811015614bd6578484038952614bad8284614b43565b614bb78582614b30565b9450614bc283614b6a565b925060208a01995050600181019050614b96565b50829750879450505050509392505050565b5f6060820190508181035f830152614c018187896148dd565b90508181036020830152614c16818587614b76565b9050614c256040830184614221565b9695505050505050565b7f6d6967726174696f6e20696e2070726f677265737300000000000000000000005f82015250565b5f614c63601583614145565b9150614c6e82614c2f565b602082019050919050565b5f6020820190508181035f830152614c9081614c57565b9050919050565b7f746f6f20666577206e6f646573000000000000000000000000000000000000005f82015250565b5f614ccb600d83614145565b9150614cd682614c97565b602082019050919050565b5f6020820190508181035f830152614cf881614cbf565b9050919050565b614d0881613b03565b82525050565b5f606082019050614d215f8301866143d2565b614d2e6020830185614cff565b614d3b6040830184614221565b949350505050565b7f6e6f7420756e646572206d61696e74656e616e636500000000000000000000005f82015250565b5f614d77601583614145565b9150614d8282614d43565b602082019050919050565b5f6020820190508181035f830152614da481614d6b565b9050919050565b7f6e6f742070756c6c696e670000000000000000000000000000000000000000005f82015250565b5f614ddf600b83614145565b9150614dea82614dab565b602082019050919050565b5f6020820190508181035f830152614e0c81614dd3565b9050919050565b5f614e1d82614275565b91505f8203614e2f57614e2e6141bd565b5b600182039050919050565b7f696e76616c6964206164647265737300000000000000000000000000000000005f82015250565b5f614e6e600f83614145565b9150614e7982614e3a565b602082019050919050565b5f6020820190508181035f830152614e9b81614e62565b9050919050565b7f6f70657261746f7220646f65736e2774206578697374000000000000000000005f82015250565b5f614ed6601683614145565b9150614ee182614ea2565b602082019050919050565b5f6020820190508181035f830152614f0381614eca565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffd5b7f746f6f206d616e79206f70657261746f727300000000000000000000000000005f82015250565b5f614f6b601283614145565b9150614f7682614f37565b602082019050919050565b5f6020820190508181035f830152614f9881614f5f565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026150287fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82614fed565b6150328683614fed565b95508019841693508086168417925050509392505050565b5f61506461505f61505a84613b03565b6142d9565b613b03565b9050919050565b5f819050919050565b61507d8361504a565b6150916150898261506b565b848454614ff9565b825550505050565b5f5f905090565b6150a8615099565b6150b3818484615074565b505050565b5b818110156150d6576150cb5f826150a0565b6001810190506150b9565b5050565b601f82111561511b576150ec81614fcc565b6150f584614fde565b81016020851015615104578190505b61511861511085614fde565b8301826150b8565b50505b505050565b5f82821c905092915050565b5f61513b5f1984600802615120565b1980831691505092915050565b5f615153838361512c565b9150826002028217905092915050565b61516c82613b1b565b67ffffffffffffffff81111561518557615184614f9f565b5b61518f8254614462565b61519a8282856150da565b5f60209050601f8311600181146151cb575f84156151b9578287015190505b6151c38582615148565b86555061522a565b601f1984166151d986614fcc565b5f5b82811015615200578489015182556001820191506020850194506020810190506151db565b8683101561521d5784890151615219601f89168261512c565b8355505b6001600288020188555050505b505050505050565b7f6e6f7420696e2070726f677265737300000000000000000000000000000000005f82015250565b5f615266600f83614145565b915061527182615232565b602082019050919050565b5f6020820190508181035f8301526152938161525a565b9050919050565b7f646174612070756c6c20696e2070726f677265737300000000000000000000005f82015250565b5f6152ce601583614145565b91506152d98261529a565b602082019050919050565b5f6020820190508181035f8301526152fb816152c2565b9050919050565b5f5ffd5b61530f82613b43565b810181811067ffffffffffffffff8211171561532e5761532d614f9f565b5b80604052505050565b5f6153406139af565b905061534c8282615306565b919050565b5f5ffd5b5f5ffd5b5f67ffffffffffffffff82111561537357615372614f9f565b5b61537c82613b43565b9050602081019050919050565b5f61539b61539684615359565b615337565b9050828152602081018484840111156153b7576153b6615355565b5b6153c28482856145ad565b509392505050565b5f82601f8301126153de576153dd613f67565b5b81356153ee848260208601615389565b91505092915050565b5f6040828403121561540c5761540b615302565b5b6154166040615337565b90505f61542584828501614106565b5f83015250602082013567ffffffffffffffff81111561544857615447615351565b5b615454848285016153ca565b60208301525092915050565b5f61546b36836153f7565b9050919050565b5f61547c82613b03565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036154ae576154ad6141bd565b5b600182019050919050565b7f746f6f206d616e79206e6f6465730000000000000000000000000000000000005f82015250565b5f6154ed600e83614145565b91506154f8826154b9565b602082019050919050565b5f6020820190508181035f83015261551a816154e1565b9050919050565b7f746f6f20666577206f70657261746f72730000000000000000000000000000005f82015250565b5f615555601183614145565b915061556082615521565b602082019050919050565b5f6020820190508181035f83015261558281615549565b9050919050565b7f6d6967726174696f6e20616c726561647920696e2070726f67726573730000005f82015250565b5f6155bd601d83614145565b91506155c882615589565b602082019050919050565b5f6020820190508181035f8301526155ea816155b1565b9050919050565b7f6e6f7468696e6720746f20646f000000000000000000000000000000000000005f82015250565b5f615625600d83614145565b9150615630826155f1565b602082019050919050565b5f6020820190508181035f83015261565281615619565b9050919050565b5f61566382614275565b915060ff8203615676576156756141bd565b5b600182019050919050565b5f813561568d8161409b565b80915050919050565b5f73ffffffffffffffffffffffffffffffffffffffff6156b5846142ac565b9350801983169250808416831791505092915050565b5f6156e56156e06156db84613a9b565b6142d9565b613a9b565b9050919050565b5f6156f6826156cb565b9050919050565b5f615707826156ec565b9050919050565b5f819050919050565b615720826156fd565b61573361572c8261570e565b8354615696565b8255505050565b5f823560016040038336030381126157555761575461473f565b5b80830191505092915050565b5f81549050919050565b5f61577582613b03565b915061578083613b03565b925082820261578e81613b03565b915082820484148315176157a5576157a46141bd565b5b5092915050565b5f8190506157bb82600261576b565b9050919050565b5f819050815f5260205f209050919050565b6158047fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83602003600802615120565b815481168255505050565b61581881614fcc565b615823838254615148565b8083555f825550505050565b602084105f811461588957601f841160018114615857576158508685615148565b8355615883565b61586083614fcc565b61587761586c87614fde565b8201600183016150b8565b615881878561580f565b505b506158d6565b61589282614fcc565b61589b86614fde565b8101601f871680156158b5576158b481600184036157d4565b5b6158c96158c188614fde565b8401836150b8565b6001886002021785555050505b5050505050565b680100000000000000008411156158f7576158f6614f9f565b5b602083105f811461594057602085105f811461591e576159178685615148565b835561593a565b8360ff191693508361592f84614fcc565b556001866002020183555b5061594a565b6001856002020182555b5050505050565b805461595c81614462565b8084111561597157615970848284866158dd565b5b80841015615986576159858482848661582f565b5b50505050565b818110156159a95761599e5f826150a0565b60018101905061598c565b5050565b6159b75f82615951565b50565b5f82146159ca576159c9614249565b5b6159d3816159ad565b5050565b6159e35f5f83016150a0565b6159f05f600183016159ba565b50565b5f8214615a0357615a02614249565b5b615a0c816159d7565b5050565b5b81811015615a2e57615a235f826159f3565b600281019050615a11565b5050565b81831015615a6b57615a43826157ac565b615a4c846157ac565b615a55836157c2565b818101838201615a658183615a10565b50505050505b505050565b68010000000000000000821115615a8a57615a89614f9f565b5b615a9381615761565b828255615aa1838284615a32565b505050565b5f82905092915050565b5f8135615abc816140f0565b80915050919050565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff615af0846142ac565b9350801983169250808416831791505092915050565b615b0f8261504a565b615b22615b1b8261506b565b8354615ac5565b8255505050565b5f5f83356001602003843603038112615b4557615b4461473f565b5b80840192508235915067ffffffffffffffff821115615b6757615b66614743565b5b602083019250600182023603831315615b8357615b82614747565b5b509250929050565b5f82905092915050565b615b9f8383615b8b565b67ffffffffffffffff811115615bb857615bb7614f9f565b5b615bc28254614462565b615bcd8282856150da565b5f601f831160018114615bfa575f8415615be8578287013590505b615bf28582615148565b865550615c59565b601f198416615c0886614fcc565b5f5b82811015615c2f57848901358255600182019150602085019450602081019050615c0a565b86831015615c4c5784890135615c48601f89168261512c565b8355505b6001600288020188555050505b50505050505050565b615c6d838383615b95565b505050565b5f81015f830180615c8281615ab0565b9050615c8e8184615b06565b5050506001810160208301615ca38185615b29565b615cae818386615c62565b505050505050565b615cc08282615c72565b5050565b615cce8383615aa6565b615cd88183615a70565b615ce1836149b3565b615cea836157c2565b5f5b83811015615d2057615cfe838761573a565b615d088184615cb6565b60208401935060028301925050600181019050615cec565b50505050505050565b615d34838383615cc4565b505050565b5f81015f830180615d4981615681565b9050615d558184615717565b5050506001810160208301615d6a8185614772565b615d75818386615d29565b505050506002810160408301615d8b8185615b29565b615d96818386615c62565b505050505050565b615da88282615d39565b5050565b7f616e6f74686572206d61696e74656e616e636520696e2070726f6772657373005f82015250565b5f615de0601f83614145565b9150615deb82615dac565b602082019050919050565b5f6020820190508181035f830152615e0d81615dd4565b9050919050565b7f696e76616c6964206964000000000000000000000000000000000000000000005f82015250565b5f615e48600a83614145565b9150615e5382615e14565b602082019050919050565b5f6020820190508181035f830152615e7581615e3c565b9050919050565b7f6e6f646520646f65736e277420657869737400000000000000000000000000005f82015250565b5f615eb0601283614145565b9150615ebb82615e7c565b602082019050919050565b5f6020820190508181035f830152615edd81615ea4565b905091905056fea26469706673582212205ec0504f700c355842dfb4a4d399a8e48b0ca02d4766027c3ae5b1d4f339375864736f6c634300081c0033 + ///0x608060405234801561000f575f5ffd5b50600436106100a7575f3560e01c8063ad36e6d01161006f578063ad36e6d014610127578063c130809a14610131578063cdbfc62d1461013b578063dd3fd26914610157578063f019b15414610173578063f2fde38b1461018f576100a7565b80633048bfba146100ab57806355a47d0a146100b557806365706f9c146100d157806375418b9d146100ed5780638b5252d61461010b575b5f5ffd5b6100b36101ab565b005b6100cf60048036038101906100ca919061251f565b61037f565b005b6100eb60048036038101906100e6919061257f565b6106bd565b005b6100f5610761565b60405161010291906128bc565b60405180910390f35b6101256004803603810190610120919061293d565b610f8f565b005b61012f610fec565b005b6101396111c6565b005b610155600480360381019061015091906129a6565b6113c9565b005b610171600480360381019061016c91906129ed565b611a99565b005b61018d60048036038101906101889190612a18565b611d15565b005b6101a960048036038101906101a49190612a9f565b6120ab565b005b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610239576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161023090612b24565b60405180910390fd5b61024161217b565b610280576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161027790612b8c565b60405180910390fd5b5f61020a5f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff16809291906102f190612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507f8fb9cd054d0a022110cced239e908b834e4cd219511856d4eaae3051d932d60461020b5f9054906101000a90046fffffffffffffffffffffffffffffffff166040516103759190612c1d565b60405180910390a1565b6103876121d5565b6103c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103bd90612c80565b60405180910390fd5b6102085f015f9054906101000a900467ffffffffffffffff1667ffffffffffffffff168267ffffffffffffffff1614610434576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042b90612ce8565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff166002806102065f9054906101000a900467ffffffffffffffff1661046f9190612d33565b67ffffffffffffffff166002811061048a57610489612d63565b5b61010202015f018260ff1661010081106104a7576104a6612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461051e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161051590612dda565b60405180910390fd5b61053781610208600101546121e590919063ffffffff16565b6106b95761055481610208600101546121fa90919063ffffffff16565b6102086001018190555061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff168092919061058c90612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550505f6102086001015403610646577f01269879535f40ee8957e15e160bf1866c5e2728ff0cbc583d848821e2639b4e6102085f015f9054906101000a900467ffffffffffffffff163361020b5f9054906101000a90046fffffffffffffffffffffffffffffffff1660405161063993929190612e16565b60405180910390a16106b8565b7faf5e90e72015f43138f66b4cd08bd1dfa2839030104f22a00af843fe847c6d196102085f015f9054906101000a900467ffffffffffffffff163361020b5f9054906101000a90046fffffffffffffffffffffffffffffffff166040516106af93929190612e16565b60405180910390a15b5b5050565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461074b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161074290612b24565b60405180910390fd5b80610207818161075b9190612f2a565b90505050565b6107696123a7565b6107716123a7565b5f5f5f61077c6121d5565b15610bb9576102085f015f9054906101000a900467ffffffffffffffff1684606001515f019067ffffffffffffffff16908167ffffffffffffffff16815250506102086001015484606001516020018181525050600260016102065f9054906101000a900467ffffffffffffffff166107f59190612f38565b6107ff9190612d33565b67ffffffffffffffff1692505f60026102065f9054906101000a900467ffffffffffffffff1661082f9190612d33565b67ffffffffffffffff1690506108616002826002811061085257610851612d63565b5b6101020201610100015461220e565b91506001826108709190612f73565b67ffffffffffffffff81111561088957610888612fa6565b5b6040519080825280602002602001820160405280156108c257816020015b6108af61240f565b8152602001906001900390816108a75790505b5085602001515f0181905250600281600281106108e2576108e1612d63565b5b6101020201610101015f9054906101000a900460ff1685602001516020019060ff16908160ff16815250505f5f90505b828111610bb257610949816002846002811061093157610930612d63565b5b610102020161010001546121e590919063ffffffff16565b610b9f576002826002811061096157610960612d63565b5b61010202015f0181610100811061097b5761097a612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1693508386602001515f015182815181106109b9576109b8612d63565b5b60200260200101515f019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050610a268160028760028110610a0e57610a0d612d63565b5b610102020161010001546121e590919063ffffffff16565b80610aab57508373ffffffffffffffffffffffffffffffffffffffff1660028660028110610a5757610a56612d63565b5b61010202015f01826101008110610a7157610a70612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b15610b9e5760015f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f208054610af890613000565b80601f0160208091040260200160405190810160405280929190818152602001828054610b2490613000565b8015610b6f5780601f10610b4657610100808354040283529160200191610b6f565b820191905f5260205f20905b815481529060010190602001808311610b5257829003601f168201915b505050505086602001515f01518281518110610b8e57610b8d612d63565b5b6020026020010151602001819052505b5b8080610baa90613030565b915050610912565b5050610be9565b60026102065f9054906101000a900467ffffffffffffffff16610bdc9190612d33565b67ffffffffffffffff1692505b610c0f60028460028110610c0057610bff612d63565b5b6101020201610100015461220e565b9050600181610c1e9190612f73565b67ffffffffffffffff811115610c3757610c36612fa6565b5b604051908082528060200260200182016040528015610c7057816020015b610c5d61240f565b815260200190600190039081610c555790505b50845f01515f018190525060028360028110610c8f57610c8e612d63565b5b6101020201610101015f9054906101000a900460ff16845f01516020019060ff16908160ff16815250505f5f90505b818111610ea157610cf58160028660028110610cdd57610cdc612d63565b5b610102020161010001546121e590919063ffffffff16565b610e8e5760028460028110610d0d57610d0c612d63565b5b61010202015f01816101008110610d2757610d26612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16925082855f01515f01518281518110610d6457610d63612d63565b5b60200260200101515f019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f208054610de990613000565b80601f0160208091040260200160405190810160405280929190818152602001828054610e1590613000565b8015610e605780601f10610e3757610100808354040283529160200191610e60565b820191905f5260205f20905b815481529060010190602001808311610e4357829003601f168201915b5050505050855f01515f01518281518110610e7e57610e7d612d63565b5b6020026020010151602001819052505b8080610e9990613030565b915050610cbe565b506102065f9054906101000a900467ffffffffffffffff16846040019067ffffffffffffffff16908167ffffffffffffffff168152505061020a5f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684608001515f019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505061020b5f9054906101000a90046fffffffffffffffffffffffffffffffff168460a001906fffffffffffffffffffffffffffffffff1690816fffffffffffffffffffffffffffffffff16815250508394505050505090565b610f9b8282905061221f565b818160015f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f209182610fe7929190613218565b505050565b610ff461217b565b611033576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161102a90612b8c565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff1661020a5f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146110c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110bc90612dda565b60405180910390fd5b5f61020a5f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff168092919061113690612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507ff91067eb420c28d3124865fc996e6aa9d541b9b4fef9188cb965a6cc6491638e3361020b5f9054906101000a90046fffffffffffffffffffffffffffffffff166040516111bc9291906132e5565b60405180910390a1565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611254576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161124b90612b24565b60405180910390fd5b61125c6121d5565b61129b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161129290612c80565b60405180910390fd5b6102065f81819054906101000a900467ffffffffffffffff16809291906112c19061330c565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550505f6102086001018190555061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff168092919061132190612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507ff73240422246f63ed633ef3ce0726b8ab8fb69d46c8a4e5ecb0b2922668674a16102085f015f9054906101000a900467ffffffffffffffff1661020b5f9054906101000a90046fffffffffffffffffffffffffffffffff166040516113bf929190613333565b60405180910390a1565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611457576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161144e90612b24565b60405180910390fd5b61145f6121d5565b1561149f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611496906133a4565b60405180910390fd5b6114a761217b565b156114e7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114de9061340c565b60405180910390fd5b6102085f015f81819054906101000a900467ffffffffffffffff168092919061150f9061342a565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550505f60026102065f9054906101000a900467ffffffffffffffff1661155a9190612d33565b67ffffffffffffffff1690506102065f81819054906101000a900467ffffffffffffffff168092919061158c9061342a565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550505f60026102065f9054906101000a900467ffffffffffffffff166115d79190612d33565b67ffffffffffffffff1690505f5f90505b61160e600284600281106115ff576115fe612d63565b5b6101020201610100015461220e565b81116117b2576002836002811061162857611627612d63565b5b61010202015f0181610100811061164257611641612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166002836002811061168d5761168c612d63565b5b61010202015f018261010081106116a7576116a6612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461179f57600283600281106116f7576116f6612d63565b5b61010202015f0181610100811061171157611710612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff166002836002811061174657611745612d63565b5b61010202015f018261010081106117605761175f612d63565b5b015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b80806117aa90613030565b9150506115e8565b505f600283600281106117c8576117c7612d63565b5b6101020201610100015490505f5f5f5f90505b86805f01906117ea9190613465565b90508110156119465786805f01906118029190613465565b8281811061181357611812612d63565b5b9050604002015f01602081019061182a91906129ed565b925086805f019061183b9190613465565b8281811061184c5761184b612d63565b5b90506040020160200160208101906118649190612a9f565b91505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036118b3576118ac83856121fa90919063ffffffff16565b93506118c9565b6118c683856122bd90919063ffffffff16565b93505b81600286600281106118de576118dd612d63565b5b61010202015f018460ff1661010081106118fb576118fa612d63565b5b015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080806001019150506117db565b50826002856002811061195c5761195b612d63565b5b6101020201610100018190555085602001602081019061197c91906129ed565b600285600281106119905761198f612d63565b5b6101020201610101015f6101000a81548160ff021916908360ff160217905550826102086001018190555061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff16809291906119e990612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507f78dad2bc0b47c688ed84f3fee79abc18e6c9822db05a79ca19dff54533c7470d6102085f015f9054906101000a900467ffffffffffffffff168761020b5f9054906101000a90046fffffffffffffffffffffffffffffffff16604051611a899392919061368b565b60405180910390a1505050505050565b611aa16121d5565b15611ae1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ad8906133a4565b60405180910390fd5b611ae961217b565b15611b29576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b209061340c565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff166002806102065f9054906101000a900467ffffffffffffffff16611b649190612d33565b67ffffffffffffffff1660028110611b7f57611b7e612d63565b5b61010202015f018260ff166101008110611b9c57611b9b612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611c13576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c0a90612dda565b60405180910390fd5b3361020a5f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff1680929190611c8490612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507fbc2748cf02f7a1291525e866efc76ab3b96d32d7afcbb26c53daec617b38b4793361020b5f9054906101000a90046fffffffffffffffffffffffffffffffff16604051611d0a9291906132e5565b60405180910390a150565b611d218282905061221f565b5f5f611d2b6121d5565b15611ea1573373ffffffffffffffffffffffffffffffffffffffff1660028060016102065f9054906101000a900467ffffffffffffffff16611d6d9190612f38565b611d779190612d33565b67ffffffffffffffff1660028110611d9257611d91612d63565b5b61010202015f018660ff166101008110611daf57611dae612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614915081611e9c573373ffffffffffffffffffffffffffffffffffffffff166002806102065f9054906101000a900467ffffffffffffffff16611e299190612d33565b67ffffffffffffffff1660028110611e4457611e43612d63565b5b61010202015f018660ff166101008110611e6157611e60612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161490505b611f4f565b3373ffffffffffffffffffffffffffffffffffffffff166002806102065f9054906101000a900467ffffffffffffffff16611edc9190612d33565b67ffffffffffffffff1660028110611ef757611ef6612d63565b5b61010202015f018660ff166101008110611f1457611f13612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161491505b8180611f585750805b611f97576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f8e90612dda565b60405180910390fd5b838360015f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f209182611fe3929190613218565b5061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff168092919061201290612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507f125181ec21882dec51a2392905dff3a82cbd0262f18b5c0c035488671b40afb233858561020b5f9054906101000a90046fffffffffffffffffffffffffffffffff1660405161209c9493929190613711565b60405180910390a15050505050565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612139576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161213090612b24565b60405180910390fd5b805f5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b5f5f73ffffffffffffffffffffffffffffffffffffffff1661020a5f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415905090565b5f5f610208600101541415905090565b5f5f8260ff166001901b841614905092915050565b5f8160ff166001901b198316905092915050565b5f612218826122d0565b9050919050565b5f8111612261576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161225890613799565b60405180910390fd5b6102075f015f9054906101000a900461ffff1661ffff168111156122ba576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122b190613801565b60405180910390fd5b50565b5f8160ff166001901b8317905092915050565b5f60076122ee6fffffffffffffffffffffffffffffffff841161239c565b901b9050600661230a67ffffffffffffffff8385901c1161239c565b901b81179050600561232463ffffffff8385901c1161239c565b901b81179050600461233c61ffff8385901c1161239c565b901b81179050600361235360ff8385901c1161239c565b901b81179050600261236a600f8385901c1161239c565b901b811790507d01010202020203030303030303030000000000000000000000000000000082821c1a81179050919050565b5f8115159050919050565b6040518060c001604052806123ba61243e565b81526020016123c761243e565b81526020015f67ffffffffffffffff1681526020016123e461245a565b81526020016123f161247c565b81526020015f6fffffffffffffffffffffffffffffffff1681525090565b60405180604001604052805f73ffffffffffffffffffffffffffffffffffffffff168152602001606081525090565b6040518060400160405280606081526020015f60ff1681525090565b60405180604001604052805f67ffffffffffffffff1681526020015f81525090565b60405180602001604052805f73ffffffffffffffffffffffffffffffffffffffff1681525090565b5f5ffd5b5f5ffd5b5f67ffffffffffffffff82169050919050565b6124c8816124ac565b81146124d2575f5ffd5b50565b5f813590506124e3816124bf565b92915050565b5f60ff82169050919050565b6124fe816124e9565b8114612508575f5ffd5b50565b5f81359050612519816124f5565b92915050565b5f5f60408385031215612535576125346124a4565b5b5f612542858286016124d5565b92505060206125538582860161250b565b9150509250929050565b5f5ffd5b5f602082840312156125765761257561255d565b5b81905092915050565b5f60208284031215612594576125936124a4565b5b5f6125a184828501612561565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6125fc826125d3565b9050919050565b61260c816125f2565b82525050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61265482612612565b61265e818561261c565b935061266e81856020860161262c565b6126778161263a565b840191505092915050565b5f604083015f8301516126975f860182612603565b50602083015184820360208601526126af828261264a565b9150508091505092915050565b5f6126c78383612682565b905092915050565b5f602082019050919050565b5f6126e5826125aa565b6126ef81856125b4565b935083602082028501612701856125c4565b805f5b8581101561273c578484038952815161271d85826126bc565b9450612728836126cf565b925060208a01995050600181019050612704565b50829750879550505050505092915050565b612757816124e9565b82525050565b5f604083015f8301518482035f86015261277782826126db565b915050602083015161278c602086018261274e565b508091505092915050565b6127a0816124ac565b82525050565b5f819050919050565b6127b8816127a6565b82525050565b604082015f8201516127d25f850182612797565b5060208201516127e560208501826127af565b50505050565b602082015f8201516127ff5f850182612603565b50505050565b5f6fffffffffffffffffffffffffffffffff82169050919050565b61282981612805565b82525050565b5f60e083015f8301518482035f860152612849828261275d565b91505060208301518482036020860152612863828261275d565b91505060408301516128786040860182612797565b50606083015161288b60608601826127be565b50608083015161289e60a08601826127eb565b5060a08301516128b160c0860182612820565b508091505092915050565b5f6020820190508181035f8301526128d4818461282f565b905092915050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f83601f8401126128fd576128fc6128dc565b5b8235905067ffffffffffffffff81111561291a576129196128e0565b5b602083019150836001820283011115612936576129356128e4565b5b9250929050565b5f5f60208385031215612953576129526124a4565b5b5f83013567ffffffffffffffff8111156129705761296f6124a8565b5b61297c858286016128e8565b92509250509250929050565b5f6040828403121561299d5761299c61255d565b5b81905092915050565b5f602082840312156129bb576129ba6124a4565b5b5f82013567ffffffffffffffff8111156129d8576129d76124a8565b5b6129e484828501612988565b91505092915050565b5f60208284031215612a0257612a016124a4565b5b5f612a0f8482850161250b565b91505092915050565b5f5f5f60408486031215612a2f57612a2e6124a4565b5b5f612a3c8682870161250b565b935050602084013567ffffffffffffffff811115612a5d57612a5c6124a8565b5b612a69868287016128e8565b92509250509250925092565b612a7e816125f2565b8114612a88575f5ffd5b50565b5f81359050612a9981612a75565b92915050565b5f60208284031215612ab457612ab36124a4565b5b5f612ac184828501612a8b565b91505092915050565b5f82825260208201905092915050565b7f6e6f7420746865206f776e6572000000000000000000000000000000000000005f82015250565b5f612b0e600d83612aca565b9150612b1982612ada565b602082019050919050565b5f6020820190508181035f830152612b3b81612b02565b9050919050565b7f6e6f206d61696e74656e616e63650000000000000000000000000000000000005f82015250565b5f612b76600e83612aca565b9150612b8182612b42565b602082019050919050565b5f6020820190508181035f830152612ba381612b6a565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f612be182612805565b91506fffffffffffffffffffffffffffffffff8203612c0357612c02612baa565b5b600182019050919050565b612c1781612805565b82525050565b5f602082019050612c305f830184612c0e565b92915050565b7f6e6f206d6967726174696f6e00000000000000000000000000000000000000005f82015250565b5f612c6a600c83612aca565b9150612c7582612c36565b602082019050919050565b5f6020820190508181035f830152612c9781612c5e565b9050919050565b7f77726f6e67206d6967726174696f6e20696400000000000000000000000000005f82015250565b5f612cd2601283612aca565b9150612cdd82612c9e565b602082019050919050565b5f6020820190508181035f830152612cff81612cc6565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f612d3d826124ac565b9150612d48836124ac565b925082612d5857612d57612d06565b5b828206905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f77726f6e67206f70657261746f720000000000000000000000000000000000005f82015250565b5f612dc4600e83612aca565b9150612dcf82612d90565b602082019050919050565b5f6020820190508181035f830152612df181612db8565b9050919050565b612e01816124ac565b82525050565b612e10816125f2565b82525050565b5f606082019050612e295f830186612df8565b612e366020830185612e07565b612e436040830184612c0e565b949350505050565b5f61ffff82169050919050565b612e6181612e4b565b8114612e6b575f5ffd5b50565b5f8135612e7a81612e58565b80915050919050565b5f815f1b9050919050565b5f61ffff612e9b84612e83565b9350801983169250808416831791505092915050565b5f819050919050565b5f612ed4612ecf612eca84612e4b565b612eb1565b612e4b565b9050919050565b5f819050919050565b612eed82612eba565b612f00612ef982612edb565b8354612e8e565b8255505050565b5f81015f830180612f1781612e6e565b9050612f238184612ee4565b5050505050565b612f348282612f07565b5050565b5f612f42826124ac565b9150612f4d836124ac565b9250828203905067ffffffffffffffff811115612f6d57612f6c612baa565b5b92915050565b5f612f7d826127a6565b9150612f88836127a6565b9250828201905080821115612fa057612f9f612baa565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061301757607f821691505b60208210810361302a57613029612fd3565b5b50919050565b5f61303a826127a6565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361306c5761306b612baa565b5b600182019050919050565b5f82905092915050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026130dd7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826130a2565b6130e786836130a2565b95508019841693508086168417925050509392505050565b5f61311961311461310f846127a6565b612eb1565b6127a6565b9050919050565b5f819050919050565b613132836130ff565b61314661313e82613120565b8484546130ae565b825550505050565b5f5f905090565b61315d61314e565b613168818484613129565b505050565b5b8181101561318b576131805f82613155565b60018101905061316e565b5050565b601f8211156131d0576131a181613081565b6131aa84613093565b810160208510156131b9578190505b6131cd6131c585613093565b83018261316d565b50505b505050565b5f82821c905092915050565b5f6131f05f19846008026131d5565b1980831691505092915050565b5f61320883836131e1565b9150826002028217905092915050565b6132228383613077565b67ffffffffffffffff81111561323b5761323a612fa6565b5b6132458254613000565b61325082828561318f565b5f601f83116001811461327d575f841561326b578287013590505b61327585826131fd565b8655506132dc565b601f19841661328b86613081565b5f5b828110156132b25784890135825560018201915060208501945060208101905061328d565b868310156132cf57848901356132cb601f8916826131e1565b8355505b6001600288020188555050505b50505050505050565b5f6040820190506132f85f830185612e07565b6133056020830184612c0e565b9392505050565b5f613316826124ac565b91505f820361332857613327612baa565b5b600182039050919050565b5f6040820190506133465f830185612df8565b6133536020830184612c0e565b9392505050565b7f6d6967726174696f6e20696e2070726f677265737300000000000000000000005f82015250565b5f61338e601583612aca565b91506133998261335a565b602082019050919050565b5f6020820190508181035f8301526133bb81613382565b9050919050565b7f6d61696e74656e616e636520696e2070726f67726573730000000000000000005f82015250565b5f6133f6601783612aca565b9150613401826133c2565b602082019050919050565b5f6020820190508181035f830152613423816133ea565b9050919050565b5f613434826124ac565b915067ffffffffffffffff820361344e5761344d612baa565b5b600182019050919050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f8335600160200384360303811261348157613480613459565b5b80840192508235915067ffffffffffffffff8211156134a3576134a261345d565b5b6020830192506040820236038313156134bf576134be613461565b5b509250929050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f833560016020038436030381126134ef576134ee6134cf565b5b83810192508235915060208301925067ffffffffffffffff821115613517576135166134c7565b5b60408202360383131561352d5761352c6134cb565b5b509250929050565b5f82825260208201905092915050565b5f819050919050565b5f61355c602084018461250b565b905092915050565b5f6135726020840184612a8b565b905092915050565b6040820161358a5f83018361354e565b6135965f85018261274e565b506135a46020830183613564565b6135b16020850182612603565b50505050565b5f6135c2838361357a565b60408301905092915050565b5f82905092915050565b5f604082019050919050565b5f6135ef8385613535565b93506135fa82613545565b805f5b858110156136325761360f82846135ce565b61361988826135b7565b9750613624836135d8565b9250506001810190506135fd565b5085925050509392505050565b5f604083016136505f8401846134d3565b8583035f8701526136628382846135e4565b92505050613673602084018461354e565b613680602086018261274e565b508091505092915050565b5f60608201905061369e5f830186612df8565b81810360208301526136b0818561363f565b90506136bf6040830184612c0e565b949350505050565b5f82825260208201905092915050565b828183375f83830152505050565b5f6136f083856136c7565b93506136fd8385846136d7565b6137068361263a565b840190509392505050565b5f6060820190506137245f830187612e07565b81810360208301526137378185876136e5565b90506137466040830184612c0e565b95945050505050565b7f656d707479206f70657261746f722064617461000000000000000000000000005f82015250565b5f613783601383612aca565b915061378e8261374f565b602082019050919050565b5f6020820190508181035f8301526137b081613777565b9050919050565b7f6f70657261746f72206461746120746f6f206c617267650000000000000000005f82015250565b5f6137eb601783612aca565b91506137f6826137b7565b602082019050919050565b5f6020820190508181035f830152613818816137df565b905091905056fea26469706673582212205070bfb78cba4fb204ce3a9ae24b5f710c62732176365ee8389cdab18c3c2d7164736f6c634300081c0033 /// ``` #[rustfmt::skip] #[allow(clippy::all)] pub static DEPLOYED_BYTECODE: alloy_sol_types::private::Bytes = alloy_sol_types::private::Bytes::from_static( - b"`\x80`@R4\x80\x15a\0\x0FW__\xFD[P`\x046\x10a\0\xA7W_5`\xE0\x1C\x80c\xAD6\xE6\xD0\x11a\0oW\x80c\xAD6\xE6\xD0\x14a\x01\x15W\x80c\xC10\x80\x9A\x14a\x01\x1FW\x80c\xCCEf*\x14a\x01)W\x80c\xF2\xFD\xE3\x8B\x14a\x01EW\x80c\xF5\xF2\xD9\xF1\x14a\x01aW\x80c\xFF\xD7@\xDF\x14a\x01kWa\0\xA7V[\x80c0H\xBF\xBA\x14a\0\xABW\x80c@\x99\0\xE8\x14a\0\xB5W\x80cH\x86\xF6,\x14a\0\xD1W\x80cl\x0Ba\xB9\x14a\0\xDBW\x80cuA\x8B\x9D\x14a\0\xF7W[__\xFD[a\0\xB3a\x01\x87V[\0[a\0\xCF`\x04\x806\x03\x81\x01\x90a\0\xCA\x91\x90a9\xE2V[a\x02\xDBV[\0[a\0\xD9a\x03~V[\0[a\0\xF5`\x04\x806\x03\x81\x01\x90a\0\xF0\x91\x90a:+V[a\x08,V[\0[a\0\xFFa\tVV[`@Qa\x01\x0C\x91\x90a?GV[`@Q\x80\x91\x03\x90\xF3[a\x01\x1Da\nXV[\0[a\x01'a\x0B}V[\0[a\x01C`\x04\x806\x03\x81\x01\x90a\x01>\x91\x90a@\x1DV[a\x0C\xD1V[\0[a\x01_`\x04\x806\x03\x81\x01\x90a\x01Z\x91\x90a@\xC5V[a\x10;V[\0[a\x01ia\x11\x0BV[\0[a\x01\x85`\x04\x806\x03\x81\x01\x90a\x01\x80\x91\x90aA\x1AV[a\x12zV[\0[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x02\x15W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x02\x0C\x90aA\x9FV[`@Q\x80\x91\x03\x90\xFD[a\x02\x1F`\ta\x14\x0EV[`\n`\x08\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x02M\x90aA\xEAV[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\x8F\xB9\xCD\x05M\n\x02!\x10\xCC\xED#\x9E\x90\x8B\x83NL\xD2\x19Q\x18V\xD4\xEA\xAE0Q\xD92\xD6\x04`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x02\xD1\x91\x90aB0V[`@Q\x80\x91\x03\x90\xA1V[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x03iW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x03`\x90aA\x9FV[`@Q\x80\x91\x03\x90\xFD[\x80`\x01\x81\x81a\x03x\x91\x90aC\xC4V[\x90PPPV[a\x03\x923`\x05a\x14\xC6\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[`\n`\x08\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x03\xC0\x90aA\xEAV[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\xA7j\x8F\xC1\xA9\x02f\xDD\xEE\x897\xA1\x8E\x12\xF0\x1E\xAD\xE9F\xB3\xB6a\x97\xFF\xF2\x89\xAF\x92w\xC2\xBD%3`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x04F\x92\x91\x90aC\xE1V[`@Q\x80\x91\x03\x90\xA1_`\x05`\x03\x01_\x90T\x90a\x01\0\n\x90\x04`\xFF\x16`\xFF\x16\x11a\x08*W__\x90P[`\x05_\x01\x80T\x90P\x81\x10\x15a\x04\xDBWa\x04\xCE`\x05_\x01\x82\x81T\x81\x10a\x04\x96Wa\x04\x95aD\x08V[[\x90_R` _ \x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02a\x15\xE4\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x80\x80`\x01\x01\x91PPa\x04nV[P__\x90P[`\x05`\x01\x01\x80T\x90P\x81\x10\x15a\x07\x18Wa\x07\x0B`\x05`\x01\x01\x82\x81T\x81\x10a\x05\x0BWa\x05\naD\x08V[[\x90_R` _ \x90`\x03\x02\x01`@Q\x80``\x01`@R\x90\x81_\x82\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01`\x01\x82\x01\x80T\x80` \x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01_\x90[\x82\x82\x10\x15a\x06cW\x83\x82\x90_R` _ \x90`\x02\x02\x01`@Q\x80`@\x01`@R\x90\x81_\x82\x01T\x81R` \x01`\x01\x82\x01\x80Ta\x05\xD4\x90aDbV[\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01\x82\x80Ta\x06\0\x90aDbV[\x80\x15a\x06KW\x80`\x1F\x10a\x06\"Wa\x01\0\x80\x83T\x04\x02\x83R\x91` \x01\x91a\x06KV[\x82\x01\x91\x90_R` _ \x90[\x81T\x81R\x90`\x01\x01\x90` \x01\x80\x83\x11a\x06.W\x82\x90\x03`\x1F\x16\x82\x01\x91[PPPPP\x81RPP\x81R` \x01\x90`\x01\x01\x90a\x05\x9AV[PPPP\x81R` \x01`\x02\x82\x01\x80Ta\x06{\x90aDbV[\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01\x82\x80Ta\x06\xA7\x90aDbV[\x80\x15a\x06\xF2W\x80`\x1F\x10a\x06\xC9Wa\x01\0\x80\x83T\x04\x02\x83R\x91` \x01\x91a\x06\xF2V[\x82\x01\x91\x90_R` _ \x90[\x81T\x81R\x90`\x01\x01\x90` \x01\x80\x83\x11a\x06\xD5W\x82\x90\x03`\x1F\x16\x82\x01\x91[PPPPP\x81RPP`\x02a\x18v\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x80\x80`\x01\x01\x91PPa\x04\xE1V[P`\n_\x81\x81\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x07>\x90aD\x92V[\x91\x90a\x01\0\n\x81T\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPPa\x07o`\x05a\x1B\x03V[`\n`\x08\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x07\x9D\x90aA\xEAV[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\x11\xCEP\x16\x0Ef\x10\x057\xFDK\n\xE2m\xE6mQ\xDA\xB7\x13\xAD\x9213S\xA1\x8C$\xE8\xF6\xDA\xAB`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x08!\x91\x90aB0V[`@Q\x80\x91\x03\x90\xA1[V[a\x08@3`\x02a\x1B\xAC\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x08\x7FW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x08v\x90aE\x0BV[`@Q\x80\x91\x03\x90\xFD[a\x08\x953\x82`\x02a\x1D\x04\x90\x92\x91\x90c\xFF\xFF\xFF\xFF\x16V[`\n`\x08\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x08\xC3\x90aA\xEAV[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7Fj\xDF\xB8\x96\xD3@v\x81\xD0_\xB8t\xD4\xDF\xB7\x06\x8En*6\xF0\x9A\xCD8\xA3\xB7\xD0L\x01t_\xEE3\x82`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\tK\x93\x92\x91\x90aF3V[`@Q\x80\x91\x03\x90\xA1PV[a\t^a7FV[`@Q\x80`\xA0\x01`@R\x80a\ts`\x02a\x1D\x96V[\x81R` \x01a\t\x8F`\x02_\x01`\x05a\x1F\x99\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x81R` \x01`\t`@Q\x80` \x01`@R\x90\x81_\x82\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RPP\x81R` \x01`\n_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RP\x90P\x90V[a\nl3`\x02a\x1B\xAC\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\n\xABW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\n\xA2\x90aE\x0BV[`@Q\x80\x91\x03\x90\xFD[a\n\xBF3`\ta'\0\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[`\n`\x08\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\n\xED\x90aA\xEAV[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\xF9\x10g\xEBB\x0C(\xD3\x12He\xFC\x99nj\xA9\xD5A\xB9\xB4\xFE\xF9\x18\x8C\xB9e\xA6\xCCd\x91c\x8E3`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x0Bs\x92\x91\x90aC\xE1V[`@Q\x80\x91\x03\x90\xA1V[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x0C\x0BW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x0C\x02\x90aA\x9FV[`@Q\x80\x91\x03\x90\xFD[a\x0C\x15`\x05a('V[`\n`\x08\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x0CC\x90aA\xEAV[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\x9C\xE1\x92\xAE\xA5\xFA\xF2\x15\x1B\xBC$l\xD8\x91\x8D.\xBAp/\xA2iQ\xF6\x7F+\xF7\xB3\x81~h\x9D\x98`\n`\x08\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x0C\xC7\x91\x90aB0V[`@Q\x80\x91\x03\x90\xA1V[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\r_W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\rV\x90aA\x9FV[`@Q\x80\x91\x03\x90\xFD[a\ri`\ta({V[\x15a\r\xA9W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\r\xA0\x90aF\xB9V[`@Q\x80\x91\x03\x90\xFD[__\x90P[\x84\x84\x90P\x81\x10\x15a\x0E@Wa\r\xF4\x85\x85\x83\x81\x81\x10a\r\xCFWa\r\xCEaD\x08V[[\x90P` \x02\x01` \x81\x01\x90a\r\xE4\x91\x90a@\xC5V[`\x02a\x1B\xAC\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x0E3W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x0E*\x90aG!V[`@Q\x80\x91\x03\x90\xFD[\x80\x80`\x01\x01\x91PPa\r\xAEV[P__\x90P[\x82\x82\x90P\x81\x10\x15a\x0F%Wa\x0E\x8F\x83\x83\x83\x81\x81\x10a\x0EgWa\x0EfaD\x08V[[\x90P` \x02\x81\x01\x90a\x0Ey\x91\x90aGKV[\x80` \x01\x90a\x0E\x88\x91\x90aGrV[\x90Pa(\xD5V[a\x0E\xD8\x83\x83\x83\x81\x81\x10a\x0E\xA5Wa\x0E\xA4aD\x08V[[\x90P` \x02\x81\x01\x90a\x0E\xB7\x91\x90aGKV[_\x01` \x81\x01\x90a\x0E\xC8\x91\x90a@\xC5V[`\x02a\x1B\xAC\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x15a\x0F\x18W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x0F\x0F\x90aH\x1EV[`@Q\x80\x91\x03\x90\xFD[\x80\x80`\x01\x01\x91PPa\x0EFV[Pa\x0FT\x82\x82\x90P\x85\x85\x90Pa\x0F;`\x02a)tV[a\x0FE\x91\x90aH&\x82\x82a=\xB0V[\x91PP` \x83\x01Q\x84\x82\x03` \x86\x01Ra>@\x82\x82a<\xCAV[\x91PP`@\x83\x01Q\x84\x82\x03`@\x86\x01Ra>Z\x82\x82a=\xB0V[\x91PP\x80\x91PP\x92\x91PPV[` \x82\x01_\x82\x01Qa>{_\x85\x01\x82a:\xCBV[PPPPV[_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[a>\x9D\x81a>\x81V[\x82RPPV[_o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[a>\xC7\x81a>\xA3V[\x82RPPV[_`\xA0\x83\x01_\x83\x01Q\x84\x82\x03_\x86\x01Ra>\xE7\x82\x82a==V[\x91PP` \x83\x01Q\x84\x82\x03` \x86\x01Ra?\x01\x82\x82a>\x0CV[\x91PP`@\x83\x01Qa?\x16`@\x86\x01\x82a>gV[P``\x83\x01Qa?)``\x86\x01\x82a>\x94V[P`\x80\x83\x01Qa?<`\x80\x86\x01\x82a>\xBEV[P\x80\x91PP\x92\x91PPV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra?_\x81\x84a>\xCDV[\x90P\x92\x91PPV[__\xFD[__\xFD[__\xFD[__\x83`\x1F\x84\x01\x12a?\x88Wa?\x87a?gV[[\x825\x90Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a?\xA5Wa?\xA4a?kV[[` \x83\x01\x91P\x83` \x82\x02\x83\x01\x11\x15a?\xC1Wa?\xC0a?oV[[\x92P\x92\x90PV[__\x83`\x1F\x84\x01\x12a?\xDDWa?\xDCa?gV[[\x825\x90Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a?\xFAWa?\xF9a?kV[[` \x83\x01\x91P\x83` \x82\x02\x83\x01\x11\x15a@\x16Wa@\x15a?oV[[\x92P\x92\x90PV[____`@\x85\x87\x03\x12\x15a@5Wa@4a9\xB8V[[_\x85\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a@RWa@Qa9\xBCV[[a@^\x87\x82\x88\x01a?sV[\x94P\x94PP` \x85\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a@\x81Wa@\x80a9\xBCV[[a@\x8D\x87\x82\x88\x01a?\xC8V[\x92P\x92PP\x92\x95\x91\x94P\x92PV[a@\xA4\x81a:\xBAV[\x81\x14a@\xAEW__\xFD[PV[_\x815\x90Pa@\xBF\x81a@\x9BV[\x92\x91PPV[_` \x82\x84\x03\x12\x15a@\xDAWa@\xD9a9\xB8V[[_a@\xE7\x84\x82\x85\x01a@\xB1V[\x91PP\x92\x91PPV[a@\xF9\x81a;\x03V[\x81\x14aA\x03W__\xFD[PV[_\x815\x90PaA\x14\x81a@\xF0V[\x92\x91PPV[_` \x82\x84\x03\x12\x15aA/WaA.a9\xB8V[[_aA<\x84\x82\x85\x01aA\x06V[\x91PP\x92\x91PPV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[\x7Fnot the owner\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aA\x89`\r\x83aAEV[\x91PaA\x94\x82aAUV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaA\xB6\x81aA}V[\x90P\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`\x11`\x04R`$_\xFD[_aA\xF4\x82a>\xA3V[\x91Po\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x03aB\x16WaB\x15aA\xBDV[[`\x01\x82\x01\x90P\x91\x90PV[aB*\x81a>\xA3V[\x82RPPV[_` \x82\x01\x90PaBC_\x83\x01\x84aB!V[\x92\x91PPV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R_`\x04R`$_\xFD[_`\xFF\x82\x16\x90P\x91\x90PV[aB\x8A\x81aBuV[\x81\x14aB\x94W__\xFD[PV[_\x815aB\xA3\x81aB\x81V[\x80\x91PP\x91\x90PV[_\x81_\x1B\x90P\x91\x90PV[_`\xFFaB\xC3\x84aB\xACV[\x93P\x80\x19\x83\x16\x92P\x80\x84\x16\x83\x17\x91PP\x92\x91PPV[_\x81\x90P\x91\x90PV[_aB\xFCaB\xF7aB\xF2\x84aBuV[aB\xD9V[aBuV[\x90P\x91\x90PV[_\x81\x90P\x91\x90PV[aC\x15\x82aB\xE2V[aC(aC!\x82aC\x03V[\x83TaB\xB7V[\x82UPPPV[_\x81`\x08\x1B\x90P\x91\x90PV[_a\xFF\0aCH\x84aC/V[\x93P\x80\x19\x83\x16\x92P\x80\x84\x16\x83\x17\x91PP\x92\x91PPV[aCg\x82aB\xE2V[aCzaCs\x82aC\x03V[\x83TaC;V[\x82UPPPV[_\x81\x01_\x83\x01\x80aC\x91\x81aB\x97V[\x90PaC\x9D\x81\x84aC\x0CV[PPP_\x81\x01` \x83\x01\x80aC\xB1\x81aB\x97V[\x90PaC\xBD\x81\x84aC^V[PPPPPV[aC\xCE\x82\x82aC\x81V[PPV[aC\xDB\x81a:\xBAV[\x82RPPV[_`@\x82\x01\x90PaC\xF4_\x83\x01\x85aC\xD2V[aD\x01` \x83\x01\x84aB!V[\x93\x92PPPV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`2`\x04R`$_\xFD[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`\"`\x04R`$_\xFD[_`\x02\x82\x04\x90P`\x01\x82\x16\x80aDyW`\x7F\x82\x16\x91P[` \x82\x10\x81\x03aD\x8CWaD\x8BaD5V[[P\x91\x90PV[_aD\x9C\x82a>\x81V[\x91Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x03aD\xB6WaD\xB5aA\xBDV[[`\x01\x82\x01\x90P\x91\x90PV[\x7Fnot an operator\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aD\xF5`\x0F\x83aAEV[\x91PaE\0\x82aD\xC1V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaE\"\x81aD\xE9V[\x90P\x91\x90PV[_aE7` \x84\x01\x84aA\x06V[\x90P\x92\x91PPV[__\xFD[__\xFD[__\xFD[__\x835`\x01` \x03\x846\x03\x03\x81\x12aEgWaEfaEGV[[\x83\x81\x01\x92P\x825\x91P` \x83\x01\x92Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15aE\x8FWaE\x8EaE?V[[`\x01\x82\x026\x03\x83\x13\x15aE\xA5WaE\xA4aECV[[P\x92P\x92\x90PV[\x82\x81\x837_\x83\x83\x01RPPPV[_aE\xC6\x83\x85a;%V[\x93PaE\xD3\x83\x85\x84aE\xADV[aE\xDC\x83a;CV[\x84\x01\x90P\x93\x92PPPV[_`@\x83\x01aE\xF8_\x84\x01\x84aE)V[aF\x04_\x86\x01\x82a;\x0CV[PaF\x12` \x84\x01\x84aEKV[\x85\x83\x03` \x87\x01RaF%\x83\x82\x84aE\xBBV[\x92PPP\x80\x91PP\x92\x91PPV[_``\x82\x01\x90PaFF_\x83\x01\x86aC\xD2V[\x81\x81\x03` \x83\x01RaFX\x81\x85aE\xE7V[\x90PaFg`@\x83\x01\x84aB!V[\x94\x93PPPPV[\x7Fmaintenance in progress\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aF\xA3`\x17\x83aAEV[\x91PaF\xAE\x82aFoV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaF\xD0\x81aF\x97V[\x90P\x91\x90PV[\x7Funknown operator\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aG\x0B`\x10\x83aAEV[\x91PaG\x16\x82aF\xD7V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaG8\x81aF\xFFV[\x90P\x91\x90PV[__\xFD[__\xFD[__\xFD[_\x825`\x01``\x03\x836\x03\x03\x81\x12aGfWaGeaG?V[[\x80\x83\x01\x91PP\x92\x91PPV[__\x835`\x01` \x03\x846\x03\x03\x81\x12aG\x8EWaG\x8DaG?V[[\x80\x84\x01\x92P\x825\x91Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15aG\xB0WaG\xAFaGCV[[` \x83\x01\x92P` \x82\x026\x03\x83\x13\x15aG\xCCWaG\xCBaGGV[[P\x92P\x92\x90PV[\x7Foperator already exists\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aH\x08`\x17\x83aAEV[\x91PaH\x13\x82aG\xD4V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaH5\x81aG\xFCV[\x90P\x91\x90PV[_aHF\x82a;\x03V[\x91PaHQ\x83a;\x03V[\x92P\x82\x82\x03\x90P\x81\x81\x11\x15aHiWaHhaA\xBDV[[\x92\x91PPV[_aHy\x82a;\x03V[\x91PaH\x84\x83a;\x03V[\x92P\x82\x82\x01\x90P\x80\x82\x11\x15aH\x9CWaH\x9BaA\xBDV[[\x92\x91PPV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[_\x81\x90P\x91\x90PV[_aH\xC9` \x84\x01\x84a@\xB1V[\x90P\x92\x91PPV[_` \x82\x01\x90P\x91\x90PV[_aH\xE8\x83\x85aH\xA2V[\x93PaH\xF3\x82aH\xB2V[\x80_[\x85\x81\x10\x15aI+WaI\x08\x82\x84aH\xBBV[aI\x12\x88\x82a=\x8DV[\x97PaI\x1D\x83aH\xD1V[\x92PP`\x01\x81\x01\x90PaH\xF6V[P\x85\x92PPP\x93\x92PPPV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[_\x81\x90P\x91\x90PV[__\x835`\x01` \x03\x846\x03\x03\x81\x12aImWaIlaEGV[[\x83\x81\x01\x92P\x825\x91P` \x83\x01\x92Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15aI\x95WaI\x94aE?V[[` \x82\x026\x03\x83\x13\x15aI\xABWaI\xAAaECV[[P\x92P\x92\x90PV[_\x81\x90P\x91\x90PV[_`@\x83\x01aI\xCD_\x84\x01\x84aE)V[aI\xD9_\x86\x01\x82a;\x0CV[PaI\xE7` \x84\x01\x84aEKV[\x85\x83\x03` \x87\x01RaI\xFA\x83\x82\x84aE\xBBV[\x92PPP\x80\x91PP\x92\x91PPV[_aJ\x13\x83\x83aI\xBCV[\x90P\x92\x91PPV[_\x825`\x01`@\x03\x836\x03\x03\x81\x12aJ6WaJ5aEGV[[\x82\x81\x01\x91PP\x92\x91PPV[_` \x82\x01\x90P\x91\x90PV[_aJY\x83\x85a:\xE4V[\x93P\x83` \x84\x02\x85\x01aJk\x84aI\xB3V[\x80_[\x87\x81\x10\x15aJ\xAEW\x84\x84\x03\x89RaJ\x85\x82\x84aJ\x1BV[aJ\x8F\x85\x82aJ\x08V[\x94PaJ\x9A\x83aJBV[\x92P` \x8A\x01\x99PP`\x01\x81\x01\x90PaJnV[P\x82\x97P\x87\x94PPPPP\x93\x92PPPV[_``\x83\x01aJ\xD1_\x84\x01\x84aH\xBBV[aJ\xDD_\x86\x01\x82a:\xCBV[PaJ\xEB` \x84\x01\x84aIQV[\x85\x83\x03` \x87\x01RaJ\xFE\x83\x82\x84aJNV[\x92PPPaK\x0F`@\x84\x01\x84aEKV[\x85\x83\x03`@\x87\x01RaK\"\x83\x82\x84aE\xBBV[\x92PPP\x80\x91PP\x92\x91PPV[_aK;\x83\x83aJ\xC0V[\x90P\x92\x91PPV[_\x825`\x01``\x03\x836\x03\x03\x81\x12aK^WaK]aEGV[[\x82\x81\x01\x91PP\x92\x91PPV[_` \x82\x01\x90P\x91\x90PV[_aK\x81\x83\x85aI8V[\x93P\x83` \x84\x02\x85\x01aK\x93\x84aIHV[\x80_[\x87\x81\x10\x15aK\xD6W\x84\x84\x03\x89RaK\xAD\x82\x84aKCV[aK\xB7\x85\x82aK0V[\x94PaK\xC2\x83aKjV[\x92P` \x8A\x01\x99PP`\x01\x81\x01\x90PaK\x96V[P\x82\x97P\x87\x94PPPPP\x93\x92PPPV[_``\x82\x01\x90P\x81\x81\x03_\x83\x01RaL\x01\x81\x87\x89aH\xDDV[\x90P\x81\x81\x03` \x83\x01RaL\x16\x81\x85\x87aKvV[\x90PaL%`@\x83\x01\x84aB!V[\x96\x95PPPPPPV[\x7Fmigration in progress\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aLc`\x15\x83aAEV[\x91PaLn\x82aL/V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaL\x90\x81aLWV[\x90P\x91\x90PV[\x7Ftoo few nodes\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aL\xCB`\r\x83aAEV[\x91PaL\xD6\x82aL\x97V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaL\xF8\x81aL\xBFV[\x90P\x91\x90PV[aM\x08\x81a;\x03V[\x82RPPV[_``\x82\x01\x90PaM!_\x83\x01\x86aC\xD2V[aM.` \x83\x01\x85aL\xFFV[aM;`@\x83\x01\x84aB!V[\x94\x93PPPPV[\x7Fnot under maintenance\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aMw`\x15\x83aAEV[\x91PaM\x82\x82aMCV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaM\xA4\x81aMkV[\x90P\x91\x90PV[\x7Fnot pulling\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aM\xDF`\x0B\x83aAEV[\x91PaM\xEA\x82aM\xABV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaN\x0C\x81aM\xD3V[\x90P\x91\x90PV[_aN\x1D\x82aBuV[\x91P_\x82\x03aN/WaN.aA\xBDV[[`\x01\x82\x03\x90P\x91\x90PV[\x7Finvalid address\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aNn`\x0F\x83aAEV[\x91PaNy\x82aN:V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaN\x9B\x81aNbV[\x90P\x91\x90PV[\x7Foperator doesn't exist\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aN\xD6`\x16\x83aAEV[\x91PaN\xE1\x82aN\xA2V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaO\x03\x81aN\xCAV[\x90P\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`1`\x04R`$_\xFD[\x7Ftoo many operators\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aOk`\x12\x83aAEV[\x91PaOv\x82aO7V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaO\x98\x81aO_V[\x90P\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`A`\x04R`$_\xFD[_\x81\x90P\x81_R` _ \x90P\x91\x90PV[_` `\x1F\x83\x01\x04\x90P\x91\x90PV[_\x82\x82\x1B\x90P\x92\x91PPV[_`\x08\x83\x02aP(\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82aO\xEDV[aP2\x86\x83aO\xEDV[\x95P\x80\x19\x84\x16\x93P\x80\x86\x16\x84\x17\x92PPP\x93\x92PPPV[_aPdaP_aPZ\x84a;\x03V[aB\xD9V[a;\x03V[\x90P\x91\x90PV[_\x81\x90P\x91\x90PV[aP}\x83aPJV[aP\x91aP\x89\x82aPkV[\x84\x84TaO\xF9V[\x82UPPPPV[__\x90P\x90V[aP\xA8aP\x99V[aP\xB3\x81\x84\x84aPtV[PPPV[[\x81\x81\x10\x15aP\xD6WaP\xCB_\x82aP\xA0V[`\x01\x81\x01\x90PaP\xB9V[PPV[`\x1F\x82\x11\x15aQ\x1BWaP\xEC\x81aO\xCCV[aP\xF5\x84aO\xDEV[\x81\x01` \x85\x10\x15aQ\x04W\x81\x90P[aQ\x18aQ\x10\x85aO\xDEV[\x83\x01\x82aP\xB8V[PP[PPPV[_\x82\x82\x1C\x90P\x92\x91PPV[_aQ;_\x19\x84`\x08\x02aQ V[\x19\x80\x83\x16\x91PP\x92\x91PPV[_aQS\x83\x83aQ,V[\x91P\x82`\x02\x02\x82\x17\x90P\x92\x91PPV[aQl\x82a;\x1BV[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15aQ\x85WaQ\x84aO\x9FV[[aQ\x8F\x82TaDbV[aQ\x9A\x82\x82\x85aP\xDAV[_` \x90P`\x1F\x83\x11`\x01\x81\x14aQ\xCBW_\x84\x15aQ\xB9W\x82\x87\x01Q\x90P[aQ\xC3\x85\x82aQHV[\x86UPaR*V[`\x1F\x19\x84\x16aQ\xD9\x86aO\xCCV[_[\x82\x81\x10\x15aR\0W\x84\x89\x01Q\x82U`\x01\x82\x01\x91P` \x85\x01\x94P` \x81\x01\x90PaQ\xDBV[\x86\x83\x10\x15aR\x1DW\x84\x89\x01QaR\x19`\x1F\x89\x16\x82aQ,V[\x83UP[`\x01`\x02\x88\x02\x01\x88UPPP[PPPPPPV[\x7Fnot in progress\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aRf`\x0F\x83aAEV[\x91PaRq\x82aR2V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaR\x93\x81aRZV[\x90P\x91\x90PV[\x7Fdata pull in progress\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aR\xCE`\x15\x83aAEV[\x91PaR\xD9\x82aR\x9AV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaR\xFB\x81aR\xC2V[\x90P\x91\x90PV[__\xFD[aS\x0F\x82a;CV[\x81\x01\x81\x81\x10g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x17\x15aS.WaS-aO\x9FV[[\x80`@RPPPV[_aS@a9\xAFV[\x90PaSL\x82\x82aS\x06V[\x91\x90PV[__\xFD[__\xFD[_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15aSsWaSraO\x9FV[[aS|\x82a;CV[\x90P` \x81\x01\x90P\x91\x90PV[_aS\x9BaS\x96\x84aSYV[aS7V[\x90P\x82\x81R` \x81\x01\x84\x84\x84\x01\x11\x15aS\xB7WaS\xB6aSUV[[aS\xC2\x84\x82\x85aE\xADV[P\x93\x92PPPV[_\x82`\x1F\x83\x01\x12aS\xDEWaS\xDDa?gV[[\x815aS\xEE\x84\x82` \x86\x01aS\x89V[\x91PP\x92\x91PPV[_`@\x82\x84\x03\x12\x15aT\x0CWaT\x0BaS\x02V[[aT\x16`@aS7V[\x90P_aT%\x84\x82\x85\x01aA\x06V[_\x83\x01RP` \x82\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15aTHWaTGaSQV[[aTT\x84\x82\x85\x01aS\xCAV[` \x83\x01RP\x92\x91PPV[_aTk6\x83aS\xF7V[\x90P\x91\x90PV[_aT|\x82a;\x03V[\x91P\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x03aT\xAEWaT\xADaA\xBDV[[`\x01\x82\x01\x90P\x91\x90PV[\x7Ftoo many nodes\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aT\xED`\x0E\x83aAEV[\x91PaT\xF8\x82aT\xB9V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaU\x1A\x81aT\xE1V[\x90P\x91\x90PV[\x7Ftoo few operators\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aUU`\x11\x83aAEV[\x91PaU`\x82aU!V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaU\x82\x81aUIV[\x90P\x91\x90PV[\x7Fmigration already in progress\0\0\0_\x82\x01RPV[_aU\xBD`\x1D\x83aAEV[\x91PaU\xC8\x82aU\x89V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaU\xEA\x81aU\xB1V[\x90P\x91\x90PV[\x7Fnothing to do\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_aV%`\r\x83aAEV[\x91PaV0\x82aU\xF1V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01RaVR\x81aV\x19V[\x90P\x91\x90PV[_aVc\x82aBuV[\x91P`\xFF\x82\x03aVvWaVuaA\xBDV[[`\x01\x82\x01\x90P\x91\x90PV[_\x815aV\x8D\x81a@\x9BV[\x80\x91PP\x91\x90PV[_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFFaV\xB5\x84aB\xACV[\x93P\x80\x19\x83\x16\x92P\x80\x84\x16\x83\x17\x91PP\x92\x91PPV[_aV\xE5aV\xE0aV\xDB\x84a:\x9BV[aB\xD9V[a:\x9BV[\x90P\x91\x90PV[_aV\xF6\x82aV\xCBV[\x90P\x91\x90PV[_aW\x07\x82aV\xECV[\x90P\x91\x90PV[_\x81\x90P\x91\x90PV[aW \x82aV\xFDV[aW3aW,\x82aW\x0EV[\x83TaV\x96V[\x82UPPPV[_\x825`\x01`@\x03\x836\x03\x03\x81\x12aWUWaWTaG?V[[\x80\x83\x01\x91PP\x92\x91PPV[_\x81T\x90P\x91\x90PV[_aWu\x82a;\x03V[\x91PaW\x80\x83a;\x03V[\x92P\x82\x82\x02aW\x8E\x81a;\x03V[\x91P\x82\x82\x04\x84\x14\x83\x15\x17aW\xA5WaW\xA4aA\xBDV[[P\x92\x91PPV[_\x81\x90PaW\xBB\x82`\x02aWkV[\x90P\x91\x90PV[_\x81\x90P\x81_R` _ \x90P\x91\x90PV[aX\x04\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x83` \x03`\x08\x02aQ V[\x81T\x81\x16\x82UPPPV[aX\x18\x81aO\xCCV[aX#\x83\x82TaQHV[\x80\x83U_\x82UPPPPV[` \x84\x10_\x81\x14aX\x89W`\x1F\x84\x11`\x01\x81\x14aXWWaXP\x86\x85aQHV[\x83UaX\x83V[aX`\x83aO\xCCV[aXwaXl\x87aO\xDEV[\x82\x01`\x01\x83\x01aP\xB8V[aX\x81\x87\x85aX\x0FV[P[PaX\xD6V[aX\x92\x82aO\xCCV[aX\x9B\x86aO\xDEV[\x81\x01`\x1F\x87\x16\x80\x15aX\xB5WaX\xB4\x81`\x01\x84\x03aW\xD4V[[aX\xC9aX\xC1\x88aO\xDEV[\x84\x01\x83aP\xB8V[`\x01\x88`\x02\x02\x17\x85UPPP[PPPPPV[h\x01\0\0\0\0\0\0\0\0\x84\x11\x15aX\xF7WaX\xF6aO\x9FV[[` \x83\x10_\x81\x14aY@W` \x85\x10_\x81\x14aY\x1EWaY\x17\x86\x85aQHV[\x83UaY:V[\x83`\xFF\x19\x16\x93P\x83aY/\x84aO\xCCV[U`\x01\x86`\x02\x02\x01\x83U[PaYJV[`\x01\x85`\x02\x02\x01\x82U[PPPPPV[\x80TaY\\\x81aDbV[\x80\x84\x11\x15aYqWaYp\x84\x82\x84\x86aX\xDDV[[\x80\x84\x10\x15aY\x86WaY\x85\x84\x82\x84\x86aX/V[[PPPPV[\x81\x81\x10\x15aY\xA9WaY\x9E_\x82aP\xA0V[`\x01\x81\x01\x90PaY\x8CV[PPV[aY\xB7_\x82aYQV[PV[_\x82\x14aY\xCAWaY\xC9aBIV[[aY\xD3\x81aY\xADV[PPV[aY\xE3__\x83\x01aP\xA0V[aY\xF0_`\x01\x83\x01aY\xBAV[PV[_\x82\x14aZ\x03WaZ\x02aBIV[[aZ\x0C\x81aY\xD7V[PPV[[\x81\x81\x10\x15aZ.WaZ#_\x82aY\xF3V[`\x02\x81\x01\x90PaZ\x11V[PPV[\x81\x83\x10\x15aZkWaZC\x82aW\xACV[aZL\x84aW\xACV[aZU\x83aW\xC2V[\x81\x81\x01\x83\x82\x01aZe\x81\x83aZ\x10V[PPPPP[PPPV[h\x01\0\0\0\0\0\0\0\0\x82\x11\x15aZ\x8AWaZ\x89aO\x9FV[[aZ\x93\x81aWaV[\x82\x82UaZ\xA1\x83\x82\x84aZ2V[PPPV[_\x82\x90P\x92\x91PPV[_\x815aZ\xBC\x81a@\xF0V[\x80\x91PP\x91\x90PV[_\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFFaZ\xF0\x84aB\xACV[\x93P\x80\x19\x83\x16\x92P\x80\x84\x16\x83\x17\x91PP\x92\x91PPV[a[\x0F\x82aPJV[a[\"a[\x1B\x82aPkV[\x83TaZ\xC5V[\x82UPPPV[__\x835`\x01` \x03\x846\x03\x03\x81\x12a[EWa[DaG?V[[\x80\x84\x01\x92P\x825\x91Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15a[gWa[faGCV[[` \x83\x01\x92P`\x01\x82\x026\x03\x83\x13\x15a[\x83Wa[\x82aGGV[[P\x92P\x92\x90PV[_\x82\x90P\x92\x91PPV[a[\x9F\x83\x83a[\x8BV[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a[\xB8Wa[\xB7aO\x9FV[[a[\xC2\x82TaDbV[a[\xCD\x82\x82\x85aP\xDAV[_`\x1F\x83\x11`\x01\x81\x14a[\xFAW_\x84\x15a[\xE8W\x82\x87\x015\x90P[a[\xF2\x85\x82aQHV[\x86UPa\\YV[`\x1F\x19\x84\x16a\\\x08\x86aO\xCCV[_[\x82\x81\x10\x15a\\/W\x84\x89\x015\x82U`\x01\x82\x01\x91P` \x85\x01\x94P` \x81\x01\x90Pa\\\nV[\x86\x83\x10\x15a\\LW\x84\x89\x015a\\H`\x1F\x89\x16\x82aQ,V[\x83UP[`\x01`\x02\x88\x02\x01\x88UPPP[PPPPPPPV[a\\m\x83\x83\x83a[\x95V[PPPV[_\x81\x01_\x83\x01\x80a\\\x82\x81aZ\xB0V[\x90Pa\\\x8E\x81\x84a[\x06V[PPP`\x01\x81\x01` \x83\x01a\\\xA3\x81\x85a[)V[a\\\xAE\x81\x83\x86a\\bV[PPPPPPV[a\\\xC0\x82\x82a\\rV[PPV[a\\\xCE\x83\x83aZ\xA6V[a\\\xD8\x81\x83aZpV[a\\\xE1\x83aI\xB3V[a\\\xEA\x83aW\xC2V[_[\x83\x81\x10\x15a] Wa\\\xFE\x83\x87aW:V[a]\x08\x81\x84a\\\xB6V[` \x84\x01\x93P`\x02\x83\x01\x92PP`\x01\x81\x01\x90Pa\\\xECV[PPPPPPPV[a]4\x83\x83\x83a\\\xC4V[PPPV[_\x81\x01_\x83\x01\x80a]I\x81aV\x81V[\x90Pa]U\x81\x84aW\x17V[PPP`\x01\x81\x01` \x83\x01a]j\x81\x85aGrV[a]u\x81\x83\x86a])V[PPPP`\x02\x81\x01`@\x83\x01a]\x8B\x81\x85a[)V[a]\x96\x81\x83\x86a\\bV[PPPPPPV[a]\xA8\x82\x82a]9V[PPV[\x7Fanother maintenance in progress\0_\x82\x01RPV[_a]\xE0`\x1F\x83aAEV[\x91Pa]\xEB\x82a]\xACV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra^\r\x81a]\xD4V[\x90P\x91\x90PV[\x7Finvalid id\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a^H`\n\x83aAEV[\x91Pa^S\x82a^\x14V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra^u\x81a^\xD63\xEF<\xE0rk\x8A\xB8\xFBi\xD4l\x8AN^\xCB\x0B)\"f\x86t\xA1a\x02\x08_\x01_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x13\xBF\x92\x91\x90a33V[`@Q\x80\x91\x03\x90\xA1V[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x14WW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x14N\x90a+$V[`@Q\x80\x91\x03\x90\xFD[a\x14_a!\xD5V[\x15a\x14\x9FW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x14\x96\x90a3\xA4V[`@Q\x80\x91\x03\x90\xFD[a\x14\xA7a!{V[\x15a\x14\xE7W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x14\xDE\x90a4\x0CV[`@Q\x80\x91\x03\x90\xFD[a\x02\x08_\x01_\x81\x81\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x15\x0F\x90a4*V[\x91\x90a\x01\0\n\x81T\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP_`\x02a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x15Z\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90Pa\x02\x06_\x81\x81\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x15\x8C\x90a4*V[\x91\x90a\x01\0\n\x81T\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP_`\x02a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x15\xD7\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90P__\x90P[a\x16\x0E`\x02\x84`\x02\x81\x10a\x15\xFFWa\x15\xFEa-cV[[a\x01\x02\x02\x01a\x01\0\x01Ta\"\x0EV[\x81\x11a\x17\xB2W`\x02\x83`\x02\x81\x10a\x16(Wa\x16'a-cV[[a\x01\x02\x02\x01_\x01\x81a\x01\0\x81\x10a\x16BWa\x16Aa-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x83`\x02\x81\x10a\x16\x8DWa\x16\x8Ca-cV[[a\x01\x02\x02\x01_\x01\x82a\x01\0\x81\x10a\x16\xA7Wa\x16\xA6a-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x17\x9FW`\x02\x83`\x02\x81\x10a\x16\xF7Wa\x16\xF6a-cV[[a\x01\x02\x02\x01_\x01\x81a\x01\0\x81\x10a\x17\x11Wa\x17\x10a-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x83`\x02\x81\x10a\x17FWa\x17Ea-cV[[a\x01\x02\x02\x01_\x01\x82a\x01\0\x81\x10a\x17`Wa\x17_a-cV[[\x01_a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UP[\x80\x80a\x17\xAA\x90a00V[\x91PPa\x15\xE8V[P_`\x02\x83`\x02\x81\x10a\x17\xC8Wa\x17\xC7a-cV[[a\x01\x02\x02\x01a\x01\0\x01T\x90P____\x90P[\x86\x80_\x01\x90a\x17\xEA\x91\x90a4eV[\x90P\x81\x10\x15a\x19FW\x86\x80_\x01\x90a\x18\x02\x91\x90a4eV[\x82\x81\x81\x10a\x18\x13Wa\x18\x12a-cV[[\x90P`@\x02\x01_\x01` \x81\x01\x90a\x18*\x91\x90a)\xEDV[\x92P\x86\x80_\x01\x90a\x18;\x91\x90a4eV[\x82\x81\x81\x10a\x18LWa\x18Ka-cV[[\x90P`@\x02\x01` \x01` \x81\x01\x90a\x18d\x91\x90a*\x9FV[\x91P_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x82s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x03a\x18\xB3Wa\x18\xAC\x83\x85a!\xFA\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x93Pa\x18\xC9V[a\x18\xC6\x83\x85a\"\xBD\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x93P[\x81`\x02\x86`\x02\x81\x10a\x18\xDEWa\x18\xDDa-cV[[a\x01\x02\x02\x01_\x01\x84`\xFF\x16a\x01\0\x81\x10a\x18\xFBWa\x18\xFAa-cV[[\x01_a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UP\x80\x80`\x01\x01\x91PPa\x17\xDBV[P\x82`\x02\x85`\x02\x81\x10a\x19\\Wa\x19[a-cV[[a\x01\x02\x02\x01a\x01\0\x01\x81\x90UP\x85` \x01` \x81\x01\x90a\x19|\x91\x90a)\xEDV[`\x02\x85`\x02\x81\x10a\x19\x90Wa\x19\x8Fa-cV[[a\x01\x02\x02\x01a\x01\x01\x01_a\x01\0\n\x81T\x81`\xFF\x02\x19\x16\x90\x83`\xFF\x16\x02\x17\x90UP\x82a\x02\x08`\x01\x01\x81\x90UPa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x19\xE9\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7Fx\xDA\xD2\xBC\x0BG\xC6\x88\xED\x84\xF3\xFE\xE7\x9A\xBC\x18\xE6\xC9\x82-\xB0Zy\xCA\x19\xDF\xF5E3\xC7G\ra\x02\x08_\x01_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x87a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x1A\x89\x93\x92\x91\x90a6\x8BV[`@Q\x80\x91\x03\x90\xA1PPPPPPV[a\x1A\xA1a!\xD5V[\x15a\x1A\xE1W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x1A\xD8\x90a3\xA4V[`@Q\x80\x91\x03\x90\xFD[a\x1A\xE9a!{V[\x15a\x1B)W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x1B \x90a4\x0CV[`@Q\x80\x91\x03\x90\xFD[3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x80a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x1Bd\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x81\x10a\x1B\x7FWa\x1B~a-cV[[a\x01\x02\x02\x01_\x01\x82`\xFF\x16a\x01\0\x81\x10a\x1B\x9CWa\x1B\x9Ba-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x1C\x13W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x1C\n\x90a-\xDAV[`@Q\x80\x91\x03\x90\xFD[3a\x02\n_\x01_a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x1C\x84\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\xBC'H\xCF\x02\xF7\xA1)\x15%\xE8f\xEF\xC7j\xB3\xB9m2\xD7\xAF\xCB\xB2lS\xDA\xECa{8\xB4y3a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x1D\n\x92\x91\x90a2\xE5V[`@Q\x80\x91\x03\x90\xA1PV[a\x1D!\x82\x82\x90Pa\"\x1FV[__a\x1D+a!\xD5V[\x15a\x1E\xA1W3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x80`\x01a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x1Dm\x91\x90a/8V[a\x1Dw\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x81\x10a\x1D\x92Wa\x1D\x91a-cV[[a\x01\x02\x02\x01_\x01\x86`\xFF\x16a\x01\0\x81\x10a\x1D\xAFWa\x1D\xAEa-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14\x91P\x81a\x1E\x9CW3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x80a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x1E)\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x81\x10a\x1EDWa\x1ECa-cV[[a\x01\x02\x02\x01_\x01\x86`\xFF\x16a\x01\0\x81\x10a\x1EaWa\x1E`a-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14\x90P[a\x1FOV[3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x80a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x1E\xDC\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x81\x10a\x1E\xF7Wa\x1E\xF6a-cV[[a\x01\x02\x02\x01_\x01\x86`\xFF\x16a\x01\0\x81\x10a\x1F\x14Wa\x1F\x13a-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14\x91P[\x81\x80a\x1FXWP\x80[a\x1F\x97W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x1F\x8E\x90a-\xDAV[`@Q\x80\x91\x03\x90\xFD[\x83\x83`\x01_3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ \x91\x82a\x1F\xE3\x92\x91\x90a2\x18V[Pa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a \x12\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\x12Q\x81\xEC!\x88-\xECQ\xA29)\x05\xDF\xF3\xA8,\xBD\x02b\xF1\x8B\\\x0C\x03T\x88g\x1B@\xAF\xB23\x85\x85a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa \x9C\x94\x93\x92\x91\x90a7\x11V[`@Q\x80\x91\x03\x90\xA1PPPPPV[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a!9W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a!0\x90a+$V[`@Q\x80\x91\x03\x90\xFD[\x80__a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPPV[__s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x02\n_\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14\x15\x90P\x90V[__a\x02\x08`\x01\x01T\x14\x15\x90P\x90V[__\x82`\xFF\x16`\x01\x90\x1B\x84\x16\x14\x90P\x92\x91PPV[_\x81`\xFF\x16`\x01\x90\x1B\x19\x83\x16\x90P\x92\x91PPV[_a\"\x18\x82a\"\xD0V[\x90P\x91\x90PV[_\x81\x11a\"aW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\"X\x90a7\x99V[`@Q\x80\x91\x03\x90\xFD[a\x02\x07_\x01_\x90T\x90a\x01\0\n\x90\x04a\xFF\xFF\x16a\xFF\xFF\x16\x81\x11\x15a\"\xBAW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\"\xB1\x90a8\x01V[`@Q\x80\x91\x03\x90\xFD[PV[_\x81`\xFF\x16`\x01\x90\x1B\x83\x17\x90P\x92\x91PPV[_`\x07a\"\xEEo\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x84\x11a#\x9CV[\x90\x1B\x90P`\x06a#\ng\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x83\x85\x90\x1C\x11a#\x9CV[\x90\x1B\x81\x17\x90P`\x05a#$c\xFF\xFF\xFF\xFF\x83\x85\x90\x1C\x11a#\x9CV[\x90\x1B\x81\x17\x90P`\x04a#V[\x81R` \x01a#\xC7a$>V[\x81R` \x01_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01a#\xE4a$ZV[\x81R` \x01a#\xF1a$|V[\x81R` \x01_o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RP\x90V[`@Q\x80`@\x01`@R\x80_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01``\x81RP\x90V[`@Q\x80`@\x01`@R\x80``\x81R` \x01_`\xFF\x16\x81RP\x90V[`@Q\x80`@\x01`@R\x80_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01_\x81RP\x90V[`@Q\x80` \x01`@R\x80_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RP\x90V[__\xFD[__\xFD[_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[a$\xC8\x81a$\xACV[\x81\x14a$\xD2W__\xFD[PV[_\x815\x90Pa$\xE3\x81a$\xBFV[\x92\x91PPV[_`\xFF\x82\x16\x90P\x91\x90PV[a$\xFE\x81a$\xE9V[\x81\x14a%\x08W__\xFD[PV[_\x815\x90Pa%\x19\x81a$\xF5V[\x92\x91PPV[__`@\x83\x85\x03\x12\x15a%5Wa%4a$\xA4V[[_a%B\x85\x82\x86\x01a$\xD5V[\x92PP` a%S\x85\x82\x86\x01a%\x0BV[\x91PP\x92P\x92\x90PV[__\xFD[_` \x82\x84\x03\x12\x15a%vWa%ua%]V[[\x81\x90P\x92\x91PPV[_` \x82\x84\x03\x12\x15a%\x94Wa%\x93a$\xA4V[[_a%\xA1\x84\x82\x85\x01a%aV[\x91PP\x92\x91PPV[_\x81Q\x90P\x91\x90PV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[_\x81\x90P` \x82\x01\x90P\x91\x90PV[_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[_a%\xFC\x82a%\xD3V[\x90P\x91\x90PV[a&\x0C\x81a%\xF2V[\x82RPPV[_\x81Q\x90P\x91\x90PV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[\x82\x81\x83^_\x83\x83\x01RPPPV[_`\x1F\x19`\x1F\x83\x01\x16\x90P\x91\x90PV[_a&T\x82a&\x12V[a&^\x81\x85a&\x1CV[\x93Pa&n\x81\x85` \x86\x01a&,V[a&w\x81a&:V[\x84\x01\x91PP\x92\x91PPV[_`@\x83\x01_\x83\x01Qa&\x97_\x86\x01\x82a&\x03V[P` \x83\x01Q\x84\x82\x03` \x86\x01Ra&\xAF\x82\x82a&JV[\x91PP\x80\x91PP\x92\x91PPV[_a&\xC7\x83\x83a&\x82V[\x90P\x92\x91PPV[_` \x82\x01\x90P\x91\x90PV[_a&\xE5\x82a%\xAAV[a&\xEF\x81\x85a%\xB4V[\x93P\x83` \x82\x02\x85\x01a'\x01\x85a%\xC4V[\x80_[\x85\x81\x10\x15a'\x82a1 V[\x84\x84Ta0\xAEV[\x82UPPPPV[__\x90P\x90V[a1]a1NV[a1h\x81\x84\x84a1)V[PPPV[[\x81\x81\x10\x15a1\x8BWa1\x80_\x82a1UV[`\x01\x81\x01\x90Pa1nV[PPV[`\x1F\x82\x11\x15a1\xD0Wa1\xA1\x81a0\x81V[a1\xAA\x84a0\x93V[\x81\x01` \x85\x10\x15a1\xB9W\x81\x90P[a1\xCDa1\xC5\x85a0\x93V[\x83\x01\x82a1mV[PP[PPPV[_\x82\x82\x1C\x90P\x92\x91PPV[_a1\xF0_\x19\x84`\x08\x02a1\xD5V[\x19\x80\x83\x16\x91PP\x92\x91PPV[_a2\x08\x83\x83a1\xE1V[\x91P\x82`\x02\x02\x82\x17\x90P\x92\x91PPV[a2\"\x83\x83a0wV[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a2;Wa2:a/\xA6V[[a2E\x82Ta0\0V[a2P\x82\x82\x85a1\x8FV[_`\x1F\x83\x11`\x01\x81\x14a2}W_\x84\x15a2kW\x82\x87\x015\x90P[a2u\x85\x82a1\xFDV[\x86UPa2\xDCV[`\x1F\x19\x84\x16a2\x8B\x86a0\x81V[_[\x82\x81\x10\x15a2\xB2W\x84\x89\x015\x82U`\x01\x82\x01\x91P` \x85\x01\x94P` \x81\x01\x90Pa2\x8DV[\x86\x83\x10\x15a2\xCFW\x84\x89\x015a2\xCB`\x1F\x89\x16\x82a1\xE1V[\x83UP[`\x01`\x02\x88\x02\x01\x88UPPP[PPPPPPPV[_`@\x82\x01\x90Pa2\xF8_\x83\x01\x85a.\x07V[a3\x05` \x83\x01\x84a,\x0EV[\x93\x92PPPV[_a3\x16\x82a$\xACV[\x91P_\x82\x03a3(Wa3'a+\xAAV[[`\x01\x82\x03\x90P\x91\x90PV[_`@\x82\x01\x90Pa3F_\x83\x01\x85a-\xF8V[a3S` \x83\x01\x84a,\x0EV[\x93\x92PPPV[\x7Fmigration in progress\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a3\x8E`\x15\x83a*\xCAV[\x91Pa3\x99\x82a3ZV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra3\xBB\x81a3\x82V[\x90P\x91\x90PV[\x7Fmaintenance in progress\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a3\xF6`\x17\x83a*\xCAV[\x91Pa4\x01\x82a3\xC2V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra4#\x81a3\xEAV[\x90P\x91\x90PV[_a44\x82a$\xACV[\x91Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x03a4NWa4Ma+\xAAV[[`\x01\x82\x01\x90P\x91\x90PV[__\xFD[__\xFD[__\xFD[__\x835`\x01` \x03\x846\x03\x03\x81\x12a4\x81Wa4\x80a4YV[[\x80\x84\x01\x92P\x825\x91Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15a4\xA3Wa4\xA2a4]V[[` \x83\x01\x92P`@\x82\x026\x03\x83\x13\x15a4\xBFWa4\xBEa4aV[[P\x92P\x92\x90PV[__\xFD[__\xFD[__\xFD[__\x835`\x01` \x03\x846\x03\x03\x81\x12a4\xEFWa4\xEEa4\xCFV[[\x83\x81\x01\x92P\x825\x91P` \x83\x01\x92Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15a5\x17Wa5\x16a4\xC7V[[`@\x82\x026\x03\x83\x13\x15a5-Wa5,a4\xCBV[[P\x92P\x92\x90PV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[_\x81\x90P\x91\x90PV[_a5\\` \x84\x01\x84a%\x0BV[\x90P\x92\x91PPV[_a5r` \x84\x01\x84a*\x8BV[\x90P\x92\x91PPV[`@\x82\x01a5\x8A_\x83\x01\x83a5NV[a5\x96_\x85\x01\x82a'NV[Pa5\xA4` \x83\x01\x83a5dV[a5\xB1` \x85\x01\x82a&\x03V[PPPPV[_a5\xC2\x83\x83a5zV[`@\x83\x01\x90P\x92\x91PPV[_\x82\x90P\x92\x91PPV[_`@\x82\x01\x90P\x91\x90PV[_a5\xEF\x83\x85a55V[\x93Pa5\xFA\x82a5EV[\x80_[\x85\x81\x10\x15a62Wa6\x0F\x82\x84a5\xCEV[a6\x19\x88\x82a5\xB7V[\x97Pa6$\x83a5\xD8V[\x92PP`\x01\x81\x01\x90Pa5\xFDV[P\x85\x92PPP\x93\x92PPPV[_`@\x83\x01a6P_\x84\x01\x84a4\xD3V[\x85\x83\x03_\x87\x01Ra6b\x83\x82\x84a5\xE4V[\x92PPPa6s` \x84\x01\x84a5NV[a6\x80` \x86\x01\x82a'NV[P\x80\x91PP\x92\x91PPV[_``\x82\x01\x90Pa6\x9E_\x83\x01\x86a-\xF8V[\x81\x81\x03` \x83\x01Ra6\xB0\x81\x85a6?V[\x90Pa6\xBF`@\x83\x01\x84a,\x0EV[\x94\x93PPPPV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[\x82\x81\x837_\x83\x83\x01RPPPV[_a6\xF0\x83\x85a6\xC7V[\x93Pa6\xFD\x83\x85\x84a6\xD7V[a7\x06\x83a&:V[\x84\x01\x90P\x93\x92PPPV[_``\x82\x01\x90Pa7$_\x83\x01\x87a.\x07V[\x81\x81\x03` \x83\x01Ra77\x81\x85\x87a6\xE5V[\x90Pa7F`@\x83\x01\x84a,\x0EV[\x95\x94PPPPPV[\x7Fempty operator data\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a7\x83`\x13\x83a*\xCAV[\x91Pa7\x8E\x82a7OV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra7\xB0\x81a7wV[\x90P\x91\x90PV[\x7Foperator data too large\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a7\xEB`\x17\x83a*\xCAV[\x91Pa7\xF6\x82a7\xB7V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra8\x18\x81a7\xDFV[\x90P\x91\x90PV\xFE\xA2dipfsX\"\x12 Pp\xBF\xB7\x8C\xBAO\xB2\x04\xCE:\x9A\xE2K_q\x0Cbs!v6^\xE88\x9C\xDA\xB1\x8C<-qdsolcC\0\x08\x1C\x003", ); /**```solidity -struct ClusterView { NodeOperatorsView operators; MigrationView migration; Maintenance maintenance; uint64 keyspaceVersion; uint128 version; } +struct ClusterView { KeyspaceView primaryKeyspace; KeyspaceView secondaryKeyspace; uint64 keyspaceVersion; Migration migration; Maintenance maintenance; uint128 version; } ```*/ #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] pub struct ClusterView { #[allow(missing_docs)] - pub operators: ::RustType, + pub primaryKeyspace: ::RustType, #[allow(missing_docs)] - pub migration: ::RustType, - #[allow(missing_docs)] - pub maintenance: ::RustType, + pub secondaryKeyspace: ::RustType, #[allow(missing_docs)] pub keyspaceVersion: u64, #[allow(missing_docs)] + pub migration: ::RustType, + #[allow(missing_docs)] + pub maintenance: ::RustType, + #[allow(missing_docs)] pub version: u128, } #[allow( @@ -684,18 +614,20 @@ struct ClusterView { NodeOperatorsView operators; MigrationView migration; Maint use alloy::sol_types as alloy_sol_types; #[doc(hidden)] type UnderlyingSolTuple<'a> = ( - NodeOperatorsView, - MigrationView, - Maintenance, + KeyspaceView, + KeyspaceView, alloy::sol_types::sol_data::Uint<64>, + Migration, + Maintenance, alloy::sol_types::sol_data::Uint<128>, ); #[doc(hidden)] type UnderlyingRustTuple<'a> = ( - ::RustType, - ::RustType, - ::RustType, + ::RustType, + ::RustType, u64, + ::RustType, + ::RustType, u128, ); #[cfg(test)] @@ -714,10 +646,11 @@ struct ClusterView { NodeOperatorsView operators; MigrationView migration; Maint impl ::core::convert::From for UnderlyingRustTuple<'_> { fn from(value: ClusterView) -> Self { ( - value.operators, + value.primaryKeyspace, + value.secondaryKeyspace, + value.keyspaceVersion, value.migration, value.maintenance, - value.keyspaceVersion, value.version, ) } @@ -727,11 +660,12 @@ struct ClusterView { NodeOperatorsView operators; MigrationView migration; Maint impl ::core::convert::From> for ClusterView { fn from(tuple: UnderlyingRustTuple<'_>) -> Self { Self { - operators: tuple.0, - migration: tuple.1, - maintenance: tuple.2, - keyspaceVersion: tuple.3, - version: tuple.4, + primaryKeyspace: tuple.0, + secondaryKeyspace: tuple.1, + keyspaceVersion: tuple.2, + migration: tuple.3, + maintenance: tuple.4, + version: tuple.5, } } } @@ -744,18 +678,19 @@ struct ClusterView { NodeOperatorsView operators; MigrationView migration; Maint #[inline] fn stv_to_tokens(&self) -> ::Token<'_> { ( - ::tokenize( - &self.operators, + ::tokenize( + &self.primaryKeyspace, ), - ::tokenize( - &self.migration, - ), - ::tokenize( - &self.maintenance, + ::tokenize( + &self.secondaryKeyspace, ), as alloy_sol_types::SolType>::tokenize(&self.keyspaceVersion), + ::tokenize(&self.migration), + ::tokenize( + &self.maintenance, + ), as alloy_sol_types::SolType>::tokenize(&self.version), @@ -833,29 +768,35 @@ struct ClusterView { NodeOperatorsView operators; MigrationView migration; Maint #[inline] fn eip712_root_type() -> alloy_sol_types::private::Cow<'static, str> { alloy_sol_types::private::Cow::Borrowed( - "ClusterView(NodeOperatorsView operators,MigrationView migration,Maintenance maintenance,uint64 keyspaceVersion,uint128 version)", + "ClusterView(KeyspaceView primaryKeyspace,KeyspaceView secondaryKeyspace,uint64 keyspaceVersion,Migration migration,Maintenance maintenance,uint128 version)", ) } #[inline] fn eip712_components() -> alloy_sol_types::private::Vec< alloy_sol_types::private::Cow<'static, str>, > { - let mut components = alloy_sol_types::private::Vec::with_capacity(3); + let mut components = alloy_sol_types::private::Vec::with_capacity(4); components .push( - ::eip712_root_type(), + ::eip712_root_type(), ); components .extend( - ::eip712_components(), + ::eip712_components(), ); components .push( - ::eip712_root_type(), + ::eip712_root_type(), + ); + components + .extend( + ::eip712_components(), ); + components + .push(::eip712_root_type()); components .extend( - ::eip712_components(), + ::eip712_components(), ); components .push( @@ -870,16 +811,12 @@ struct ClusterView { NodeOperatorsView operators; MigrationView migration; Maint #[inline] fn eip712_encode_data(&self) -> alloy_sol_types::private::Vec { [ - ::eip712_data_word( - &self.operators, - ) - .0, - ::eip712_data_word( - &self.migration, + ::eip712_data_word( + &self.primaryKeyspace, ) .0, - ::eip712_data_word( - &self.maintenance, + ::eip712_data_word( + &self.secondaryKeyspace, ) .0, ::eip712_data_word( + &self.migration, + ) + .0, + ::eip712_data_word( + &self.maintenance, + ) + .0, as alloy_sol_types::SolType>::eip712_data_word(&self.version) @@ -901,20 +846,23 @@ struct ClusterView { NodeOperatorsView operators; MigrationView migration; Maint #[inline] fn topic_preimage_length(rust: &Self::RustType) -> usize { 0usize - + ::topic_preimage_length( - &rust.operators, - ) - + ::topic_preimage_length( - &rust.migration, + + ::topic_preimage_length( + &rust.primaryKeyspace, ) - + ::topic_preimage_length( - &rust.maintenance, + + ::topic_preimage_length( + &rust.secondaryKeyspace, ) + as alloy_sol_types::EventTopic>::topic_preimage_length( &rust.keyspaceVersion, ) + + ::topic_preimage_length( + &rust.migration, + ) + + ::topic_preimage_length( + &rust.maintenance, + ) + as alloy_sol_types::EventTopic>::topic_preimage_length( @@ -929,16 +877,12 @@ struct ClusterView { NodeOperatorsView operators; MigrationView migration; Maint out.reserve( ::topic_preimage_length(rust), ); - ::encode_topic_preimage( - &rust.operators, - out, - ); - ::encode_topic_preimage( - &rust.migration, + ::encode_topic_preimage( + &rust.primaryKeyspace, out, ); - ::encode_topic_preimage( - &rust.maintenance, + ::encode_topic_preimage( + &rust.secondaryKeyspace, out, ); ::encode_topic_preimage( + &rust.migration, + out, + ); + ::encode_topic_preimage( + &rust.maintenance, + out, + ); as alloy_sol_types::EventTopic>::encode_topic_preimage( @@ -970,13 +922,15 @@ struct ClusterView { NodeOperatorsView operators; MigrationView migration; Maint } }; /**```solidity -struct Maintenance { address slot; } +struct KeyspaceSlot { uint8 idx; address operator; } ```*/ #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] - pub struct Maintenance { + pub struct KeyspaceSlot { #[allow(missing_docs)] - pub slot: alloy::sol_types::private::Address, + pub idx: u8, + #[allow(missing_docs)] + pub operator: alloy::sol_types::private::Address, } #[allow( non_camel_case_types, @@ -987,9 +941,12 @@ struct Maintenance { address slot; } const _: () = { use alloy::sol_types as alloy_sol_types; #[doc(hidden)] - type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Address,); + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::Uint<8>, + alloy::sol_types::sol_data::Address, + ); #[doc(hidden)] - type UnderlyingRustTuple<'a> = (alloy::sol_types::private::Address,); + type UnderlyingRustTuple<'a> = (u8, alloy::sol_types::private::Address); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] fn _type_assertion( @@ -1003,29 +960,35 @@ struct Maintenance { address slot; } } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: Maintenance) -> Self { - (value.slot,) + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: KeyspaceSlot) -> Self { + (value.idx, value.operator) } } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From> for Maintenance { + impl ::core::convert::From> for KeyspaceSlot { fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self { slot: tuple.0 } + Self { + idx: tuple.0, + operator: tuple.1, + } } } #[automatically_derived] - impl alloy_sol_types::SolValue for Maintenance { + impl alloy_sol_types::SolValue for KeyspaceSlot { type SolType = Self; } #[automatically_derived] - impl alloy_sol_types::private::SolTypeValue for Maintenance { + impl alloy_sol_types::private::SolTypeValue for KeyspaceSlot { #[inline] fn stv_to_tokens(&self) -> ::Token<'_> { ( + as alloy_sol_types::SolType>::tokenize(&self.idx), ::tokenize( - &self.slot, + &self.operator, ), ) } @@ -1071,7 +1034,7 @@ struct Maintenance { address slot; } } } #[automatically_derived] - impl alloy_sol_types::SolType for Maintenance { + impl alloy_sol_types::SolType for KeyspaceSlot { type RustType = Self; type Token<'a> = alloy_sol_types::private::Cow<'static, str> { - alloy_sol_types::private::Cow::Borrowed("Maintenance(address slot)") + alloy_sol_types::private::Cow::Borrowed( + "KeyspaceSlot(uint8 idx,address operator)", + ) } #[inline] fn eip712_components() -> alloy_sol_types::private::Vec< @@ -1114,20 +1079,29 @@ struct Maintenance { address slot; } } #[inline] fn eip712_encode_data(&self) -> alloy_sol_types::private::Vec { - ::eip712_data_word( - &self.slot, - ) - .0 - .to_vec() + [ + as alloy_sol_types::SolType>::eip712_data_word(&self.idx) + .0, + ::eip712_data_word( + &self.operator, + ) + .0, + ] + .concat() } } #[automatically_derived] - impl alloy_sol_types::EventTopic for Maintenance { + impl alloy_sol_types::EventTopic for KeyspaceSlot { #[inline] fn topic_preimage_length(rust: &Self::RustType) -> usize { 0usize + + as alloy_sol_types::EventTopic>::topic_preimage_length(&rust.idx) + ::topic_preimage_length( - &rust.slot, + &rust.operator, ) } #[inline] @@ -1138,8 +1112,11 @@ struct Maintenance { address slot; } out.reserve( ::topic_preimage_length(rust), ); + as alloy_sol_types::EventTopic>::encode_topic_preimage(&rust.idx, out); ::encode_topic_preimage( - &rust.slot, + &rust.operator, out, ); } @@ -1159,23 +1136,17 @@ struct Maintenance { address slot; } } }; /**```solidity -struct MigrationView { address[] operatorsToRemove; NodeOperatorView[] operatorsToAdd; address[] pullingOperators; } +struct KeyspaceView { NodeOperator[] operators; uint8 replicationStrategy; } ```*/ #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] - pub struct MigrationView { + pub struct KeyspaceView { #[allow(missing_docs)] - pub operatorsToRemove: alloy::sol_types::private::Vec< - alloy::sol_types::private::Address, - >, - #[allow(missing_docs)] - pub operatorsToAdd: alloy::sol_types::private::Vec< - ::RustType, + pub operators: alloy::sol_types::private::Vec< + ::RustType, >, #[allow(missing_docs)] - pub pullingOperators: alloy::sol_types::private::Vec< - alloy::sol_types::private::Address, - >, + pub replicationStrategy: u8, } #[allow( non_camel_case_types, @@ -1187,17 +1158,15 @@ struct MigrationView { address[] operatorsToRemove; NodeOperatorView[] operators use alloy::sol_types as alloy_sol_types; #[doc(hidden)] type UnderlyingSolTuple<'a> = ( - alloy::sol_types::sol_data::Array, - alloy::sol_types::sol_data::Array, - alloy::sol_types::sol_data::Array, + alloy::sol_types::sol_data::Array, + alloy::sol_types::sol_data::Uint<8>, ); #[doc(hidden)] type UnderlyingRustTuple<'a> = ( - alloy::sol_types::private::Vec, alloy::sol_types::private::Vec< - ::RustType, + ::RustType, >, - alloy::sol_types::private::Vec, + u8, ); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] @@ -1212,40 +1181,36 @@ struct MigrationView { address[] operatorsToRemove; NodeOperatorView[] operators } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: MigrationView) -> Self { - (value.operatorsToRemove, value.operatorsToAdd, value.pullingOperators) + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: KeyspaceView) -> Self { + (value.operators, value.replicationStrategy) } } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From> for MigrationView { + impl ::core::convert::From> for KeyspaceView { fn from(tuple: UnderlyingRustTuple<'_>) -> Self { Self { - operatorsToRemove: tuple.0, - operatorsToAdd: tuple.1, - pullingOperators: tuple.2, + operators: tuple.0, + replicationStrategy: tuple.1, } } } #[automatically_derived] - impl alloy_sol_types::SolValue for MigrationView { + impl alloy_sol_types::SolValue for KeyspaceView { type SolType = Self; } #[automatically_derived] - impl alloy_sol_types::private::SolTypeValue for MigrationView { + impl alloy_sol_types::private::SolTypeValue for KeyspaceView { #[inline] fn stv_to_tokens(&self) -> ::Token<'_> { ( as alloy_sol_types::SolType>::tokenize(&self.operatorsToRemove), - as alloy_sol_types::SolType>::tokenize(&self.operatorsToAdd), - as alloy_sol_types::SolType>::tokenize(&self.pullingOperators), + NodeOperator, + > as alloy_sol_types::SolType>::tokenize(&self.operators), + as alloy_sol_types::SolType>::tokenize(&self.replicationStrategy), ) } #[inline] @@ -1290,7 +1255,7 @@ struct MigrationView { address[] operatorsToRemove; NodeOperatorView[] operators } } #[automatically_derived] - impl alloy_sol_types::SolType for MigrationView { + impl alloy_sol_types::SolType for KeyspaceView { type RustType = Self; type Token<'a> = alloy_sol_types::private::Cow<'static, str> { alloy_sol_types::private::Cow::Borrowed( - "MigrationView(address[] operatorsToRemove,NodeOperatorView[] operatorsToAdd,address[] pullingOperators)", + "KeyspaceView(NodeOperator[] operators,uint8 replicationStrategy)", ) } #[inline] @@ -1330,11 +1295,11 @@ struct MigrationView { address[] operatorsToRemove; NodeOperatorView[] operators let mut components = alloy_sol_types::private::Vec::with_capacity(1); components .push( - ::eip712_root_type(), + ::eip712_root_type(), ); components .extend( - ::eip712_components(), + ::eip712_components(), ); components } @@ -1342,21 +1307,13 @@ struct MigrationView { address[] operatorsToRemove; NodeOperatorView[] operators fn eip712_encode_data(&self) -> alloy_sol_types::private::Vec { [ as alloy_sol_types::SolType>::eip712_data_word( - &self.operatorsToRemove, - ) - .0, - as alloy_sol_types::SolType>::eip712_data_word( - &self.operatorsToAdd, - ) + NodeOperator, + > as alloy_sol_types::SolType>::eip712_data_word(&self.operators) .0, - as alloy_sol_types::SolType>::eip712_data_word( - &self.pullingOperators, + &self.replicationStrategy, ) .0, ] @@ -1364,24 +1321,19 @@ struct MigrationView { address[] operatorsToRemove; NodeOperatorView[] operators } } #[automatically_derived] - impl alloy_sol_types::EventTopic for MigrationView { + impl alloy_sol_types::EventTopic for KeyspaceView { #[inline] fn topic_preimage_length(rust: &Self::RustType) -> usize { 0usize + as alloy_sol_types::EventTopic>::topic_preimage_length( - &rust.operatorsToRemove, - ) - + as alloy_sol_types::EventTopic>::topic_preimage_length( - &rust.operatorsToAdd, + &rust.operators, ) - + as alloy_sol_types::EventTopic>::topic_preimage_length( - &rust.pullingOperators, + &rust.replicationStrategy, ) } #[inline] @@ -1393,21 +1345,15 @@ struct MigrationView { address[] operatorsToRemove; NodeOperatorView[] operators ::topic_preimage_length(rust), ); as alloy_sol_types::EventTopic>::encode_topic_preimage( - &rust.operatorsToRemove, - out, - ); - as alloy_sol_types::EventTopic>::encode_topic_preimage( - &rust.operatorsToAdd, + &rust.operators, out, ); - as alloy_sol_types::EventTopic>::encode_topic_preimage( - &rust.pullingOperators, + &rust.replicationStrategy, out, ); } @@ -1427,15 +1373,13 @@ struct MigrationView { address[] operatorsToRemove; NodeOperatorView[] operators } }; /**```solidity -struct Node { uint256 id; bytes data; } +struct Maintenance { address slot; } ```*/ #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] - pub struct Node { - #[allow(missing_docs)] - pub id: alloy::sol_types::private::primitives::aliases::U256, + pub struct Maintenance { #[allow(missing_docs)] - pub data: alloy::sol_types::private::Bytes, + pub slot: alloy::sol_types::private::Address, } #[allow( non_camel_case_types, @@ -1446,15 +1390,9 @@ struct Node { uint256 id; bytes data; } const _: () = { use alloy::sol_types as alloy_sol_types; #[doc(hidden)] - type UnderlyingSolTuple<'a> = ( - alloy::sol_types::sol_data::Uint<256>, - alloy::sol_types::sol_data::Bytes, - ); + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Address,); #[doc(hidden)] - type UnderlyingRustTuple<'a> = ( - alloy::sol_types::private::primitives::aliases::U256, - alloy::sol_types::private::Bytes, - ); + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::Address,); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] fn _type_assertion( @@ -1468,32 +1406,29 @@ struct Node { uint256 id; bytes data; } } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: Node) -> Self { - (value.id, value.data) + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: Maintenance) -> Self { + (value.slot,) } } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From> for Node { + impl ::core::convert::From> for Maintenance { fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self { id: tuple.0, data: tuple.1 } + Self { slot: tuple.0 } } } #[automatically_derived] - impl alloy_sol_types::SolValue for Node { + impl alloy_sol_types::SolValue for Maintenance { type SolType = Self; } #[automatically_derived] - impl alloy_sol_types::private::SolTypeValue for Node { + impl alloy_sol_types::private::SolTypeValue for Maintenance { #[inline] fn stv_to_tokens(&self) -> ::Token<'_> { ( - as alloy_sol_types::SolType>::tokenize(&self.id), - ::tokenize( - &self.data, + ::tokenize( + &self.slot, ), ) } @@ -1539,7 +1474,7 @@ struct Node { uint256 id; bytes data; } } } #[automatically_derived] - impl alloy_sol_types::SolType for Node { + impl alloy_sol_types::SolType for Maintenance { type RustType = Self; type Token<'a> = alloy_sol_types::private::Cow<'static, str> { - alloy_sol_types::private::Cow::Borrowed("Node(uint256 id,bytes data)") + alloy_sol_types::private::Cow::Borrowed("Maintenance(address slot)") } #[inline] fn eip712_components() -> alloy_sol_types::private::Vec< @@ -1582,29 +1517,20 @@ struct Node { uint256 id; bytes data; } } #[inline] fn eip712_encode_data(&self) -> alloy_sol_types::private::Vec { - [ - as alloy_sol_types::SolType>::eip712_data_word(&self.id) - .0, - ::eip712_data_word( - &self.data, - ) - .0, - ] - .concat() + ::eip712_data_word( + &self.slot, + ) + .0 + .to_vec() } } #[automatically_derived] - impl alloy_sol_types::EventTopic for Node { + impl alloy_sol_types::EventTopic for Maintenance { #[inline] fn topic_preimage_length(rust: &Self::RustType) -> usize { 0usize - + as alloy_sol_types::EventTopic>::topic_preimage_length(&rust.id) - + ::topic_preimage_length( - &rust.data, + + ::topic_preimage_length( + &rust.slot, ) } #[inline] @@ -1615,11 +1541,8 @@ struct Node { uint256 id; bytes data; } out.reserve( ::topic_preimage_length(rust), ); - as alloy_sol_types::EventTopic>::encode_topic_preimage(&rust.id, out); - ::encode_topic_preimage( - &rust.data, + ::encode_topic_preimage( + &rust.slot, out, ); } @@ -1639,19 +1562,15 @@ struct Node { uint256 id; bytes data; } } }; /**```solidity -struct NodeOperatorView { address addr; Node[] nodes; bytes data; } +struct Migration { uint64 id; uint256 pullingOperatorsBitmask; } ```*/ #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] - pub struct NodeOperatorView { - #[allow(missing_docs)] - pub addr: alloy::sol_types::private::Address, + pub struct Migration { #[allow(missing_docs)] - pub nodes: alloy::sol_types::private::Vec< - ::RustType, - >, + pub id: u64, #[allow(missing_docs)] - pub data: alloy::sol_types::private::Bytes, + pub pullingOperatorsBitmask: alloy::sol_types::private::primitives::aliases::U256, } #[allow( non_camel_case_types, @@ -1663,17 +1582,13 @@ struct NodeOperatorView { address addr; Node[] nodes; bytes data; } use alloy::sol_types as alloy_sol_types; #[doc(hidden)] type UnderlyingSolTuple<'a> = ( - alloy::sol_types::sol_data::Address, - alloy::sol_types::sol_data::Array, - alloy::sol_types::sol_data::Bytes, + alloy::sol_types::sol_data::Uint<64>, + alloy::sol_types::sol_data::Uint<256>, ); #[doc(hidden)] type UnderlyingRustTuple<'a> = ( - alloy::sol_types::private::Address, - alloy::sol_types::private::Vec< - ::RustType, - >, - alloy::sol_types::private::Bytes, + u64, + alloy::sol_types::private::primitives::aliases::U256, ); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] @@ -1688,39 +1603,37 @@ struct NodeOperatorView { address addr; Node[] nodes; bytes data; } } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: NodeOperatorView) -> Self { - (value.addr, value.nodes, value.data) + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: Migration) -> Self { + (value.id, value.pullingOperatorsBitmask) } } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From> for NodeOperatorView { + impl ::core::convert::From> for Migration { fn from(tuple: UnderlyingRustTuple<'_>) -> Self { Self { - addr: tuple.0, - nodes: tuple.1, - data: tuple.2, + id: tuple.0, + pullingOperatorsBitmask: tuple.1, } } } #[automatically_derived] - impl alloy_sol_types::SolValue for NodeOperatorView { + impl alloy_sol_types::SolValue for Migration { type SolType = Self; } #[automatically_derived] - impl alloy_sol_types::private::SolTypeValue for NodeOperatorView { + impl alloy_sol_types::private::SolTypeValue for Migration { #[inline] fn stv_to_tokens(&self) -> ::Token<'_> { ( - ::tokenize( - &self.addr, - ), - as alloy_sol_types::SolType>::tokenize(&self.nodes), - ::tokenize( - &self.data, + as alloy_sol_types::SolType>::tokenize(&self.id), + as alloy_sol_types::SolType>::tokenize( + &self.pullingOperatorsBitmask, ), ) } @@ -1766,7 +1679,7 @@ struct NodeOperatorView { address addr; Node[] nodes; bytes data; } } } #[automatically_derived] - impl alloy_sol_types::SolType for NodeOperatorView { + impl alloy_sol_types::SolType for Migration { type RustType = Self; type Token<'a> = alloy_sol_types::private::Cow<'static, str> { alloy_sol_types::private::Cow::Borrowed( - "NodeOperatorView(address addr,Node[] nodes,bytes data)", + "Migration(uint64 id,uint256 pullingOperatorsBitmask)", ) } #[inline] fn eip712_components() -> alloy_sol_types::private::Vec< alloy_sol_types::private::Cow<'static, str>, > { - let mut components = alloy_sol_types::private::Vec::with_capacity(1); - components - .push(::eip712_root_type()); - components - .extend(::eip712_components()); - components + alloy_sol_types::private::Vec::new() + } + #[inline] + fn eip712_encode_type() -> alloy_sol_types::private::Cow<'static, str> { + ::eip712_root_type() } #[inline] fn eip712_encode_data(&self) -> alloy_sol_types::private::Vec { [ - ::eip712_data_word( - &self.addr, - ) - .0, - as alloy_sol_types::SolType>::eip712_data_word(&self.nodes) + as alloy_sol_types::SolType>::eip712_data_word(&self.id) .0, - ::eip712_data_word( - &self.data, + as alloy_sol_types::SolType>::eip712_data_word( + &self.pullingOperatorsBitmask, ) .0, ] @@ -1830,18 +1740,17 @@ struct NodeOperatorView { address addr; Node[] nodes; bytes data; } } } #[automatically_derived] - impl alloy_sol_types::EventTopic for NodeOperatorView { + impl alloy_sol_types::EventTopic for Migration { #[inline] fn topic_preimage_length(rust: &Self::RustType) -> usize { 0usize - + ::topic_preimage_length( - &rust.addr, - ) - + as alloy_sol_types::EventTopic>::topic_preimage_length(&rust.nodes) - + ::topic_preimage_length( - &rust.data, + + as alloy_sol_types::EventTopic>::topic_preimage_length(&rust.id) + + as alloy_sol_types::EventTopic>::topic_preimage_length( + &rust.pullingOperatorsBitmask, ) } #[inline] @@ -1852,18 +1761,13 @@ struct NodeOperatorView { address addr; Node[] nodes; bytes data; } out.reserve( ::topic_preimage_length(rust), ); - ::encode_topic_preimage( - &rust.addr, - out, - ); - as alloy_sol_types::EventTopic>::encode_topic_preimage(&rust.id, out); + as alloy_sol_types::EventTopic>::encode_topic_preimage( - &rust.nodes, - out, - ); - ::encode_topic_preimage( - &rust.data, + &rust.pullingOperatorsBitmask, out, ); } @@ -1883,15 +1787,17 @@ struct NodeOperatorView { address addr; Node[] nodes; bytes data; } } }; /**```solidity -struct NodeOperatorsView { NodeOperatorView[] slots; } +struct MigrationPlan { KeyspaceSlot[] slotsToUpdate; uint8 replicationStrategy; } ```*/ #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] - pub struct NodeOperatorsView { + pub struct MigrationPlan { #[allow(missing_docs)] - pub slots: alloy::sol_types::private::Vec< - ::RustType, + pub slotsToUpdate: alloy::sol_types::private::Vec< + ::RustType, >, + #[allow(missing_docs)] + pub replicationStrategy: u8, } #[allow( non_camel_case_types, @@ -1903,13 +1809,15 @@ struct NodeOperatorsView { NodeOperatorView[] slots; } use alloy::sol_types as alloy_sol_types; #[doc(hidden)] type UnderlyingSolTuple<'a> = ( - alloy::sol_types::sol_data::Array, + alloy::sol_types::sol_data::Array, + alloy::sol_types::sol_data::Uint<8>, ); #[doc(hidden)] type UnderlyingRustTuple<'a> = ( alloy::sol_types::private::Vec< - ::RustType, + ::RustType, >, + u8, ); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] @@ -1924,30 +1832,36 @@ struct NodeOperatorsView { NodeOperatorView[] slots; } } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: NodeOperatorsView) -> Self { - (value.slots,) + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: MigrationPlan) -> Self { + (value.slotsToUpdate, value.replicationStrategy) } } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From> for NodeOperatorsView { + impl ::core::convert::From> for MigrationPlan { fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self { slots: tuple.0 } + Self { + slotsToUpdate: tuple.0, + replicationStrategy: tuple.1, + } } } #[automatically_derived] - impl alloy_sol_types::SolValue for NodeOperatorsView { + impl alloy_sol_types::SolValue for MigrationPlan { type SolType = Self; } #[automatically_derived] - impl alloy_sol_types::private::SolTypeValue for NodeOperatorsView { + impl alloy_sol_types::private::SolTypeValue for MigrationPlan { #[inline] fn stv_to_tokens(&self) -> ::Token<'_> { ( as alloy_sol_types::SolType>::tokenize(&self.slots), + KeyspaceSlot, + > as alloy_sol_types::SolType>::tokenize(&self.slotsToUpdate), + as alloy_sol_types::SolType>::tokenize(&self.replicationStrategy), ) } #[inline] @@ -1992,7 +1906,7 @@ struct NodeOperatorsView { NodeOperatorView[] slots; } } } #[automatically_derived] - impl alloy_sol_types::SolType for NodeOperatorsView { + impl alloy_sol_types::SolType for MigrationPlan { type RustType = Self; type Token<'a> = alloy_sol_types::private::Cow<'static, str> { alloy_sol_types::private::Cow::Borrowed( - "NodeOperatorsView(NodeOperatorView[] slots)", + "MigrationPlan(KeyspaceSlot[] slotsToUpdate,uint8 replicationStrategy)", ) } #[inline] @@ -2032,31 +1946,46 @@ struct NodeOperatorsView { NodeOperatorView[] slots; } let mut components = alloy_sol_types::private::Vec::with_capacity(1); components .push( - ::eip712_root_type(), + ::eip712_root_type(), ); components .extend( - ::eip712_components(), + ::eip712_components(), ); components } #[inline] fn eip712_encode_data(&self) -> alloy_sol_types::private::Vec { - as alloy_sol_types::SolType>::eip712_data_word(&self.slots) - .0 - .to_vec() + [ + as alloy_sol_types::SolType>::eip712_data_word(&self.slotsToUpdate) + .0, + as alloy_sol_types::SolType>::eip712_data_word( + &self.replicationStrategy, + ) + .0, + ] + .concat() } } #[automatically_derived] - impl alloy_sol_types::EventTopic for NodeOperatorsView { + impl alloy_sol_types::EventTopic for MigrationPlan { #[inline] fn topic_preimage_length(rust: &Self::RustType) -> usize { 0usize + as alloy_sol_types::EventTopic>::topic_preimage_length(&rust.slots) + KeyspaceSlot, + > as alloy_sol_types::EventTopic>::topic_preimage_length( + &rust.slotsToUpdate, + ) + + as alloy_sol_types::EventTopic>::topic_preimage_length( + &rust.replicationStrategy, + ) } #[inline] fn encode_topic_preimage( @@ -2067,9 +1996,15 @@ struct NodeOperatorsView { NodeOperatorView[] slots; } ::topic_preimage_length(rust), ); as alloy_sol_types::EventTopic>::encode_topic_preimage( - &rust.slots, + &rust.slotsToUpdate, + out, + ); + as alloy_sol_types::EventTopic>::encode_topic_preimage( + &rust.replicationStrategy, out, ); } @@ -2089,15 +2024,15 @@ struct NodeOperatorsView { NodeOperatorView[] slots; } } }; /**```solidity -struct Settings { uint8 minOperators; uint8 minNodes; } +struct NodeOperator { address addr; bytes data; } ```*/ #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] - pub struct Settings { + pub struct NodeOperator { #[allow(missing_docs)] - pub minOperators: u8, + pub addr: alloy::sol_types::private::Address, #[allow(missing_docs)] - pub minNodes: u8, + pub data: alloy::sol_types::private::Bytes, } #[allow( non_camel_case_types, @@ -2109,11 +2044,14 @@ struct Settings { uint8 minOperators; uint8 minNodes; } use alloy::sol_types as alloy_sol_types; #[doc(hidden)] type UnderlyingSolTuple<'a> = ( - alloy::sol_types::sol_data::Uint<8>, - alloy::sol_types::sol_data::Uint<8>, + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Bytes, ); #[doc(hidden)] - type UnderlyingRustTuple<'a> = (u8, u8); + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::Address, + alloy::sol_types::private::Bytes, + ); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] fn _type_assertion( @@ -2127,36 +2065,36 @@ struct Settings { uint8 minOperators; uint8 minNodes; } } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: Settings) -> Self { - (value.minOperators, value.minNodes) + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: NodeOperator) -> Self { + (value.addr, value.data) } } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From> for Settings { + impl ::core::convert::From> for NodeOperator { fn from(tuple: UnderlyingRustTuple<'_>) -> Self { Self { - minOperators: tuple.0, - minNodes: tuple.1, + addr: tuple.0, + data: tuple.1, } } } #[automatically_derived] - impl alloy_sol_types::SolValue for Settings { + impl alloy_sol_types::SolValue for NodeOperator { type SolType = Self; } #[automatically_derived] - impl alloy_sol_types::private::SolTypeValue for Settings { + impl alloy_sol_types::private::SolTypeValue for NodeOperator { #[inline] fn stv_to_tokens(&self) -> ::Token<'_> { ( - as alloy_sol_types::SolType>::tokenize(&self.minOperators), - as alloy_sol_types::SolType>::tokenize(&self.minNodes), + ::tokenize( + &self.addr, + ), + ::tokenize( + &self.data, + ), ) } #[inline] @@ -2201,7 +2139,7 @@ struct Settings { uint8 minOperators; uint8 minNodes; } } } #[automatically_derived] - impl alloy_sol_types::SolType for Settings { + impl alloy_sol_types::SolType for NodeOperator { type RustType = Self; type Token<'a> = alloy_sol_types::private::Cow<'static, str> { alloy_sol_types::private::Cow::Borrowed( - "Settings(uint8 minOperators,uint8 minNodes)", + "NodeOperator(address addr,bytes data)", ) } #[inline] @@ -2247,32 +2185,28 @@ struct Settings { uint8 minOperators; uint8 minNodes; } #[inline] fn eip712_encode_data(&self) -> alloy_sol_types::private::Vec { [ - as alloy_sol_types::SolType>::eip712_data_word(&self.minOperators) + ::eip712_data_word( + &self.addr, + ) .0, - as alloy_sol_types::SolType>::eip712_data_word(&self.minNodes) + ::eip712_data_word( + &self.data, + ) .0, ] .concat() } } #[automatically_derived] - impl alloy_sol_types::EventTopic for Settings { + impl alloy_sol_types::EventTopic for NodeOperator { #[inline] fn topic_preimage_length(rust: &Self::RustType) -> usize { 0usize - + as alloy_sol_types::EventTopic>::topic_preimage_length( - &rust.minOperators, + + ::topic_preimage_length( + &rust.addr, ) - + as alloy_sol_types::EventTopic>::topic_preimage_length( - &rust.minNodes, + + ::topic_preimage_length( + &rust.data, ) } #[inline] @@ -2283,16 +2217,211 @@ struct Settings { uint8 minOperators; uint8 minNodes; } out.reserve( ::topic_preimage_length(rust), ); - as alloy_sol_types::EventTopic>::encode_topic_preimage( - &rust.minOperators, + ::encode_topic_preimage( + &rust.addr, + out, + ); + ::encode_topic_preimage( + &rust.data, out, ); + } + #[inline] + fn encode_topic( + rust: &Self::RustType, + ) -> alloy_sol_types::abi::token::WordToken { + let mut out = alloy_sol_types::private::Vec::new(); + ::encode_topic_preimage( + rust, + &mut out, + ); + alloy_sol_types::abi::token::WordToken( + alloy_sol_types::private::keccak256(out), + ) + } + } + }; + /**```solidity +struct Settings { uint16 maxOperatorDataBytes; } +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct Settings { + #[allow(missing_docs)] + pub maxOperatorDataBytes: u16, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Uint<16>,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (u16,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: Settings) -> Self { + (value.maxOperatorDataBytes,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for Settings { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + maxOperatorDataBytes: tuple.0, + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolValue for Settings { + type SolType = Self; + } + #[automatically_derived] + impl alloy_sol_types::private::SolTypeValue for Settings { + #[inline] + fn stv_to_tokens(&self) -> ::Token<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.maxOperatorDataBytes), + ) + } + #[inline] + fn stv_abi_encoded_size(&self) -> usize { + if let Some(size) = ::ENCODED_SIZE { + return size; + } + let tuple = as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encoded_size(&tuple) + } + #[inline] + fn stv_eip712_data_word(&self) -> alloy_sol_types::Word { + ::eip712_hash_struct(self) + } + #[inline] + fn stv_abi_encode_packed_to( + &self, + out: &mut alloy_sol_types::private::Vec, + ) { + let tuple = as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encode_packed_to(&tuple, out) + } + #[inline] + fn stv_abi_packed_encoded_size(&self) -> usize { + if let Some(size) = ::PACKED_ENCODED_SIZE { + return size; + } + let tuple = as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_packed_encoded_size(&tuple) + } + } + #[automatically_derived] + impl alloy_sol_types::SolType for Settings { + type RustType = Self; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SOL_NAME: &'static str = ::NAME; + const ENCODED_SIZE: Option = as alloy_sol_types::SolType>::ENCODED_SIZE; + const PACKED_ENCODED_SIZE: Option = as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; + #[inline] + fn valid_token(token: &Self::Token<'_>) -> bool { + as alloy_sol_types::SolType>::valid_token(token) + } + #[inline] + fn detokenize(token: Self::Token<'_>) -> Self::RustType { + let tuple = as alloy_sol_types::SolType>::detokenize(token); + >>::from(tuple) + } + } + #[automatically_derived] + impl alloy_sol_types::SolStruct for Settings { + const NAME: &'static str = "Settings"; + #[inline] + fn eip712_root_type() -> alloy_sol_types::private::Cow<'static, str> { + alloy_sol_types::private::Cow::Borrowed( + "Settings(uint16 maxOperatorDataBytes)", + ) + } + #[inline] + fn eip712_components() -> alloy_sol_types::private::Vec< + alloy_sol_types::private::Cow<'static, str>, + > { + alloy_sol_types::private::Vec::new() + } + #[inline] + fn eip712_encode_type() -> alloy_sol_types::private::Cow<'static, str> { + ::eip712_root_type() + } + #[inline] + fn eip712_encode_data(&self) -> alloy_sol_types::private::Vec { + as alloy_sol_types::SolType>::eip712_data_word( + &self.maxOperatorDataBytes, + ) + .0 + .to_vec() + } + } + #[automatically_derived] + impl alloy_sol_types::EventTopic for Settings { + #[inline] + fn topic_preimage_length(rust: &Self::RustType) -> usize { + 0usize + + as alloy_sol_types::EventTopic>::topic_preimage_length( + &rust.maxOperatorDataBytes, + ) + } + #[inline] + fn encode_topic_preimage( + rust: &Self::RustType, + out: &mut alloy_sol_types::private::Vec, + ) { + out.reserve( + ::topic_preimage_length(rust), + ); as alloy_sol_types::EventTopic>::encode_topic_preimage( - &rust.minNodes, + &rust.maxOperatorDataBytes, out, ); } @@ -2313,7 +2442,7 @@ struct Settings { uint8 minOperators; uint8 minNodes; } }; /**Event with signature `MaintenanceAborted(uint128)` and selector `0x8fb9cd054d0a022110cced239e908b834e4cd219511856d4eaae3051d932d604`. ```solidity -event MaintenanceAborted(uint128 version); +event MaintenanceAborted(uint128 clusterVersion); ```*/ #[allow( non_camel_case_types, @@ -2324,7 +2453,7 @@ event MaintenanceAborted(uint128 version); #[derive(Clone)] pub struct MaintenanceAborted { #[allow(missing_docs)] - pub version: u128, + pub clusterVersion: u128, } #[allow( non_camel_case_types, @@ -2383,7 +2512,7 @@ event MaintenanceAborted(uint128 version); topics: ::RustType, data: as alloy_sol_types::SolType>::RustType, ) -> Self { - Self { version: data.0 } + Self { clusterVersion: data.0 } } #[inline] fn check_signature( @@ -2405,7 +2534,7 @@ event MaintenanceAborted(uint128 version); ( as alloy_sol_types::SolType>::tokenize(&self.version), + > as alloy_sol_types::SolType>::tokenize(&self.clusterVersion), ) } #[inline] @@ -2445,7 +2574,7 @@ event MaintenanceAborted(uint128 version); }; /**Event with signature `MaintenanceCompleted(address,uint128)` and selector `0xf91067eb420c28d3124865fc996e6aa9d541b9b4fef9188cb965a6cc6491638e`. ```solidity -event MaintenanceCompleted(address operator, uint128 version); +event MaintenanceCompleted(address operatorAddress, uint128 clusterVersion); ```*/ #[allow( non_camel_case_types, @@ -2456,9 +2585,9 @@ event MaintenanceCompleted(address operator, uint128 version); #[derive(Clone)] pub struct MaintenanceCompleted { #[allow(missing_docs)] - pub operator: alloy::sol_types::private::Address, + pub operatorAddress: alloy::sol_types::private::Address, #[allow(missing_docs)] - pub version: u128, + pub clusterVersion: u128, } #[allow( non_camel_case_types, @@ -2521,8 +2650,8 @@ event MaintenanceCompleted(address operator, uint128 version); data: as alloy_sol_types::SolType>::RustType, ) -> Self { Self { - operator: data.0, - version: data.1, + operatorAddress: data.0, + clusterVersion: data.1, } } #[inline] @@ -2544,11 +2673,11 @@ event MaintenanceCompleted(address operator, uint128 version); fn tokenize_body(&self) -> Self::DataToken<'_> { ( ::tokenize( - &self.operator, + &self.operatorAddress, ), as alloy_sol_types::SolType>::tokenize(&self.version), + > as alloy_sol_types::SolType>::tokenize(&self.clusterVersion), ) } #[inline] @@ -2588,7 +2717,7 @@ event MaintenanceCompleted(address operator, uint128 version); }; /**Event with signature `MaintenanceStarted(address,uint128)` and selector `0xbc2748cf02f7a1291525e866efc76ab3b96d32d7afcbb26c53daec617b38b479`. ```solidity -event MaintenanceStarted(address operator, uint128 version); +event MaintenanceStarted(address operatorAddress, uint128 clusterVersion); ```*/ #[allow( non_camel_case_types, @@ -2599,9 +2728,9 @@ event MaintenanceStarted(address operator, uint128 version); #[derive(Clone)] pub struct MaintenanceStarted { #[allow(missing_docs)] - pub operator: alloy::sol_types::private::Address, + pub operatorAddress: alloy::sol_types::private::Address, #[allow(missing_docs)] - pub version: u128, + pub clusterVersion: u128, } #[allow( non_camel_case_types, @@ -2664,8 +2793,8 @@ event MaintenanceStarted(address operator, uint128 version); data: as alloy_sol_types::SolType>::RustType, ) -> Self { Self { - operator: data.0, - version: data.1, + operatorAddress: data.0, + clusterVersion: data.1, } } #[inline] @@ -2687,11 +2816,11 @@ event MaintenanceStarted(address operator, uint128 version); fn tokenize_body(&self) -> Self::DataToken<'_> { ( ::tokenize( - &self.operator, + &self.operatorAddress, ), as alloy_sol_types::SolType>::tokenize(&self.version), + > as alloy_sol_types::SolType>::tokenize(&self.clusterVersion), ) } #[inline] @@ -2729,9 +2858,9 @@ event MaintenanceStarted(address operator, uint128 version); } } }; - /**Event with signature `MigrationAborted(uint128)` and selector `0x9ce192aea5faf2151bbc246cd8918d2eba702fa26951f67f2bf7b3817e689d98`. + /**Event with signature `MigrationAborted(uint64,uint128)` and selector `0xf73240422246f63ed633ef3ce0726b8ab8fb69d46c8a4e5ecb0b2922668674a1`. ```solidity -event MigrationAborted(uint128 version); +event MigrationAborted(uint64 id, uint128 clusterVersion); ```*/ #[allow( non_camel_case_types, @@ -2742,7 +2871,9 @@ event MigrationAborted(uint128 version); #[derive(Clone)] pub struct MigrationAborted { #[allow(missing_docs)] - pub version: u128, + pub id: u64, + #[allow(missing_docs)] + pub clusterVersion: u128, } #[allow( non_camel_case_types, @@ -2754,54 +2885,60 @@ event MigrationAborted(uint128 version); use alloy::sol_types as alloy_sol_types; #[automatically_derived] impl alloy_sol_types::SolEvent for MigrationAborted { - type DataTuple<'a> = (alloy::sol_types::sol_data::Uint<128>,); + type DataTuple<'a> = ( + alloy::sol_types::sol_data::Uint<64>, + alloy::sol_types::sol_data::Uint<128>, + ); type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); - const SIGNATURE: &'static str = "MigrationAborted(uint128)"; + const SIGNATURE: &'static str = "MigrationAborted(uint64,uint128)"; const SIGNATURE_HASH: alloy_sol_types::private::B256 = alloy_sol_types::private::B256::new([ - 156u8, - 225u8, - 146u8, - 174u8, - 165u8, - 250u8, - 242u8, - 21u8, - 27u8, - 188u8, - 36u8, - 108u8, - 216u8, - 145u8, - 141u8, - 46u8, - 186u8, - 112u8, - 47u8, - 162u8, - 105u8, - 81u8, - 246u8, - 127u8, - 43u8, 247u8, - 179u8, - 129u8, - 126u8, - 104u8, - 157u8, - 152u8, - ]); - const ANONYMOUS: bool = false; - #[allow(unused_variables)] - #[inline] - fn new( + 50u8, + 64u8, + 66u8, + 34u8, + 70u8, + 246u8, + 62u8, + 214u8, + 51u8, + 239u8, + 60u8, + 224u8, + 114u8, + 107u8, + 138u8, + 184u8, + 251u8, + 105u8, + 212u8, + 108u8, + 138u8, + 78u8, + 94u8, + 203u8, + 11u8, + 41u8, + 34u8, + 102u8, + 134u8, + 116u8, + 161u8, + ]); + const ANONYMOUS: bool = false; + #[allow(unused_variables)] + #[inline] + fn new( topics: ::RustType, data: as alloy_sol_types::SolType>::RustType, ) -> Self { - Self { version: data.0 } + Self { + id: data.0, + clusterVersion: data.1, + } } #[inline] fn check_signature( @@ -2821,9 +2958,12 @@ event MigrationAborted(uint128 version); #[inline] fn tokenize_body(&self) -> Self::DataToken<'_> { ( + as alloy_sol_types::SolType>::tokenize(&self.id), as alloy_sol_types::SolType>::tokenize(&self.version), + > as alloy_sol_types::SolType>::tokenize(&self.clusterVersion), ) } #[inline] @@ -2861,9 +3001,9 @@ event MigrationAborted(uint128 version); } } }; - /**Event with signature `MigrationCompleted(uint128)` and selector `0x11ce50160e66100537fd4b0ae26de66d51dab713ad92313353a18c24e8f6daab`. + /**Event with signature `MigrationCompleted(uint64,address,uint128)` and selector `0x01269879535f40ee8957e15e160bf1866c5e2728ff0cbc583d848821e2639b4e`. ```solidity -event MigrationCompleted(uint128 version); +event MigrationCompleted(uint64 id, address operatorAddress, uint128 clusterVersion); ```*/ #[allow( non_camel_case_types, @@ -2874,7 +3014,11 @@ event MigrationCompleted(uint128 version); #[derive(Clone)] pub struct MigrationCompleted { #[allow(missing_docs)] - pub version: u128, + pub id: u64, + #[allow(missing_docs)] + pub operatorAddress: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub clusterVersion: u128, } #[allow( non_camel_case_types, @@ -2886,45 +3030,49 @@ event MigrationCompleted(uint128 version); use alloy::sol_types as alloy_sol_types; #[automatically_derived] impl alloy_sol_types::SolEvent for MigrationCompleted { - type DataTuple<'a> = (alloy::sol_types::sol_data::Uint<128>,); + type DataTuple<'a> = ( + alloy::sol_types::sol_data::Uint<64>, + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Uint<128>, + ); type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); - const SIGNATURE: &'static str = "MigrationCompleted(uint128)"; + const SIGNATURE: &'static str = "MigrationCompleted(uint64,address,uint128)"; const SIGNATURE_HASH: alloy_sol_types::private::B256 = alloy_sol_types::private::B256::new([ - 17u8, - 206u8, - 80u8, + 1u8, + 38u8, + 152u8, + 121u8, + 83u8, + 95u8, + 64u8, + 238u8, + 137u8, + 87u8, + 225u8, + 94u8, 22u8, - 14u8, - 102u8, - 16u8, - 5u8, - 55u8, - 253u8, - 75u8, - 10u8, + 11u8, + 241u8, + 134u8, + 108u8, + 94u8, + 39u8, + 40u8, + 255u8, + 12u8, + 188u8, + 88u8, + 61u8, + 132u8, + 136u8, + 33u8, 226u8, - 109u8, - 230u8, - 109u8, - 81u8, - 218u8, - 183u8, - 19u8, - 173u8, - 146u8, - 49u8, - 51u8, - 83u8, - 161u8, - 140u8, - 36u8, - 232u8, - 246u8, - 218u8, - 171u8, + 99u8, + 155u8, + 78u8, ]); const ANONYMOUS: bool = false; #[allow(unused_variables)] @@ -2933,7 +3081,11 @@ event MigrationCompleted(uint128 version); topics: ::RustType, data: as alloy_sol_types::SolType>::RustType, ) -> Self { - Self { version: data.0 } + Self { + id: data.0, + operatorAddress: data.1, + clusterVersion: data.2, + } } #[inline] fn check_signature( @@ -2953,9 +3105,15 @@ event MigrationCompleted(uint128 version); #[inline] fn tokenize_body(&self) -> Self::DataToken<'_> { ( + as alloy_sol_types::SolType>::tokenize(&self.id), + ::tokenize( + &self.operatorAddress, + ), as alloy_sol_types::SolType>::tokenize(&self.version), + > as alloy_sol_types::SolType>::tokenize(&self.clusterVersion), ) } #[inline] @@ -2993,9 +3151,9 @@ event MigrationCompleted(uint128 version); } } }; - /**Event with signature `MigrationDataPullCompleted(address,uint128)` and selector `0xa76a8fc1a90266ddee8937a18e12f01eade946b3b66197fff289af9277c2bd25`. + /**Event with signature `MigrationDataPullCompleted(uint64,address,uint128)` and selector `0xaf5e90e72015f43138f66b4cd08bd1dfa2839030104f22a00af843fe847c6d19`. ```solidity -event MigrationDataPullCompleted(address operator, uint128 version); +event MigrationDataPullCompleted(uint64 id, address operatorAddress, uint128 clusterVersion); ```*/ #[allow( non_camel_case_types, @@ -3006,9 +3164,11 @@ event MigrationDataPullCompleted(address operator, uint128 version); #[derive(Clone)] pub struct MigrationDataPullCompleted { #[allow(missing_docs)] - pub operator: alloy::sol_types::private::Address, + pub id: u64, #[allow(missing_docs)] - pub version: u128, + pub operatorAddress: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub clusterVersion: u128, } #[allow( non_camel_case_types, @@ -3021,6 +3181,7 @@ event MigrationDataPullCompleted(address operator, uint128 version); #[automatically_derived] impl alloy_sol_types::SolEvent for MigrationDataPullCompleted { type DataTuple<'a> = ( + alloy::sol_types::sol_data::Uint<64>, alloy::sol_types::sol_data::Address, alloy::sol_types::sol_data::Uint<128>, ); @@ -3028,40 +3189,40 @@ event MigrationDataPullCompleted(address operator, uint128 version); 'a, > as alloy_sol_types::SolType>::Token<'a>; type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); - const SIGNATURE: &'static str = "MigrationDataPullCompleted(address,uint128)"; + const SIGNATURE: &'static str = "MigrationDataPullCompleted(uint64,address,uint128)"; const SIGNATURE_HASH: alloy_sol_types::private::B256 = alloy_sol_types::private::B256::new([ - 167u8, - 106u8, - 143u8, - 193u8, - 169u8, - 2u8, - 102u8, - 221u8, - 238u8, - 137u8, - 55u8, - 161u8, - 142u8, - 18u8, - 240u8, - 30u8, - 173u8, - 233u8, - 70u8, - 179u8, - 182u8, - 97u8, - 151u8, - 255u8, - 242u8, - 137u8, 175u8, - 146u8, - 119u8, - 194u8, - 189u8, - 37u8, + 94u8, + 144u8, + 231u8, + 32u8, + 21u8, + 244u8, + 49u8, + 56u8, + 246u8, + 107u8, + 76u8, + 208u8, + 139u8, + 209u8, + 223u8, + 162u8, + 131u8, + 144u8, + 48u8, + 16u8, + 79u8, + 34u8, + 160u8, + 10u8, + 248u8, + 67u8, + 254u8, + 132u8, + 124u8, + 109u8, + 25u8, ]); const ANONYMOUS: bool = false; #[allow(unused_variables)] @@ -3071,8 +3232,9 @@ event MigrationDataPullCompleted(address operator, uint128 version); data: as alloy_sol_types::SolType>::RustType, ) -> Self { Self { - operator: data.0, - version: data.1, + id: data.0, + operatorAddress: data.1, + clusterVersion: data.2, } } #[inline] @@ -3093,12 +3255,15 @@ event MigrationDataPullCompleted(address operator, uint128 version); #[inline] fn tokenize_body(&self) -> Self::DataToken<'_> { ( + as alloy_sol_types::SolType>::tokenize(&self.id), ::tokenize( - &self.operator, + &self.operatorAddress, ), as alloy_sol_types::SolType>::tokenize(&self.version), + > as alloy_sol_types::SolType>::tokenize(&self.clusterVersion), ) } #[inline] @@ -3138,9 +3303,9 @@ event MigrationDataPullCompleted(address operator, uint128 version); } } }; - /**Event with signature `MigrationStarted(address[],(address,(uint256,bytes)[],bytes)[],uint128)` and selector `0x7e05e40117b6e18ab284c04a3508c3826422dc84a65e9c236a8248774416f8ac`. + /**Event with signature `MigrationStarted(uint64,((uint8,address)[],uint8),uint128)` and selector `0x78dad2bc0b47c688ed84f3fee79abc18e6c9822db05a79ca19dff54533c7470d`. ```solidity -event MigrationStarted(address[] operatorsToRemove, NodeOperatorView[] operatorsToAdd, uint128 version); +event MigrationStarted(uint64 id, MigrationPlan plan, uint128 clusterVersion); ```*/ #[allow( non_camel_case_types, @@ -3151,15 +3316,11 @@ event MigrationStarted(address[] operatorsToRemove, NodeOperatorView[] operators #[derive(Clone)] pub struct MigrationStarted { #[allow(missing_docs)] - pub operatorsToRemove: alloy::sol_types::private::Vec< - alloy::sol_types::private::Address, - >, + pub id: u64, #[allow(missing_docs)] - pub operatorsToAdd: alloy::sol_types::private::Vec< - ::RustType, - >, + pub plan: ::RustType, #[allow(missing_docs)] - pub version: u128, + pub clusterVersion: u128, } #[allow( non_camel_case_types, @@ -3172,198 +3333,48 @@ event MigrationStarted(address[] operatorsToRemove, NodeOperatorView[] operators #[automatically_derived] impl alloy_sol_types::SolEvent for MigrationStarted { type DataTuple<'a> = ( - alloy::sol_types::sol_data::Array, - alloy::sol_types::sol_data::Array, + alloy::sol_types::sol_data::Uint<64>, + MigrationPlan, alloy::sol_types::sol_data::Uint<128>, ); type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); - const SIGNATURE: &'static str = "MigrationStarted(address[],(address,(uint256,bytes)[],bytes)[],uint128)"; + const SIGNATURE: &'static str = "MigrationStarted(uint64,((uint8,address)[],uint8),uint128)"; const SIGNATURE_HASH: alloy_sol_types::private::B256 = alloy_sol_types::private::B256::new([ - 126u8, - 5u8, - 228u8, - 1u8, - 23u8, - 182u8, - 225u8, - 138u8, - 178u8, - 132u8, - 192u8, - 74u8, - 53u8, - 8u8, - 195u8, - 130u8, - 100u8, - 34u8, - 220u8, + 120u8, + 218u8, + 210u8, + 188u8, + 11u8, + 71u8, + 198u8, + 136u8, + 237u8, 132u8, - 166u8, - 94u8, - 156u8, - 35u8, - 106u8, - 130u8, - 72u8, - 119u8, - 68u8, - 22u8, - 248u8, - 172u8, - ]); - const ANONYMOUS: bool = false; - #[allow(unused_variables)] - #[inline] - fn new( - topics: ::RustType, - data: as alloy_sol_types::SolType>::RustType, - ) -> Self { - Self { - operatorsToRemove: data.0, - operatorsToAdd: data.1, - version: data.2, - } - } - #[inline] - fn check_signature( - topics: &::RustType, - ) -> alloy_sol_types::Result<()> { - if topics.0 != Self::SIGNATURE_HASH { - return Err( - alloy_sol_types::Error::invalid_event_signature_hash( - Self::SIGNATURE, - topics.0, - Self::SIGNATURE_HASH, - ), - ); - } - Ok(()) - } - #[inline] - fn tokenize_body(&self) -> Self::DataToken<'_> { - ( - as alloy_sol_types::SolType>::tokenize(&self.operatorsToRemove), - as alloy_sol_types::SolType>::tokenize(&self.operatorsToAdd), - as alloy_sol_types::SolType>::tokenize(&self.version), - ) - } - #[inline] - fn topics(&self) -> ::RustType { - (Self::SIGNATURE_HASH.into(),) - } - #[inline] - fn encode_topics_raw( - &self, - out: &mut [alloy_sol_types::abi::token::WordToken], - ) -> alloy_sol_types::Result<()> { - if out.len() < ::COUNT { - return Err(alloy_sol_types::Error::Overrun); - } - out[0usize] = alloy_sol_types::abi::token::WordToken( - Self::SIGNATURE_HASH, - ); - Ok(()) - } - } - #[automatically_derived] - impl alloy_sol_types::private::IntoLogData for MigrationStarted { - fn to_log_data(&self) -> alloy_sol_types::private::LogData { - From::from(self) - } - fn into_log_data(self) -> alloy_sol_types::private::LogData { - From::from(&self) - } - } - #[automatically_derived] - impl From<&MigrationStarted> for alloy_sol_types::private::LogData { - #[inline] - fn from(this: &MigrationStarted) -> alloy_sol_types::private::LogData { - alloy_sol_types::SolEvent::encode_log_data(this) - } - } - }; - /**Event with signature `NodeRemoved(address,uint256,uint128)` and selector `0xbd184de79f134b0f3da466d278f5417cbcb1450d72f1bd1a1b84f18b1bcd03ca`. -```solidity -event NodeRemoved(address operator, uint256 id, uint128 version); -```*/ - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - #[derive(Clone)] - pub struct NodeRemoved { - #[allow(missing_docs)] - pub operator: alloy::sol_types::private::Address, - #[allow(missing_docs)] - pub id: alloy::sol_types::private::primitives::aliases::U256, - #[allow(missing_docs)] - pub version: u128, - } - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - #[automatically_derived] - impl alloy_sol_types::SolEvent for NodeRemoved { - type DataTuple<'a> = ( - alloy::sol_types::sol_data::Address, - alloy::sol_types::sol_data::Uint<256>, - alloy::sol_types::sol_data::Uint<128>, - ); - type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); - const SIGNATURE: &'static str = "NodeRemoved(address,uint256,uint128)"; - const SIGNATURE_HASH: alloy_sol_types::private::B256 = alloy_sol_types::private::B256::new([ - 189u8, - 24u8, - 77u8, + 243u8, + 254u8, 231u8, - 159u8, - 19u8, - 75u8, - 15u8, - 61u8, - 164u8, - 102u8, - 210u8, - 120u8, - 245u8, - 65u8, - 124u8, + 154u8, 188u8, - 177u8, + 24u8, + 230u8, + 201u8, + 130u8, + 45u8, + 176u8, + 90u8, + 121u8, + 202u8, + 25u8, + 223u8, + 245u8, 69u8, + 51u8, + 199u8, + 71u8, 13u8, - 114u8, - 241u8, - 189u8, - 26u8, - 27u8, - 132u8, - 241u8, - 139u8, - 27u8, - 205u8, - 3u8, - 202u8, ]); const ANONYMOUS: bool = false; #[allow(unused_variables)] @@ -3373,9 +3384,9 @@ event NodeRemoved(address operator, uint256 id, uint128 version); data: as alloy_sol_types::SolType>::RustType, ) -> Self { Self { - operator: data.0, - id: data.1, - version: data.2, + id: data.0, + plan: data.1, + clusterVersion: data.2, } } #[inline] @@ -3396,15 +3407,13 @@ event NodeRemoved(address operator, uint256 id, uint128 version); #[inline] fn tokenize_body(&self) -> Self::DataToken<'_> { ( - ::tokenize( - &self.operator, - ), as alloy_sol_types::SolType>::tokenize(&self.id), + ::tokenize(&self.plan), as alloy_sol_types::SolType>::tokenize(&self.version), + > as alloy_sol_types::SolType>::tokenize(&self.clusterVersion), ) } #[inline] @@ -3426,7 +3435,7 @@ event NodeRemoved(address operator, uint256 id, uint128 version); } } #[automatically_derived] - impl alloy_sol_types::private::IntoLogData for NodeRemoved { + impl alloy_sol_types::private::IntoLogData for MigrationStarted { fn to_log_data(&self) -> alloy_sol_types::private::LogData { From::from(self) } @@ -3435,16 +3444,16 @@ event NodeRemoved(address operator, uint256 id, uint128 version); } } #[automatically_derived] - impl From<&NodeRemoved> for alloy_sol_types::private::LogData { + impl From<&MigrationStarted> for alloy_sol_types::private::LogData { #[inline] - fn from(this: &NodeRemoved) -> alloy_sol_types::private::LogData { + fn from(this: &MigrationStarted) -> alloy_sol_types::private::LogData { alloy_sol_types::SolEvent::encode_log_data(this) } } }; - /**Event with signature `NodeSet(address,(uint256,bytes),uint128)` and selector `0x6adfb896d3407681d05fb874d4dfb7068e6e2a36f09acd38a3b7d04c01745fee`. + /**Event with signature `NodeOperatorDataUpdated(address,bytes,uint128)` and selector `0x125181ec21882dec51a2392905dff3a82cbd0262f18b5c0c035488671b40afb2`. ```solidity -event NodeSet(address operator, Node node, uint128 version); +event NodeOperatorDataUpdated(address operatorAddress, bytes data, uint128 clusterVersion); ```*/ #[allow( non_camel_case_types, @@ -3453,13 +3462,13 @@ event NodeSet(address operator, Node node, uint128 version); clippy::style )] #[derive(Clone)] - pub struct NodeSet { + pub struct NodeOperatorDataUpdated { #[allow(missing_docs)] - pub operator: alloy::sol_types::private::Address, + pub operatorAddress: alloy::sol_types::private::Address, #[allow(missing_docs)] - pub node: ::RustType, + pub data: alloy::sol_types::private::Bytes, #[allow(missing_docs)] - pub version: u128, + pub clusterVersion: u128, } #[allow( non_camel_case_types, @@ -3470,50 +3479,50 @@ event NodeSet(address operator, Node node, uint128 version); const _: () = { use alloy::sol_types as alloy_sol_types; #[automatically_derived] - impl alloy_sol_types::SolEvent for NodeSet { + impl alloy_sol_types::SolEvent for NodeOperatorDataUpdated { type DataTuple<'a> = ( alloy::sol_types::sol_data::Address, - Node, + alloy::sol_types::sol_data::Bytes, alloy::sol_types::sol_data::Uint<128>, ); type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); - const SIGNATURE: &'static str = "NodeSet(address,(uint256,bytes),uint128)"; + const SIGNATURE: &'static str = "NodeOperatorDataUpdated(address,bytes,uint128)"; const SIGNATURE_HASH: alloy_sol_types::private::B256 = alloy_sol_types::private::B256::new([ - 106u8, - 223u8, - 184u8, - 150u8, - 211u8, - 64u8, - 118u8, + 18u8, + 81u8, 129u8, - 208u8, - 95u8, - 184u8, - 116u8, - 212u8, - 223u8, - 183u8, - 6u8, - 142u8, - 110u8, - 42u8, - 54u8, - 240u8, - 154u8, - 205u8, - 56u8, - 163u8, - 183u8, - 208u8, - 76u8, - 1u8, - 116u8, - 95u8, - 238u8, + 236u8, + 33u8, + 136u8, + 45u8, + 236u8, + 81u8, + 162u8, + 57u8, + 41u8, + 5u8, + 223u8, + 243u8, + 168u8, + 44u8, + 189u8, + 2u8, + 98u8, + 241u8, + 139u8, + 92u8, + 12u8, + 3u8, + 84u8, + 136u8, + 103u8, + 27u8, + 64u8, + 175u8, + 178u8, ]); const ANONYMOUS: bool = false; #[allow(unused_variables)] @@ -3523,9 +3532,9 @@ event NodeSet(address operator, Node node, uint128 version); data: as alloy_sol_types::SolType>::RustType, ) -> Self { Self { - operator: data.0, - node: data.1, - version: data.2, + operatorAddress: data.0, + data: data.1, + clusterVersion: data.2, } } #[inline] @@ -3547,12 +3556,14 @@ event NodeSet(address operator, Node node, uint128 version); fn tokenize_body(&self) -> Self::DataToken<'_> { ( ::tokenize( - &self.operator, + &self.operatorAddress, + ), + ::tokenize( + &self.data, ), - ::tokenize(&self.node), as alloy_sol_types::SolType>::tokenize(&self.version), + > as alloy_sol_types::SolType>::tokenize(&self.clusterVersion), ) } #[inline] @@ -3574,7 +3585,7 @@ event NodeSet(address operator, Node node, uint128 version); } } #[automatically_derived] - impl alloy_sol_types::private::IntoLogData for NodeSet { + impl alloy_sol_types::private::IntoLogData for NodeOperatorDataUpdated { fn to_log_data(&self) -> alloy_sol_types::private::LogData { From::from(self) } @@ -3583,16 +3594,18 @@ event NodeSet(address operator, Node node, uint128 version); } } #[automatically_derived] - impl From<&NodeSet> for alloy_sol_types::private::LogData { + impl From<&NodeOperatorDataUpdated> for alloy_sol_types::private::LogData { #[inline] - fn from(this: &NodeSet) -> alloy_sol_types::private::LogData { + fn from( + this: &NodeOperatorDataUpdated, + ) -> alloy_sol_types::private::LogData { alloy_sol_types::SolEvent::encode_log_data(this) } } }; /**Constructor`. ```solidity -constructor(Settings initialSettings, NodeOperatorView[] initialOperators); +constructor(Settings initialSettings, address[] initialOperators); ```*/ #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] @@ -3601,7 +3614,7 @@ constructor(Settings initialSettings, NodeOperatorView[] initialOperators); pub initialSettings: ::RustType, #[allow(missing_docs)] pub initialOperators: alloy::sol_types::private::Vec< - ::RustType, + alloy::sol_types::private::Address, >, } const _: () = { @@ -3610,14 +3623,12 @@ constructor(Settings initialSettings, NodeOperatorView[] initialOperators); #[doc(hidden)] type UnderlyingSolTuple<'a> = ( Settings, - alloy::sol_types::sol_data::Array, + alloy::sol_types::sol_data::Array, ); #[doc(hidden)] type UnderlyingRustTuple<'a> = ( ::RustType, - alloy::sol_types::private::Vec< - ::RustType, - >, + alloy::sol_types::private::Vec, ); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] @@ -3652,7 +3663,7 @@ constructor(Settings initialSettings, NodeOperatorView[] initialOperators); impl alloy_sol_types::SolConstructor for constructorCall { type Parameters<'a> = ( Settings, - alloy::sol_types::sol_data::Array, + alloy::sol_types::sol_data::Array, ); type Token<'a> = as alloy_sol_types::SolType>::tokenize(&self.initialOperators), ) } @@ -4034,14 +4045,19 @@ function completeMaintenance() external; } } }; - /**Function with signature `completeMigration()` and selector `0x4886f62c`. + /**Function with signature `completeMigration(uint64,uint8)` and selector `0x55a47d0a`. ```solidity -function completeMigration() external; +function completeMigration(uint64 id, uint8 operatorIdx) external; ```*/ #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] - pub struct completeMigrationCall {} - ///Container type for the return parameters of the [`completeMigration()`](completeMigrationCall) function. + pub struct completeMigrationCall { + #[allow(missing_docs)] + pub id: u64, + #[allow(missing_docs)] + pub operatorIdx: u8, + } + ///Container type for the return parameters of the [`completeMigration(uint64,uint8)`](completeMigrationCall) function. #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] pub struct completeMigrationReturn {} @@ -4055,9 +4071,12 @@ function completeMigration() external; use alloy::sol_types as alloy_sol_types; { #[doc(hidden)] - type UnderlyingSolTuple<'a> = (); + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::Uint<64>, + alloy::sol_types::sol_data::Uint<8>, + ); #[doc(hidden)] - type UnderlyingRustTuple<'a> = (); + type UnderlyingRustTuple<'a> = (u64, u8); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] fn _type_assertion( @@ -4074,7 +4093,7 @@ function completeMigration() external; impl ::core::convert::From for UnderlyingRustTuple<'_> { fn from(value: completeMigrationCall) -> Self { - () + (value.id, value.operatorIdx) } } #[automatically_derived] @@ -4082,7 +4101,10 @@ function completeMigration() external; impl ::core::convert::From> for completeMigrationCall { fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self {} + Self { + id: tuple.0, + operatorIdx: tuple.1, + } } } } @@ -4121,7 +4143,10 @@ function completeMigration() external; } #[automatically_derived] impl alloy_sol_types::SolCall for completeMigrationCall { - type Parameters<'a> = (); + type Parameters<'a> = ( + alloy::sol_types::sol_data::Uint<64>, + alloy::sol_types::sol_data::Uint<8>, + ); type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; @@ -4130,8 +4155,8 @@ function completeMigration() external; type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SIGNATURE: &'static str = "completeMigration()"; - const SELECTOR: [u8; 4] = [72u8, 134u8, 246u8, 44u8]; + const SIGNATURE: &'static str = "completeMigration(uint64,uint8)"; + const SELECTOR: [u8; 4] = [85u8, 164u8, 125u8, 10u8]; #[inline] fn new<'a>( tuple: as alloy_sol_types::SolType>::RustType, @@ -4140,7 +4165,14 @@ function completeMigration() external; } #[inline] fn tokenize(&self) -> Self::Token<'_> { - () + ( + as alloy_sol_types::SolType>::tokenize(&self.id), + as alloy_sol_types::SolType>::tokenize(&self.operatorIdx), + ) } #[inline] fn abi_decode_returns( @@ -4275,20 +4307,20 @@ function getView() external view returns (ClusterView memory); } } }; - /**Function with signature `removeNode(uint256)` and selector `0xffd740df`. + /**Function with signature `registerNodeOperator(bytes)` and selector `0x8b5252d6`. ```solidity -function removeNode(uint256 id) external; +function registerNodeOperator(bytes memory data) external; ```*/ #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] - pub struct removeNodeCall { + pub struct registerNodeOperatorCall { #[allow(missing_docs)] - pub id: alloy::sol_types::private::primitives::aliases::U256, + pub data: alloy::sol_types::private::Bytes, } - ///Container type for the return parameters of the [`removeNode(uint256)`](removeNodeCall) function. + ///Container type for the return parameters of the [`registerNodeOperator(bytes)`](registerNodeOperatorCall) function. #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] - pub struct removeNodeReturn {} + pub struct registerNodeOperatorReturn {} #[allow( non_camel_case_types, non_snake_case, @@ -4299,11 +4331,9 @@ function removeNode(uint256 id) external; use alloy::sol_types as alloy_sol_types; { #[doc(hidden)] - type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Uint<256>,); + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Bytes,); #[doc(hidden)] - type UnderlyingRustTuple<'a> = ( - alloy::sol_types::private::primitives::aliases::U256, - ); + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::Bytes,); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] fn _type_assertion( @@ -4317,16 +4347,18 @@ function removeNode(uint256 id) external; } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: removeNodeCall) -> Self { - (value.id,) + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: registerNodeOperatorCall) -> Self { + (value.data,) } } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From> for removeNodeCall { + impl ::core::convert::From> + for registerNodeOperatorCall { fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self { id: tuple.0 } + Self { data: tuple.0 } } } } @@ -4348,32 +4380,34 @@ function removeNode(uint256 id) external; } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: removeNodeReturn) -> Self { + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: registerNodeOperatorReturn) -> Self { () } } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From> for removeNodeReturn { + impl ::core::convert::From> + for registerNodeOperatorReturn { fn from(tuple: UnderlyingRustTuple<'_>) -> Self { Self {} } } } #[automatically_derived] - impl alloy_sol_types::SolCall for removeNodeCall { - type Parameters<'a> = (alloy::sol_types::sol_data::Uint<256>,); + impl alloy_sol_types::SolCall for registerNodeOperatorCall { + type Parameters<'a> = (alloy::sol_types::sol_data::Bytes,); type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - type Return = removeNodeReturn; + type Return = registerNodeOperatorReturn; type ReturnTuple<'a> = (); type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SIGNATURE: &'static str = "removeNode(uint256)"; - const SELECTOR: [u8; 4] = [255u8, 215u8, 64u8, 223u8]; + const SIGNATURE: &'static str = "registerNodeOperator(bytes)"; + const SELECTOR: [u8; 4] = [139u8, 82u8, 82u8, 214u8]; #[inline] fn new<'a>( tuple: as alloy_sol_types::SolType>::RustType, @@ -4383,9 +4417,9 @@ function removeNode(uint256 id) external; #[inline] fn tokenize(&self) -> Self::Token<'_> { ( - as alloy_sol_types::SolType>::tokenize(&self.id), + ::tokenize( + &self.data, + ), ) } #[inline] @@ -4400,20 +4434,20 @@ function removeNode(uint256 id) external; } } }; - /**Function with signature `setNode((uint256,bytes))` and selector `0x6c0b61b9`. + /**Function with signature `startMaintenance(uint8)` and selector `0xdd3fd269`. ```solidity -function setNode(Node memory node) external; +function startMaintenance(uint8 operatorIdx) external; ```*/ #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] - pub struct setNodeCall { + pub struct startMaintenanceCall { #[allow(missing_docs)] - pub node: ::RustType, + pub operatorIdx: u8, } - ///Container type for the return parameters of the [`setNode((uint256,bytes))`](setNodeCall) function. + ///Container type for the return parameters of the [`startMaintenance(uint8)`](startMaintenanceCall) function. #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] - pub struct setNodeReturn {} + pub struct startMaintenanceReturn {} #[allow( non_camel_case_types, non_snake_case, @@ -4424,11 +4458,9 @@ function setNode(Node memory node) external; use alloy::sol_types as alloy_sol_types; { #[doc(hidden)] - type UnderlyingSolTuple<'a> = (Node,); + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Uint<8>,); #[doc(hidden)] - type UnderlyingRustTuple<'a> = ( - ::RustType, - ); + type UnderlyingRustTuple<'a> = (u8,); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] fn _type_assertion( @@ -4442,16 +4474,18 @@ function setNode(Node memory node) external; } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: setNodeCall) -> Self { - (value.node,) + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: startMaintenanceCall) -> Self { + (value.operatorIdx,) } } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From> for setNodeCall { + impl ::core::convert::From> + for startMaintenanceCall { fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self { node: tuple.0 } + Self { operatorIdx: tuple.0 } } } } @@ -4473,32 +4507,34 @@ function setNode(Node memory node) external; } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: setNodeReturn) -> Self { + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: startMaintenanceReturn) -> Self { () } } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From> for setNodeReturn { + impl ::core::convert::From> + for startMaintenanceReturn { fn from(tuple: UnderlyingRustTuple<'_>) -> Self { Self {} } } } #[automatically_derived] - impl alloy_sol_types::SolCall for setNodeCall { - type Parameters<'a> = (Node,); + impl alloy_sol_types::SolCall for startMaintenanceCall { + type Parameters<'a> = (alloy::sol_types::sol_data::Uint<8>,); type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - type Return = setNodeReturn; + type Return = startMaintenanceReturn; type ReturnTuple<'a> = (); type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SIGNATURE: &'static str = "setNode((uint256,bytes))"; - const SELECTOR: [u8; 4] = [108u8, 11u8, 97u8, 185u8]; + const SIGNATURE: &'static str = "startMaintenance(uint8)"; + const SELECTOR: [u8; 4] = [221u8, 63u8, 210u8, 105u8]; #[inline] fn new<'a>( tuple: as alloy_sol_types::SolType>::RustType, @@ -4507,7 +4543,11 @@ function setNode(Node memory node) external; } #[inline] fn tokenize(&self) -> Self::Token<'_> { - (::tokenize(&self.node),) + ( + as alloy_sol_types::SolType>::tokenize(&self.operatorIdx), + ) } #[inline] fn abi_decode_returns( @@ -4521,17 +4561,20 @@ function setNode(Node memory node) external; } } }; - /**Function with signature `startMaintenance()` and selector `0xf5f2d9f1`. + /**Function with signature `startMigration(((uint8,address)[],uint8))` and selector `0xcdbfc62d`. ```solidity -function startMaintenance() external; +function startMigration(MigrationPlan memory plan) external; ```*/ #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] - pub struct startMaintenanceCall {} - ///Container type for the return parameters of the [`startMaintenance()`](startMaintenanceCall) function. + pub struct startMigrationCall { + #[allow(missing_docs)] + pub plan: ::RustType, + } + ///Container type for the return parameters of the [`startMigration(((uint8,address)[],uint8))`](startMigrationCall) function. #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] - pub struct startMaintenanceReturn {} + pub struct startMigrationReturn {} #[allow( non_camel_case_types, non_snake_case, @@ -4542,9 +4585,11 @@ function startMaintenance() external; use alloy::sol_types as alloy_sol_types; { #[doc(hidden)] - type UnderlyingSolTuple<'a> = (); + type UnderlyingSolTuple<'a> = (MigrationPlan,); #[doc(hidden)] - type UnderlyingRustTuple<'a> = (); + type UnderlyingRustTuple<'a> = ( + ::RustType, + ); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] fn _type_assertion( @@ -4558,18 +4603,16 @@ function startMaintenance() external; } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From - for UnderlyingRustTuple<'_> { - fn from(value: startMaintenanceCall) -> Self { - () + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: startMigrationCall) -> Self { + (value.plan,) } } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From> - for startMaintenanceCall { + impl ::core::convert::From> for startMigrationCall { fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self {} + Self { plan: tuple.0 } } } } @@ -4591,34 +4634,34 @@ function startMaintenance() external; } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From + impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: startMaintenanceReturn) -> Self { + fn from(value: startMigrationReturn) -> Self { () } } #[automatically_derived] #[doc(hidden)] impl ::core::convert::From> - for startMaintenanceReturn { + for startMigrationReturn { fn from(tuple: UnderlyingRustTuple<'_>) -> Self { Self {} } } } #[automatically_derived] - impl alloy_sol_types::SolCall for startMaintenanceCall { - type Parameters<'a> = (); + impl alloy_sol_types::SolCall for startMigrationCall { + type Parameters<'a> = (MigrationPlan,); type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - type Return = startMaintenanceReturn; + type Return = startMigrationReturn; type ReturnTuple<'a> = (); type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SIGNATURE: &'static str = "startMaintenance()"; - const SELECTOR: [u8; 4] = [245u8, 242u8, 217u8, 241u8]; + const SIGNATURE: &'static str = "startMigration(((uint8,address)[],uint8))"; + const SELECTOR: [u8; 4] = [205u8, 191u8, 198u8, 45u8]; #[inline] fn new<'a>( tuple: as alloy_sol_types::SolType>::RustType, @@ -4627,7 +4670,7 @@ function startMaintenance() external; } #[inline] fn tokenize(&self) -> Self::Token<'_> { - () + (::tokenize(&self.plan),) } #[inline] fn abi_decode_returns( @@ -4641,26 +4684,20 @@ function startMaintenance() external; } } }; - /**Function with signature `startMigration(address[],(address,(uint256,bytes)[],bytes)[])` and selector `0xcc45662a`. + /**Function with signature `transferOwnership(address)` and selector `0xf2fde38b`. ```solidity -function startMigration(address[] memory operatorsToRemove, NodeOperatorView[] memory operatorsToAdd) external; +function transferOwnership(address newOwner) external; ```*/ #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] - pub struct startMigrationCall { - #[allow(missing_docs)] - pub operatorsToRemove: alloy::sol_types::private::Vec< - alloy::sol_types::private::Address, - >, + pub struct transferOwnershipCall { #[allow(missing_docs)] - pub operatorsToAdd: alloy::sol_types::private::Vec< - ::RustType, - >, + pub newOwner: alloy::sol_types::private::Address, } - ///Container type for the return parameters of the [`startMigration(address[],(address,(uint256,bytes)[],bytes)[])`](startMigrationCall) function. + ///Container type for the return parameters of the [`transferOwnership(address)`](transferOwnershipCall) function. #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] - pub struct startMigrationReturn {} + pub struct transferOwnershipReturn {} #[allow( non_camel_case_types, non_snake_case, @@ -4671,17 +4708,9 @@ function startMigration(address[] memory operatorsToRemove, NodeOperatorView[] m use alloy::sol_types as alloy_sol_types; { #[doc(hidden)] - type UnderlyingSolTuple<'a> = ( - alloy::sol_types::sol_data::Array, - alloy::sol_types::sol_data::Array, - ); + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Address,); #[doc(hidden)] - type UnderlyingRustTuple<'a> = ( - alloy::sol_types::private::Vec, - alloy::sol_types::private::Vec< - ::RustType, - >, - ); + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::Address,); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] fn _type_assertion( @@ -4695,19 +4724,18 @@ function startMigration(address[] memory operatorsToRemove, NodeOperatorView[] m } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: startMigrationCall) -> Self { - (value.operatorsToRemove, value.operatorsToAdd) + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: transferOwnershipCall) -> Self { + (value.newOwner,) } } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From> for startMigrationCall { + impl ::core::convert::From> + for transferOwnershipCall { fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self { - operatorsToRemove: tuple.0, - operatorsToAdd: tuple.1, - } + Self { newOwner: tuple.0 } } } } @@ -4729,37 +4757,34 @@ function startMigration(address[] memory operatorsToRemove, NodeOperatorView[] m } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From + impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: startMigrationReturn) -> Self { + fn from(value: transferOwnershipReturn) -> Self { () } } #[automatically_derived] #[doc(hidden)] impl ::core::convert::From> - for startMigrationReturn { + for transferOwnershipReturn { fn from(tuple: UnderlyingRustTuple<'_>) -> Self { Self {} } } } #[automatically_derived] - impl alloy_sol_types::SolCall for startMigrationCall { - type Parameters<'a> = ( - alloy::sol_types::sol_data::Array, - alloy::sol_types::sol_data::Array, - ); + impl alloy_sol_types::SolCall for transferOwnershipCall { + type Parameters<'a> = (alloy::sol_types::sol_data::Address,); type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - type Return = startMigrationReturn; + type Return = transferOwnershipReturn; type ReturnTuple<'a> = (); type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SIGNATURE: &'static str = "startMigration(address[],(address,(uint256,bytes)[],bytes)[])"; - const SELECTOR: [u8; 4] = [204u8, 69u8, 102u8, 42u8]; + const SIGNATURE: &'static str = "transferOwnership(address)"; + const SELECTOR: [u8; 4] = [242u8, 253u8, 227u8, 139u8]; #[inline] fn new<'a>( tuple: as alloy_sol_types::SolType>::RustType, @@ -4769,12 +4794,9 @@ function startMigration(address[] memory operatorsToRemove, NodeOperatorView[] m #[inline] fn tokenize(&self) -> Self::Token<'_> { ( - as alloy_sol_types::SolType>::tokenize(&self.operatorsToRemove), - as alloy_sol_types::SolType>::tokenize(&self.operatorsToAdd), + ::tokenize( + &self.newOwner, + ), ) } #[inline] @@ -4789,20 +4811,22 @@ function startMigration(address[] memory operatorsToRemove, NodeOperatorView[] m } } }; - /**Function with signature `transferOwnership(address)` and selector `0xf2fde38b`. + /**Function with signature `updateNodeOperatorData(uint8,bytes)` and selector `0xf019b154`. ```solidity -function transferOwnership(address newOwner) external; +function updateNodeOperatorData(uint8 operatorIdx, bytes memory data) external; ```*/ #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] - pub struct transferOwnershipCall { + pub struct updateNodeOperatorDataCall { #[allow(missing_docs)] - pub newOwner: alloy::sol_types::private::Address, + pub operatorIdx: u8, + #[allow(missing_docs)] + pub data: alloy::sol_types::private::Bytes, } - ///Container type for the return parameters of the [`transferOwnership(address)`](transferOwnershipCall) function. + ///Container type for the return parameters of the [`updateNodeOperatorData(uint8,bytes)`](updateNodeOperatorDataCall) function. #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] - pub struct transferOwnershipReturn {} + pub struct updateNodeOperatorDataReturn {} #[allow( non_camel_case_types, non_snake_case, @@ -4813,9 +4837,12 @@ function transferOwnership(address newOwner) external; use alloy::sol_types as alloy_sol_types; { #[doc(hidden)] - type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Address,); + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::Uint<8>, + alloy::sol_types::sol_data::Bytes, + ); #[doc(hidden)] - type UnderlyingRustTuple<'a> = (alloy::sol_types::private::Address,); + type UnderlyingRustTuple<'a> = (u8, alloy::sol_types::private::Bytes); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] fn _type_assertion( @@ -4829,18 +4856,21 @@ function transferOwnership(address newOwner) external; } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From + impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: transferOwnershipCall) -> Self { - (value.newOwner,) + fn from(value: updateNodeOperatorDataCall) -> Self { + (value.operatorIdx, value.data) } } #[automatically_derived] #[doc(hidden)] impl ::core::convert::From> - for transferOwnershipCall { + for updateNodeOperatorDataCall { fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self { newOwner: tuple.0 } + Self { + operatorIdx: tuple.0, + data: tuple.1, + } } } } @@ -4862,34 +4892,37 @@ function transferOwnership(address newOwner) external; } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From + impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: transferOwnershipReturn) -> Self { + fn from(value: updateNodeOperatorDataReturn) -> Self { () } } #[automatically_derived] #[doc(hidden)] impl ::core::convert::From> - for transferOwnershipReturn { + for updateNodeOperatorDataReturn { fn from(tuple: UnderlyingRustTuple<'_>) -> Self { Self {} } } } #[automatically_derived] - impl alloy_sol_types::SolCall for transferOwnershipCall { - type Parameters<'a> = (alloy::sol_types::sol_data::Address,); + impl alloy_sol_types::SolCall for updateNodeOperatorDataCall { + type Parameters<'a> = ( + alloy::sol_types::sol_data::Uint<8>, + alloy::sol_types::sol_data::Bytes, + ); type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - type Return = transferOwnershipReturn; + type Return = updateNodeOperatorDataReturn; type ReturnTuple<'a> = (); type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SIGNATURE: &'static str = "transferOwnership(address)"; - const SELECTOR: [u8; 4] = [242u8, 253u8, 227u8, 139u8]; + const SIGNATURE: &'static str = "updateNodeOperatorData(uint8,bytes)"; + const SELECTOR: [u8; 4] = [240u8, 25u8, 177u8, 84u8]; #[inline] fn new<'a>( tuple: as alloy_sol_types::SolType>::RustType, @@ -4899,8 +4932,11 @@ function transferOwnership(address newOwner) external; #[inline] fn tokenize(&self) -> Self::Token<'_> { ( - ::tokenize( - &self.newOwner, + as alloy_sol_types::SolType>::tokenize(&self.operatorIdx), + ::tokenize( + &self.data, ), ) } @@ -4916,7 +4952,7 @@ function transferOwnership(address newOwner) external; } } }; - /**Function with signature `updateSettings((uint8,uint8))` and selector `0x409900e8`. + /**Function with signature `updateSettings((uint16))` and selector `0x65706f9c`. ```solidity function updateSettings(Settings memory newSettings) external; ```*/ @@ -4926,7 +4962,7 @@ function updateSettings(Settings memory newSettings) external; #[allow(missing_docs)] pub newSettings: ::RustType, } - ///Container type for the return parameters of the [`updateSettings((uint8,uint8))`](updateSettingsCall) function. + ///Container type for the return parameters of the [`updateSettings((uint16))`](updateSettingsCall) function. #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] pub struct updateSettingsReturn {} @@ -5015,8 +5051,8 @@ function updateSettings(Settings memory newSettings) external; type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SIGNATURE: &'static str = "updateSettings((uint8,uint8))"; - const SELECTOR: [u8; 4] = [64u8, 153u8, 0u8, 232u8]; + const SIGNATURE: &'static str = "updateSettings((uint16))"; + const SELECTOR: [u8; 4] = [101u8, 112u8, 111u8, 156u8]; #[inline] fn new<'a>( tuple: as alloy_sol_types::SolType>::RustType, @@ -5052,9 +5088,7 @@ function updateSettings(Settings memory newSettings) external; #[allow(missing_docs)] getView(getViewCall), #[allow(missing_docs)] - removeNode(removeNodeCall), - #[allow(missing_docs)] - setNode(setNodeCall), + registerNodeOperator(registerNodeOperatorCall), #[allow(missing_docs)] startMaintenance(startMaintenanceCall), #[allow(missing_docs)] @@ -5062,6 +5096,8 @@ function updateSettings(Settings memory newSettings) external; #[allow(missing_docs)] transferOwnership(transferOwnershipCall), #[allow(missing_docs)] + updateNodeOperatorData(updateNodeOperatorDataCall), + #[allow(missing_docs)] updateSettings(updateSettingsCall), } #[automatically_derived] @@ -5074,16 +5110,16 @@ function updateSettings(Settings memory newSettings) external; /// Prefer using `SolInterface` methods instead. pub const SELECTORS: &'static [[u8; 4usize]] = &[ [48u8, 72u8, 191u8, 186u8], - [64u8, 153u8, 0u8, 232u8], - [72u8, 134u8, 246u8, 44u8], - [108u8, 11u8, 97u8, 185u8], + [85u8, 164u8, 125u8, 10u8], + [101u8, 112u8, 111u8, 156u8], [117u8, 65u8, 139u8, 157u8], + [139u8, 82u8, 82u8, 214u8], [173u8, 54u8, 230u8, 208u8], [193u8, 48u8, 128u8, 154u8], - [204u8, 69u8, 102u8, 42u8], + [205u8, 191u8, 198u8, 45u8], + [221u8, 63u8, 210u8, 105u8], + [240u8, 25u8, 177u8, 84u8], [242u8, 253u8, 227u8, 139u8], - [245u8, 242u8, 217u8, 241u8], - [255u8, 215u8, 64u8, 223u8], ]; } #[automatically_derived] @@ -5107,10 +5143,9 @@ function updateSettings(Settings memory newSettings) external; ::SELECTOR } Self::getView(_) => ::SELECTOR, - Self::removeNode(_) => { - ::SELECTOR + Self::registerNodeOperator(_) => { + ::SELECTOR } - Self::setNode(_) => ::SELECTOR, Self::startMaintenance(_) => { ::SELECTOR } @@ -5120,6 +5155,9 @@ function updateSettings(Settings memory newSettings) external; Self::transferOwnership(_) => { ::SELECTOR } + Self::updateNodeOperatorData(_) => { + ::SELECTOR + } Self::updateSettings(_) => { ::SELECTOR } @@ -5158,56 +5196,56 @@ function updateSettings(Settings memory newSettings) external; abortMaintenance }, { - fn updateSettings( + fn completeMigration( data: &[u8], validate: bool, ) -> alloy_sol_types::Result { - ::abi_decode_raw( + ::abi_decode_raw( data, validate, ) - .map(ClusterCalls::updateSettings) + .map(ClusterCalls::completeMigration) } - updateSettings + completeMigration }, { - fn completeMigration( + fn updateSettings( data: &[u8], validate: bool, ) -> alloy_sol_types::Result { - ::abi_decode_raw( + ::abi_decode_raw( data, validate, ) - .map(ClusterCalls::completeMigration) + .map(ClusterCalls::updateSettings) } - completeMigration + updateSettings }, { - fn setNode( + fn getView( data: &[u8], validate: bool, ) -> alloy_sol_types::Result { - ::abi_decode_raw( + ::abi_decode_raw( data, validate, ) - .map(ClusterCalls::setNode) + .map(ClusterCalls::getView) } - setNode + getView }, { - fn getView( + fn registerNodeOperator( data: &[u8], validate: bool, ) -> alloy_sol_types::Result { - ::abi_decode_raw( + ::abi_decode_raw( data, validate, ) - .map(ClusterCalls::getView) + .map(ClusterCalls::registerNodeOperator) } - getView + registerNodeOperator }, { fn completeMaintenance( @@ -5249,43 +5287,43 @@ function updateSettings(Settings memory newSettings) external; startMigration }, { - fn transferOwnership( + fn startMaintenance( data: &[u8], validate: bool, ) -> alloy_sol_types::Result { - ::abi_decode_raw( + ::abi_decode_raw( data, validate, ) - .map(ClusterCalls::transferOwnership) + .map(ClusterCalls::startMaintenance) } - transferOwnership + startMaintenance }, { - fn startMaintenance( + fn updateNodeOperatorData( data: &[u8], validate: bool, ) -> alloy_sol_types::Result { - ::abi_decode_raw( + ::abi_decode_raw( data, validate, ) - .map(ClusterCalls::startMaintenance) + .map(ClusterCalls::updateNodeOperatorData) } - startMaintenance + updateNodeOperatorData }, { - fn removeNode( + fn transferOwnership( data: &[u8], validate: bool, ) -> alloy_sol_types::Result { - ::abi_decode_raw( + ::abi_decode_raw( data, validate, ) - .map(ClusterCalls::removeNode) + .map(ClusterCalls::transferOwnership) } - removeNode + transferOwnership }, ]; let Ok(idx) = Self::SELECTORS.binary_search(&selector) else { @@ -5324,11 +5362,10 @@ function updateSettings(Settings memory newSettings) external; Self::getView(inner) => { ::abi_encoded_size(inner) } - Self::removeNode(inner) => { - ::abi_encoded_size(inner) - } - Self::setNode(inner) => { - ::abi_encoded_size(inner) + Self::registerNodeOperator(inner) => { + ::abi_encoded_size( + inner, + ) } Self::startMaintenance(inner) => { ::abi_encoded_size( @@ -5345,6 +5382,11 @@ function updateSettings(Settings memory newSettings) external; inner, ) } + Self::updateNodeOperatorData(inner) => { + ::abi_encoded_size( + inner, + ) + } Self::updateSettings(inner) => { ::abi_encoded_size( inner, @@ -5382,15 +5424,12 @@ function updateSettings(Settings memory newSettings) external; Self::getView(inner) => { ::abi_encode_raw(inner, out) } - Self::removeNode(inner) => { - ::abi_encode_raw( + Self::registerNodeOperator(inner) => { + ::abi_encode_raw( inner, out, ) } - Self::setNode(inner) => { - ::abi_encode_raw(inner, out) - } Self::startMaintenance(inner) => { ::abi_encode_raw( inner, @@ -5409,6 +5448,12 @@ function updateSettings(Settings memory newSettings) external; out, ) } + Self::updateNodeOperatorData(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } Self::updateSettings(inner) => { ::abi_encode_raw( inner, @@ -5435,9 +5480,7 @@ function updateSettings(Settings memory newSettings) external; #[allow(missing_docs)] MigrationStarted(MigrationStarted), #[allow(missing_docs)] - NodeRemoved(NodeRemoved), - #[allow(missing_docs)] - NodeSet(NodeSet), + NodeOperatorDataUpdated(NodeOperatorDataUpdated), } #[automatically_derived] impl ClusterEvents { @@ -5449,106 +5492,106 @@ function updateSettings(Settings memory newSettings) external; /// Prefer using `SolInterface` methods instead. pub const SELECTORS: &'static [[u8; 32usize]] = &[ [ - 17u8, - 206u8, - 80u8, + 1u8, + 38u8, + 152u8, + 121u8, + 83u8, + 95u8, + 64u8, + 238u8, + 137u8, + 87u8, + 225u8, + 94u8, 22u8, - 14u8, - 102u8, - 16u8, - 5u8, - 55u8, - 253u8, - 75u8, - 10u8, + 11u8, + 241u8, + 134u8, + 108u8, + 94u8, + 39u8, + 40u8, + 255u8, + 12u8, + 188u8, + 88u8, + 61u8, + 132u8, + 136u8, + 33u8, 226u8, - 109u8, - 230u8, - 109u8, - 81u8, - 218u8, - 183u8, - 19u8, - 173u8, - 146u8, - 49u8, - 51u8, - 83u8, - 161u8, - 140u8, - 36u8, - 232u8, - 246u8, - 218u8, - 171u8, + 99u8, + 155u8, + 78u8, ], [ - 106u8, - 223u8, - 184u8, - 150u8, - 211u8, - 64u8, - 118u8, + 18u8, + 81u8, 129u8, - 208u8, - 95u8, - 184u8, - 116u8, - 212u8, + 236u8, + 33u8, + 136u8, + 45u8, + 236u8, + 81u8, + 162u8, + 57u8, + 41u8, + 5u8, 223u8, - 183u8, - 6u8, - 142u8, - 110u8, - 42u8, - 54u8, - 240u8, - 154u8, - 205u8, - 56u8, - 163u8, - 183u8, - 208u8, - 76u8, - 1u8, - 116u8, - 95u8, - 238u8, + 243u8, + 168u8, + 44u8, + 189u8, + 2u8, + 98u8, + 241u8, + 139u8, + 92u8, + 12u8, + 3u8, + 84u8, + 136u8, + 103u8, + 27u8, + 64u8, + 175u8, + 178u8, ], [ - 126u8, - 5u8, - 228u8, - 1u8, - 23u8, - 182u8, - 225u8, - 138u8, - 178u8, - 132u8, - 192u8, - 74u8, - 53u8, - 8u8, - 195u8, - 130u8, - 100u8, - 34u8, - 220u8, + 120u8, + 218u8, + 210u8, + 188u8, + 11u8, + 71u8, + 198u8, + 136u8, + 237u8, 132u8, - 166u8, - 94u8, - 156u8, - 35u8, - 106u8, + 243u8, + 254u8, + 231u8, + 154u8, + 188u8, + 24u8, + 230u8, + 201u8, 130u8, - 72u8, - 119u8, - 68u8, - 22u8, - 248u8, - 172u8, + 45u8, + 176u8, + 90u8, + 121u8, + 202u8, + 25u8, + 223u8, + 245u8, + 69u8, + 51u8, + 199u8, + 71u8, + 13u8, ], [ 143u8, @@ -5585,72 +5628,38 @@ function updateSettings(Settings memory newSettings) external; 4u8, ], [ - 156u8, - 225u8, - 146u8, - 174u8, - 165u8, - 250u8, - 242u8, + 175u8, + 94u8, + 144u8, + 231u8, + 32u8, 21u8, - 27u8, - 188u8, - 36u8, - 108u8, - 216u8, - 145u8, - 141u8, - 46u8, - 186u8, - 112u8, - 47u8, - 162u8, - 105u8, - 81u8, + 244u8, + 49u8, + 56u8, 246u8, - 127u8, - 43u8, - 247u8, - 179u8, - 129u8, - 126u8, - 104u8, - 157u8, - 152u8, - ], - [ - 167u8, - 106u8, - 143u8, - 193u8, - 169u8, - 2u8, - 102u8, - 221u8, - 238u8, - 137u8, - 55u8, - 161u8, - 142u8, - 18u8, - 240u8, - 30u8, - 173u8, - 233u8, - 70u8, - 179u8, - 182u8, - 97u8, - 151u8, - 255u8, - 242u8, - 137u8, - 175u8, - 146u8, - 119u8, - 194u8, - 189u8, - 37u8, + 107u8, + 76u8, + 208u8, + 139u8, + 209u8, + 223u8, + 162u8, + 131u8, + 144u8, + 48u8, + 16u8, + 79u8, + 34u8, + 160u8, + 10u8, + 248u8, + 67u8, + 254u8, + 132u8, + 124u8, + 109u8, + 25u8, ], [ 188u8, @@ -5687,38 +5696,38 @@ function updateSettings(Settings memory newSettings) external; 121u8, ], [ - 189u8, - 24u8, - 77u8, - 231u8, - 159u8, - 19u8, - 75u8, - 15u8, - 61u8, - 164u8, - 102u8, - 210u8, - 120u8, - 245u8, - 65u8, - 124u8, - 188u8, - 177u8, - 69u8, - 13u8, + 247u8, + 50u8, + 64u8, + 66u8, + 34u8, + 70u8, + 246u8, + 62u8, + 214u8, + 51u8, + 239u8, + 60u8, + 224u8, 114u8, - 241u8, - 189u8, - 26u8, - 27u8, - 132u8, - 241u8, - 139u8, - 27u8, - 205u8, - 3u8, - 202u8, + 107u8, + 138u8, + 184u8, + 251u8, + 105u8, + 212u8, + 108u8, + 138u8, + 78u8, + 94u8, + 203u8, + 11u8, + 41u8, + 34u8, + 102u8, + 134u8, + 116u8, + 161u8, ], [ 249u8, @@ -5759,7 +5768,7 @@ function updateSettings(Settings memory newSettings) external; #[automatically_derived] impl alloy_sol_types::SolEventInterface for ClusterEvents { const NAME: &'static str = "ClusterEvents"; - const COUNT: usize = 9usize; + const COUNT: usize = 8usize; fn decode_raw_log( topics: &[alloy_sol_types::Word], data: &[u8], @@ -5832,21 +5841,15 @@ function updateSettings(Settings memory newSettings) external; ) .map(Self::MigrationStarted) } - Some(::SIGNATURE_HASH) => { - ::decode_raw_log( - topics, - data, - validate, - ) - .map(Self::NodeRemoved) - } - Some(::SIGNATURE_HASH) => { - ::decode_raw_log( + Some( + ::SIGNATURE_HASH, + ) => { + ::decode_raw_log( topics, data, validate, ) - .map(Self::NodeSet) + .map(Self::NodeOperatorDataUpdated) } _ => { alloy_sol_types::private::Err(alloy_sol_types::Error::InvalidLog { @@ -5887,10 +5890,7 @@ function updateSettings(Settings memory newSettings) external; Self::MigrationStarted(inner) => { alloy_sol_types::private::IntoLogData::to_log_data(inner) } - Self::NodeRemoved(inner) => { - alloy_sol_types::private::IntoLogData::to_log_data(inner) - } - Self::NodeSet(inner) => { + Self::NodeOperatorDataUpdated(inner) => { alloy_sol_types::private::IntoLogData::to_log_data(inner) } } @@ -5918,10 +5918,7 @@ function updateSettings(Settings memory newSettings) external; Self::MigrationStarted(inner) => { alloy_sol_types::private::IntoLogData::into_log_data(inner) } - Self::NodeRemoved(inner) => { - alloy_sol_types::private::IntoLogData::into_log_data(inner) - } - Self::NodeSet(inner) => { + Self::NodeOperatorDataUpdated(inner) => { alloy_sol_types::private::IntoLogData::into_log_data(inner) } } @@ -5956,7 +5953,7 @@ For more fine-grained control over the deployment process, use [`deploy_builder` provider: P, initialSettings: ::RustType, initialOperators: alloy::sol_types::private::Vec< - ::RustType, + alloy::sol_types::private::Address, >, ) -> impl ::core::future::Future< Output = alloy_contract::Result>, @@ -5977,7 +5974,7 @@ the bytecode concatenated with the constructor's ABI-encoded arguments.*/ provider: P, initialSettings: ::RustType, initialOperators: alloy::sol_types::private::Vec< - ::RustType, + alloy::sol_types::private::Address, >, ) -> alloy_contract::RawCallBuilder { ClusterInstance::< @@ -6041,7 +6038,7 @@ For more fine-grained control over the deployment process, use [`deploy_builder` provider: P, initialSettings: ::RustType, initialOperators: alloy::sol_types::private::Vec< - ::RustType, + alloy::sol_types::private::Address, >, ) -> alloy_contract::Result> { let call_builder = Self::deploy_builder( @@ -6062,7 +6059,7 @@ the bytecode concatenated with the constructor's ABI-encoded arguments.*/ provider: P, initialSettings: ::RustType, initialOperators: alloy::sol_types::private::Vec< - ::RustType, + alloy::sol_types::private::Address, >, ) -> alloy_contract::RawCallBuilder { alloy_contract::RawCallBuilder::new_raw_deploy( @@ -6150,49 +6147,44 @@ the bytecode concatenated with the constructor's ABI-encoded arguments.*/ ///Creates a new call builder for the [`completeMigration`] function. pub fn completeMigration( &self, + id: u64, + operatorIdx: u8, ) -> alloy_contract::SolCallBuilder { - self.call_builder(&completeMigrationCall {}) + self.call_builder( + &completeMigrationCall { + id, + operatorIdx, + }, + ) } ///Creates a new call builder for the [`getView`] function. pub fn getView(&self) -> alloy_contract::SolCallBuilder { self.call_builder(&getViewCall {}) } - ///Creates a new call builder for the [`removeNode`] function. - pub fn removeNode( - &self, - id: alloy::sol_types::private::primitives::aliases::U256, - ) -> alloy_contract::SolCallBuilder { - self.call_builder(&removeNodeCall { id }) - } - ///Creates a new call builder for the [`setNode`] function. - pub fn setNode( + ///Creates a new call builder for the [`registerNodeOperator`] function. + pub fn registerNodeOperator( &self, - node: ::RustType, - ) -> alloy_contract::SolCallBuilder { - self.call_builder(&setNodeCall { node }) + data: alloy::sol_types::private::Bytes, + ) -> alloy_contract::SolCallBuilder { + self.call_builder(®isterNodeOperatorCall { data }) } ///Creates a new call builder for the [`startMaintenance`] function. pub fn startMaintenance( &self, + operatorIdx: u8, ) -> alloy_contract::SolCallBuilder { - self.call_builder(&startMaintenanceCall {}) + self.call_builder( + &startMaintenanceCall { + operatorIdx, + }, + ) } ///Creates a new call builder for the [`startMigration`] function. pub fn startMigration( &self, - operatorsToRemove: alloy::sol_types::private::Vec< - alloy::sol_types::private::Address, - >, - operatorsToAdd: alloy::sol_types::private::Vec< - ::RustType, - >, + plan: ::RustType, ) -> alloy_contract::SolCallBuilder { - self.call_builder( - &startMigrationCall { - operatorsToRemove, - operatorsToAdd, - }, - ) + self.call_builder(&startMigrationCall { plan }) } ///Creates a new call builder for the [`transferOwnership`] function. pub fn transferOwnership( @@ -6201,6 +6193,19 @@ the bytecode concatenated with the constructor's ABI-encoded arguments.*/ ) -> alloy_contract::SolCallBuilder { self.call_builder(&transferOwnershipCall { newOwner }) } + ///Creates a new call builder for the [`updateNodeOperatorData`] function. + pub fn updateNodeOperatorData( + &self, + operatorIdx: u8, + data: alloy::sol_types::private::Bytes, + ) -> alloy_contract::SolCallBuilder { + self.call_builder( + &updateNodeOperatorDataCall { + operatorIdx, + data, + }, + ) + } ///Creates a new call builder for the [`updateSettings`] function. pub fn updateSettings( &self, @@ -6267,15 +6272,11 @@ the bytecode concatenated with the constructor's ABI-encoded arguments.*/ ) -> alloy_contract::Event { self.event_filter::() } - ///Creates a new event filter for the [`NodeRemoved`] event. - pub fn NodeRemoved_filter( + ///Creates a new event filter for the [`NodeOperatorDataUpdated`] event. + pub fn NodeOperatorDataUpdated_filter( &self, - ) -> alloy_contract::Event { - self.event_filter::() - } - ///Creates a new event filter for the [`NodeSet`] event. - pub fn NodeSet_filter(&self) -> alloy_contract::Event { - self.event_filter::() + ) -> alloy_contract::Event { + self.event_filter::() } } } From 226e49f29cdef0790f7ce48410a52f737ec4e036 Mon Sep 17 00:00:00 2001 From: Github Bot Date: Tue, 20 May 2025 09:39:07 +0000 Subject: [PATCH 17/79] Bump VERSION to 250520.0 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index dc325536..2dc6aad7 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -250514.0 +250520.0 From 438753cc723a766c20a7f5c72c35809844e0e868 Mon Sep 17 00:00:00 2001 From: Darksome Date: Tue, 20 May 2025 10:12:28 +0000 Subject: [PATCH 18/79] rename things --- contracts/src/Cluster.sol | 88 ++++---- contracts/test/Suite.sol | 84 +++---- .../cluster/src/contract/evm/bindings/mod.rs | 206 +++++++++--------- crates/cluster/src/node.rs | 3 +- 4 files changed, 190 insertions(+), 191 deletions(-) diff --git a/contracts/src/Cluster.sol b/contracts/src/Cluster.sol index 4da06483..45afef62 100644 --- a/contracts/src/Cluster.sol +++ b/contracts/src/Cluster.sol @@ -21,6 +21,8 @@ event NodeOperatorDataUpdated(address operatorAddress, bytes data, uint128 clust contract Cluster { using Bitmask for uint256; + // TODO: Should we just make all the fields public? + address owner; mapping(address => bytes) operatorData; @@ -72,25 +74,25 @@ contract Cluster { function startMigration(MigrationPlan calldata plan) external onlyOwner noMigration noMaintenance { migration.id++; - uint256 prevKeyspaceIdx = keyspaceVersion % 2; + uint256 keyspaceIdx = keyspaceVersion % 2; keyspaceVersion++; - uint256 currKeyspaceIdx = keyspaceVersion % 2; + uint256 migrationKeyspaceIdx = keyspaceVersion % 2; // NOTE: We are not zeroing out the rest of the buffer, so there might be some junk left. // The source of truth on whether the value is set or not should be the bitmask! - for (uint256 i = 0; i <= keyspaces[prevKeyspaceIdx].operatorsBitmask.highest1(); i++) { - if (keyspaces[currKeyspaceIdx].operators[i] != keyspaces[prevKeyspaceIdx].operators[i]) { - keyspaces[currKeyspaceIdx].operators[i] = keyspaces[prevKeyspaceIdx].operators[i]; + for (uint256 i = 0; i <= keyspaces[keyspaceIdx].operatorsBitmask.highest1(); i++) { + if (keyspaces[migrationKeyspaceIdx].operators[i] != keyspaces[keyspaceIdx].operators[i]) { + keyspaces[migrationKeyspaceIdx].operators[i] = keyspaces[keyspaceIdx].operators[i]; } } - uint256 operatorsBitmask = keyspaces[prevKeyspaceIdx].operatorsBitmask; + uint256 operatorsBitmask = keyspaces[keyspaceIdx].operatorsBitmask; uint8 idx; address addr; - for (uint256 i = 0; i < plan.slotsToUpdate.length; i++) { - idx = plan.slotsToUpdate[i].idx; - addr = plan.slotsToUpdate[i].operator; + for (uint256 i = 0; i < plan.slots.length; i++) { + idx = plan.slots[i].idx; + addr = plan.slots[i].operator; if (addr == address(0)) { operatorsBitmask = operatorsBitmask.set0(idx); @@ -98,11 +100,11 @@ contract Cluster { operatorsBitmask = operatorsBitmask.set1(idx); } - keyspaces[currKeyspaceIdx].operators[idx] = addr; + keyspaces[migrationKeyspaceIdx].operators[idx] = addr; } - keyspaces[currKeyspaceIdx].operatorsBitmask = operatorsBitmask; - keyspaces[currKeyspaceIdx].replicationStrategy = plan.replicationStrategy; + keyspaces[migrationKeyspaceIdx].operatorsBitmask = operatorsBitmask; + keyspaces[migrationKeyspaceIdx].replicationStrategy = plan.replicationStrategy; migration.pullingOperatorsBitmask = operatorsBitmask; @@ -168,19 +170,19 @@ contract Cluster { function updateNodeOperatorData(uint8 operatorIdx, bytes calldata data) external { validateOperatorDataSize(data.length); - bool inPrimaryKeyspace; - bool inSecondaryKeyspace; + bool inKeyspace; + bool inMigrationKeyspace; if (isMigrationInProgress()) { - inPrimaryKeyspace = keyspaces[(keyspaceVersion - 1) % 2].operators[operatorIdx] == msg.sender; - if (!inPrimaryKeyspace) { - inSecondaryKeyspace = keyspaces[keyspaceVersion % 2].operators[operatorIdx] == msg.sender; + inKeyspace = keyspaces[(keyspaceVersion - 1) % 2].operators[operatorIdx] == msg.sender; + if (!inKeyspace) { + inMigrationKeyspace = keyspaces[keyspaceVersion % 2].operators[operatorIdx] == msg.sender; } } else { - inPrimaryKeyspace = keyspaces[keyspaceVersion % 2].operators[operatorIdx] == msg.sender; + inKeyspace = keyspaces[keyspaceVersion % 2].operators[operatorIdx] == msg.sender; } - require(inPrimaryKeyspace || inSecondaryKeyspace, "wrong operator"); + require(inKeyspace || inMigrationKeyspace, "wrong operator"); operatorData[msg.sender] = data; version++; @@ -198,7 +200,7 @@ contract Cluster { function getView() public view returns (ClusterView memory) { ClusterView memory clusterView; - uint256 primaryKeyspaceIdx; + uint256 keyspaceIdx; address addr; uint256 highestSlotIdx; @@ -207,42 +209,42 @@ contract Cluster { clusterView.migration.id = migration.id; clusterView.migration.pullingOperatorsBitmask = migration.pullingOperatorsBitmask; - primaryKeyspaceIdx = (keyspaceVersion - 1) % 2; - uint256 secondaryKeyspaceIdx = keyspaceVersion % 2; + keyspaceIdx = (keyspaceVersion - 1) % 2; + uint256 migrationKeyspaceIdx = keyspaceVersion % 2; - highestSlotIdx = keyspaces[secondaryKeyspaceIdx].operatorsBitmask.highest1(); - clusterView.secondaryKeyspace.operators = new NodeOperator[](highestSlotIdx + 1); - clusterView.secondaryKeyspace.replicationStrategy = keyspaces[secondaryKeyspaceIdx].replicationStrategy; + highestSlotIdx = keyspaces[migrationKeyspaceIdx].operatorsBitmask.highest1(); + clusterView.migrationKeyspace.operators = new NodeOperator[](highestSlotIdx + 1); + clusterView.migrationKeyspace.replicationStrategy = keyspaces[migrationKeyspaceIdx].replicationStrategy; for (uint256 i = 0; i <= highestSlotIdx; i++) { - if (keyspaces[secondaryKeyspaceIdx].operatorsBitmask.is0(uint8(i))) { + if (keyspaces[migrationKeyspaceIdx].operatorsBitmask.is0(uint8(i))) { continue; } - addr = keyspaces[secondaryKeyspaceIdx].operators[i]; - clusterView.secondaryKeyspace.operators[i].addr = addr; + addr = keyspaces[migrationKeyspaceIdx].operators[i]; + clusterView.migrationKeyspace.operators[i].addr = addr; // Populate data only if it won't be present in the primary keyspace view, to optimize the cluster view size. - if (keyspaces[primaryKeyspaceIdx].operatorsBitmask.is0(uint8(i)) || keyspaces[primaryKeyspaceIdx].operators[i] != addr) { - clusterView.secondaryKeyspace.operators[i].data = operatorData[addr]; + if (keyspaces[keyspaceIdx].operatorsBitmask.is0(uint8(i)) || keyspaces[keyspaceIdx].operators[i] != addr) { + clusterView.migrationKeyspace.operators[i].data = operatorData[addr]; } } } else { - primaryKeyspaceIdx = keyspaceVersion % 2; + keyspaceIdx = keyspaceVersion % 2; } - highestSlotIdx = keyspaces[primaryKeyspaceIdx].operatorsBitmask.highest1(); - clusterView.primaryKeyspace.operators = new NodeOperator[](highestSlotIdx + 1); - clusterView.primaryKeyspace.replicationStrategy = keyspaces[primaryKeyspaceIdx].replicationStrategy; + highestSlotIdx = keyspaces[keyspaceIdx].operatorsBitmask.highest1(); + clusterView.keyspace.operators = new NodeOperator[](highestSlotIdx + 1); + clusterView.keyspace.replicationStrategy = keyspaces[keyspaceIdx].replicationStrategy; for (uint256 i = 0; i <= highestSlotIdx; i++) { - if (keyspaces[primaryKeyspaceIdx].operatorsBitmask.is0(uint8(i))) { + if (keyspaces[keyspaceIdx].operatorsBitmask.is0(uint8(i))) { continue; } - addr = keyspaces[primaryKeyspaceIdx].operators[i]; - clusterView.primaryKeyspace.operators[i].addr = addr; - clusterView.primaryKeyspace.operators[i].data = operatorData[addr]; + addr = keyspaces[keyspaceIdx].operators[i]; + clusterView.keyspace.operators[i].addr = addr; + clusterView.keyspace.operators[i].data = operatorData[addr]; } clusterView.keyspaceVersion = keyspaceVersion; @@ -290,11 +292,10 @@ struct KeyspaceSlot { } struct MigrationPlan { - KeyspaceSlot[] slotsToUpdate; + KeyspaceSlot[] slots; uint8 replicationStrategy; } - struct Migration { uint64 id; uint256 pullingOperatorsBitmask; @@ -305,13 +306,14 @@ struct Maintenance { } struct ClusterView { - KeyspaceView primaryKeyspace; - KeyspaceView secondaryKeyspace; - uint64 keyspaceVersion; + KeyspaceView keyspace; Migration migration; + KeyspaceView migrationKeyspace; + Maintenance maintenance; + uint64 keyspaceVersion; uint128 version; } diff --git a/contracts/test/Suite.sol b/contracts/test/Suite.sol index 825203b5..be8a0f2f 100644 --- a/contracts/test/Suite.sol +++ b/contracts/test/Suite.sol @@ -70,13 +70,13 @@ contract ClusterTest is Test { newCluster(vm, 256); } - function test_clusterContainsInitialOperatorsInPrimaryKeyspace() public view { - assertKeyspaceSlotsCount(clusterView.primaryKeyspace, 5); - assertKeyspaceSlot(clusterView.primaryKeyspace, 0, 1); - assertKeyspaceSlot(clusterView.primaryKeyspace, 1, 2); - assertKeyspaceSlot(clusterView.primaryKeyspace, 2, 3); - assertKeyspaceSlot(clusterView.primaryKeyspace, 3, 4); - assertKeyspaceSlot(clusterView.primaryKeyspace, 4, 5); + function test_clusterContainsInitialOperatorsInKeyspace() public view { + assertKeyspaceSlotsCount(clusterView.keyspace, 5); + assertKeyspaceSlot(clusterView.keyspace, 0, 1); + assertKeyspaceSlot(clusterView.keyspace, 1, 2); + assertKeyspaceSlot(clusterView.keyspace, 2, 3); + assertKeyspaceSlot(clusterView.keyspace, 3, 4); + assertKeyspaceSlot(clusterView.keyspace, 4, 5); } function test_clusterInitialVersionIs0() public view { @@ -136,18 +136,18 @@ contract ClusterTest is Test { assertMigrationPullingOperator(5); } - function test_startMigrationPopulatesSecondaryKeyspace() public { + function test_startMigrationPopulatesMigrationKeyspace() public { registerNodeOperator(6, "operator6"); registerNodeOperator(7, "operator7"); startMigration(OWNER, newMigration().set(4, 6).set(5, 7).clear(2)); - assertKeyspaceSlotsCount(clusterView.secondaryKeyspace, 6); - assertKeyspaceSlot(clusterView.secondaryKeyspace, 0, 1, ""); - assertKeyspaceSlot(clusterView.secondaryKeyspace, 1, 2, ""); - assertKeyspaceSlotEmpty(clusterView.secondaryKeyspace, 2); - assertKeyspaceSlot(clusterView.secondaryKeyspace, 3, 4, ""); - assertKeyspaceSlot(clusterView.secondaryKeyspace, 4, 6, "operator6"); - assertKeyspaceSlot(clusterView.secondaryKeyspace, 5, 7, "operator7"); + assertKeyspaceSlotsCount(clusterView.migrationKeyspace, 6); + assertKeyspaceSlot(clusterView.migrationKeyspace, 0, 1, ""); + assertKeyspaceSlot(clusterView.migrationKeyspace, 1, 2, ""); + assertKeyspaceSlotEmpty(clusterView.migrationKeyspace, 2); + assertKeyspaceSlot(clusterView.migrationKeyspace, 3, 4, ""); + assertKeyspaceSlot(clusterView.migrationKeyspace, 4, 6, "operator6"); + assertKeyspaceSlot(clusterView.migrationKeyspace, 5, 7, "operator7"); } // completeMigration @@ -186,15 +186,15 @@ contract ClusterTest is Test { assertVersion(2); } - function test_completeMigrationDoesNotUpdatePrimaryKeyspaceIfNotCompleted() public { + function test_completeMigrationDoesNotUpdateKeyspaceIfNotCompleted() public { startMigration(OWNER, newMigration().set(5, 6)); completeMigration(OPERATOR, 1, 0); - assertKeyspaceSlotsCount(clusterView.primaryKeyspace, 5); - assertKeyspaceSlot(clusterView.primaryKeyspace, 0, 1); - assertKeyspaceSlot(clusterView.primaryKeyspace, 1, 2); - assertKeyspaceSlot(clusterView.primaryKeyspace, 2, 3); - assertKeyspaceSlot(clusterView.primaryKeyspace, 3, 4); - assertKeyspaceSlot(clusterView.primaryKeyspace, 4, 5); + assertKeyspaceSlotsCount(clusterView.keyspace, 5); + assertKeyspaceSlot(clusterView.keyspace, 0, 1); + assertKeyspaceSlot(clusterView.keyspace, 1, 2); + assertKeyspaceSlot(clusterView.keyspace, 2, 3); + assertKeyspaceSlot(clusterView.keyspace, 3, 4); + assertKeyspaceSlot(clusterView.keyspace, 4, 5); } function test_completeMigrationUpdatesOperatorsIfCompleted() public { @@ -205,12 +205,12 @@ contract ClusterTest is Test { completeMigration(3, 1, 2); completeMigration(4, 1, 3); completeMigration(6, 1, 4); - assertKeyspaceSlotsCount(clusterView.primaryKeyspace, 5); - assertKeyspaceSlot(clusterView.primaryKeyspace, 0, 1); - assertKeyspaceSlot(clusterView.primaryKeyspace, 1, 2); - assertKeyspaceSlot(clusterView.primaryKeyspace, 2, 3); - assertKeyspaceSlot(clusterView.primaryKeyspace, 3, 4); - assertKeyspaceSlot(clusterView.primaryKeyspace, 4, 6, "operator6"); + assertKeyspaceSlotsCount(clusterView.keyspace, 5); + assertKeyspaceSlot(clusterView.keyspace, 0, 1); + assertKeyspaceSlot(clusterView.keyspace, 1, 2); + assertKeyspaceSlot(clusterView.keyspace, 2, 3); + assertKeyspaceSlot(clusterView.keyspace, 3, 4); + assertKeyspaceSlot(clusterView.keyspace, 4, 6, "operator6"); } function test_completeMigrationDeletesMigrationIfCompleted() public { @@ -293,15 +293,15 @@ contract ClusterTest is Test { assertKeyspaceVersion(0); } - function test_abortMigrationDoesNotUpdatePrimaryKeyspace() public { + function test_abortMigrationDoesNotUpdateKeyspace() public { startMigration(OWNER, newMigration().clear(0)); abortMigration(OWNER); - assertKeyspaceSlotsCount(clusterView.primaryKeyspace, 5); - assertKeyspaceSlot(clusterView.primaryKeyspace, 0, 1); - assertKeyspaceSlot(clusterView.primaryKeyspace, 1, 2); - assertKeyspaceSlot(clusterView.primaryKeyspace, 2, 3); - assertKeyspaceSlot(clusterView.primaryKeyspace, 3, 4); - assertKeyspaceSlot(clusterView.primaryKeyspace, 4, 5); + assertKeyspaceSlotsCount(clusterView.keyspace, 5); + assertKeyspaceSlot(clusterView.keyspace, 0, 1); + assertKeyspaceSlot(clusterView.keyspace, 1, 2); + assertKeyspaceSlot(clusterView.keyspace, 2, 3); + assertKeyspaceSlot(clusterView.keyspace, 3, 4); + assertKeyspaceSlot(clusterView.keyspace, 4, 5); } function test_abortMigrationDeletesMigration() public { @@ -510,7 +510,7 @@ contract ClusterTest is Test { function test_updateNodeOperatorDataDoesUpdateTheData() public { updateNodeOperatorData(OPERATOR, 0, "new data"); - assertKeyspaceSlot(clusterView.primaryKeyspace, 0, OPERATOR, "new data"); + assertKeyspaceSlot(clusterView.keyspace, 0, OPERATOR, "new data"); } function test_updateNodeOperatorDataBumpsVersion() public { @@ -710,7 +710,7 @@ contract ClusterTest is Test { return TestMigration({ vm: vm, plan: MigrationPlan({ - slotsToUpdate: new KeyspaceSlot[](0), + slots: new KeyspaceSlot[](0), replicationStrategy: 0 }) }); @@ -797,13 +797,13 @@ library TestMigrationLib { } function setSlot(TestMigration memory self, uint8 idx, KeyspaceSlot memory slot) internal pure returns (TestMigration memory) { - KeyspaceSlot[] memory slotsToUpdate = new KeyspaceSlot[](self.plan.slotsToUpdate.length + 1); - for (uint256 i = 0; i < self.plan.slotsToUpdate.length; i++) { - slotsToUpdate[i] = self.plan.slotsToUpdate[i]; + KeyspaceSlot[] memory slots = new KeyspaceSlot[](self.plan.slots.length + 1); + for (uint256 i = 0; i < self.plan.slots.length; i++) { + slots[i] = self.plan.slots[i]; } - slotsToUpdate[self.plan.slotsToUpdate.length] = slot; - self.plan.slotsToUpdate = slotsToUpdate; + slots[self.plan.slots.length] = slot; + self.plan.slots = slots; return self; } diff --git a/crates/cluster/src/contract/evm/bindings/mod.rs b/crates/cluster/src/contract/evm/bindings/mod.rs index b551880d..56143058 100644 --- a/crates/cluster/src/contract/evm/bindings/mod.rs +++ b/crates/cluster/src/contract/evm/bindings/mod.rs @@ -9,11 +9,11 @@ Generated by the following Solidity interface... ```solidity interface Cluster { struct ClusterView { - KeyspaceView primaryKeyspace; - KeyspaceView secondaryKeyspace; - uint64 keyspaceVersion; + KeyspaceView keyspace; Migration migration; + KeyspaceView migrationKeyspace; Maintenance maintenance; + uint64 keyspaceVersion; uint128 version; } struct KeyspaceSlot { @@ -32,7 +32,7 @@ interface Cluster { uint256 pullingOperatorsBitmask; } struct MigrationPlan { - KeyspaceSlot[] slotsToUpdate; + KeyspaceSlot[] slots; uint8 replicationStrategy; } struct NodeOperator { @@ -144,7 +144,7 @@ interface Cluster { "internalType": "struct ClusterView", "components": [ { - "name": "primaryKeyspace", + "name": "keyspace", "type": "tuple", "internalType": "struct KeyspaceView", "components": [ @@ -173,7 +173,24 @@ interface Cluster { ] }, { - "name": "secondaryKeyspace", + "name": "migration", + "type": "tuple", + "internalType": "struct Migration", + "components": [ + { + "name": "id", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "pullingOperatorsBitmask", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "name": "migrationKeyspace", "type": "tuple", "internalType": "struct KeyspaceView", "components": [ @@ -201,28 +218,6 @@ interface Cluster { } ] }, - { - "name": "keyspaceVersion", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "migration", - "type": "tuple", - "internalType": "struct Migration", - "components": [ - { - "name": "id", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "pullingOperatorsBitmask", - "type": "uint256", - "internalType": "uint256" - } - ] - }, { "name": "maintenance", "type": "tuple", @@ -235,6 +230,11 @@ interface Cluster { } ] }, + { + "name": "keyspaceVersion", + "type": "uint64", + "internalType": "uint64" + }, { "name": "version", "type": "uint128", @@ -281,7 +281,7 @@ interface Cluster { "internalType": "struct MigrationPlan", "components": [ { - "name": "slotsToUpdate", + "name": "slots", "type": "tuple[]", "internalType": "struct KeyspaceSlot[]", "components": [ @@ -496,7 +496,7 @@ interface Cluster { "internalType": "struct MigrationPlan", "components": [ { - "name": "slotsToUpdate", + "name": "slots", "type": "tuple[]", "internalType": "struct KeyspaceSlot[]", "components": [ @@ -568,40 +568,40 @@ pub mod Cluster { /// The creation / init bytecode of the contract. /// /// ```text - ///0x608060405234801561000f575f5ffd5b50604051613d0f380380613d0f833981810160405281019061003191906103bd565b335f5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550816102075f820151815f015f6101000a81548161ffff021916908361ffff1602179055509050505f5f90505b8151811015610139578181815181106100b8576100b7610417565b5b602002602001015160025f600281106100d4576100d3610417565b5b61010202015f018261010081106100ee576100ed610417565b5b015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808060010191505061009c565b5061014a815161017260201b60201c565b60025f6002811061015e5761015d610417565b5b6101020201610100018190555050506104ad565b5f60018260ff166001901b610187919061047a565b9050919050565b5f604051905090565b5f5ffd5b5f5ffd5b5f5ffd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6101e9826101a3565b810181811067ffffffffffffffff82111715610208576102076101b3565b5b80604052505050565b5f61021a61018e565b905061022682826101e0565b919050565b5f61ffff82169050919050565b6102418161022b565b811461024b575f5ffd5b50565b5f8151905061025c81610238565b92915050565b5f602082840312156102775761027661019f565b5b6102816020610211565b90505f6102908482850161024e565b5f8301525092915050565b5f5ffd5b5f67ffffffffffffffff8211156102b9576102b86101b3565b5b602082029050602081019050919050565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6102f7826102ce565b9050919050565b610307816102ed565b8114610311575f5ffd5b50565b5f81519050610322816102fe565b92915050565b5f61033a6103358461029f565b610211565b9050808382526020820190506020840283018581111561035d5761035c6102ca565b5b835b8181101561038657806103728882610314565b84526020840193505060208101905061035f565b5050509392505050565b5f82601f8301126103a4576103a361029b565b5b81516103b4848260208601610328565b91505092915050565b5f5f604083850312156103d3576103d2610197565b5b5f6103e085828601610262565b925050602083015167ffffffffffffffff8111156104015761040061019b565b5b61040d85828601610390565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f819050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61048482610444565b915061048f83610444565b92508282039050818111156104a7576104a661044d565b5b92915050565b613855806104ba5f395ff3fe608060405234801561000f575f5ffd5b50600436106100a7575f3560e01c8063ad36e6d01161006f578063ad36e6d014610127578063c130809a14610131578063cdbfc62d1461013b578063dd3fd26914610157578063f019b15414610173578063f2fde38b1461018f576100a7565b80633048bfba146100ab57806355a47d0a146100b557806365706f9c146100d157806375418b9d146100ed5780638b5252d61461010b575b5f5ffd5b6100b36101ab565b005b6100cf60048036038101906100ca919061251f565b61037f565b005b6100eb60048036038101906100e6919061257f565b6106bd565b005b6100f5610761565b60405161010291906128bc565b60405180910390f35b6101256004803603810190610120919061293d565b610f8f565b005b61012f610fec565b005b6101396111c6565b005b610155600480360381019061015091906129a6565b6113c9565b005b610171600480360381019061016c91906129ed565b611a99565b005b61018d60048036038101906101889190612a18565b611d15565b005b6101a960048036038101906101a49190612a9f565b6120ab565b005b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610239576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161023090612b24565b60405180910390fd5b61024161217b565b610280576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161027790612b8c565b60405180910390fd5b5f61020a5f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff16809291906102f190612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507f8fb9cd054d0a022110cced239e908b834e4cd219511856d4eaae3051d932d60461020b5f9054906101000a90046fffffffffffffffffffffffffffffffff166040516103759190612c1d565b60405180910390a1565b6103876121d5565b6103c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103bd90612c80565b60405180910390fd5b6102085f015f9054906101000a900467ffffffffffffffff1667ffffffffffffffff168267ffffffffffffffff1614610434576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042b90612ce8565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff166002806102065f9054906101000a900467ffffffffffffffff1661046f9190612d33565b67ffffffffffffffff166002811061048a57610489612d63565b5b61010202015f018260ff1661010081106104a7576104a6612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461051e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161051590612dda565b60405180910390fd5b61053781610208600101546121e590919063ffffffff16565b6106b95761055481610208600101546121fa90919063ffffffff16565b6102086001018190555061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff168092919061058c90612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550505f6102086001015403610646577f01269879535f40ee8957e15e160bf1866c5e2728ff0cbc583d848821e2639b4e6102085f015f9054906101000a900467ffffffffffffffff163361020b5f9054906101000a90046fffffffffffffffffffffffffffffffff1660405161063993929190612e16565b60405180910390a16106b8565b7faf5e90e72015f43138f66b4cd08bd1dfa2839030104f22a00af843fe847c6d196102085f015f9054906101000a900467ffffffffffffffff163361020b5f9054906101000a90046fffffffffffffffffffffffffffffffff166040516106af93929190612e16565b60405180910390a15b5b5050565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461074b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161074290612b24565b60405180910390fd5b80610207818161075b9190612f2a565b90505050565b6107696123a7565b6107716123a7565b5f5f5f61077c6121d5565b15610bb9576102085f015f9054906101000a900467ffffffffffffffff1684606001515f019067ffffffffffffffff16908167ffffffffffffffff16815250506102086001015484606001516020018181525050600260016102065f9054906101000a900467ffffffffffffffff166107f59190612f38565b6107ff9190612d33565b67ffffffffffffffff1692505f60026102065f9054906101000a900467ffffffffffffffff1661082f9190612d33565b67ffffffffffffffff1690506108616002826002811061085257610851612d63565b5b6101020201610100015461220e565b91506001826108709190612f73565b67ffffffffffffffff81111561088957610888612fa6565b5b6040519080825280602002602001820160405280156108c257816020015b6108af61240f565b8152602001906001900390816108a75790505b5085602001515f0181905250600281600281106108e2576108e1612d63565b5b6101020201610101015f9054906101000a900460ff1685602001516020019060ff16908160ff16815250505f5f90505b828111610bb257610949816002846002811061093157610930612d63565b5b610102020161010001546121e590919063ffffffff16565b610b9f576002826002811061096157610960612d63565b5b61010202015f0181610100811061097b5761097a612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1693508386602001515f015182815181106109b9576109b8612d63565b5b60200260200101515f019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050610a268160028760028110610a0e57610a0d612d63565b5b610102020161010001546121e590919063ffffffff16565b80610aab57508373ffffffffffffffffffffffffffffffffffffffff1660028660028110610a5757610a56612d63565b5b61010202015f01826101008110610a7157610a70612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b15610b9e5760015f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f208054610af890613000565b80601f0160208091040260200160405190810160405280929190818152602001828054610b2490613000565b8015610b6f5780601f10610b4657610100808354040283529160200191610b6f565b820191905f5260205f20905b815481529060010190602001808311610b5257829003601f168201915b505050505086602001515f01518281518110610b8e57610b8d612d63565b5b6020026020010151602001819052505b5b8080610baa90613030565b915050610912565b5050610be9565b60026102065f9054906101000a900467ffffffffffffffff16610bdc9190612d33565b67ffffffffffffffff1692505b610c0f60028460028110610c0057610bff612d63565b5b6101020201610100015461220e565b9050600181610c1e9190612f73565b67ffffffffffffffff811115610c3757610c36612fa6565b5b604051908082528060200260200182016040528015610c7057816020015b610c5d61240f565b815260200190600190039081610c555790505b50845f01515f018190525060028360028110610c8f57610c8e612d63565b5b6101020201610101015f9054906101000a900460ff16845f01516020019060ff16908160ff16815250505f5f90505b818111610ea157610cf58160028660028110610cdd57610cdc612d63565b5b610102020161010001546121e590919063ffffffff16565b610e8e5760028460028110610d0d57610d0c612d63565b5b61010202015f01816101008110610d2757610d26612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16925082855f01515f01518281518110610d6457610d63612d63565b5b60200260200101515f019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f208054610de990613000565b80601f0160208091040260200160405190810160405280929190818152602001828054610e1590613000565b8015610e605780601f10610e3757610100808354040283529160200191610e60565b820191905f5260205f20905b815481529060010190602001808311610e4357829003601f168201915b5050505050855f01515f01518281518110610e7e57610e7d612d63565b5b6020026020010151602001819052505b8080610e9990613030565b915050610cbe565b506102065f9054906101000a900467ffffffffffffffff16846040019067ffffffffffffffff16908167ffffffffffffffff168152505061020a5f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684608001515f019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505061020b5f9054906101000a90046fffffffffffffffffffffffffffffffff168460a001906fffffffffffffffffffffffffffffffff1690816fffffffffffffffffffffffffffffffff16815250508394505050505090565b610f9b8282905061221f565b818160015f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f209182610fe7929190613218565b505050565b610ff461217b565b611033576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161102a90612b8c565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff1661020a5f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146110c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110bc90612dda565b60405180910390fd5b5f61020a5f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff168092919061113690612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507ff91067eb420c28d3124865fc996e6aa9d541b9b4fef9188cb965a6cc6491638e3361020b5f9054906101000a90046fffffffffffffffffffffffffffffffff166040516111bc9291906132e5565b60405180910390a1565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611254576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161124b90612b24565b60405180910390fd5b61125c6121d5565b61129b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161129290612c80565b60405180910390fd5b6102065f81819054906101000a900467ffffffffffffffff16809291906112c19061330c565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550505f6102086001018190555061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff168092919061132190612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507ff73240422246f63ed633ef3ce0726b8ab8fb69d46c8a4e5ecb0b2922668674a16102085f015f9054906101000a900467ffffffffffffffff1661020b5f9054906101000a90046fffffffffffffffffffffffffffffffff166040516113bf929190613333565b60405180910390a1565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611457576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161144e90612b24565b60405180910390fd5b61145f6121d5565b1561149f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611496906133a4565b60405180910390fd5b6114a761217b565b156114e7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114de9061340c565b60405180910390fd5b6102085f015f81819054906101000a900467ffffffffffffffff168092919061150f9061342a565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550505f60026102065f9054906101000a900467ffffffffffffffff1661155a9190612d33565b67ffffffffffffffff1690506102065f81819054906101000a900467ffffffffffffffff168092919061158c9061342a565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550505f60026102065f9054906101000a900467ffffffffffffffff166115d79190612d33565b67ffffffffffffffff1690505f5f90505b61160e600284600281106115ff576115fe612d63565b5b6101020201610100015461220e565b81116117b2576002836002811061162857611627612d63565b5b61010202015f0181610100811061164257611641612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166002836002811061168d5761168c612d63565b5b61010202015f018261010081106116a7576116a6612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461179f57600283600281106116f7576116f6612d63565b5b61010202015f0181610100811061171157611710612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff166002836002811061174657611745612d63565b5b61010202015f018261010081106117605761175f612d63565b5b015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b80806117aa90613030565b9150506115e8565b505f600283600281106117c8576117c7612d63565b5b6101020201610100015490505f5f5f5f90505b86805f01906117ea9190613465565b90508110156119465786805f01906118029190613465565b8281811061181357611812612d63565b5b9050604002015f01602081019061182a91906129ed565b925086805f019061183b9190613465565b8281811061184c5761184b612d63565b5b90506040020160200160208101906118649190612a9f565b91505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036118b3576118ac83856121fa90919063ffffffff16565b93506118c9565b6118c683856122bd90919063ffffffff16565b93505b81600286600281106118de576118dd612d63565b5b61010202015f018460ff1661010081106118fb576118fa612d63565b5b015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080806001019150506117db565b50826002856002811061195c5761195b612d63565b5b6101020201610100018190555085602001602081019061197c91906129ed565b600285600281106119905761198f612d63565b5b6101020201610101015f6101000a81548160ff021916908360ff160217905550826102086001018190555061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff16809291906119e990612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507f78dad2bc0b47c688ed84f3fee79abc18e6c9822db05a79ca19dff54533c7470d6102085f015f9054906101000a900467ffffffffffffffff168761020b5f9054906101000a90046fffffffffffffffffffffffffffffffff16604051611a899392919061368b565b60405180910390a1505050505050565b611aa16121d5565b15611ae1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ad8906133a4565b60405180910390fd5b611ae961217b565b15611b29576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b209061340c565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff166002806102065f9054906101000a900467ffffffffffffffff16611b649190612d33565b67ffffffffffffffff1660028110611b7f57611b7e612d63565b5b61010202015f018260ff166101008110611b9c57611b9b612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611c13576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c0a90612dda565b60405180910390fd5b3361020a5f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff1680929190611c8490612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507fbc2748cf02f7a1291525e866efc76ab3b96d32d7afcbb26c53daec617b38b4793361020b5f9054906101000a90046fffffffffffffffffffffffffffffffff16604051611d0a9291906132e5565b60405180910390a150565b611d218282905061221f565b5f5f611d2b6121d5565b15611ea1573373ffffffffffffffffffffffffffffffffffffffff1660028060016102065f9054906101000a900467ffffffffffffffff16611d6d9190612f38565b611d779190612d33565b67ffffffffffffffff1660028110611d9257611d91612d63565b5b61010202015f018660ff166101008110611daf57611dae612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614915081611e9c573373ffffffffffffffffffffffffffffffffffffffff166002806102065f9054906101000a900467ffffffffffffffff16611e299190612d33565b67ffffffffffffffff1660028110611e4457611e43612d63565b5b61010202015f018660ff166101008110611e6157611e60612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161490505b611f4f565b3373ffffffffffffffffffffffffffffffffffffffff166002806102065f9054906101000a900467ffffffffffffffff16611edc9190612d33565b67ffffffffffffffff1660028110611ef757611ef6612d63565b5b61010202015f018660ff166101008110611f1457611f13612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161491505b8180611f585750805b611f97576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f8e90612dda565b60405180910390fd5b838360015f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f209182611fe3929190613218565b5061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff168092919061201290612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507f125181ec21882dec51a2392905dff3a82cbd0262f18b5c0c035488671b40afb233858561020b5f9054906101000a90046fffffffffffffffffffffffffffffffff1660405161209c9493929190613711565b60405180910390a15050505050565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612139576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161213090612b24565b60405180910390fd5b805f5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b5f5f73ffffffffffffffffffffffffffffffffffffffff1661020a5f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415905090565b5f5f610208600101541415905090565b5f5f8260ff166001901b841614905092915050565b5f8160ff166001901b198316905092915050565b5f612218826122d0565b9050919050565b5f8111612261576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161225890613799565b60405180910390fd5b6102075f015f9054906101000a900461ffff1661ffff168111156122ba576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122b190613801565b60405180910390fd5b50565b5f8160ff166001901b8317905092915050565b5f60076122ee6fffffffffffffffffffffffffffffffff841161239c565b901b9050600661230a67ffffffffffffffff8385901c1161239c565b901b81179050600561232463ffffffff8385901c1161239c565b901b81179050600461233c61ffff8385901c1161239c565b901b81179050600361235360ff8385901c1161239c565b901b81179050600261236a600f8385901c1161239c565b901b811790507d01010202020203030303030303030000000000000000000000000000000082821c1a81179050919050565b5f8115159050919050565b6040518060c001604052806123ba61243e565b81526020016123c761243e565b81526020015f67ffffffffffffffff1681526020016123e461245a565b81526020016123f161247c565b81526020015f6fffffffffffffffffffffffffffffffff1681525090565b60405180604001604052805f73ffffffffffffffffffffffffffffffffffffffff168152602001606081525090565b6040518060400160405280606081526020015f60ff1681525090565b60405180604001604052805f67ffffffffffffffff1681526020015f81525090565b60405180602001604052805f73ffffffffffffffffffffffffffffffffffffffff1681525090565b5f5ffd5b5f5ffd5b5f67ffffffffffffffff82169050919050565b6124c8816124ac565b81146124d2575f5ffd5b50565b5f813590506124e3816124bf565b92915050565b5f60ff82169050919050565b6124fe816124e9565b8114612508575f5ffd5b50565b5f81359050612519816124f5565b92915050565b5f5f60408385031215612535576125346124a4565b5b5f612542858286016124d5565b92505060206125538582860161250b565b9150509250929050565b5f5ffd5b5f602082840312156125765761257561255d565b5b81905092915050565b5f60208284031215612594576125936124a4565b5b5f6125a184828501612561565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6125fc826125d3565b9050919050565b61260c816125f2565b82525050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61265482612612565b61265e818561261c565b935061266e81856020860161262c565b6126778161263a565b840191505092915050565b5f604083015f8301516126975f860182612603565b50602083015184820360208601526126af828261264a565b9150508091505092915050565b5f6126c78383612682565b905092915050565b5f602082019050919050565b5f6126e5826125aa565b6126ef81856125b4565b935083602082028501612701856125c4565b805f5b8581101561273c578484038952815161271d85826126bc565b9450612728836126cf565b925060208a01995050600181019050612704565b50829750879550505050505092915050565b612757816124e9565b82525050565b5f604083015f8301518482035f86015261277782826126db565b915050602083015161278c602086018261274e565b508091505092915050565b6127a0816124ac565b82525050565b5f819050919050565b6127b8816127a6565b82525050565b604082015f8201516127d25f850182612797565b5060208201516127e560208501826127af565b50505050565b602082015f8201516127ff5f850182612603565b50505050565b5f6fffffffffffffffffffffffffffffffff82169050919050565b61282981612805565b82525050565b5f60e083015f8301518482035f860152612849828261275d565b91505060208301518482036020860152612863828261275d565b91505060408301516128786040860182612797565b50606083015161288b60608601826127be565b50608083015161289e60a08601826127eb565b5060a08301516128b160c0860182612820565b508091505092915050565b5f6020820190508181035f8301526128d4818461282f565b905092915050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f83601f8401126128fd576128fc6128dc565b5b8235905067ffffffffffffffff81111561291a576129196128e0565b5b602083019150836001820283011115612936576129356128e4565b5b9250929050565b5f5f60208385031215612953576129526124a4565b5b5f83013567ffffffffffffffff8111156129705761296f6124a8565b5b61297c858286016128e8565b92509250509250929050565b5f6040828403121561299d5761299c61255d565b5b81905092915050565b5f602082840312156129bb576129ba6124a4565b5b5f82013567ffffffffffffffff8111156129d8576129d76124a8565b5b6129e484828501612988565b91505092915050565b5f60208284031215612a0257612a016124a4565b5b5f612a0f8482850161250b565b91505092915050565b5f5f5f60408486031215612a2f57612a2e6124a4565b5b5f612a3c8682870161250b565b935050602084013567ffffffffffffffff811115612a5d57612a5c6124a8565b5b612a69868287016128e8565b92509250509250925092565b612a7e816125f2565b8114612a88575f5ffd5b50565b5f81359050612a9981612a75565b92915050565b5f60208284031215612ab457612ab36124a4565b5b5f612ac184828501612a8b565b91505092915050565b5f82825260208201905092915050565b7f6e6f7420746865206f776e6572000000000000000000000000000000000000005f82015250565b5f612b0e600d83612aca565b9150612b1982612ada565b602082019050919050565b5f6020820190508181035f830152612b3b81612b02565b9050919050565b7f6e6f206d61696e74656e616e63650000000000000000000000000000000000005f82015250565b5f612b76600e83612aca565b9150612b8182612b42565b602082019050919050565b5f6020820190508181035f830152612ba381612b6a565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f612be182612805565b91506fffffffffffffffffffffffffffffffff8203612c0357612c02612baa565b5b600182019050919050565b612c1781612805565b82525050565b5f602082019050612c305f830184612c0e565b92915050565b7f6e6f206d6967726174696f6e00000000000000000000000000000000000000005f82015250565b5f612c6a600c83612aca565b9150612c7582612c36565b602082019050919050565b5f6020820190508181035f830152612c9781612c5e565b9050919050565b7f77726f6e67206d6967726174696f6e20696400000000000000000000000000005f82015250565b5f612cd2601283612aca565b9150612cdd82612c9e565b602082019050919050565b5f6020820190508181035f830152612cff81612cc6565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f612d3d826124ac565b9150612d48836124ac565b925082612d5857612d57612d06565b5b828206905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f77726f6e67206f70657261746f720000000000000000000000000000000000005f82015250565b5f612dc4600e83612aca565b9150612dcf82612d90565b602082019050919050565b5f6020820190508181035f830152612df181612db8565b9050919050565b612e01816124ac565b82525050565b612e10816125f2565b82525050565b5f606082019050612e295f830186612df8565b612e366020830185612e07565b612e436040830184612c0e565b949350505050565b5f61ffff82169050919050565b612e6181612e4b565b8114612e6b575f5ffd5b50565b5f8135612e7a81612e58565b80915050919050565b5f815f1b9050919050565b5f61ffff612e9b84612e83565b9350801983169250808416831791505092915050565b5f819050919050565b5f612ed4612ecf612eca84612e4b565b612eb1565b612e4b565b9050919050565b5f819050919050565b612eed82612eba565b612f00612ef982612edb565b8354612e8e565b8255505050565b5f81015f830180612f1781612e6e565b9050612f238184612ee4565b5050505050565b612f348282612f07565b5050565b5f612f42826124ac565b9150612f4d836124ac565b9250828203905067ffffffffffffffff811115612f6d57612f6c612baa565b5b92915050565b5f612f7d826127a6565b9150612f88836127a6565b9250828201905080821115612fa057612f9f612baa565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061301757607f821691505b60208210810361302a57613029612fd3565b5b50919050565b5f61303a826127a6565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361306c5761306b612baa565b5b600182019050919050565b5f82905092915050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026130dd7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826130a2565b6130e786836130a2565b95508019841693508086168417925050509392505050565b5f61311961311461310f846127a6565b612eb1565b6127a6565b9050919050565b5f819050919050565b613132836130ff565b61314661313e82613120565b8484546130ae565b825550505050565b5f5f905090565b61315d61314e565b613168818484613129565b505050565b5b8181101561318b576131805f82613155565b60018101905061316e565b5050565b601f8211156131d0576131a181613081565b6131aa84613093565b810160208510156131b9578190505b6131cd6131c585613093565b83018261316d565b50505b505050565b5f82821c905092915050565b5f6131f05f19846008026131d5565b1980831691505092915050565b5f61320883836131e1565b9150826002028217905092915050565b6132228383613077565b67ffffffffffffffff81111561323b5761323a612fa6565b5b6132458254613000565b61325082828561318f565b5f601f83116001811461327d575f841561326b578287013590505b61327585826131fd565b8655506132dc565b601f19841661328b86613081565b5f5b828110156132b25784890135825560018201915060208501945060208101905061328d565b868310156132cf57848901356132cb601f8916826131e1565b8355505b6001600288020188555050505b50505050505050565b5f6040820190506132f85f830185612e07565b6133056020830184612c0e565b9392505050565b5f613316826124ac565b91505f820361332857613327612baa565b5b600182039050919050565b5f6040820190506133465f830185612df8565b6133536020830184612c0e565b9392505050565b7f6d6967726174696f6e20696e2070726f677265737300000000000000000000005f82015250565b5f61338e601583612aca565b91506133998261335a565b602082019050919050565b5f6020820190508181035f8301526133bb81613382565b9050919050565b7f6d61696e74656e616e636520696e2070726f67726573730000000000000000005f82015250565b5f6133f6601783612aca565b9150613401826133c2565b602082019050919050565b5f6020820190508181035f830152613423816133ea565b9050919050565b5f613434826124ac565b915067ffffffffffffffff820361344e5761344d612baa565b5b600182019050919050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f8335600160200384360303811261348157613480613459565b5b80840192508235915067ffffffffffffffff8211156134a3576134a261345d565b5b6020830192506040820236038313156134bf576134be613461565b5b509250929050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f833560016020038436030381126134ef576134ee6134cf565b5b83810192508235915060208301925067ffffffffffffffff821115613517576135166134c7565b5b60408202360383131561352d5761352c6134cb565b5b509250929050565b5f82825260208201905092915050565b5f819050919050565b5f61355c602084018461250b565b905092915050565b5f6135726020840184612a8b565b905092915050565b6040820161358a5f83018361354e565b6135965f85018261274e565b506135a46020830183613564565b6135b16020850182612603565b50505050565b5f6135c2838361357a565b60408301905092915050565b5f82905092915050565b5f604082019050919050565b5f6135ef8385613535565b93506135fa82613545565b805f5b858110156136325761360f82846135ce565b61361988826135b7565b9750613624836135d8565b9250506001810190506135fd565b5085925050509392505050565b5f604083016136505f8401846134d3565b8583035f8701526136628382846135e4565b92505050613673602084018461354e565b613680602086018261274e565b508091505092915050565b5f60608201905061369e5f830186612df8565b81810360208301526136b0818561363f565b90506136bf6040830184612c0e565b949350505050565b5f82825260208201905092915050565b828183375f83830152505050565b5f6136f083856136c7565b93506136fd8385846136d7565b6137068361263a565b840190509392505050565b5f6060820190506137245f830187612e07565b81810360208301526137378185876136e5565b90506137466040830184612c0e565b95945050505050565b7f656d707479206f70657261746f722064617461000000000000000000000000005f82015250565b5f613783601383612aca565b915061378e8261374f565b602082019050919050565b5f6020820190508181035f8301526137b081613777565b9050919050565b7f6f70657261746f72206461746120746f6f206c617267650000000000000000005f82015250565b5f6137eb601783612aca565b91506137f6826137b7565b602082019050919050565b5f6020820190508181035f830152613818816137df565b905091905056fea26469706673582212205070bfb78cba4fb204ce3a9ae24b5f710c62732176365ee8389cdab18c3c2d7164736f6c634300081c0033 + ///0x608060405234801561000f575f5ffd5b50604051613d0f380380613d0f833981810160405281019061003191906103bd565b335f5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550816102075f820151815f015f6101000a81548161ffff021916908361ffff1602179055509050505f5f90505b8151811015610139578181815181106100b8576100b7610417565b5b602002602001015160025f600281106100d4576100d3610417565b5b61010202015f018261010081106100ee576100ed610417565b5b015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808060010191505061009c565b5061014a815161017260201b60201c565b60025f6002811061015e5761015d610417565b5b6101020201610100018190555050506104ad565b5f60018260ff166001901b610187919061047a565b9050919050565b5f604051905090565b5f5ffd5b5f5ffd5b5f5ffd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6101e9826101a3565b810181811067ffffffffffffffff82111715610208576102076101b3565b5b80604052505050565b5f61021a61018e565b905061022682826101e0565b919050565b5f61ffff82169050919050565b6102418161022b565b811461024b575f5ffd5b50565b5f8151905061025c81610238565b92915050565b5f602082840312156102775761027661019f565b5b6102816020610211565b90505f6102908482850161024e565b5f8301525092915050565b5f5ffd5b5f67ffffffffffffffff8211156102b9576102b86101b3565b5b602082029050602081019050919050565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6102f7826102ce565b9050919050565b610307816102ed565b8114610311575f5ffd5b50565b5f81519050610322816102fe565b92915050565b5f61033a6103358461029f565b610211565b9050808382526020820190506020840283018581111561035d5761035c6102ca565b5b835b8181101561038657806103728882610314565b84526020840193505060208101905061035f565b5050509392505050565b5f82601f8301126103a4576103a361029b565b5b81516103b4848260208601610328565b91505092915050565b5f5f604083850312156103d3576103d2610197565b5b5f6103e085828601610262565b925050602083015167ffffffffffffffff8111156104015761040061019b565b5b61040d85828601610390565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f819050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61048482610444565b915061048f83610444565b92508282039050818111156104a7576104a661044d565b5b92915050565b613855806104ba5f395ff3fe608060405234801561000f575f5ffd5b50600436106100a7575f3560e01c8063ad36e6d01161006f578063ad36e6d014610127578063c130809a14610131578063cdbfc62d1461013b578063dd3fd26914610157578063f019b15414610173578063f2fde38b1461018f576100a7565b80633048bfba146100ab57806355a47d0a146100b557806365706f9c146100d157806375418b9d146100ed5780638b5252d61461010b575b5f5ffd5b6100b36101ab565b005b6100cf60048036038101906100ca919061251f565b61037f565b005b6100eb60048036038101906100e6919061257f565b6106bd565b005b6100f5610761565b60405161010291906128bc565b60405180910390f35b6101256004803603810190610120919061293d565b610f8f565b005b61012f610fec565b005b6101396111c6565b005b610155600480360381019061015091906129a6565b6113c9565b005b610171600480360381019061016c91906129ed565b611a99565b005b61018d60048036038101906101889190612a18565b611d15565b005b6101a960048036038101906101a49190612a9f565b6120ab565b005b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610239576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161023090612b24565b60405180910390fd5b61024161217b565b610280576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161027790612b8c565b60405180910390fd5b5f61020a5f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff16809291906102f190612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507f8fb9cd054d0a022110cced239e908b834e4cd219511856d4eaae3051d932d60461020b5f9054906101000a90046fffffffffffffffffffffffffffffffff166040516103759190612c1d565b60405180910390a1565b6103876121d5565b6103c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103bd90612c80565b60405180910390fd5b6102085f015f9054906101000a900467ffffffffffffffff1667ffffffffffffffff168267ffffffffffffffff1614610434576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042b90612ce8565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff166002806102065f9054906101000a900467ffffffffffffffff1661046f9190612d33565b67ffffffffffffffff166002811061048a57610489612d63565b5b61010202015f018260ff1661010081106104a7576104a6612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461051e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161051590612dda565b60405180910390fd5b61053781610208600101546121e590919063ffffffff16565b6106b95761055481610208600101546121fa90919063ffffffff16565b6102086001018190555061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff168092919061058c90612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550505f6102086001015403610646577f01269879535f40ee8957e15e160bf1866c5e2728ff0cbc583d848821e2639b4e6102085f015f9054906101000a900467ffffffffffffffff163361020b5f9054906101000a90046fffffffffffffffffffffffffffffffff1660405161063993929190612e16565b60405180910390a16106b8565b7faf5e90e72015f43138f66b4cd08bd1dfa2839030104f22a00af843fe847c6d196102085f015f9054906101000a900467ffffffffffffffff163361020b5f9054906101000a90046fffffffffffffffffffffffffffffffff166040516106af93929190612e16565b60405180910390a15b5b5050565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461074b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161074290612b24565b60405180910390fd5b80610207818161075b9190612f2a565b90505050565b6107696123a7565b6107716123a7565b5f5f5f61077c6121d5565b15610bb9576102085f015f9054906101000a900467ffffffffffffffff1684602001515f019067ffffffffffffffff16908167ffffffffffffffff16815250506102086001015484602001516020018181525050600260016102065f9054906101000a900467ffffffffffffffff166107f59190612f38565b6107ff9190612d33565b67ffffffffffffffff1692505f60026102065f9054906101000a900467ffffffffffffffff1661082f9190612d33565b67ffffffffffffffff1690506108616002826002811061085257610851612d63565b5b6101020201610100015461220e565b91506001826108709190612f73565b67ffffffffffffffff81111561088957610888612fa6565b5b6040519080825280602002602001820160405280156108c257816020015b6108af61240f565b8152602001906001900390816108a75790505b5085604001515f0181905250600281600281106108e2576108e1612d63565b5b6101020201610101015f9054906101000a900460ff1685604001516020019060ff16908160ff16815250505f5f90505b828111610bb257610949816002846002811061093157610930612d63565b5b610102020161010001546121e590919063ffffffff16565b610b9f576002826002811061096157610960612d63565b5b61010202015f0181610100811061097b5761097a612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1693508386604001515f015182815181106109b9576109b8612d63565b5b60200260200101515f019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050610a268160028760028110610a0e57610a0d612d63565b5b610102020161010001546121e590919063ffffffff16565b80610aab57508373ffffffffffffffffffffffffffffffffffffffff1660028660028110610a5757610a56612d63565b5b61010202015f01826101008110610a7157610a70612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b15610b9e5760015f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f208054610af890613000565b80601f0160208091040260200160405190810160405280929190818152602001828054610b2490613000565b8015610b6f5780601f10610b4657610100808354040283529160200191610b6f565b820191905f5260205f20905b815481529060010190602001808311610b5257829003601f168201915b505050505086604001515f01518281518110610b8e57610b8d612d63565b5b6020026020010151602001819052505b5b8080610baa90613030565b915050610912565b5050610be9565b60026102065f9054906101000a900467ffffffffffffffff16610bdc9190612d33565b67ffffffffffffffff1692505b610c0f60028460028110610c0057610bff612d63565b5b6101020201610100015461220e565b9050600181610c1e9190612f73565b67ffffffffffffffff811115610c3757610c36612fa6565b5b604051908082528060200260200182016040528015610c7057816020015b610c5d61240f565b815260200190600190039081610c555790505b50845f01515f018190525060028360028110610c8f57610c8e612d63565b5b6101020201610101015f9054906101000a900460ff16845f01516020019060ff16908160ff16815250505f5f90505b818111610ea157610cf58160028660028110610cdd57610cdc612d63565b5b610102020161010001546121e590919063ffffffff16565b610e8e5760028460028110610d0d57610d0c612d63565b5b61010202015f01816101008110610d2757610d26612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16925082855f01515f01518281518110610d6457610d63612d63565b5b60200260200101515f019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f208054610de990613000565b80601f0160208091040260200160405190810160405280929190818152602001828054610e1590613000565b8015610e605780601f10610e3757610100808354040283529160200191610e60565b820191905f5260205f20905b815481529060010190602001808311610e4357829003601f168201915b5050505050855f01515f01518281518110610e7e57610e7d612d63565b5b6020026020010151602001819052505b8080610e9990613030565b915050610cbe565b506102065f9054906101000a900467ffffffffffffffff16846080019067ffffffffffffffff16908167ffffffffffffffff168152505061020a5f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684606001515f019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505061020b5f9054906101000a90046fffffffffffffffffffffffffffffffff168460a001906fffffffffffffffffffffffffffffffff1690816fffffffffffffffffffffffffffffffff16815250508394505050505090565b610f9b8282905061221f565b818160015f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f209182610fe7929190613218565b505050565b610ff461217b565b611033576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161102a90612b8c565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff1661020a5f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146110c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110bc90612dda565b60405180910390fd5b5f61020a5f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff168092919061113690612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507ff91067eb420c28d3124865fc996e6aa9d541b9b4fef9188cb965a6cc6491638e3361020b5f9054906101000a90046fffffffffffffffffffffffffffffffff166040516111bc9291906132e5565b60405180910390a1565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611254576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161124b90612b24565b60405180910390fd5b61125c6121d5565b61129b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161129290612c80565b60405180910390fd5b6102065f81819054906101000a900467ffffffffffffffff16809291906112c19061330c565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550505f6102086001018190555061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff168092919061132190612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507ff73240422246f63ed633ef3ce0726b8ab8fb69d46c8a4e5ecb0b2922668674a16102085f015f9054906101000a900467ffffffffffffffff1661020b5f9054906101000a90046fffffffffffffffffffffffffffffffff166040516113bf929190613333565b60405180910390a1565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611457576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161144e90612b24565b60405180910390fd5b61145f6121d5565b1561149f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611496906133a4565b60405180910390fd5b6114a761217b565b156114e7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114de9061340c565b60405180910390fd5b6102085f015f81819054906101000a900467ffffffffffffffff168092919061150f9061342a565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550505f60026102065f9054906101000a900467ffffffffffffffff1661155a9190612d33565b67ffffffffffffffff1690506102065f81819054906101000a900467ffffffffffffffff168092919061158c9061342a565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550505f60026102065f9054906101000a900467ffffffffffffffff166115d79190612d33565b67ffffffffffffffff1690505f5f90505b61160e600284600281106115ff576115fe612d63565b5b6101020201610100015461220e565b81116117b2576002836002811061162857611627612d63565b5b61010202015f0181610100811061164257611641612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166002836002811061168d5761168c612d63565b5b61010202015f018261010081106116a7576116a6612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461179f57600283600281106116f7576116f6612d63565b5b61010202015f0181610100811061171157611710612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff166002836002811061174657611745612d63565b5b61010202015f018261010081106117605761175f612d63565b5b015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b80806117aa90613030565b9150506115e8565b505f600283600281106117c8576117c7612d63565b5b6101020201610100015490505f5f5f5f90505b86805f01906117ea9190613465565b90508110156119465786805f01906118029190613465565b8281811061181357611812612d63565b5b9050604002015f01602081019061182a91906129ed565b925086805f019061183b9190613465565b8281811061184c5761184b612d63565b5b90506040020160200160208101906118649190612a9f565b91505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036118b3576118ac83856121fa90919063ffffffff16565b93506118c9565b6118c683856122bd90919063ffffffff16565b93505b81600286600281106118de576118dd612d63565b5b61010202015f018460ff1661010081106118fb576118fa612d63565b5b015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080806001019150506117db565b50826002856002811061195c5761195b612d63565b5b6101020201610100018190555085602001602081019061197c91906129ed565b600285600281106119905761198f612d63565b5b6101020201610101015f6101000a81548160ff021916908360ff160217905550826102086001018190555061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff16809291906119e990612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507f78dad2bc0b47c688ed84f3fee79abc18e6c9822db05a79ca19dff54533c7470d6102085f015f9054906101000a900467ffffffffffffffff168761020b5f9054906101000a90046fffffffffffffffffffffffffffffffff16604051611a899392919061368b565b60405180910390a1505050505050565b611aa16121d5565b15611ae1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ad8906133a4565b60405180910390fd5b611ae961217b565b15611b29576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b209061340c565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff166002806102065f9054906101000a900467ffffffffffffffff16611b649190612d33565b67ffffffffffffffff1660028110611b7f57611b7e612d63565b5b61010202015f018260ff166101008110611b9c57611b9b612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611c13576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c0a90612dda565b60405180910390fd5b3361020a5f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff1680929190611c8490612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507fbc2748cf02f7a1291525e866efc76ab3b96d32d7afcbb26c53daec617b38b4793361020b5f9054906101000a90046fffffffffffffffffffffffffffffffff16604051611d0a9291906132e5565b60405180910390a150565b611d218282905061221f565b5f5f611d2b6121d5565b15611ea1573373ffffffffffffffffffffffffffffffffffffffff1660028060016102065f9054906101000a900467ffffffffffffffff16611d6d9190612f38565b611d779190612d33565b67ffffffffffffffff1660028110611d9257611d91612d63565b5b61010202015f018660ff166101008110611daf57611dae612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614915081611e9c573373ffffffffffffffffffffffffffffffffffffffff166002806102065f9054906101000a900467ffffffffffffffff16611e299190612d33565b67ffffffffffffffff1660028110611e4457611e43612d63565b5b61010202015f018660ff166101008110611e6157611e60612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161490505b611f4f565b3373ffffffffffffffffffffffffffffffffffffffff166002806102065f9054906101000a900467ffffffffffffffff16611edc9190612d33565b67ffffffffffffffff1660028110611ef757611ef6612d63565b5b61010202015f018660ff166101008110611f1457611f13612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161491505b8180611f585750805b611f97576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f8e90612dda565b60405180910390fd5b838360015f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f209182611fe3929190613218565b5061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff168092919061201290612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507f125181ec21882dec51a2392905dff3a82cbd0262f18b5c0c035488671b40afb233858561020b5f9054906101000a90046fffffffffffffffffffffffffffffffff1660405161209c9493929190613711565b60405180910390a15050505050565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612139576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161213090612b24565b60405180910390fd5b805f5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b5f5f73ffffffffffffffffffffffffffffffffffffffff1661020a5f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415905090565b5f5f610208600101541415905090565b5f5f8260ff166001901b841614905092915050565b5f8160ff166001901b198316905092915050565b5f612218826122d0565b9050919050565b5f8111612261576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161225890613799565b60405180910390fd5b6102075f015f9054906101000a900461ffff1661ffff168111156122ba576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122b190613801565b60405180910390fd5b50565b5f8160ff166001901b8317905092915050565b5f60076122ee6fffffffffffffffffffffffffffffffff841161239c565b901b9050600661230a67ffffffffffffffff8385901c1161239c565b901b81179050600561232463ffffffff8385901c1161239c565b901b81179050600461233c61ffff8385901c1161239c565b901b81179050600361235360ff8385901c1161239c565b901b81179050600261236a600f8385901c1161239c565b901b811790507d01010202020203030303030303030000000000000000000000000000000082821c1a81179050919050565b5f8115159050919050565b6040518060c001604052806123ba61243e565b81526020016123c761245a565b81526020016123d461243e565b81526020016123e161247c565b81526020015f67ffffffffffffffff1681526020015f6fffffffffffffffffffffffffffffffff1681525090565b60405180604001604052805f73ffffffffffffffffffffffffffffffffffffffff168152602001606081525090565b6040518060400160405280606081526020015f60ff1681525090565b60405180604001604052805f67ffffffffffffffff1681526020015f81525090565b60405180602001604052805f73ffffffffffffffffffffffffffffffffffffffff1681525090565b5f5ffd5b5f5ffd5b5f67ffffffffffffffff82169050919050565b6124c8816124ac565b81146124d2575f5ffd5b50565b5f813590506124e3816124bf565b92915050565b5f60ff82169050919050565b6124fe816124e9565b8114612508575f5ffd5b50565b5f81359050612519816124f5565b92915050565b5f5f60408385031215612535576125346124a4565b5b5f612542858286016124d5565b92505060206125538582860161250b565b9150509250929050565b5f5ffd5b5f602082840312156125765761257561255d565b5b81905092915050565b5f60208284031215612594576125936124a4565b5b5f6125a184828501612561565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6125fc826125d3565b9050919050565b61260c816125f2565b82525050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61265482612612565b61265e818561261c565b935061266e81856020860161262c565b6126778161263a565b840191505092915050565b5f604083015f8301516126975f860182612603565b50602083015184820360208601526126af828261264a565b9150508091505092915050565b5f6126c78383612682565b905092915050565b5f602082019050919050565b5f6126e5826125aa565b6126ef81856125b4565b935083602082028501612701856125c4565b805f5b8581101561273c578484038952815161271d85826126bc565b9450612728836126cf565b925060208a01995050600181019050612704565b50829750879550505050505092915050565b612757816124e9565b82525050565b5f604083015f8301518482035f86015261277782826126db565b915050602083015161278c602086018261274e565b508091505092915050565b6127a0816124ac565b82525050565b5f819050919050565b6127b8816127a6565b82525050565b604082015f8201516127d25f850182612797565b5060208201516127e560208501826127af565b50505050565b602082015f8201516127ff5f850182612603565b50505050565b5f6fffffffffffffffffffffffffffffffff82169050919050565b61282981612805565b82525050565b5f60e083015f8301518482035f860152612849828261275d565b915050602083015161285e60208601826127be565b5060408301518482036060860152612876828261275d565b915050606083015161288b60808601826127eb565b50608083015161289e60a0860182612797565b5060a08301516128b160c0860182612820565b508091505092915050565b5f6020820190508181035f8301526128d4818461282f565b905092915050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f83601f8401126128fd576128fc6128dc565b5b8235905067ffffffffffffffff81111561291a576129196128e0565b5b602083019150836001820283011115612936576129356128e4565b5b9250929050565b5f5f60208385031215612953576129526124a4565b5b5f83013567ffffffffffffffff8111156129705761296f6124a8565b5b61297c858286016128e8565b92509250509250929050565b5f6040828403121561299d5761299c61255d565b5b81905092915050565b5f602082840312156129bb576129ba6124a4565b5b5f82013567ffffffffffffffff8111156129d8576129d76124a8565b5b6129e484828501612988565b91505092915050565b5f60208284031215612a0257612a016124a4565b5b5f612a0f8482850161250b565b91505092915050565b5f5f5f60408486031215612a2f57612a2e6124a4565b5b5f612a3c8682870161250b565b935050602084013567ffffffffffffffff811115612a5d57612a5c6124a8565b5b612a69868287016128e8565b92509250509250925092565b612a7e816125f2565b8114612a88575f5ffd5b50565b5f81359050612a9981612a75565b92915050565b5f60208284031215612ab457612ab36124a4565b5b5f612ac184828501612a8b565b91505092915050565b5f82825260208201905092915050565b7f6e6f7420746865206f776e6572000000000000000000000000000000000000005f82015250565b5f612b0e600d83612aca565b9150612b1982612ada565b602082019050919050565b5f6020820190508181035f830152612b3b81612b02565b9050919050565b7f6e6f206d61696e74656e616e63650000000000000000000000000000000000005f82015250565b5f612b76600e83612aca565b9150612b8182612b42565b602082019050919050565b5f6020820190508181035f830152612ba381612b6a565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f612be182612805565b91506fffffffffffffffffffffffffffffffff8203612c0357612c02612baa565b5b600182019050919050565b612c1781612805565b82525050565b5f602082019050612c305f830184612c0e565b92915050565b7f6e6f206d6967726174696f6e00000000000000000000000000000000000000005f82015250565b5f612c6a600c83612aca565b9150612c7582612c36565b602082019050919050565b5f6020820190508181035f830152612c9781612c5e565b9050919050565b7f77726f6e67206d6967726174696f6e20696400000000000000000000000000005f82015250565b5f612cd2601283612aca565b9150612cdd82612c9e565b602082019050919050565b5f6020820190508181035f830152612cff81612cc6565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f612d3d826124ac565b9150612d48836124ac565b925082612d5857612d57612d06565b5b828206905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f77726f6e67206f70657261746f720000000000000000000000000000000000005f82015250565b5f612dc4600e83612aca565b9150612dcf82612d90565b602082019050919050565b5f6020820190508181035f830152612df181612db8565b9050919050565b612e01816124ac565b82525050565b612e10816125f2565b82525050565b5f606082019050612e295f830186612df8565b612e366020830185612e07565b612e436040830184612c0e565b949350505050565b5f61ffff82169050919050565b612e6181612e4b565b8114612e6b575f5ffd5b50565b5f8135612e7a81612e58565b80915050919050565b5f815f1b9050919050565b5f61ffff612e9b84612e83565b9350801983169250808416831791505092915050565b5f819050919050565b5f612ed4612ecf612eca84612e4b565b612eb1565b612e4b565b9050919050565b5f819050919050565b612eed82612eba565b612f00612ef982612edb565b8354612e8e565b8255505050565b5f81015f830180612f1781612e6e565b9050612f238184612ee4565b5050505050565b612f348282612f07565b5050565b5f612f42826124ac565b9150612f4d836124ac565b9250828203905067ffffffffffffffff811115612f6d57612f6c612baa565b5b92915050565b5f612f7d826127a6565b9150612f88836127a6565b9250828201905080821115612fa057612f9f612baa565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061301757607f821691505b60208210810361302a57613029612fd3565b5b50919050565b5f61303a826127a6565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361306c5761306b612baa565b5b600182019050919050565b5f82905092915050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026130dd7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826130a2565b6130e786836130a2565b95508019841693508086168417925050509392505050565b5f61311961311461310f846127a6565b612eb1565b6127a6565b9050919050565b5f819050919050565b613132836130ff565b61314661313e82613120565b8484546130ae565b825550505050565b5f5f905090565b61315d61314e565b613168818484613129565b505050565b5b8181101561318b576131805f82613155565b60018101905061316e565b5050565b601f8211156131d0576131a181613081565b6131aa84613093565b810160208510156131b9578190505b6131cd6131c585613093565b83018261316d565b50505b505050565b5f82821c905092915050565b5f6131f05f19846008026131d5565b1980831691505092915050565b5f61320883836131e1565b9150826002028217905092915050565b6132228383613077565b67ffffffffffffffff81111561323b5761323a612fa6565b5b6132458254613000565b61325082828561318f565b5f601f83116001811461327d575f841561326b578287013590505b61327585826131fd565b8655506132dc565b601f19841661328b86613081565b5f5b828110156132b25784890135825560018201915060208501945060208101905061328d565b868310156132cf57848901356132cb601f8916826131e1565b8355505b6001600288020188555050505b50505050505050565b5f6040820190506132f85f830185612e07565b6133056020830184612c0e565b9392505050565b5f613316826124ac565b91505f820361332857613327612baa565b5b600182039050919050565b5f6040820190506133465f830185612df8565b6133536020830184612c0e565b9392505050565b7f6d6967726174696f6e20696e2070726f677265737300000000000000000000005f82015250565b5f61338e601583612aca565b91506133998261335a565b602082019050919050565b5f6020820190508181035f8301526133bb81613382565b9050919050565b7f6d61696e74656e616e636520696e2070726f67726573730000000000000000005f82015250565b5f6133f6601783612aca565b9150613401826133c2565b602082019050919050565b5f6020820190508181035f830152613423816133ea565b9050919050565b5f613434826124ac565b915067ffffffffffffffff820361344e5761344d612baa565b5b600182019050919050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f8335600160200384360303811261348157613480613459565b5b80840192508235915067ffffffffffffffff8211156134a3576134a261345d565b5b6020830192506040820236038313156134bf576134be613461565b5b509250929050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f833560016020038436030381126134ef576134ee6134cf565b5b83810192508235915060208301925067ffffffffffffffff821115613517576135166134c7565b5b60408202360383131561352d5761352c6134cb565b5b509250929050565b5f82825260208201905092915050565b5f819050919050565b5f61355c602084018461250b565b905092915050565b5f6135726020840184612a8b565b905092915050565b6040820161358a5f83018361354e565b6135965f85018261274e565b506135a46020830183613564565b6135b16020850182612603565b50505050565b5f6135c2838361357a565b60408301905092915050565b5f82905092915050565b5f604082019050919050565b5f6135ef8385613535565b93506135fa82613545565b805f5b858110156136325761360f82846135ce565b61361988826135b7565b9750613624836135d8565b9250506001810190506135fd565b5085925050509392505050565b5f604083016136505f8401846134d3565b8583035f8701526136628382846135e4565b92505050613673602084018461354e565b613680602086018261274e565b508091505092915050565b5f60608201905061369e5f830186612df8565b81810360208301526136b0818561363f565b90506136bf6040830184612c0e565b949350505050565b5f82825260208201905092915050565b828183375f83830152505050565b5f6136f083856136c7565b93506136fd8385846136d7565b6137068361263a565b840190509392505050565b5f6060820190506137245f830187612e07565b81810360208301526137378185876136e5565b90506137466040830184612c0e565b95945050505050565b7f656d707479206f70657261746f722064617461000000000000000000000000005f82015250565b5f613783601383612aca565b915061378e8261374f565b602082019050919050565b5f6020820190508181035f8301526137b081613777565b9050919050565b7f6f70657261746f72206461746120746f6f206c617267650000000000000000005f82015250565b5f6137eb601783612aca565b91506137f6826137b7565b602082019050919050565b5f6020820190508181035f830152613818816137df565b905091905056fea2646970667358221220fa04dead425e6aa2ee51652b77cd8bec344f89d5a5d18b42f4889b7abad1732264736f6c634300081c0033 /// ``` #[rustfmt::skip] #[allow(clippy::all)] pub static BYTECODE: alloy_sol_types::private::Bytes = alloy_sol_types::private::Bytes::from_static( - b"`\x80`@R4\x80\x15a\0\x0FW__\xFD[P`@Qa=\x0F8\x03\x80a=\x0F\x839\x81\x81\x01`@R\x81\x01\x90a\x001\x91\x90a\x03\xBDV[3__a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UP\x81a\x02\x07_\x82\x01Q\x81_\x01_a\x01\0\n\x81T\x81a\xFF\xFF\x02\x19\x16\x90\x83a\xFF\xFF\x16\x02\x17\x90UP\x90PP__\x90P[\x81Q\x81\x10\x15a\x019W\x81\x81\x81Q\x81\x10a\0\xB8Wa\0\xB7a\x04\x17V[[` \x02` \x01\x01Q`\x02_`\x02\x81\x10a\0\xD4Wa\0\xD3a\x04\x17V[[a\x01\x02\x02\x01_\x01\x82a\x01\0\x81\x10a\0\xEEWa\0\xEDa\x04\x17V[[\x01_a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UP\x80\x80`\x01\x01\x91PPa\0\x9CV[Pa\x01J\x81Qa\x01r` \x1B` \x1CV[`\x02_`\x02\x81\x10a\x01^Wa\x01]a\x04\x17V[[a\x01\x02\x02\x01a\x01\0\x01\x81\x90UPPPa\x04\xADV[_`\x01\x82`\xFF\x16`\x01\x90\x1Ba\x01\x87\x91\x90a\x04zV[\x90P\x91\x90PV[_`@Q\x90P\x90V[__\xFD[__\xFD[__\xFD[_`\x1F\x19`\x1F\x83\x01\x16\x90P\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`A`\x04R`$_\xFD[a\x01\xE9\x82a\x01\xA3V[\x81\x01\x81\x81\x10g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x17\x15a\x02\x08Wa\x02\x07a\x01\xB3V[[\x80`@RPPPV[_a\x02\x1Aa\x01\x8EV[\x90Pa\x02&\x82\x82a\x01\xE0V[\x91\x90PV[_a\xFF\xFF\x82\x16\x90P\x91\x90PV[a\x02A\x81a\x02+V[\x81\x14a\x02KW__\xFD[PV[_\x81Q\x90Pa\x02\\\x81a\x028V[\x92\x91PPV[_` \x82\x84\x03\x12\x15a\x02wWa\x02va\x01\x9FV[[a\x02\x81` a\x02\x11V[\x90P_a\x02\x90\x84\x82\x85\x01a\x02NV[_\x83\x01RP\x92\x91PPV[__\xFD[_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15a\x02\xB9Wa\x02\xB8a\x01\xB3V[[` \x82\x02\x90P` \x81\x01\x90P\x91\x90PV[__\xFD[_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[_a\x02\xF7\x82a\x02\xCEV[\x90P\x91\x90PV[a\x03\x07\x81a\x02\xEDV[\x81\x14a\x03\x11W__\xFD[PV[_\x81Q\x90Pa\x03\"\x81a\x02\xFEV[\x92\x91PPV[_a\x03:a\x035\x84a\x02\x9FV[a\x02\x11V[\x90P\x80\x83\x82R` \x82\x01\x90P` \x84\x02\x83\x01\x85\x81\x11\x15a\x03]Wa\x03\\a\x02\xCAV[[\x83[\x81\x81\x10\x15a\x03\x86W\x80a\x03r\x88\x82a\x03\x14V[\x84R` \x84\x01\x93PP` \x81\x01\x90Pa\x03_V[PPP\x93\x92PPPV[_\x82`\x1F\x83\x01\x12a\x03\xA4Wa\x03\xA3a\x02\x9BV[[\x81Qa\x03\xB4\x84\x82` \x86\x01a\x03(V[\x91PP\x92\x91PPV[__`@\x83\x85\x03\x12\x15a\x03\xD3Wa\x03\xD2a\x01\x97V[[_a\x03\xE0\x85\x82\x86\x01a\x02bV[\x92PP` \x83\x01Qg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x04\x01Wa\x04\0a\x01\x9BV[[a\x04\r\x85\x82\x86\x01a\x03\x90V[\x91PP\x92P\x92\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`2`\x04R`$_\xFD[_\x81\x90P\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`\x11`\x04R`$_\xFD[_a\x04\x84\x82a\x04DV[\x91Pa\x04\x8F\x83a\x04DV[\x92P\x82\x82\x03\x90P\x81\x81\x11\x15a\x04\xA7Wa\x04\xA6a\x04MV[[\x92\x91PPV[a8U\x80a\x04\xBA_9_\xF3\xFE`\x80`@R4\x80\x15a\0\x0FW__\xFD[P`\x046\x10a\0\xA7W_5`\xE0\x1C\x80c\xAD6\xE6\xD0\x11a\0oW\x80c\xAD6\xE6\xD0\x14a\x01'W\x80c\xC10\x80\x9A\x14a\x011W\x80c\xCD\xBF\xC6-\x14a\x01;W\x80c\xDD?\xD2i\x14a\x01WW\x80c\xF0\x19\xB1T\x14a\x01sW\x80c\xF2\xFD\xE3\x8B\x14a\x01\x8FWa\0\xA7V[\x80c0H\xBF\xBA\x14a\0\xABW\x80cU\xA4}\n\x14a\0\xB5W\x80cepo\x9C\x14a\0\xD1W\x80cuA\x8B\x9D\x14a\0\xEDW\x80c\x8BRR\xD6\x14a\x01\x0BW[__\xFD[a\0\xB3a\x01\xABV[\0[a\0\xCF`\x04\x806\x03\x81\x01\x90a\0\xCA\x91\x90a%\x1FV[a\x03\x7FV[\0[a\0\xEB`\x04\x806\x03\x81\x01\x90a\0\xE6\x91\x90a%\x7FV[a\x06\xBDV[\0[a\0\xF5a\x07aV[`@Qa\x01\x02\x91\x90a(\xBCV[`@Q\x80\x91\x03\x90\xF3[a\x01%`\x04\x806\x03\x81\x01\x90a\x01 \x91\x90a)=V[a\x0F\x8FV[\0[a\x01/a\x0F\xECV[\0[a\x019a\x11\xC6V[\0[a\x01U`\x04\x806\x03\x81\x01\x90a\x01P\x91\x90a)\xA6V[a\x13\xC9V[\0[a\x01q`\x04\x806\x03\x81\x01\x90a\x01l\x91\x90a)\xEDV[a\x1A\x99V[\0[a\x01\x8D`\x04\x806\x03\x81\x01\x90a\x01\x88\x91\x90a*\x18V[a\x1D\x15V[\0[a\x01\xA9`\x04\x806\x03\x81\x01\x90a\x01\xA4\x91\x90a*\x9FV[a \xABV[\0[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x029W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x020\x90a+$V[`@Q\x80\x91\x03\x90\xFD[a\x02Aa!{V[a\x02\x80W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x02w\x90a+\x8CV[`@Q\x80\x91\x03\x90\xFD[_a\x02\n_\x01_a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x02\xF1\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\x8F\xB9\xCD\x05M\n\x02!\x10\xCC\xED#\x9E\x90\x8B\x83NL\xD2\x19Q\x18V\xD4\xEA\xAE0Q\xD92\xD6\x04a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x03u\x91\x90a,\x1DV[`@Q\x80\x91\x03\x90\xA1V[a\x03\x87a!\xD5V[a\x03\xC6W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x03\xBD\x90a,\x80V[`@Q\x80\x91\x03\x90\xFD[a\x02\x08_\x01_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x82g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x044W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x04+\x90a,\xE8V[`@Q\x80\x91\x03\x90\xFD[3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x80a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x04o\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x81\x10a\x04\x8AWa\x04\x89a-cV[[a\x01\x02\x02\x01_\x01\x82`\xFF\x16a\x01\0\x81\x10a\x04\xA7Wa\x04\xA6a-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x05\x1EW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x05\x15\x90a-\xDAV[`@Q\x80\x91\x03\x90\xFD[a\x057\x81a\x02\x08`\x01\x01Ta!\xE5\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x06\xB9Wa\x05T\x81a\x02\x08`\x01\x01Ta!\xFA\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x02\x08`\x01\x01\x81\x90UPa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x05\x8C\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP_a\x02\x08`\x01\x01T\x03a\x06FW\x7F\x01&\x98yS_@\xEE\x89W\xE1^\x16\x0B\xF1\x86l^'(\xFF\x0C\xBCX=\x84\x88!\xE2c\x9BNa\x02\x08_\x01_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x069\x93\x92\x91\x90a.\x16V[`@Q\x80\x91\x03\x90\xA1a\x06\xB8V[\x7F\xAF^\x90\xE7 \x15\xF418\xF6kL\xD0\x8B\xD1\xDF\xA2\x83\x900\x10O\"\xA0\n\xF8C\xFE\x84|m\x19a\x02\x08_\x01_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x06\xAF\x93\x92\x91\x90a.\x16V[`@Q\x80\x91\x03\x90\xA1[[PPV[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x07KW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x07B\x90a+$V[`@Q\x80\x91\x03\x90\xFD[\x80a\x02\x07\x81\x81a\x07[\x91\x90a/*V[\x90PPPV[a\x07ia#\xA7V[a\x07qa#\xA7V[___a\x07|a!\xD5V[\x15a\x0B\xB9Wa\x02\x08_\x01_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x84``\x01Q_\x01\x90g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RPPa\x02\x08`\x01\x01T\x84``\x01Q` \x01\x81\x81RPP`\x02`\x01a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x07\xF5\x91\x90a/8V[a\x07\xFF\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x92P_`\x02a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x08/\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90Pa\x08a`\x02\x82`\x02\x81\x10a\x08RWa\x08Qa-cV[[a\x01\x02\x02\x01a\x01\0\x01Ta\"\x0EV[\x91P`\x01\x82a\x08p\x91\x90a/sV[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x08\x89Wa\x08\x88a/\xA6V[[`@Q\x90\x80\x82R\x80` \x02` \x01\x82\x01`@R\x80\x15a\x08\xC2W\x81` \x01[a\x08\xAFa$\x0FV[\x81R` \x01\x90`\x01\x90\x03\x90\x81a\x08\xA7W\x90P[P\x85` \x01Q_\x01\x81\x90RP`\x02\x81`\x02\x81\x10a\x08\xE2Wa\x08\xE1a-cV[[a\x01\x02\x02\x01a\x01\x01\x01_\x90T\x90a\x01\0\n\x90\x04`\xFF\x16\x85` \x01Q` \x01\x90`\xFF\x16\x90\x81`\xFF\x16\x81RPP__\x90P[\x82\x81\x11a\x0B\xB2Wa\tI\x81`\x02\x84`\x02\x81\x10a\t1Wa\t0a-cV[[a\x01\x02\x02\x01a\x01\0\x01Ta!\xE5\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x0B\x9FW`\x02\x82`\x02\x81\x10a\taWa\t`a-cV[[a\x01\x02\x02\x01_\x01\x81a\x01\0\x81\x10a\t{Wa\tza-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x93P\x83\x86` \x01Q_\x01Q\x82\x81Q\x81\x10a\t\xB9Wa\t\xB8a-cV[[` \x02` \x01\x01Q_\x01\x90s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RPPa\n&\x81`\x02\x87`\x02\x81\x10a\n\x0EWa\n\ra-cV[[a\x01\x02\x02\x01a\x01\0\x01Ta!\xE5\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x80a\n\xABWP\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x86`\x02\x81\x10a\nWWa\nVa-cV[[a\x01\x02\x02\x01_\x01\x82a\x01\0\x81\x10a\nqWa\npa-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14\x15[\x15a\x0B\x9EW`\x01_\x85s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ \x80Ta\n\xF8\x90a0\0V[\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01\x82\x80Ta\x0B$\x90a0\0V[\x80\x15a\x0BoW\x80`\x1F\x10a\x0BFWa\x01\0\x80\x83T\x04\x02\x83R\x91` \x01\x91a\x0BoV[\x82\x01\x91\x90_R` _ \x90[\x81T\x81R\x90`\x01\x01\x90` \x01\x80\x83\x11a\x0BRW\x82\x90\x03`\x1F\x16\x82\x01\x91[PPPPP\x86` \x01Q_\x01Q\x82\x81Q\x81\x10a\x0B\x8EWa\x0B\x8Da-cV[[` \x02` \x01\x01Q` \x01\x81\x90RP[[\x80\x80a\x0B\xAA\x90a00V[\x91PPa\t\x12V[PPa\x0B\xE9V[`\x02a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x0B\xDC\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x92P[a\x0C\x0F`\x02\x84`\x02\x81\x10a\x0C\0Wa\x0B\xFFa-cV[[a\x01\x02\x02\x01a\x01\0\x01Ta\"\x0EV[\x90P`\x01\x81a\x0C\x1E\x91\x90a/sV[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x0C7Wa\x0C6a/\xA6V[[`@Q\x90\x80\x82R\x80` \x02` \x01\x82\x01`@R\x80\x15a\x0CpW\x81` \x01[a\x0C]a$\x0FV[\x81R` \x01\x90`\x01\x90\x03\x90\x81a\x0CUW\x90P[P\x84_\x01Q_\x01\x81\x90RP`\x02\x83`\x02\x81\x10a\x0C\x8FWa\x0C\x8Ea-cV[[a\x01\x02\x02\x01a\x01\x01\x01_\x90T\x90a\x01\0\n\x90\x04`\xFF\x16\x84_\x01Q` \x01\x90`\xFF\x16\x90\x81`\xFF\x16\x81RPP__\x90P[\x81\x81\x11a\x0E\xA1Wa\x0C\xF5\x81`\x02\x86`\x02\x81\x10a\x0C\xDDWa\x0C\xDCa-cV[[a\x01\x02\x02\x01a\x01\0\x01Ta!\xE5\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x0E\x8EW`\x02\x84`\x02\x81\x10a\r\rWa\r\x0Ca-cV[[a\x01\x02\x02\x01_\x01\x81a\x01\0\x81\x10a\r'Wa\r&a-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x92P\x82\x85_\x01Q_\x01Q\x82\x81Q\x81\x10a\rdWa\rca-cV[[` \x02` \x01\x01Q_\x01\x90s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RPP`\x01_\x84s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ \x80Ta\r\xE9\x90a0\0V[\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01\x82\x80Ta\x0E\x15\x90a0\0V[\x80\x15a\x0E`W\x80`\x1F\x10a\x0E7Wa\x01\0\x80\x83T\x04\x02\x83R\x91` \x01\x91a\x0E`V[\x82\x01\x91\x90_R` _ \x90[\x81T\x81R\x90`\x01\x01\x90` \x01\x80\x83\x11a\x0ECW\x82\x90\x03`\x1F\x16\x82\x01\x91[PPPPP\x85_\x01Q_\x01Q\x82\x81Q\x81\x10a\x0E~Wa\x0E}a-cV[[` \x02` \x01\x01Q` \x01\x81\x90RP[\x80\x80a\x0E\x99\x90a00V[\x91PPa\x0C\xBEV[Pa\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x84`@\x01\x90g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RPPa\x02\n_\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x84`\x80\x01Q_\x01\x90s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RPPa\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x84`\xA0\x01\x90o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RPP\x83\x94PPPPP\x90V[a\x0F\x9B\x82\x82\x90Pa\"\x1FV[\x81\x81`\x01_3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ \x91\x82a\x0F\xE7\x92\x91\x90a2\x18V[PPPV[a\x0F\xF4a!{V[a\x103W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x10*\x90a+\x8CV[`@Q\x80\x91\x03\x90\xFD[3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x02\n_\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x10\xC5W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x10\xBC\x90a-\xDAV[`@Q\x80\x91\x03\x90\xFD[_a\x02\n_\x01_a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x116\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\xF9\x10g\xEBB\x0C(\xD3\x12He\xFC\x99nj\xA9\xD5A\xB9\xB4\xFE\xF9\x18\x8C\xB9e\xA6\xCCd\x91c\x8E3a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x11\xBC\x92\x91\x90a2\xE5V[`@Q\x80\x91\x03\x90\xA1V[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x12TW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x12K\x90a+$V[`@Q\x80\x91\x03\x90\xFD[a\x12\\a!\xD5V[a\x12\x9BW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x12\x92\x90a,\x80V[`@Q\x80\x91\x03\x90\xFD[a\x02\x06_\x81\x81\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x12\xC1\x90a3\x0CV[\x91\x90a\x01\0\n\x81T\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP_a\x02\x08`\x01\x01\x81\x90UPa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x13!\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\xF72@B\"F\xF6>\xD63\xEF<\xE0rk\x8A\xB8\xFBi\xD4l\x8AN^\xCB\x0B)\"f\x86t\xA1a\x02\x08_\x01_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x13\xBF\x92\x91\x90a33V[`@Q\x80\x91\x03\x90\xA1V[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x14WW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x14N\x90a+$V[`@Q\x80\x91\x03\x90\xFD[a\x14_a!\xD5V[\x15a\x14\x9FW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x14\x96\x90a3\xA4V[`@Q\x80\x91\x03\x90\xFD[a\x14\xA7a!{V[\x15a\x14\xE7W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x14\xDE\x90a4\x0CV[`@Q\x80\x91\x03\x90\xFD[a\x02\x08_\x01_\x81\x81\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x15\x0F\x90a4*V[\x91\x90a\x01\0\n\x81T\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP_`\x02a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x15Z\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90Pa\x02\x06_\x81\x81\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x15\x8C\x90a4*V[\x91\x90a\x01\0\n\x81T\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP_`\x02a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x15\xD7\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90P__\x90P[a\x16\x0E`\x02\x84`\x02\x81\x10a\x15\xFFWa\x15\xFEa-cV[[a\x01\x02\x02\x01a\x01\0\x01Ta\"\x0EV[\x81\x11a\x17\xB2W`\x02\x83`\x02\x81\x10a\x16(Wa\x16'a-cV[[a\x01\x02\x02\x01_\x01\x81a\x01\0\x81\x10a\x16BWa\x16Aa-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x83`\x02\x81\x10a\x16\x8DWa\x16\x8Ca-cV[[a\x01\x02\x02\x01_\x01\x82a\x01\0\x81\x10a\x16\xA7Wa\x16\xA6a-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x17\x9FW`\x02\x83`\x02\x81\x10a\x16\xF7Wa\x16\xF6a-cV[[a\x01\x02\x02\x01_\x01\x81a\x01\0\x81\x10a\x17\x11Wa\x17\x10a-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x83`\x02\x81\x10a\x17FWa\x17Ea-cV[[a\x01\x02\x02\x01_\x01\x82a\x01\0\x81\x10a\x17`Wa\x17_a-cV[[\x01_a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UP[\x80\x80a\x17\xAA\x90a00V[\x91PPa\x15\xE8V[P_`\x02\x83`\x02\x81\x10a\x17\xC8Wa\x17\xC7a-cV[[a\x01\x02\x02\x01a\x01\0\x01T\x90P____\x90P[\x86\x80_\x01\x90a\x17\xEA\x91\x90a4eV[\x90P\x81\x10\x15a\x19FW\x86\x80_\x01\x90a\x18\x02\x91\x90a4eV[\x82\x81\x81\x10a\x18\x13Wa\x18\x12a-cV[[\x90P`@\x02\x01_\x01` \x81\x01\x90a\x18*\x91\x90a)\xEDV[\x92P\x86\x80_\x01\x90a\x18;\x91\x90a4eV[\x82\x81\x81\x10a\x18LWa\x18Ka-cV[[\x90P`@\x02\x01` \x01` \x81\x01\x90a\x18d\x91\x90a*\x9FV[\x91P_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x82s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x03a\x18\xB3Wa\x18\xAC\x83\x85a!\xFA\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x93Pa\x18\xC9V[a\x18\xC6\x83\x85a\"\xBD\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x93P[\x81`\x02\x86`\x02\x81\x10a\x18\xDEWa\x18\xDDa-cV[[a\x01\x02\x02\x01_\x01\x84`\xFF\x16a\x01\0\x81\x10a\x18\xFBWa\x18\xFAa-cV[[\x01_a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UP\x80\x80`\x01\x01\x91PPa\x17\xDBV[P\x82`\x02\x85`\x02\x81\x10a\x19\\Wa\x19[a-cV[[a\x01\x02\x02\x01a\x01\0\x01\x81\x90UP\x85` \x01` \x81\x01\x90a\x19|\x91\x90a)\xEDV[`\x02\x85`\x02\x81\x10a\x19\x90Wa\x19\x8Fa-cV[[a\x01\x02\x02\x01a\x01\x01\x01_a\x01\0\n\x81T\x81`\xFF\x02\x19\x16\x90\x83`\xFF\x16\x02\x17\x90UP\x82a\x02\x08`\x01\x01\x81\x90UPa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x19\xE9\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7Fx\xDA\xD2\xBC\x0BG\xC6\x88\xED\x84\xF3\xFE\xE7\x9A\xBC\x18\xE6\xC9\x82-\xB0Zy\xCA\x19\xDF\xF5E3\xC7G\ra\x02\x08_\x01_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x87a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x1A\x89\x93\x92\x91\x90a6\x8BV[`@Q\x80\x91\x03\x90\xA1PPPPPPV[a\x1A\xA1a!\xD5V[\x15a\x1A\xE1W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x1A\xD8\x90a3\xA4V[`@Q\x80\x91\x03\x90\xFD[a\x1A\xE9a!{V[\x15a\x1B)W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x1B \x90a4\x0CV[`@Q\x80\x91\x03\x90\xFD[3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x80a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x1Bd\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x81\x10a\x1B\x7FWa\x1B~a-cV[[a\x01\x02\x02\x01_\x01\x82`\xFF\x16a\x01\0\x81\x10a\x1B\x9CWa\x1B\x9Ba-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x1C\x13W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x1C\n\x90a-\xDAV[`@Q\x80\x91\x03\x90\xFD[3a\x02\n_\x01_a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x1C\x84\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\xBC'H\xCF\x02\xF7\xA1)\x15%\xE8f\xEF\xC7j\xB3\xB9m2\xD7\xAF\xCB\xB2lS\xDA\xECa{8\xB4y3a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x1D\n\x92\x91\x90a2\xE5V[`@Q\x80\x91\x03\x90\xA1PV[a\x1D!\x82\x82\x90Pa\"\x1FV[__a\x1D+a!\xD5V[\x15a\x1E\xA1W3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x80`\x01a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x1Dm\x91\x90a/8V[a\x1Dw\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x81\x10a\x1D\x92Wa\x1D\x91a-cV[[a\x01\x02\x02\x01_\x01\x86`\xFF\x16a\x01\0\x81\x10a\x1D\xAFWa\x1D\xAEa-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14\x91P\x81a\x1E\x9CW3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x80a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x1E)\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x81\x10a\x1EDWa\x1ECa-cV[[a\x01\x02\x02\x01_\x01\x86`\xFF\x16a\x01\0\x81\x10a\x1EaWa\x1E`a-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14\x90P[a\x1FOV[3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x80a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x1E\xDC\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x81\x10a\x1E\xF7Wa\x1E\xF6a-cV[[a\x01\x02\x02\x01_\x01\x86`\xFF\x16a\x01\0\x81\x10a\x1F\x14Wa\x1F\x13a-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14\x91P[\x81\x80a\x1FXWP\x80[a\x1F\x97W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x1F\x8E\x90a-\xDAV[`@Q\x80\x91\x03\x90\xFD[\x83\x83`\x01_3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ \x91\x82a\x1F\xE3\x92\x91\x90a2\x18V[Pa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a \x12\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\x12Q\x81\xEC!\x88-\xECQ\xA29)\x05\xDF\xF3\xA8,\xBD\x02b\xF1\x8B\\\x0C\x03T\x88g\x1B@\xAF\xB23\x85\x85a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa \x9C\x94\x93\x92\x91\x90a7\x11V[`@Q\x80\x91\x03\x90\xA1PPPPPV[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a!9W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a!0\x90a+$V[`@Q\x80\x91\x03\x90\xFD[\x80__a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPPV[__s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x02\n_\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14\x15\x90P\x90V[__a\x02\x08`\x01\x01T\x14\x15\x90P\x90V[__\x82`\xFF\x16`\x01\x90\x1B\x84\x16\x14\x90P\x92\x91PPV[_\x81`\xFF\x16`\x01\x90\x1B\x19\x83\x16\x90P\x92\x91PPV[_a\"\x18\x82a\"\xD0V[\x90P\x91\x90PV[_\x81\x11a\"aW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\"X\x90a7\x99V[`@Q\x80\x91\x03\x90\xFD[a\x02\x07_\x01_\x90T\x90a\x01\0\n\x90\x04a\xFF\xFF\x16a\xFF\xFF\x16\x81\x11\x15a\"\xBAW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\"\xB1\x90a8\x01V[`@Q\x80\x91\x03\x90\xFD[PV[_\x81`\xFF\x16`\x01\x90\x1B\x83\x17\x90P\x92\x91PPV[_`\x07a\"\xEEo\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x84\x11a#\x9CV[\x90\x1B\x90P`\x06a#\ng\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x83\x85\x90\x1C\x11a#\x9CV[\x90\x1B\x81\x17\x90P`\x05a#$c\xFF\xFF\xFF\xFF\x83\x85\x90\x1C\x11a#\x9CV[\x90\x1B\x81\x17\x90P`\x04a#V[\x81R` \x01a#\xC7a$>V[\x81R` \x01_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01a#\xE4a$ZV[\x81R` \x01a#\xF1a$|V[\x81R` \x01_o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RP\x90V[`@Q\x80`@\x01`@R\x80_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01``\x81RP\x90V[`@Q\x80`@\x01`@R\x80``\x81R` \x01_`\xFF\x16\x81RP\x90V[`@Q\x80`@\x01`@R\x80_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01_\x81RP\x90V[`@Q\x80` \x01`@R\x80_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RP\x90V[__\xFD[__\xFD[_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[a$\xC8\x81a$\xACV[\x81\x14a$\xD2W__\xFD[PV[_\x815\x90Pa$\xE3\x81a$\xBFV[\x92\x91PPV[_`\xFF\x82\x16\x90P\x91\x90PV[a$\xFE\x81a$\xE9V[\x81\x14a%\x08W__\xFD[PV[_\x815\x90Pa%\x19\x81a$\xF5V[\x92\x91PPV[__`@\x83\x85\x03\x12\x15a%5Wa%4a$\xA4V[[_a%B\x85\x82\x86\x01a$\xD5V[\x92PP` a%S\x85\x82\x86\x01a%\x0BV[\x91PP\x92P\x92\x90PV[__\xFD[_` \x82\x84\x03\x12\x15a%vWa%ua%]V[[\x81\x90P\x92\x91PPV[_` \x82\x84\x03\x12\x15a%\x94Wa%\x93a$\xA4V[[_a%\xA1\x84\x82\x85\x01a%aV[\x91PP\x92\x91PPV[_\x81Q\x90P\x91\x90PV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[_\x81\x90P` \x82\x01\x90P\x91\x90PV[_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[_a%\xFC\x82a%\xD3V[\x90P\x91\x90PV[a&\x0C\x81a%\xF2V[\x82RPPV[_\x81Q\x90P\x91\x90PV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[\x82\x81\x83^_\x83\x83\x01RPPPV[_`\x1F\x19`\x1F\x83\x01\x16\x90P\x91\x90PV[_a&T\x82a&\x12V[a&^\x81\x85a&\x1CV[\x93Pa&n\x81\x85` \x86\x01a&,V[a&w\x81a&:V[\x84\x01\x91PP\x92\x91PPV[_`@\x83\x01_\x83\x01Qa&\x97_\x86\x01\x82a&\x03V[P` \x83\x01Q\x84\x82\x03` \x86\x01Ra&\xAF\x82\x82a&JV[\x91PP\x80\x91PP\x92\x91PPV[_a&\xC7\x83\x83a&\x82V[\x90P\x92\x91PPV[_` \x82\x01\x90P\x91\x90PV[_a&\xE5\x82a%\xAAV[a&\xEF\x81\x85a%\xB4V[\x93P\x83` \x82\x02\x85\x01a'\x01\x85a%\xC4V[\x80_[\x85\x81\x10\x15a'\x82a1 V[\x84\x84Ta0\xAEV[\x82UPPPPV[__\x90P\x90V[a1]a1NV[a1h\x81\x84\x84a1)V[PPPV[[\x81\x81\x10\x15a1\x8BWa1\x80_\x82a1UV[`\x01\x81\x01\x90Pa1nV[PPV[`\x1F\x82\x11\x15a1\xD0Wa1\xA1\x81a0\x81V[a1\xAA\x84a0\x93V[\x81\x01` \x85\x10\x15a1\xB9W\x81\x90P[a1\xCDa1\xC5\x85a0\x93V[\x83\x01\x82a1mV[PP[PPPV[_\x82\x82\x1C\x90P\x92\x91PPV[_a1\xF0_\x19\x84`\x08\x02a1\xD5V[\x19\x80\x83\x16\x91PP\x92\x91PPV[_a2\x08\x83\x83a1\xE1V[\x91P\x82`\x02\x02\x82\x17\x90P\x92\x91PPV[a2\"\x83\x83a0wV[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a2;Wa2:a/\xA6V[[a2E\x82Ta0\0V[a2P\x82\x82\x85a1\x8FV[_`\x1F\x83\x11`\x01\x81\x14a2}W_\x84\x15a2kW\x82\x87\x015\x90P[a2u\x85\x82a1\xFDV[\x86UPa2\xDCV[`\x1F\x19\x84\x16a2\x8B\x86a0\x81V[_[\x82\x81\x10\x15a2\xB2W\x84\x89\x015\x82U`\x01\x82\x01\x91P` \x85\x01\x94P` \x81\x01\x90Pa2\x8DV[\x86\x83\x10\x15a2\xCFW\x84\x89\x015a2\xCB`\x1F\x89\x16\x82a1\xE1V[\x83UP[`\x01`\x02\x88\x02\x01\x88UPPP[PPPPPPPV[_`@\x82\x01\x90Pa2\xF8_\x83\x01\x85a.\x07V[a3\x05` \x83\x01\x84a,\x0EV[\x93\x92PPPV[_a3\x16\x82a$\xACV[\x91P_\x82\x03a3(Wa3'a+\xAAV[[`\x01\x82\x03\x90P\x91\x90PV[_`@\x82\x01\x90Pa3F_\x83\x01\x85a-\xF8V[a3S` \x83\x01\x84a,\x0EV[\x93\x92PPPV[\x7Fmigration in progress\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a3\x8E`\x15\x83a*\xCAV[\x91Pa3\x99\x82a3ZV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra3\xBB\x81a3\x82V[\x90P\x91\x90PV[\x7Fmaintenance in progress\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a3\xF6`\x17\x83a*\xCAV[\x91Pa4\x01\x82a3\xC2V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra4#\x81a3\xEAV[\x90P\x91\x90PV[_a44\x82a$\xACV[\x91Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x03a4NWa4Ma+\xAAV[[`\x01\x82\x01\x90P\x91\x90PV[__\xFD[__\xFD[__\xFD[__\x835`\x01` \x03\x846\x03\x03\x81\x12a4\x81Wa4\x80a4YV[[\x80\x84\x01\x92P\x825\x91Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15a4\xA3Wa4\xA2a4]V[[` \x83\x01\x92P`@\x82\x026\x03\x83\x13\x15a4\xBFWa4\xBEa4aV[[P\x92P\x92\x90PV[__\xFD[__\xFD[__\xFD[__\x835`\x01` \x03\x846\x03\x03\x81\x12a4\xEFWa4\xEEa4\xCFV[[\x83\x81\x01\x92P\x825\x91P` \x83\x01\x92Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15a5\x17Wa5\x16a4\xC7V[[`@\x82\x026\x03\x83\x13\x15a5-Wa5,a4\xCBV[[P\x92P\x92\x90PV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[_\x81\x90P\x91\x90PV[_a5\\` \x84\x01\x84a%\x0BV[\x90P\x92\x91PPV[_a5r` \x84\x01\x84a*\x8BV[\x90P\x92\x91PPV[`@\x82\x01a5\x8A_\x83\x01\x83a5NV[a5\x96_\x85\x01\x82a'NV[Pa5\xA4` \x83\x01\x83a5dV[a5\xB1` \x85\x01\x82a&\x03V[PPPPV[_a5\xC2\x83\x83a5zV[`@\x83\x01\x90P\x92\x91PPV[_\x82\x90P\x92\x91PPV[_`@\x82\x01\x90P\x91\x90PV[_a5\xEF\x83\x85a55V[\x93Pa5\xFA\x82a5EV[\x80_[\x85\x81\x10\x15a62Wa6\x0F\x82\x84a5\xCEV[a6\x19\x88\x82a5\xB7V[\x97Pa6$\x83a5\xD8V[\x92PP`\x01\x81\x01\x90Pa5\xFDV[P\x85\x92PPP\x93\x92PPPV[_`@\x83\x01a6P_\x84\x01\x84a4\xD3V[\x85\x83\x03_\x87\x01Ra6b\x83\x82\x84a5\xE4V[\x92PPPa6s` \x84\x01\x84a5NV[a6\x80` \x86\x01\x82a'NV[P\x80\x91PP\x92\x91PPV[_``\x82\x01\x90Pa6\x9E_\x83\x01\x86a-\xF8V[\x81\x81\x03` \x83\x01Ra6\xB0\x81\x85a6?V[\x90Pa6\xBF`@\x83\x01\x84a,\x0EV[\x94\x93PPPPV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[\x82\x81\x837_\x83\x83\x01RPPPV[_a6\xF0\x83\x85a6\xC7V[\x93Pa6\xFD\x83\x85\x84a6\xD7V[a7\x06\x83a&:V[\x84\x01\x90P\x93\x92PPPV[_``\x82\x01\x90Pa7$_\x83\x01\x87a.\x07V[\x81\x81\x03` \x83\x01Ra77\x81\x85\x87a6\xE5V[\x90Pa7F`@\x83\x01\x84a,\x0EV[\x95\x94PPPPPV[\x7Fempty operator data\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a7\x83`\x13\x83a*\xCAV[\x91Pa7\x8E\x82a7OV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra7\xB0\x81a7wV[\x90P\x91\x90PV[\x7Foperator data too large\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a7\xEB`\x17\x83a*\xCAV[\x91Pa7\xF6\x82a7\xB7V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra8\x18\x81a7\xDFV[\x90P\x91\x90PV\xFE\xA2dipfsX\"\x12 Pp\xBF\xB7\x8C\xBAO\xB2\x04\xCE:\x9A\xE2K_q\x0Cbs!v6^\xE88\x9C\xDA\xB1\x8C<-qdsolcC\0\x08\x1C\x003", + b"`\x80`@R4\x80\x15a\0\x0FW__\xFD[P`@Qa=\x0F8\x03\x80a=\x0F\x839\x81\x81\x01`@R\x81\x01\x90a\x001\x91\x90a\x03\xBDV[3__a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UP\x81a\x02\x07_\x82\x01Q\x81_\x01_a\x01\0\n\x81T\x81a\xFF\xFF\x02\x19\x16\x90\x83a\xFF\xFF\x16\x02\x17\x90UP\x90PP__\x90P[\x81Q\x81\x10\x15a\x019W\x81\x81\x81Q\x81\x10a\0\xB8Wa\0\xB7a\x04\x17V[[` \x02` \x01\x01Q`\x02_`\x02\x81\x10a\0\xD4Wa\0\xD3a\x04\x17V[[a\x01\x02\x02\x01_\x01\x82a\x01\0\x81\x10a\0\xEEWa\0\xEDa\x04\x17V[[\x01_a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UP\x80\x80`\x01\x01\x91PPa\0\x9CV[Pa\x01J\x81Qa\x01r` \x1B` \x1CV[`\x02_`\x02\x81\x10a\x01^Wa\x01]a\x04\x17V[[a\x01\x02\x02\x01a\x01\0\x01\x81\x90UPPPa\x04\xADV[_`\x01\x82`\xFF\x16`\x01\x90\x1Ba\x01\x87\x91\x90a\x04zV[\x90P\x91\x90PV[_`@Q\x90P\x90V[__\xFD[__\xFD[__\xFD[_`\x1F\x19`\x1F\x83\x01\x16\x90P\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`A`\x04R`$_\xFD[a\x01\xE9\x82a\x01\xA3V[\x81\x01\x81\x81\x10g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x17\x15a\x02\x08Wa\x02\x07a\x01\xB3V[[\x80`@RPPPV[_a\x02\x1Aa\x01\x8EV[\x90Pa\x02&\x82\x82a\x01\xE0V[\x91\x90PV[_a\xFF\xFF\x82\x16\x90P\x91\x90PV[a\x02A\x81a\x02+V[\x81\x14a\x02KW__\xFD[PV[_\x81Q\x90Pa\x02\\\x81a\x028V[\x92\x91PPV[_` \x82\x84\x03\x12\x15a\x02wWa\x02va\x01\x9FV[[a\x02\x81` a\x02\x11V[\x90P_a\x02\x90\x84\x82\x85\x01a\x02NV[_\x83\x01RP\x92\x91PPV[__\xFD[_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15a\x02\xB9Wa\x02\xB8a\x01\xB3V[[` \x82\x02\x90P` \x81\x01\x90P\x91\x90PV[__\xFD[_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[_a\x02\xF7\x82a\x02\xCEV[\x90P\x91\x90PV[a\x03\x07\x81a\x02\xEDV[\x81\x14a\x03\x11W__\xFD[PV[_\x81Q\x90Pa\x03\"\x81a\x02\xFEV[\x92\x91PPV[_a\x03:a\x035\x84a\x02\x9FV[a\x02\x11V[\x90P\x80\x83\x82R` \x82\x01\x90P` \x84\x02\x83\x01\x85\x81\x11\x15a\x03]Wa\x03\\a\x02\xCAV[[\x83[\x81\x81\x10\x15a\x03\x86W\x80a\x03r\x88\x82a\x03\x14V[\x84R` \x84\x01\x93PP` \x81\x01\x90Pa\x03_V[PPP\x93\x92PPPV[_\x82`\x1F\x83\x01\x12a\x03\xA4Wa\x03\xA3a\x02\x9BV[[\x81Qa\x03\xB4\x84\x82` \x86\x01a\x03(V[\x91PP\x92\x91PPV[__`@\x83\x85\x03\x12\x15a\x03\xD3Wa\x03\xD2a\x01\x97V[[_a\x03\xE0\x85\x82\x86\x01a\x02bV[\x92PP` \x83\x01Qg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x04\x01Wa\x04\0a\x01\x9BV[[a\x04\r\x85\x82\x86\x01a\x03\x90V[\x91PP\x92P\x92\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`2`\x04R`$_\xFD[_\x81\x90P\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`\x11`\x04R`$_\xFD[_a\x04\x84\x82a\x04DV[\x91Pa\x04\x8F\x83a\x04DV[\x92P\x82\x82\x03\x90P\x81\x81\x11\x15a\x04\xA7Wa\x04\xA6a\x04MV[[\x92\x91PPV[a8U\x80a\x04\xBA_9_\xF3\xFE`\x80`@R4\x80\x15a\0\x0FW__\xFD[P`\x046\x10a\0\xA7W_5`\xE0\x1C\x80c\xAD6\xE6\xD0\x11a\0oW\x80c\xAD6\xE6\xD0\x14a\x01'W\x80c\xC10\x80\x9A\x14a\x011W\x80c\xCD\xBF\xC6-\x14a\x01;W\x80c\xDD?\xD2i\x14a\x01WW\x80c\xF0\x19\xB1T\x14a\x01sW\x80c\xF2\xFD\xE3\x8B\x14a\x01\x8FWa\0\xA7V[\x80c0H\xBF\xBA\x14a\0\xABW\x80cU\xA4}\n\x14a\0\xB5W\x80cepo\x9C\x14a\0\xD1W\x80cuA\x8B\x9D\x14a\0\xEDW\x80c\x8BRR\xD6\x14a\x01\x0BW[__\xFD[a\0\xB3a\x01\xABV[\0[a\0\xCF`\x04\x806\x03\x81\x01\x90a\0\xCA\x91\x90a%\x1FV[a\x03\x7FV[\0[a\0\xEB`\x04\x806\x03\x81\x01\x90a\0\xE6\x91\x90a%\x7FV[a\x06\xBDV[\0[a\0\xF5a\x07aV[`@Qa\x01\x02\x91\x90a(\xBCV[`@Q\x80\x91\x03\x90\xF3[a\x01%`\x04\x806\x03\x81\x01\x90a\x01 \x91\x90a)=V[a\x0F\x8FV[\0[a\x01/a\x0F\xECV[\0[a\x019a\x11\xC6V[\0[a\x01U`\x04\x806\x03\x81\x01\x90a\x01P\x91\x90a)\xA6V[a\x13\xC9V[\0[a\x01q`\x04\x806\x03\x81\x01\x90a\x01l\x91\x90a)\xEDV[a\x1A\x99V[\0[a\x01\x8D`\x04\x806\x03\x81\x01\x90a\x01\x88\x91\x90a*\x18V[a\x1D\x15V[\0[a\x01\xA9`\x04\x806\x03\x81\x01\x90a\x01\xA4\x91\x90a*\x9FV[a \xABV[\0[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x029W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x020\x90a+$V[`@Q\x80\x91\x03\x90\xFD[a\x02Aa!{V[a\x02\x80W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x02w\x90a+\x8CV[`@Q\x80\x91\x03\x90\xFD[_a\x02\n_\x01_a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x02\xF1\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\x8F\xB9\xCD\x05M\n\x02!\x10\xCC\xED#\x9E\x90\x8B\x83NL\xD2\x19Q\x18V\xD4\xEA\xAE0Q\xD92\xD6\x04a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x03u\x91\x90a,\x1DV[`@Q\x80\x91\x03\x90\xA1V[a\x03\x87a!\xD5V[a\x03\xC6W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x03\xBD\x90a,\x80V[`@Q\x80\x91\x03\x90\xFD[a\x02\x08_\x01_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x82g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x044W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x04+\x90a,\xE8V[`@Q\x80\x91\x03\x90\xFD[3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x80a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x04o\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x81\x10a\x04\x8AWa\x04\x89a-cV[[a\x01\x02\x02\x01_\x01\x82`\xFF\x16a\x01\0\x81\x10a\x04\xA7Wa\x04\xA6a-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x05\x1EW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x05\x15\x90a-\xDAV[`@Q\x80\x91\x03\x90\xFD[a\x057\x81a\x02\x08`\x01\x01Ta!\xE5\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x06\xB9Wa\x05T\x81a\x02\x08`\x01\x01Ta!\xFA\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x02\x08`\x01\x01\x81\x90UPa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x05\x8C\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP_a\x02\x08`\x01\x01T\x03a\x06FW\x7F\x01&\x98yS_@\xEE\x89W\xE1^\x16\x0B\xF1\x86l^'(\xFF\x0C\xBCX=\x84\x88!\xE2c\x9BNa\x02\x08_\x01_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x069\x93\x92\x91\x90a.\x16V[`@Q\x80\x91\x03\x90\xA1a\x06\xB8V[\x7F\xAF^\x90\xE7 \x15\xF418\xF6kL\xD0\x8B\xD1\xDF\xA2\x83\x900\x10O\"\xA0\n\xF8C\xFE\x84|m\x19a\x02\x08_\x01_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x06\xAF\x93\x92\x91\x90a.\x16V[`@Q\x80\x91\x03\x90\xA1[[PPV[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x07KW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x07B\x90a+$V[`@Q\x80\x91\x03\x90\xFD[\x80a\x02\x07\x81\x81a\x07[\x91\x90a/*V[\x90PPPV[a\x07ia#\xA7V[a\x07qa#\xA7V[___a\x07|a!\xD5V[\x15a\x0B\xB9Wa\x02\x08_\x01_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x84` \x01Q_\x01\x90g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RPPa\x02\x08`\x01\x01T\x84` \x01Q` \x01\x81\x81RPP`\x02`\x01a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x07\xF5\x91\x90a/8V[a\x07\xFF\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x92P_`\x02a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x08/\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90Pa\x08a`\x02\x82`\x02\x81\x10a\x08RWa\x08Qa-cV[[a\x01\x02\x02\x01a\x01\0\x01Ta\"\x0EV[\x91P`\x01\x82a\x08p\x91\x90a/sV[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x08\x89Wa\x08\x88a/\xA6V[[`@Q\x90\x80\x82R\x80` \x02` \x01\x82\x01`@R\x80\x15a\x08\xC2W\x81` \x01[a\x08\xAFa$\x0FV[\x81R` \x01\x90`\x01\x90\x03\x90\x81a\x08\xA7W\x90P[P\x85`@\x01Q_\x01\x81\x90RP`\x02\x81`\x02\x81\x10a\x08\xE2Wa\x08\xE1a-cV[[a\x01\x02\x02\x01a\x01\x01\x01_\x90T\x90a\x01\0\n\x90\x04`\xFF\x16\x85`@\x01Q` \x01\x90`\xFF\x16\x90\x81`\xFF\x16\x81RPP__\x90P[\x82\x81\x11a\x0B\xB2Wa\tI\x81`\x02\x84`\x02\x81\x10a\t1Wa\t0a-cV[[a\x01\x02\x02\x01a\x01\0\x01Ta!\xE5\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x0B\x9FW`\x02\x82`\x02\x81\x10a\taWa\t`a-cV[[a\x01\x02\x02\x01_\x01\x81a\x01\0\x81\x10a\t{Wa\tza-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x93P\x83\x86`@\x01Q_\x01Q\x82\x81Q\x81\x10a\t\xB9Wa\t\xB8a-cV[[` \x02` \x01\x01Q_\x01\x90s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RPPa\n&\x81`\x02\x87`\x02\x81\x10a\n\x0EWa\n\ra-cV[[a\x01\x02\x02\x01a\x01\0\x01Ta!\xE5\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x80a\n\xABWP\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x86`\x02\x81\x10a\nWWa\nVa-cV[[a\x01\x02\x02\x01_\x01\x82a\x01\0\x81\x10a\nqWa\npa-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14\x15[\x15a\x0B\x9EW`\x01_\x85s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ \x80Ta\n\xF8\x90a0\0V[\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01\x82\x80Ta\x0B$\x90a0\0V[\x80\x15a\x0BoW\x80`\x1F\x10a\x0BFWa\x01\0\x80\x83T\x04\x02\x83R\x91` \x01\x91a\x0BoV[\x82\x01\x91\x90_R` _ \x90[\x81T\x81R\x90`\x01\x01\x90` \x01\x80\x83\x11a\x0BRW\x82\x90\x03`\x1F\x16\x82\x01\x91[PPPPP\x86`@\x01Q_\x01Q\x82\x81Q\x81\x10a\x0B\x8EWa\x0B\x8Da-cV[[` \x02` \x01\x01Q` \x01\x81\x90RP[[\x80\x80a\x0B\xAA\x90a00V[\x91PPa\t\x12V[PPa\x0B\xE9V[`\x02a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x0B\xDC\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x92P[a\x0C\x0F`\x02\x84`\x02\x81\x10a\x0C\0Wa\x0B\xFFa-cV[[a\x01\x02\x02\x01a\x01\0\x01Ta\"\x0EV[\x90P`\x01\x81a\x0C\x1E\x91\x90a/sV[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x0C7Wa\x0C6a/\xA6V[[`@Q\x90\x80\x82R\x80` \x02` \x01\x82\x01`@R\x80\x15a\x0CpW\x81` \x01[a\x0C]a$\x0FV[\x81R` \x01\x90`\x01\x90\x03\x90\x81a\x0CUW\x90P[P\x84_\x01Q_\x01\x81\x90RP`\x02\x83`\x02\x81\x10a\x0C\x8FWa\x0C\x8Ea-cV[[a\x01\x02\x02\x01a\x01\x01\x01_\x90T\x90a\x01\0\n\x90\x04`\xFF\x16\x84_\x01Q` \x01\x90`\xFF\x16\x90\x81`\xFF\x16\x81RPP__\x90P[\x81\x81\x11a\x0E\xA1Wa\x0C\xF5\x81`\x02\x86`\x02\x81\x10a\x0C\xDDWa\x0C\xDCa-cV[[a\x01\x02\x02\x01a\x01\0\x01Ta!\xE5\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x0E\x8EW`\x02\x84`\x02\x81\x10a\r\rWa\r\x0Ca-cV[[a\x01\x02\x02\x01_\x01\x81a\x01\0\x81\x10a\r'Wa\r&a-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x92P\x82\x85_\x01Q_\x01Q\x82\x81Q\x81\x10a\rdWa\rca-cV[[` \x02` \x01\x01Q_\x01\x90s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RPP`\x01_\x84s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ \x80Ta\r\xE9\x90a0\0V[\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01\x82\x80Ta\x0E\x15\x90a0\0V[\x80\x15a\x0E`W\x80`\x1F\x10a\x0E7Wa\x01\0\x80\x83T\x04\x02\x83R\x91` \x01\x91a\x0E`V[\x82\x01\x91\x90_R` _ \x90[\x81T\x81R\x90`\x01\x01\x90` \x01\x80\x83\x11a\x0ECW\x82\x90\x03`\x1F\x16\x82\x01\x91[PPPPP\x85_\x01Q_\x01Q\x82\x81Q\x81\x10a\x0E~Wa\x0E}a-cV[[` \x02` \x01\x01Q` \x01\x81\x90RP[\x80\x80a\x0E\x99\x90a00V[\x91PPa\x0C\xBEV[Pa\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x84`\x80\x01\x90g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RPPa\x02\n_\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x84``\x01Q_\x01\x90s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RPPa\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x84`\xA0\x01\x90o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RPP\x83\x94PPPPP\x90V[a\x0F\x9B\x82\x82\x90Pa\"\x1FV[\x81\x81`\x01_3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ \x91\x82a\x0F\xE7\x92\x91\x90a2\x18V[PPPV[a\x0F\xF4a!{V[a\x103W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x10*\x90a+\x8CV[`@Q\x80\x91\x03\x90\xFD[3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x02\n_\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x10\xC5W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x10\xBC\x90a-\xDAV[`@Q\x80\x91\x03\x90\xFD[_a\x02\n_\x01_a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x116\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\xF9\x10g\xEBB\x0C(\xD3\x12He\xFC\x99nj\xA9\xD5A\xB9\xB4\xFE\xF9\x18\x8C\xB9e\xA6\xCCd\x91c\x8E3a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x11\xBC\x92\x91\x90a2\xE5V[`@Q\x80\x91\x03\x90\xA1V[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x12TW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x12K\x90a+$V[`@Q\x80\x91\x03\x90\xFD[a\x12\\a!\xD5V[a\x12\x9BW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x12\x92\x90a,\x80V[`@Q\x80\x91\x03\x90\xFD[a\x02\x06_\x81\x81\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x12\xC1\x90a3\x0CV[\x91\x90a\x01\0\n\x81T\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP_a\x02\x08`\x01\x01\x81\x90UPa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x13!\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\xF72@B\"F\xF6>\xD63\xEF<\xE0rk\x8A\xB8\xFBi\xD4l\x8AN^\xCB\x0B)\"f\x86t\xA1a\x02\x08_\x01_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x13\xBF\x92\x91\x90a33V[`@Q\x80\x91\x03\x90\xA1V[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x14WW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x14N\x90a+$V[`@Q\x80\x91\x03\x90\xFD[a\x14_a!\xD5V[\x15a\x14\x9FW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x14\x96\x90a3\xA4V[`@Q\x80\x91\x03\x90\xFD[a\x14\xA7a!{V[\x15a\x14\xE7W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x14\xDE\x90a4\x0CV[`@Q\x80\x91\x03\x90\xFD[a\x02\x08_\x01_\x81\x81\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x15\x0F\x90a4*V[\x91\x90a\x01\0\n\x81T\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP_`\x02a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x15Z\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90Pa\x02\x06_\x81\x81\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x15\x8C\x90a4*V[\x91\x90a\x01\0\n\x81T\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP_`\x02a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x15\xD7\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90P__\x90P[a\x16\x0E`\x02\x84`\x02\x81\x10a\x15\xFFWa\x15\xFEa-cV[[a\x01\x02\x02\x01a\x01\0\x01Ta\"\x0EV[\x81\x11a\x17\xB2W`\x02\x83`\x02\x81\x10a\x16(Wa\x16'a-cV[[a\x01\x02\x02\x01_\x01\x81a\x01\0\x81\x10a\x16BWa\x16Aa-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x83`\x02\x81\x10a\x16\x8DWa\x16\x8Ca-cV[[a\x01\x02\x02\x01_\x01\x82a\x01\0\x81\x10a\x16\xA7Wa\x16\xA6a-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x17\x9FW`\x02\x83`\x02\x81\x10a\x16\xF7Wa\x16\xF6a-cV[[a\x01\x02\x02\x01_\x01\x81a\x01\0\x81\x10a\x17\x11Wa\x17\x10a-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x83`\x02\x81\x10a\x17FWa\x17Ea-cV[[a\x01\x02\x02\x01_\x01\x82a\x01\0\x81\x10a\x17`Wa\x17_a-cV[[\x01_a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UP[\x80\x80a\x17\xAA\x90a00V[\x91PPa\x15\xE8V[P_`\x02\x83`\x02\x81\x10a\x17\xC8Wa\x17\xC7a-cV[[a\x01\x02\x02\x01a\x01\0\x01T\x90P____\x90P[\x86\x80_\x01\x90a\x17\xEA\x91\x90a4eV[\x90P\x81\x10\x15a\x19FW\x86\x80_\x01\x90a\x18\x02\x91\x90a4eV[\x82\x81\x81\x10a\x18\x13Wa\x18\x12a-cV[[\x90P`@\x02\x01_\x01` \x81\x01\x90a\x18*\x91\x90a)\xEDV[\x92P\x86\x80_\x01\x90a\x18;\x91\x90a4eV[\x82\x81\x81\x10a\x18LWa\x18Ka-cV[[\x90P`@\x02\x01` \x01` \x81\x01\x90a\x18d\x91\x90a*\x9FV[\x91P_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x82s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x03a\x18\xB3Wa\x18\xAC\x83\x85a!\xFA\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x93Pa\x18\xC9V[a\x18\xC6\x83\x85a\"\xBD\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x93P[\x81`\x02\x86`\x02\x81\x10a\x18\xDEWa\x18\xDDa-cV[[a\x01\x02\x02\x01_\x01\x84`\xFF\x16a\x01\0\x81\x10a\x18\xFBWa\x18\xFAa-cV[[\x01_a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UP\x80\x80`\x01\x01\x91PPa\x17\xDBV[P\x82`\x02\x85`\x02\x81\x10a\x19\\Wa\x19[a-cV[[a\x01\x02\x02\x01a\x01\0\x01\x81\x90UP\x85` \x01` \x81\x01\x90a\x19|\x91\x90a)\xEDV[`\x02\x85`\x02\x81\x10a\x19\x90Wa\x19\x8Fa-cV[[a\x01\x02\x02\x01a\x01\x01\x01_a\x01\0\n\x81T\x81`\xFF\x02\x19\x16\x90\x83`\xFF\x16\x02\x17\x90UP\x82a\x02\x08`\x01\x01\x81\x90UPa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x19\xE9\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7Fx\xDA\xD2\xBC\x0BG\xC6\x88\xED\x84\xF3\xFE\xE7\x9A\xBC\x18\xE6\xC9\x82-\xB0Zy\xCA\x19\xDF\xF5E3\xC7G\ra\x02\x08_\x01_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x87a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x1A\x89\x93\x92\x91\x90a6\x8BV[`@Q\x80\x91\x03\x90\xA1PPPPPPV[a\x1A\xA1a!\xD5V[\x15a\x1A\xE1W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x1A\xD8\x90a3\xA4V[`@Q\x80\x91\x03\x90\xFD[a\x1A\xE9a!{V[\x15a\x1B)W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x1B \x90a4\x0CV[`@Q\x80\x91\x03\x90\xFD[3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x80a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x1Bd\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x81\x10a\x1B\x7FWa\x1B~a-cV[[a\x01\x02\x02\x01_\x01\x82`\xFF\x16a\x01\0\x81\x10a\x1B\x9CWa\x1B\x9Ba-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x1C\x13W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x1C\n\x90a-\xDAV[`@Q\x80\x91\x03\x90\xFD[3a\x02\n_\x01_a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x1C\x84\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\xBC'H\xCF\x02\xF7\xA1)\x15%\xE8f\xEF\xC7j\xB3\xB9m2\xD7\xAF\xCB\xB2lS\xDA\xECa{8\xB4y3a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x1D\n\x92\x91\x90a2\xE5V[`@Q\x80\x91\x03\x90\xA1PV[a\x1D!\x82\x82\x90Pa\"\x1FV[__a\x1D+a!\xD5V[\x15a\x1E\xA1W3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x80`\x01a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x1Dm\x91\x90a/8V[a\x1Dw\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x81\x10a\x1D\x92Wa\x1D\x91a-cV[[a\x01\x02\x02\x01_\x01\x86`\xFF\x16a\x01\0\x81\x10a\x1D\xAFWa\x1D\xAEa-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14\x91P\x81a\x1E\x9CW3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x80a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x1E)\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x81\x10a\x1EDWa\x1ECa-cV[[a\x01\x02\x02\x01_\x01\x86`\xFF\x16a\x01\0\x81\x10a\x1EaWa\x1E`a-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14\x90P[a\x1FOV[3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x80a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x1E\xDC\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x81\x10a\x1E\xF7Wa\x1E\xF6a-cV[[a\x01\x02\x02\x01_\x01\x86`\xFF\x16a\x01\0\x81\x10a\x1F\x14Wa\x1F\x13a-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14\x91P[\x81\x80a\x1FXWP\x80[a\x1F\x97W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x1F\x8E\x90a-\xDAV[`@Q\x80\x91\x03\x90\xFD[\x83\x83`\x01_3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ \x91\x82a\x1F\xE3\x92\x91\x90a2\x18V[Pa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a \x12\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\x12Q\x81\xEC!\x88-\xECQ\xA29)\x05\xDF\xF3\xA8,\xBD\x02b\xF1\x8B\\\x0C\x03T\x88g\x1B@\xAF\xB23\x85\x85a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa \x9C\x94\x93\x92\x91\x90a7\x11V[`@Q\x80\x91\x03\x90\xA1PPPPPV[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a!9W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a!0\x90a+$V[`@Q\x80\x91\x03\x90\xFD[\x80__a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPPV[__s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x02\n_\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14\x15\x90P\x90V[__a\x02\x08`\x01\x01T\x14\x15\x90P\x90V[__\x82`\xFF\x16`\x01\x90\x1B\x84\x16\x14\x90P\x92\x91PPV[_\x81`\xFF\x16`\x01\x90\x1B\x19\x83\x16\x90P\x92\x91PPV[_a\"\x18\x82a\"\xD0V[\x90P\x91\x90PV[_\x81\x11a\"aW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\"X\x90a7\x99V[`@Q\x80\x91\x03\x90\xFD[a\x02\x07_\x01_\x90T\x90a\x01\0\n\x90\x04a\xFF\xFF\x16a\xFF\xFF\x16\x81\x11\x15a\"\xBAW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\"\xB1\x90a8\x01V[`@Q\x80\x91\x03\x90\xFD[PV[_\x81`\xFF\x16`\x01\x90\x1B\x83\x17\x90P\x92\x91PPV[_`\x07a\"\xEEo\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x84\x11a#\x9CV[\x90\x1B\x90P`\x06a#\ng\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x83\x85\x90\x1C\x11a#\x9CV[\x90\x1B\x81\x17\x90P`\x05a#$c\xFF\xFF\xFF\xFF\x83\x85\x90\x1C\x11a#\x9CV[\x90\x1B\x81\x17\x90P`\x04a#V[\x81R` \x01a#\xC7a$ZV[\x81R` \x01a#\xD4a$>V[\x81R` \x01a#\xE1a$|V[\x81R` \x01_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01_o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RP\x90V[`@Q\x80`@\x01`@R\x80_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01``\x81RP\x90V[`@Q\x80`@\x01`@R\x80``\x81R` \x01_`\xFF\x16\x81RP\x90V[`@Q\x80`@\x01`@R\x80_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01_\x81RP\x90V[`@Q\x80` \x01`@R\x80_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RP\x90V[__\xFD[__\xFD[_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[a$\xC8\x81a$\xACV[\x81\x14a$\xD2W__\xFD[PV[_\x815\x90Pa$\xE3\x81a$\xBFV[\x92\x91PPV[_`\xFF\x82\x16\x90P\x91\x90PV[a$\xFE\x81a$\xE9V[\x81\x14a%\x08W__\xFD[PV[_\x815\x90Pa%\x19\x81a$\xF5V[\x92\x91PPV[__`@\x83\x85\x03\x12\x15a%5Wa%4a$\xA4V[[_a%B\x85\x82\x86\x01a$\xD5V[\x92PP` a%S\x85\x82\x86\x01a%\x0BV[\x91PP\x92P\x92\x90PV[__\xFD[_` \x82\x84\x03\x12\x15a%vWa%ua%]V[[\x81\x90P\x92\x91PPV[_` \x82\x84\x03\x12\x15a%\x94Wa%\x93a$\xA4V[[_a%\xA1\x84\x82\x85\x01a%aV[\x91PP\x92\x91PPV[_\x81Q\x90P\x91\x90PV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[_\x81\x90P` \x82\x01\x90P\x91\x90PV[_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[_a%\xFC\x82a%\xD3V[\x90P\x91\x90PV[a&\x0C\x81a%\xF2V[\x82RPPV[_\x81Q\x90P\x91\x90PV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[\x82\x81\x83^_\x83\x83\x01RPPPV[_`\x1F\x19`\x1F\x83\x01\x16\x90P\x91\x90PV[_a&T\x82a&\x12V[a&^\x81\x85a&\x1CV[\x93Pa&n\x81\x85` \x86\x01a&,V[a&w\x81a&:V[\x84\x01\x91PP\x92\x91PPV[_`@\x83\x01_\x83\x01Qa&\x97_\x86\x01\x82a&\x03V[P` \x83\x01Q\x84\x82\x03` \x86\x01Ra&\xAF\x82\x82a&JV[\x91PP\x80\x91PP\x92\x91PPV[_a&\xC7\x83\x83a&\x82V[\x90P\x92\x91PPV[_` \x82\x01\x90P\x91\x90PV[_a&\xE5\x82a%\xAAV[a&\xEF\x81\x85a%\xB4V[\x93P\x83` \x82\x02\x85\x01a'\x01\x85a%\xC4V[\x80_[\x85\x81\x10\x15a'\x82a1 V[\x84\x84Ta0\xAEV[\x82UPPPPV[__\x90P\x90V[a1]a1NV[a1h\x81\x84\x84a1)V[PPPV[[\x81\x81\x10\x15a1\x8BWa1\x80_\x82a1UV[`\x01\x81\x01\x90Pa1nV[PPV[`\x1F\x82\x11\x15a1\xD0Wa1\xA1\x81a0\x81V[a1\xAA\x84a0\x93V[\x81\x01` \x85\x10\x15a1\xB9W\x81\x90P[a1\xCDa1\xC5\x85a0\x93V[\x83\x01\x82a1mV[PP[PPPV[_\x82\x82\x1C\x90P\x92\x91PPV[_a1\xF0_\x19\x84`\x08\x02a1\xD5V[\x19\x80\x83\x16\x91PP\x92\x91PPV[_a2\x08\x83\x83a1\xE1V[\x91P\x82`\x02\x02\x82\x17\x90P\x92\x91PPV[a2\"\x83\x83a0wV[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a2;Wa2:a/\xA6V[[a2E\x82Ta0\0V[a2P\x82\x82\x85a1\x8FV[_`\x1F\x83\x11`\x01\x81\x14a2}W_\x84\x15a2kW\x82\x87\x015\x90P[a2u\x85\x82a1\xFDV[\x86UPa2\xDCV[`\x1F\x19\x84\x16a2\x8B\x86a0\x81V[_[\x82\x81\x10\x15a2\xB2W\x84\x89\x015\x82U`\x01\x82\x01\x91P` \x85\x01\x94P` \x81\x01\x90Pa2\x8DV[\x86\x83\x10\x15a2\xCFW\x84\x89\x015a2\xCB`\x1F\x89\x16\x82a1\xE1V[\x83UP[`\x01`\x02\x88\x02\x01\x88UPPP[PPPPPPPV[_`@\x82\x01\x90Pa2\xF8_\x83\x01\x85a.\x07V[a3\x05` \x83\x01\x84a,\x0EV[\x93\x92PPPV[_a3\x16\x82a$\xACV[\x91P_\x82\x03a3(Wa3'a+\xAAV[[`\x01\x82\x03\x90P\x91\x90PV[_`@\x82\x01\x90Pa3F_\x83\x01\x85a-\xF8V[a3S` \x83\x01\x84a,\x0EV[\x93\x92PPPV[\x7Fmigration in progress\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a3\x8E`\x15\x83a*\xCAV[\x91Pa3\x99\x82a3ZV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra3\xBB\x81a3\x82V[\x90P\x91\x90PV[\x7Fmaintenance in progress\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a3\xF6`\x17\x83a*\xCAV[\x91Pa4\x01\x82a3\xC2V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra4#\x81a3\xEAV[\x90P\x91\x90PV[_a44\x82a$\xACV[\x91Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x03a4NWa4Ma+\xAAV[[`\x01\x82\x01\x90P\x91\x90PV[__\xFD[__\xFD[__\xFD[__\x835`\x01` \x03\x846\x03\x03\x81\x12a4\x81Wa4\x80a4YV[[\x80\x84\x01\x92P\x825\x91Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15a4\xA3Wa4\xA2a4]V[[` \x83\x01\x92P`@\x82\x026\x03\x83\x13\x15a4\xBFWa4\xBEa4aV[[P\x92P\x92\x90PV[__\xFD[__\xFD[__\xFD[__\x835`\x01` \x03\x846\x03\x03\x81\x12a4\xEFWa4\xEEa4\xCFV[[\x83\x81\x01\x92P\x825\x91P` \x83\x01\x92Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15a5\x17Wa5\x16a4\xC7V[[`@\x82\x026\x03\x83\x13\x15a5-Wa5,a4\xCBV[[P\x92P\x92\x90PV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[_\x81\x90P\x91\x90PV[_a5\\` \x84\x01\x84a%\x0BV[\x90P\x92\x91PPV[_a5r` \x84\x01\x84a*\x8BV[\x90P\x92\x91PPV[`@\x82\x01a5\x8A_\x83\x01\x83a5NV[a5\x96_\x85\x01\x82a'NV[Pa5\xA4` \x83\x01\x83a5dV[a5\xB1` \x85\x01\x82a&\x03V[PPPPV[_a5\xC2\x83\x83a5zV[`@\x83\x01\x90P\x92\x91PPV[_\x82\x90P\x92\x91PPV[_`@\x82\x01\x90P\x91\x90PV[_a5\xEF\x83\x85a55V[\x93Pa5\xFA\x82a5EV[\x80_[\x85\x81\x10\x15a62Wa6\x0F\x82\x84a5\xCEV[a6\x19\x88\x82a5\xB7V[\x97Pa6$\x83a5\xD8V[\x92PP`\x01\x81\x01\x90Pa5\xFDV[P\x85\x92PPP\x93\x92PPPV[_`@\x83\x01a6P_\x84\x01\x84a4\xD3V[\x85\x83\x03_\x87\x01Ra6b\x83\x82\x84a5\xE4V[\x92PPPa6s` \x84\x01\x84a5NV[a6\x80` \x86\x01\x82a'NV[P\x80\x91PP\x92\x91PPV[_``\x82\x01\x90Pa6\x9E_\x83\x01\x86a-\xF8V[\x81\x81\x03` \x83\x01Ra6\xB0\x81\x85a6?V[\x90Pa6\xBF`@\x83\x01\x84a,\x0EV[\x94\x93PPPPV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[\x82\x81\x837_\x83\x83\x01RPPPV[_a6\xF0\x83\x85a6\xC7V[\x93Pa6\xFD\x83\x85\x84a6\xD7V[a7\x06\x83a&:V[\x84\x01\x90P\x93\x92PPPV[_``\x82\x01\x90Pa7$_\x83\x01\x87a.\x07V[\x81\x81\x03` \x83\x01Ra77\x81\x85\x87a6\xE5V[\x90Pa7F`@\x83\x01\x84a,\x0EV[\x95\x94PPPPPV[\x7Fempty operator data\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a7\x83`\x13\x83a*\xCAV[\x91Pa7\x8E\x82a7OV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra7\xB0\x81a7wV[\x90P\x91\x90PV[\x7Foperator data too large\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a7\xEB`\x17\x83a*\xCAV[\x91Pa7\xF6\x82a7\xB7V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra8\x18\x81a7\xDFV[\x90P\x91\x90PV\xFE\xA2dipfsX\"\x12 \xFA\x04\xDE\xADB^j\xA2\xEEQe+w\xCD\x8B\xEC4O\x89\xD5\xA5\xD1\x8BB\xF4\x88\x9Bz\xBA\xD1s\"dsolcC\0\x08\x1C\x003", ); /// The runtime bytecode of the contract, as deployed on the network. /// /// ```text - ///0x608060405234801561000f575f5ffd5b50600436106100a7575f3560e01c8063ad36e6d01161006f578063ad36e6d014610127578063c130809a14610131578063cdbfc62d1461013b578063dd3fd26914610157578063f019b15414610173578063f2fde38b1461018f576100a7565b80633048bfba146100ab57806355a47d0a146100b557806365706f9c146100d157806375418b9d146100ed5780638b5252d61461010b575b5f5ffd5b6100b36101ab565b005b6100cf60048036038101906100ca919061251f565b61037f565b005b6100eb60048036038101906100e6919061257f565b6106bd565b005b6100f5610761565b60405161010291906128bc565b60405180910390f35b6101256004803603810190610120919061293d565b610f8f565b005b61012f610fec565b005b6101396111c6565b005b610155600480360381019061015091906129a6565b6113c9565b005b610171600480360381019061016c91906129ed565b611a99565b005b61018d60048036038101906101889190612a18565b611d15565b005b6101a960048036038101906101a49190612a9f565b6120ab565b005b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610239576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161023090612b24565b60405180910390fd5b61024161217b565b610280576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161027790612b8c565b60405180910390fd5b5f61020a5f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff16809291906102f190612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507f8fb9cd054d0a022110cced239e908b834e4cd219511856d4eaae3051d932d60461020b5f9054906101000a90046fffffffffffffffffffffffffffffffff166040516103759190612c1d565b60405180910390a1565b6103876121d5565b6103c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103bd90612c80565b60405180910390fd5b6102085f015f9054906101000a900467ffffffffffffffff1667ffffffffffffffff168267ffffffffffffffff1614610434576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042b90612ce8565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff166002806102065f9054906101000a900467ffffffffffffffff1661046f9190612d33565b67ffffffffffffffff166002811061048a57610489612d63565b5b61010202015f018260ff1661010081106104a7576104a6612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461051e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161051590612dda565b60405180910390fd5b61053781610208600101546121e590919063ffffffff16565b6106b95761055481610208600101546121fa90919063ffffffff16565b6102086001018190555061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff168092919061058c90612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550505f6102086001015403610646577f01269879535f40ee8957e15e160bf1866c5e2728ff0cbc583d848821e2639b4e6102085f015f9054906101000a900467ffffffffffffffff163361020b5f9054906101000a90046fffffffffffffffffffffffffffffffff1660405161063993929190612e16565b60405180910390a16106b8565b7faf5e90e72015f43138f66b4cd08bd1dfa2839030104f22a00af843fe847c6d196102085f015f9054906101000a900467ffffffffffffffff163361020b5f9054906101000a90046fffffffffffffffffffffffffffffffff166040516106af93929190612e16565b60405180910390a15b5b5050565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461074b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161074290612b24565b60405180910390fd5b80610207818161075b9190612f2a565b90505050565b6107696123a7565b6107716123a7565b5f5f5f61077c6121d5565b15610bb9576102085f015f9054906101000a900467ffffffffffffffff1684606001515f019067ffffffffffffffff16908167ffffffffffffffff16815250506102086001015484606001516020018181525050600260016102065f9054906101000a900467ffffffffffffffff166107f59190612f38565b6107ff9190612d33565b67ffffffffffffffff1692505f60026102065f9054906101000a900467ffffffffffffffff1661082f9190612d33565b67ffffffffffffffff1690506108616002826002811061085257610851612d63565b5b6101020201610100015461220e565b91506001826108709190612f73565b67ffffffffffffffff81111561088957610888612fa6565b5b6040519080825280602002602001820160405280156108c257816020015b6108af61240f565b8152602001906001900390816108a75790505b5085602001515f0181905250600281600281106108e2576108e1612d63565b5b6101020201610101015f9054906101000a900460ff1685602001516020019060ff16908160ff16815250505f5f90505b828111610bb257610949816002846002811061093157610930612d63565b5b610102020161010001546121e590919063ffffffff16565b610b9f576002826002811061096157610960612d63565b5b61010202015f0181610100811061097b5761097a612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1693508386602001515f015182815181106109b9576109b8612d63565b5b60200260200101515f019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050610a268160028760028110610a0e57610a0d612d63565b5b610102020161010001546121e590919063ffffffff16565b80610aab57508373ffffffffffffffffffffffffffffffffffffffff1660028660028110610a5757610a56612d63565b5b61010202015f01826101008110610a7157610a70612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b15610b9e5760015f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f208054610af890613000565b80601f0160208091040260200160405190810160405280929190818152602001828054610b2490613000565b8015610b6f5780601f10610b4657610100808354040283529160200191610b6f565b820191905f5260205f20905b815481529060010190602001808311610b5257829003601f168201915b505050505086602001515f01518281518110610b8e57610b8d612d63565b5b6020026020010151602001819052505b5b8080610baa90613030565b915050610912565b5050610be9565b60026102065f9054906101000a900467ffffffffffffffff16610bdc9190612d33565b67ffffffffffffffff1692505b610c0f60028460028110610c0057610bff612d63565b5b6101020201610100015461220e565b9050600181610c1e9190612f73565b67ffffffffffffffff811115610c3757610c36612fa6565b5b604051908082528060200260200182016040528015610c7057816020015b610c5d61240f565b815260200190600190039081610c555790505b50845f01515f018190525060028360028110610c8f57610c8e612d63565b5b6101020201610101015f9054906101000a900460ff16845f01516020019060ff16908160ff16815250505f5f90505b818111610ea157610cf58160028660028110610cdd57610cdc612d63565b5b610102020161010001546121e590919063ffffffff16565b610e8e5760028460028110610d0d57610d0c612d63565b5b61010202015f01816101008110610d2757610d26612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16925082855f01515f01518281518110610d6457610d63612d63565b5b60200260200101515f019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f208054610de990613000565b80601f0160208091040260200160405190810160405280929190818152602001828054610e1590613000565b8015610e605780601f10610e3757610100808354040283529160200191610e60565b820191905f5260205f20905b815481529060010190602001808311610e4357829003601f168201915b5050505050855f01515f01518281518110610e7e57610e7d612d63565b5b6020026020010151602001819052505b8080610e9990613030565b915050610cbe565b506102065f9054906101000a900467ffffffffffffffff16846040019067ffffffffffffffff16908167ffffffffffffffff168152505061020a5f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684608001515f019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505061020b5f9054906101000a90046fffffffffffffffffffffffffffffffff168460a001906fffffffffffffffffffffffffffffffff1690816fffffffffffffffffffffffffffffffff16815250508394505050505090565b610f9b8282905061221f565b818160015f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f209182610fe7929190613218565b505050565b610ff461217b565b611033576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161102a90612b8c565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff1661020a5f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146110c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110bc90612dda565b60405180910390fd5b5f61020a5f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff168092919061113690612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507ff91067eb420c28d3124865fc996e6aa9d541b9b4fef9188cb965a6cc6491638e3361020b5f9054906101000a90046fffffffffffffffffffffffffffffffff166040516111bc9291906132e5565b60405180910390a1565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611254576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161124b90612b24565b60405180910390fd5b61125c6121d5565b61129b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161129290612c80565b60405180910390fd5b6102065f81819054906101000a900467ffffffffffffffff16809291906112c19061330c565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550505f6102086001018190555061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff168092919061132190612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507ff73240422246f63ed633ef3ce0726b8ab8fb69d46c8a4e5ecb0b2922668674a16102085f015f9054906101000a900467ffffffffffffffff1661020b5f9054906101000a90046fffffffffffffffffffffffffffffffff166040516113bf929190613333565b60405180910390a1565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611457576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161144e90612b24565b60405180910390fd5b61145f6121d5565b1561149f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611496906133a4565b60405180910390fd5b6114a761217b565b156114e7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114de9061340c565b60405180910390fd5b6102085f015f81819054906101000a900467ffffffffffffffff168092919061150f9061342a565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550505f60026102065f9054906101000a900467ffffffffffffffff1661155a9190612d33565b67ffffffffffffffff1690506102065f81819054906101000a900467ffffffffffffffff168092919061158c9061342a565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550505f60026102065f9054906101000a900467ffffffffffffffff166115d79190612d33565b67ffffffffffffffff1690505f5f90505b61160e600284600281106115ff576115fe612d63565b5b6101020201610100015461220e565b81116117b2576002836002811061162857611627612d63565b5b61010202015f0181610100811061164257611641612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166002836002811061168d5761168c612d63565b5b61010202015f018261010081106116a7576116a6612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461179f57600283600281106116f7576116f6612d63565b5b61010202015f0181610100811061171157611710612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff166002836002811061174657611745612d63565b5b61010202015f018261010081106117605761175f612d63565b5b015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b80806117aa90613030565b9150506115e8565b505f600283600281106117c8576117c7612d63565b5b6101020201610100015490505f5f5f5f90505b86805f01906117ea9190613465565b90508110156119465786805f01906118029190613465565b8281811061181357611812612d63565b5b9050604002015f01602081019061182a91906129ed565b925086805f019061183b9190613465565b8281811061184c5761184b612d63565b5b90506040020160200160208101906118649190612a9f565b91505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036118b3576118ac83856121fa90919063ffffffff16565b93506118c9565b6118c683856122bd90919063ffffffff16565b93505b81600286600281106118de576118dd612d63565b5b61010202015f018460ff1661010081106118fb576118fa612d63565b5b015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080806001019150506117db565b50826002856002811061195c5761195b612d63565b5b6101020201610100018190555085602001602081019061197c91906129ed565b600285600281106119905761198f612d63565b5b6101020201610101015f6101000a81548160ff021916908360ff160217905550826102086001018190555061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff16809291906119e990612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507f78dad2bc0b47c688ed84f3fee79abc18e6c9822db05a79ca19dff54533c7470d6102085f015f9054906101000a900467ffffffffffffffff168761020b5f9054906101000a90046fffffffffffffffffffffffffffffffff16604051611a899392919061368b565b60405180910390a1505050505050565b611aa16121d5565b15611ae1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ad8906133a4565b60405180910390fd5b611ae961217b565b15611b29576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b209061340c565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff166002806102065f9054906101000a900467ffffffffffffffff16611b649190612d33565b67ffffffffffffffff1660028110611b7f57611b7e612d63565b5b61010202015f018260ff166101008110611b9c57611b9b612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611c13576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c0a90612dda565b60405180910390fd5b3361020a5f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff1680929190611c8490612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507fbc2748cf02f7a1291525e866efc76ab3b96d32d7afcbb26c53daec617b38b4793361020b5f9054906101000a90046fffffffffffffffffffffffffffffffff16604051611d0a9291906132e5565b60405180910390a150565b611d218282905061221f565b5f5f611d2b6121d5565b15611ea1573373ffffffffffffffffffffffffffffffffffffffff1660028060016102065f9054906101000a900467ffffffffffffffff16611d6d9190612f38565b611d779190612d33565b67ffffffffffffffff1660028110611d9257611d91612d63565b5b61010202015f018660ff166101008110611daf57611dae612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614915081611e9c573373ffffffffffffffffffffffffffffffffffffffff166002806102065f9054906101000a900467ffffffffffffffff16611e299190612d33565b67ffffffffffffffff1660028110611e4457611e43612d63565b5b61010202015f018660ff166101008110611e6157611e60612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161490505b611f4f565b3373ffffffffffffffffffffffffffffffffffffffff166002806102065f9054906101000a900467ffffffffffffffff16611edc9190612d33565b67ffffffffffffffff1660028110611ef757611ef6612d63565b5b61010202015f018660ff166101008110611f1457611f13612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161491505b8180611f585750805b611f97576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f8e90612dda565b60405180910390fd5b838360015f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f209182611fe3929190613218565b5061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff168092919061201290612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507f125181ec21882dec51a2392905dff3a82cbd0262f18b5c0c035488671b40afb233858561020b5f9054906101000a90046fffffffffffffffffffffffffffffffff1660405161209c9493929190613711565b60405180910390a15050505050565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612139576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161213090612b24565b60405180910390fd5b805f5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b5f5f73ffffffffffffffffffffffffffffffffffffffff1661020a5f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415905090565b5f5f610208600101541415905090565b5f5f8260ff166001901b841614905092915050565b5f8160ff166001901b198316905092915050565b5f612218826122d0565b9050919050565b5f8111612261576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161225890613799565b60405180910390fd5b6102075f015f9054906101000a900461ffff1661ffff168111156122ba576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122b190613801565b60405180910390fd5b50565b5f8160ff166001901b8317905092915050565b5f60076122ee6fffffffffffffffffffffffffffffffff841161239c565b901b9050600661230a67ffffffffffffffff8385901c1161239c565b901b81179050600561232463ffffffff8385901c1161239c565b901b81179050600461233c61ffff8385901c1161239c565b901b81179050600361235360ff8385901c1161239c565b901b81179050600261236a600f8385901c1161239c565b901b811790507d01010202020203030303030303030000000000000000000000000000000082821c1a81179050919050565b5f8115159050919050565b6040518060c001604052806123ba61243e565b81526020016123c761243e565b81526020015f67ffffffffffffffff1681526020016123e461245a565b81526020016123f161247c565b81526020015f6fffffffffffffffffffffffffffffffff1681525090565b60405180604001604052805f73ffffffffffffffffffffffffffffffffffffffff168152602001606081525090565b6040518060400160405280606081526020015f60ff1681525090565b60405180604001604052805f67ffffffffffffffff1681526020015f81525090565b60405180602001604052805f73ffffffffffffffffffffffffffffffffffffffff1681525090565b5f5ffd5b5f5ffd5b5f67ffffffffffffffff82169050919050565b6124c8816124ac565b81146124d2575f5ffd5b50565b5f813590506124e3816124bf565b92915050565b5f60ff82169050919050565b6124fe816124e9565b8114612508575f5ffd5b50565b5f81359050612519816124f5565b92915050565b5f5f60408385031215612535576125346124a4565b5b5f612542858286016124d5565b92505060206125538582860161250b565b9150509250929050565b5f5ffd5b5f602082840312156125765761257561255d565b5b81905092915050565b5f60208284031215612594576125936124a4565b5b5f6125a184828501612561565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6125fc826125d3565b9050919050565b61260c816125f2565b82525050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61265482612612565b61265e818561261c565b935061266e81856020860161262c565b6126778161263a565b840191505092915050565b5f604083015f8301516126975f860182612603565b50602083015184820360208601526126af828261264a565b9150508091505092915050565b5f6126c78383612682565b905092915050565b5f602082019050919050565b5f6126e5826125aa565b6126ef81856125b4565b935083602082028501612701856125c4565b805f5b8581101561273c578484038952815161271d85826126bc565b9450612728836126cf565b925060208a01995050600181019050612704565b50829750879550505050505092915050565b612757816124e9565b82525050565b5f604083015f8301518482035f86015261277782826126db565b915050602083015161278c602086018261274e565b508091505092915050565b6127a0816124ac565b82525050565b5f819050919050565b6127b8816127a6565b82525050565b604082015f8201516127d25f850182612797565b5060208201516127e560208501826127af565b50505050565b602082015f8201516127ff5f850182612603565b50505050565b5f6fffffffffffffffffffffffffffffffff82169050919050565b61282981612805565b82525050565b5f60e083015f8301518482035f860152612849828261275d565b91505060208301518482036020860152612863828261275d565b91505060408301516128786040860182612797565b50606083015161288b60608601826127be565b50608083015161289e60a08601826127eb565b5060a08301516128b160c0860182612820565b508091505092915050565b5f6020820190508181035f8301526128d4818461282f565b905092915050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f83601f8401126128fd576128fc6128dc565b5b8235905067ffffffffffffffff81111561291a576129196128e0565b5b602083019150836001820283011115612936576129356128e4565b5b9250929050565b5f5f60208385031215612953576129526124a4565b5b5f83013567ffffffffffffffff8111156129705761296f6124a8565b5b61297c858286016128e8565b92509250509250929050565b5f6040828403121561299d5761299c61255d565b5b81905092915050565b5f602082840312156129bb576129ba6124a4565b5b5f82013567ffffffffffffffff8111156129d8576129d76124a8565b5b6129e484828501612988565b91505092915050565b5f60208284031215612a0257612a016124a4565b5b5f612a0f8482850161250b565b91505092915050565b5f5f5f60408486031215612a2f57612a2e6124a4565b5b5f612a3c8682870161250b565b935050602084013567ffffffffffffffff811115612a5d57612a5c6124a8565b5b612a69868287016128e8565b92509250509250925092565b612a7e816125f2565b8114612a88575f5ffd5b50565b5f81359050612a9981612a75565b92915050565b5f60208284031215612ab457612ab36124a4565b5b5f612ac184828501612a8b565b91505092915050565b5f82825260208201905092915050565b7f6e6f7420746865206f776e6572000000000000000000000000000000000000005f82015250565b5f612b0e600d83612aca565b9150612b1982612ada565b602082019050919050565b5f6020820190508181035f830152612b3b81612b02565b9050919050565b7f6e6f206d61696e74656e616e63650000000000000000000000000000000000005f82015250565b5f612b76600e83612aca565b9150612b8182612b42565b602082019050919050565b5f6020820190508181035f830152612ba381612b6a565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f612be182612805565b91506fffffffffffffffffffffffffffffffff8203612c0357612c02612baa565b5b600182019050919050565b612c1781612805565b82525050565b5f602082019050612c305f830184612c0e565b92915050565b7f6e6f206d6967726174696f6e00000000000000000000000000000000000000005f82015250565b5f612c6a600c83612aca565b9150612c7582612c36565b602082019050919050565b5f6020820190508181035f830152612c9781612c5e565b9050919050565b7f77726f6e67206d6967726174696f6e20696400000000000000000000000000005f82015250565b5f612cd2601283612aca565b9150612cdd82612c9e565b602082019050919050565b5f6020820190508181035f830152612cff81612cc6565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f612d3d826124ac565b9150612d48836124ac565b925082612d5857612d57612d06565b5b828206905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f77726f6e67206f70657261746f720000000000000000000000000000000000005f82015250565b5f612dc4600e83612aca565b9150612dcf82612d90565b602082019050919050565b5f6020820190508181035f830152612df181612db8565b9050919050565b612e01816124ac565b82525050565b612e10816125f2565b82525050565b5f606082019050612e295f830186612df8565b612e366020830185612e07565b612e436040830184612c0e565b949350505050565b5f61ffff82169050919050565b612e6181612e4b565b8114612e6b575f5ffd5b50565b5f8135612e7a81612e58565b80915050919050565b5f815f1b9050919050565b5f61ffff612e9b84612e83565b9350801983169250808416831791505092915050565b5f819050919050565b5f612ed4612ecf612eca84612e4b565b612eb1565b612e4b565b9050919050565b5f819050919050565b612eed82612eba565b612f00612ef982612edb565b8354612e8e565b8255505050565b5f81015f830180612f1781612e6e565b9050612f238184612ee4565b5050505050565b612f348282612f07565b5050565b5f612f42826124ac565b9150612f4d836124ac565b9250828203905067ffffffffffffffff811115612f6d57612f6c612baa565b5b92915050565b5f612f7d826127a6565b9150612f88836127a6565b9250828201905080821115612fa057612f9f612baa565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061301757607f821691505b60208210810361302a57613029612fd3565b5b50919050565b5f61303a826127a6565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361306c5761306b612baa565b5b600182019050919050565b5f82905092915050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026130dd7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826130a2565b6130e786836130a2565b95508019841693508086168417925050509392505050565b5f61311961311461310f846127a6565b612eb1565b6127a6565b9050919050565b5f819050919050565b613132836130ff565b61314661313e82613120565b8484546130ae565b825550505050565b5f5f905090565b61315d61314e565b613168818484613129565b505050565b5b8181101561318b576131805f82613155565b60018101905061316e565b5050565b601f8211156131d0576131a181613081565b6131aa84613093565b810160208510156131b9578190505b6131cd6131c585613093565b83018261316d565b50505b505050565b5f82821c905092915050565b5f6131f05f19846008026131d5565b1980831691505092915050565b5f61320883836131e1565b9150826002028217905092915050565b6132228383613077565b67ffffffffffffffff81111561323b5761323a612fa6565b5b6132458254613000565b61325082828561318f565b5f601f83116001811461327d575f841561326b578287013590505b61327585826131fd565b8655506132dc565b601f19841661328b86613081565b5f5b828110156132b25784890135825560018201915060208501945060208101905061328d565b868310156132cf57848901356132cb601f8916826131e1565b8355505b6001600288020188555050505b50505050505050565b5f6040820190506132f85f830185612e07565b6133056020830184612c0e565b9392505050565b5f613316826124ac565b91505f820361332857613327612baa565b5b600182039050919050565b5f6040820190506133465f830185612df8565b6133536020830184612c0e565b9392505050565b7f6d6967726174696f6e20696e2070726f677265737300000000000000000000005f82015250565b5f61338e601583612aca565b91506133998261335a565b602082019050919050565b5f6020820190508181035f8301526133bb81613382565b9050919050565b7f6d61696e74656e616e636520696e2070726f67726573730000000000000000005f82015250565b5f6133f6601783612aca565b9150613401826133c2565b602082019050919050565b5f6020820190508181035f830152613423816133ea565b9050919050565b5f613434826124ac565b915067ffffffffffffffff820361344e5761344d612baa565b5b600182019050919050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f8335600160200384360303811261348157613480613459565b5b80840192508235915067ffffffffffffffff8211156134a3576134a261345d565b5b6020830192506040820236038313156134bf576134be613461565b5b509250929050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f833560016020038436030381126134ef576134ee6134cf565b5b83810192508235915060208301925067ffffffffffffffff821115613517576135166134c7565b5b60408202360383131561352d5761352c6134cb565b5b509250929050565b5f82825260208201905092915050565b5f819050919050565b5f61355c602084018461250b565b905092915050565b5f6135726020840184612a8b565b905092915050565b6040820161358a5f83018361354e565b6135965f85018261274e565b506135a46020830183613564565b6135b16020850182612603565b50505050565b5f6135c2838361357a565b60408301905092915050565b5f82905092915050565b5f604082019050919050565b5f6135ef8385613535565b93506135fa82613545565b805f5b858110156136325761360f82846135ce565b61361988826135b7565b9750613624836135d8565b9250506001810190506135fd565b5085925050509392505050565b5f604083016136505f8401846134d3565b8583035f8701526136628382846135e4565b92505050613673602084018461354e565b613680602086018261274e565b508091505092915050565b5f60608201905061369e5f830186612df8565b81810360208301526136b0818561363f565b90506136bf6040830184612c0e565b949350505050565b5f82825260208201905092915050565b828183375f83830152505050565b5f6136f083856136c7565b93506136fd8385846136d7565b6137068361263a565b840190509392505050565b5f6060820190506137245f830187612e07565b81810360208301526137378185876136e5565b90506137466040830184612c0e565b95945050505050565b7f656d707479206f70657261746f722064617461000000000000000000000000005f82015250565b5f613783601383612aca565b915061378e8261374f565b602082019050919050565b5f6020820190508181035f8301526137b081613777565b9050919050565b7f6f70657261746f72206461746120746f6f206c617267650000000000000000005f82015250565b5f6137eb601783612aca565b91506137f6826137b7565b602082019050919050565b5f6020820190508181035f830152613818816137df565b905091905056fea26469706673582212205070bfb78cba4fb204ce3a9ae24b5f710c62732176365ee8389cdab18c3c2d7164736f6c634300081c0033 + ///0x608060405234801561000f575f5ffd5b50600436106100a7575f3560e01c8063ad36e6d01161006f578063ad36e6d014610127578063c130809a14610131578063cdbfc62d1461013b578063dd3fd26914610157578063f019b15414610173578063f2fde38b1461018f576100a7565b80633048bfba146100ab57806355a47d0a146100b557806365706f9c146100d157806375418b9d146100ed5780638b5252d61461010b575b5f5ffd5b6100b36101ab565b005b6100cf60048036038101906100ca919061251f565b61037f565b005b6100eb60048036038101906100e6919061257f565b6106bd565b005b6100f5610761565b60405161010291906128bc565b60405180910390f35b6101256004803603810190610120919061293d565b610f8f565b005b61012f610fec565b005b6101396111c6565b005b610155600480360381019061015091906129a6565b6113c9565b005b610171600480360381019061016c91906129ed565b611a99565b005b61018d60048036038101906101889190612a18565b611d15565b005b6101a960048036038101906101a49190612a9f565b6120ab565b005b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610239576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161023090612b24565b60405180910390fd5b61024161217b565b610280576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161027790612b8c565b60405180910390fd5b5f61020a5f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff16809291906102f190612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507f8fb9cd054d0a022110cced239e908b834e4cd219511856d4eaae3051d932d60461020b5f9054906101000a90046fffffffffffffffffffffffffffffffff166040516103759190612c1d565b60405180910390a1565b6103876121d5565b6103c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103bd90612c80565b60405180910390fd5b6102085f015f9054906101000a900467ffffffffffffffff1667ffffffffffffffff168267ffffffffffffffff1614610434576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042b90612ce8565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff166002806102065f9054906101000a900467ffffffffffffffff1661046f9190612d33565b67ffffffffffffffff166002811061048a57610489612d63565b5b61010202015f018260ff1661010081106104a7576104a6612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461051e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161051590612dda565b60405180910390fd5b61053781610208600101546121e590919063ffffffff16565b6106b95761055481610208600101546121fa90919063ffffffff16565b6102086001018190555061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff168092919061058c90612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550505f6102086001015403610646577f01269879535f40ee8957e15e160bf1866c5e2728ff0cbc583d848821e2639b4e6102085f015f9054906101000a900467ffffffffffffffff163361020b5f9054906101000a90046fffffffffffffffffffffffffffffffff1660405161063993929190612e16565b60405180910390a16106b8565b7faf5e90e72015f43138f66b4cd08bd1dfa2839030104f22a00af843fe847c6d196102085f015f9054906101000a900467ffffffffffffffff163361020b5f9054906101000a90046fffffffffffffffffffffffffffffffff166040516106af93929190612e16565b60405180910390a15b5b5050565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461074b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161074290612b24565b60405180910390fd5b80610207818161075b9190612f2a565b90505050565b6107696123a7565b6107716123a7565b5f5f5f61077c6121d5565b15610bb9576102085f015f9054906101000a900467ffffffffffffffff1684602001515f019067ffffffffffffffff16908167ffffffffffffffff16815250506102086001015484602001516020018181525050600260016102065f9054906101000a900467ffffffffffffffff166107f59190612f38565b6107ff9190612d33565b67ffffffffffffffff1692505f60026102065f9054906101000a900467ffffffffffffffff1661082f9190612d33565b67ffffffffffffffff1690506108616002826002811061085257610851612d63565b5b6101020201610100015461220e565b91506001826108709190612f73565b67ffffffffffffffff81111561088957610888612fa6565b5b6040519080825280602002602001820160405280156108c257816020015b6108af61240f565b8152602001906001900390816108a75790505b5085604001515f0181905250600281600281106108e2576108e1612d63565b5b6101020201610101015f9054906101000a900460ff1685604001516020019060ff16908160ff16815250505f5f90505b828111610bb257610949816002846002811061093157610930612d63565b5b610102020161010001546121e590919063ffffffff16565b610b9f576002826002811061096157610960612d63565b5b61010202015f0181610100811061097b5761097a612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1693508386604001515f015182815181106109b9576109b8612d63565b5b60200260200101515f019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050610a268160028760028110610a0e57610a0d612d63565b5b610102020161010001546121e590919063ffffffff16565b80610aab57508373ffffffffffffffffffffffffffffffffffffffff1660028660028110610a5757610a56612d63565b5b61010202015f01826101008110610a7157610a70612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b15610b9e5760015f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f208054610af890613000565b80601f0160208091040260200160405190810160405280929190818152602001828054610b2490613000565b8015610b6f5780601f10610b4657610100808354040283529160200191610b6f565b820191905f5260205f20905b815481529060010190602001808311610b5257829003601f168201915b505050505086604001515f01518281518110610b8e57610b8d612d63565b5b6020026020010151602001819052505b5b8080610baa90613030565b915050610912565b5050610be9565b60026102065f9054906101000a900467ffffffffffffffff16610bdc9190612d33565b67ffffffffffffffff1692505b610c0f60028460028110610c0057610bff612d63565b5b6101020201610100015461220e565b9050600181610c1e9190612f73565b67ffffffffffffffff811115610c3757610c36612fa6565b5b604051908082528060200260200182016040528015610c7057816020015b610c5d61240f565b815260200190600190039081610c555790505b50845f01515f018190525060028360028110610c8f57610c8e612d63565b5b6101020201610101015f9054906101000a900460ff16845f01516020019060ff16908160ff16815250505f5f90505b818111610ea157610cf58160028660028110610cdd57610cdc612d63565b5b610102020161010001546121e590919063ffffffff16565b610e8e5760028460028110610d0d57610d0c612d63565b5b61010202015f01816101008110610d2757610d26612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16925082855f01515f01518281518110610d6457610d63612d63565b5b60200260200101515f019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f208054610de990613000565b80601f0160208091040260200160405190810160405280929190818152602001828054610e1590613000565b8015610e605780601f10610e3757610100808354040283529160200191610e60565b820191905f5260205f20905b815481529060010190602001808311610e4357829003601f168201915b5050505050855f01515f01518281518110610e7e57610e7d612d63565b5b6020026020010151602001819052505b8080610e9990613030565b915050610cbe565b506102065f9054906101000a900467ffffffffffffffff16846080019067ffffffffffffffff16908167ffffffffffffffff168152505061020a5f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684606001515f019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505061020b5f9054906101000a90046fffffffffffffffffffffffffffffffff168460a001906fffffffffffffffffffffffffffffffff1690816fffffffffffffffffffffffffffffffff16815250508394505050505090565b610f9b8282905061221f565b818160015f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f209182610fe7929190613218565b505050565b610ff461217b565b611033576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161102a90612b8c565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff1661020a5f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146110c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110bc90612dda565b60405180910390fd5b5f61020a5f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff168092919061113690612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507ff91067eb420c28d3124865fc996e6aa9d541b9b4fef9188cb965a6cc6491638e3361020b5f9054906101000a90046fffffffffffffffffffffffffffffffff166040516111bc9291906132e5565b60405180910390a1565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611254576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161124b90612b24565b60405180910390fd5b61125c6121d5565b61129b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161129290612c80565b60405180910390fd5b6102065f81819054906101000a900467ffffffffffffffff16809291906112c19061330c565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550505f6102086001018190555061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff168092919061132190612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507ff73240422246f63ed633ef3ce0726b8ab8fb69d46c8a4e5ecb0b2922668674a16102085f015f9054906101000a900467ffffffffffffffff1661020b5f9054906101000a90046fffffffffffffffffffffffffffffffff166040516113bf929190613333565b60405180910390a1565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611457576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161144e90612b24565b60405180910390fd5b61145f6121d5565b1561149f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611496906133a4565b60405180910390fd5b6114a761217b565b156114e7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114de9061340c565b60405180910390fd5b6102085f015f81819054906101000a900467ffffffffffffffff168092919061150f9061342a565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550505f60026102065f9054906101000a900467ffffffffffffffff1661155a9190612d33565b67ffffffffffffffff1690506102065f81819054906101000a900467ffffffffffffffff168092919061158c9061342a565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550505f60026102065f9054906101000a900467ffffffffffffffff166115d79190612d33565b67ffffffffffffffff1690505f5f90505b61160e600284600281106115ff576115fe612d63565b5b6101020201610100015461220e565b81116117b2576002836002811061162857611627612d63565b5b61010202015f0181610100811061164257611641612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166002836002811061168d5761168c612d63565b5b61010202015f018261010081106116a7576116a6612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461179f57600283600281106116f7576116f6612d63565b5b61010202015f0181610100811061171157611710612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff166002836002811061174657611745612d63565b5b61010202015f018261010081106117605761175f612d63565b5b015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b80806117aa90613030565b9150506115e8565b505f600283600281106117c8576117c7612d63565b5b6101020201610100015490505f5f5f5f90505b86805f01906117ea9190613465565b90508110156119465786805f01906118029190613465565b8281811061181357611812612d63565b5b9050604002015f01602081019061182a91906129ed565b925086805f019061183b9190613465565b8281811061184c5761184b612d63565b5b90506040020160200160208101906118649190612a9f565b91505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036118b3576118ac83856121fa90919063ffffffff16565b93506118c9565b6118c683856122bd90919063ffffffff16565b93505b81600286600281106118de576118dd612d63565b5b61010202015f018460ff1661010081106118fb576118fa612d63565b5b015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080806001019150506117db565b50826002856002811061195c5761195b612d63565b5b6101020201610100018190555085602001602081019061197c91906129ed565b600285600281106119905761198f612d63565b5b6101020201610101015f6101000a81548160ff021916908360ff160217905550826102086001018190555061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff16809291906119e990612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507f78dad2bc0b47c688ed84f3fee79abc18e6c9822db05a79ca19dff54533c7470d6102085f015f9054906101000a900467ffffffffffffffff168761020b5f9054906101000a90046fffffffffffffffffffffffffffffffff16604051611a899392919061368b565b60405180910390a1505050505050565b611aa16121d5565b15611ae1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ad8906133a4565b60405180910390fd5b611ae961217b565b15611b29576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b209061340c565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff166002806102065f9054906101000a900467ffffffffffffffff16611b649190612d33565b67ffffffffffffffff1660028110611b7f57611b7e612d63565b5b61010202015f018260ff166101008110611b9c57611b9b612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611c13576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c0a90612dda565b60405180910390fd5b3361020a5f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff1680929190611c8490612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507fbc2748cf02f7a1291525e866efc76ab3b96d32d7afcbb26c53daec617b38b4793361020b5f9054906101000a90046fffffffffffffffffffffffffffffffff16604051611d0a9291906132e5565b60405180910390a150565b611d218282905061221f565b5f5f611d2b6121d5565b15611ea1573373ffffffffffffffffffffffffffffffffffffffff1660028060016102065f9054906101000a900467ffffffffffffffff16611d6d9190612f38565b611d779190612d33565b67ffffffffffffffff1660028110611d9257611d91612d63565b5b61010202015f018660ff166101008110611daf57611dae612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614915081611e9c573373ffffffffffffffffffffffffffffffffffffffff166002806102065f9054906101000a900467ffffffffffffffff16611e299190612d33565b67ffffffffffffffff1660028110611e4457611e43612d63565b5b61010202015f018660ff166101008110611e6157611e60612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161490505b611f4f565b3373ffffffffffffffffffffffffffffffffffffffff166002806102065f9054906101000a900467ffffffffffffffff16611edc9190612d33565b67ffffffffffffffff1660028110611ef757611ef6612d63565b5b61010202015f018660ff166101008110611f1457611f13612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161491505b8180611f585750805b611f97576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f8e90612dda565b60405180910390fd5b838360015f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f209182611fe3929190613218565b5061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff168092919061201290612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507f125181ec21882dec51a2392905dff3a82cbd0262f18b5c0c035488671b40afb233858561020b5f9054906101000a90046fffffffffffffffffffffffffffffffff1660405161209c9493929190613711565b60405180910390a15050505050565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612139576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161213090612b24565b60405180910390fd5b805f5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b5f5f73ffffffffffffffffffffffffffffffffffffffff1661020a5f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415905090565b5f5f610208600101541415905090565b5f5f8260ff166001901b841614905092915050565b5f8160ff166001901b198316905092915050565b5f612218826122d0565b9050919050565b5f8111612261576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161225890613799565b60405180910390fd5b6102075f015f9054906101000a900461ffff1661ffff168111156122ba576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122b190613801565b60405180910390fd5b50565b5f8160ff166001901b8317905092915050565b5f60076122ee6fffffffffffffffffffffffffffffffff841161239c565b901b9050600661230a67ffffffffffffffff8385901c1161239c565b901b81179050600561232463ffffffff8385901c1161239c565b901b81179050600461233c61ffff8385901c1161239c565b901b81179050600361235360ff8385901c1161239c565b901b81179050600261236a600f8385901c1161239c565b901b811790507d01010202020203030303030303030000000000000000000000000000000082821c1a81179050919050565b5f8115159050919050565b6040518060c001604052806123ba61243e565b81526020016123c761245a565b81526020016123d461243e565b81526020016123e161247c565b81526020015f67ffffffffffffffff1681526020015f6fffffffffffffffffffffffffffffffff1681525090565b60405180604001604052805f73ffffffffffffffffffffffffffffffffffffffff168152602001606081525090565b6040518060400160405280606081526020015f60ff1681525090565b60405180604001604052805f67ffffffffffffffff1681526020015f81525090565b60405180602001604052805f73ffffffffffffffffffffffffffffffffffffffff1681525090565b5f5ffd5b5f5ffd5b5f67ffffffffffffffff82169050919050565b6124c8816124ac565b81146124d2575f5ffd5b50565b5f813590506124e3816124bf565b92915050565b5f60ff82169050919050565b6124fe816124e9565b8114612508575f5ffd5b50565b5f81359050612519816124f5565b92915050565b5f5f60408385031215612535576125346124a4565b5b5f612542858286016124d5565b92505060206125538582860161250b565b9150509250929050565b5f5ffd5b5f602082840312156125765761257561255d565b5b81905092915050565b5f60208284031215612594576125936124a4565b5b5f6125a184828501612561565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6125fc826125d3565b9050919050565b61260c816125f2565b82525050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61265482612612565b61265e818561261c565b935061266e81856020860161262c565b6126778161263a565b840191505092915050565b5f604083015f8301516126975f860182612603565b50602083015184820360208601526126af828261264a565b9150508091505092915050565b5f6126c78383612682565b905092915050565b5f602082019050919050565b5f6126e5826125aa565b6126ef81856125b4565b935083602082028501612701856125c4565b805f5b8581101561273c578484038952815161271d85826126bc565b9450612728836126cf565b925060208a01995050600181019050612704565b50829750879550505050505092915050565b612757816124e9565b82525050565b5f604083015f8301518482035f86015261277782826126db565b915050602083015161278c602086018261274e565b508091505092915050565b6127a0816124ac565b82525050565b5f819050919050565b6127b8816127a6565b82525050565b604082015f8201516127d25f850182612797565b5060208201516127e560208501826127af565b50505050565b602082015f8201516127ff5f850182612603565b50505050565b5f6fffffffffffffffffffffffffffffffff82169050919050565b61282981612805565b82525050565b5f60e083015f8301518482035f860152612849828261275d565b915050602083015161285e60208601826127be565b5060408301518482036060860152612876828261275d565b915050606083015161288b60808601826127eb565b50608083015161289e60a0860182612797565b5060a08301516128b160c0860182612820565b508091505092915050565b5f6020820190508181035f8301526128d4818461282f565b905092915050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f83601f8401126128fd576128fc6128dc565b5b8235905067ffffffffffffffff81111561291a576129196128e0565b5b602083019150836001820283011115612936576129356128e4565b5b9250929050565b5f5f60208385031215612953576129526124a4565b5b5f83013567ffffffffffffffff8111156129705761296f6124a8565b5b61297c858286016128e8565b92509250509250929050565b5f6040828403121561299d5761299c61255d565b5b81905092915050565b5f602082840312156129bb576129ba6124a4565b5b5f82013567ffffffffffffffff8111156129d8576129d76124a8565b5b6129e484828501612988565b91505092915050565b5f60208284031215612a0257612a016124a4565b5b5f612a0f8482850161250b565b91505092915050565b5f5f5f60408486031215612a2f57612a2e6124a4565b5b5f612a3c8682870161250b565b935050602084013567ffffffffffffffff811115612a5d57612a5c6124a8565b5b612a69868287016128e8565b92509250509250925092565b612a7e816125f2565b8114612a88575f5ffd5b50565b5f81359050612a9981612a75565b92915050565b5f60208284031215612ab457612ab36124a4565b5b5f612ac184828501612a8b565b91505092915050565b5f82825260208201905092915050565b7f6e6f7420746865206f776e6572000000000000000000000000000000000000005f82015250565b5f612b0e600d83612aca565b9150612b1982612ada565b602082019050919050565b5f6020820190508181035f830152612b3b81612b02565b9050919050565b7f6e6f206d61696e74656e616e63650000000000000000000000000000000000005f82015250565b5f612b76600e83612aca565b9150612b8182612b42565b602082019050919050565b5f6020820190508181035f830152612ba381612b6a565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f612be182612805565b91506fffffffffffffffffffffffffffffffff8203612c0357612c02612baa565b5b600182019050919050565b612c1781612805565b82525050565b5f602082019050612c305f830184612c0e565b92915050565b7f6e6f206d6967726174696f6e00000000000000000000000000000000000000005f82015250565b5f612c6a600c83612aca565b9150612c7582612c36565b602082019050919050565b5f6020820190508181035f830152612c9781612c5e565b9050919050565b7f77726f6e67206d6967726174696f6e20696400000000000000000000000000005f82015250565b5f612cd2601283612aca565b9150612cdd82612c9e565b602082019050919050565b5f6020820190508181035f830152612cff81612cc6565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f612d3d826124ac565b9150612d48836124ac565b925082612d5857612d57612d06565b5b828206905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f77726f6e67206f70657261746f720000000000000000000000000000000000005f82015250565b5f612dc4600e83612aca565b9150612dcf82612d90565b602082019050919050565b5f6020820190508181035f830152612df181612db8565b9050919050565b612e01816124ac565b82525050565b612e10816125f2565b82525050565b5f606082019050612e295f830186612df8565b612e366020830185612e07565b612e436040830184612c0e565b949350505050565b5f61ffff82169050919050565b612e6181612e4b565b8114612e6b575f5ffd5b50565b5f8135612e7a81612e58565b80915050919050565b5f815f1b9050919050565b5f61ffff612e9b84612e83565b9350801983169250808416831791505092915050565b5f819050919050565b5f612ed4612ecf612eca84612e4b565b612eb1565b612e4b565b9050919050565b5f819050919050565b612eed82612eba565b612f00612ef982612edb565b8354612e8e565b8255505050565b5f81015f830180612f1781612e6e565b9050612f238184612ee4565b5050505050565b612f348282612f07565b5050565b5f612f42826124ac565b9150612f4d836124ac565b9250828203905067ffffffffffffffff811115612f6d57612f6c612baa565b5b92915050565b5f612f7d826127a6565b9150612f88836127a6565b9250828201905080821115612fa057612f9f612baa565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061301757607f821691505b60208210810361302a57613029612fd3565b5b50919050565b5f61303a826127a6565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361306c5761306b612baa565b5b600182019050919050565b5f82905092915050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026130dd7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826130a2565b6130e786836130a2565b95508019841693508086168417925050509392505050565b5f61311961311461310f846127a6565b612eb1565b6127a6565b9050919050565b5f819050919050565b613132836130ff565b61314661313e82613120565b8484546130ae565b825550505050565b5f5f905090565b61315d61314e565b613168818484613129565b505050565b5b8181101561318b576131805f82613155565b60018101905061316e565b5050565b601f8211156131d0576131a181613081565b6131aa84613093565b810160208510156131b9578190505b6131cd6131c585613093565b83018261316d565b50505b505050565b5f82821c905092915050565b5f6131f05f19846008026131d5565b1980831691505092915050565b5f61320883836131e1565b9150826002028217905092915050565b6132228383613077565b67ffffffffffffffff81111561323b5761323a612fa6565b5b6132458254613000565b61325082828561318f565b5f601f83116001811461327d575f841561326b578287013590505b61327585826131fd565b8655506132dc565b601f19841661328b86613081565b5f5b828110156132b25784890135825560018201915060208501945060208101905061328d565b868310156132cf57848901356132cb601f8916826131e1565b8355505b6001600288020188555050505b50505050505050565b5f6040820190506132f85f830185612e07565b6133056020830184612c0e565b9392505050565b5f613316826124ac565b91505f820361332857613327612baa565b5b600182039050919050565b5f6040820190506133465f830185612df8565b6133536020830184612c0e565b9392505050565b7f6d6967726174696f6e20696e2070726f677265737300000000000000000000005f82015250565b5f61338e601583612aca565b91506133998261335a565b602082019050919050565b5f6020820190508181035f8301526133bb81613382565b9050919050565b7f6d61696e74656e616e636520696e2070726f67726573730000000000000000005f82015250565b5f6133f6601783612aca565b9150613401826133c2565b602082019050919050565b5f6020820190508181035f830152613423816133ea565b9050919050565b5f613434826124ac565b915067ffffffffffffffff820361344e5761344d612baa565b5b600182019050919050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f8335600160200384360303811261348157613480613459565b5b80840192508235915067ffffffffffffffff8211156134a3576134a261345d565b5b6020830192506040820236038313156134bf576134be613461565b5b509250929050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f833560016020038436030381126134ef576134ee6134cf565b5b83810192508235915060208301925067ffffffffffffffff821115613517576135166134c7565b5b60408202360383131561352d5761352c6134cb565b5b509250929050565b5f82825260208201905092915050565b5f819050919050565b5f61355c602084018461250b565b905092915050565b5f6135726020840184612a8b565b905092915050565b6040820161358a5f83018361354e565b6135965f85018261274e565b506135a46020830183613564565b6135b16020850182612603565b50505050565b5f6135c2838361357a565b60408301905092915050565b5f82905092915050565b5f604082019050919050565b5f6135ef8385613535565b93506135fa82613545565b805f5b858110156136325761360f82846135ce565b61361988826135b7565b9750613624836135d8565b9250506001810190506135fd565b5085925050509392505050565b5f604083016136505f8401846134d3565b8583035f8701526136628382846135e4565b92505050613673602084018461354e565b613680602086018261274e565b508091505092915050565b5f60608201905061369e5f830186612df8565b81810360208301526136b0818561363f565b90506136bf6040830184612c0e565b949350505050565b5f82825260208201905092915050565b828183375f83830152505050565b5f6136f083856136c7565b93506136fd8385846136d7565b6137068361263a565b840190509392505050565b5f6060820190506137245f830187612e07565b81810360208301526137378185876136e5565b90506137466040830184612c0e565b95945050505050565b7f656d707479206f70657261746f722064617461000000000000000000000000005f82015250565b5f613783601383612aca565b915061378e8261374f565b602082019050919050565b5f6020820190508181035f8301526137b081613777565b9050919050565b7f6f70657261746f72206461746120746f6f206c617267650000000000000000005f82015250565b5f6137eb601783612aca565b91506137f6826137b7565b602082019050919050565b5f6020820190508181035f830152613818816137df565b905091905056fea2646970667358221220fa04dead425e6aa2ee51652b77cd8bec344f89d5a5d18b42f4889b7abad1732264736f6c634300081c0033 /// ``` #[rustfmt::skip] #[allow(clippy::all)] pub static DEPLOYED_BYTECODE: alloy_sol_types::private::Bytes = alloy_sol_types::private::Bytes::from_static( - b"`\x80`@R4\x80\x15a\0\x0FW__\xFD[P`\x046\x10a\0\xA7W_5`\xE0\x1C\x80c\xAD6\xE6\xD0\x11a\0oW\x80c\xAD6\xE6\xD0\x14a\x01'W\x80c\xC10\x80\x9A\x14a\x011W\x80c\xCD\xBF\xC6-\x14a\x01;W\x80c\xDD?\xD2i\x14a\x01WW\x80c\xF0\x19\xB1T\x14a\x01sW\x80c\xF2\xFD\xE3\x8B\x14a\x01\x8FWa\0\xA7V[\x80c0H\xBF\xBA\x14a\0\xABW\x80cU\xA4}\n\x14a\0\xB5W\x80cepo\x9C\x14a\0\xD1W\x80cuA\x8B\x9D\x14a\0\xEDW\x80c\x8BRR\xD6\x14a\x01\x0BW[__\xFD[a\0\xB3a\x01\xABV[\0[a\0\xCF`\x04\x806\x03\x81\x01\x90a\0\xCA\x91\x90a%\x1FV[a\x03\x7FV[\0[a\0\xEB`\x04\x806\x03\x81\x01\x90a\0\xE6\x91\x90a%\x7FV[a\x06\xBDV[\0[a\0\xF5a\x07aV[`@Qa\x01\x02\x91\x90a(\xBCV[`@Q\x80\x91\x03\x90\xF3[a\x01%`\x04\x806\x03\x81\x01\x90a\x01 \x91\x90a)=V[a\x0F\x8FV[\0[a\x01/a\x0F\xECV[\0[a\x019a\x11\xC6V[\0[a\x01U`\x04\x806\x03\x81\x01\x90a\x01P\x91\x90a)\xA6V[a\x13\xC9V[\0[a\x01q`\x04\x806\x03\x81\x01\x90a\x01l\x91\x90a)\xEDV[a\x1A\x99V[\0[a\x01\x8D`\x04\x806\x03\x81\x01\x90a\x01\x88\x91\x90a*\x18V[a\x1D\x15V[\0[a\x01\xA9`\x04\x806\x03\x81\x01\x90a\x01\xA4\x91\x90a*\x9FV[a \xABV[\0[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x029W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x020\x90a+$V[`@Q\x80\x91\x03\x90\xFD[a\x02Aa!{V[a\x02\x80W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x02w\x90a+\x8CV[`@Q\x80\x91\x03\x90\xFD[_a\x02\n_\x01_a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x02\xF1\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\x8F\xB9\xCD\x05M\n\x02!\x10\xCC\xED#\x9E\x90\x8B\x83NL\xD2\x19Q\x18V\xD4\xEA\xAE0Q\xD92\xD6\x04a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x03u\x91\x90a,\x1DV[`@Q\x80\x91\x03\x90\xA1V[a\x03\x87a!\xD5V[a\x03\xC6W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x03\xBD\x90a,\x80V[`@Q\x80\x91\x03\x90\xFD[a\x02\x08_\x01_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x82g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x044W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x04+\x90a,\xE8V[`@Q\x80\x91\x03\x90\xFD[3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x80a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x04o\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x81\x10a\x04\x8AWa\x04\x89a-cV[[a\x01\x02\x02\x01_\x01\x82`\xFF\x16a\x01\0\x81\x10a\x04\xA7Wa\x04\xA6a-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x05\x1EW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x05\x15\x90a-\xDAV[`@Q\x80\x91\x03\x90\xFD[a\x057\x81a\x02\x08`\x01\x01Ta!\xE5\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x06\xB9Wa\x05T\x81a\x02\x08`\x01\x01Ta!\xFA\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x02\x08`\x01\x01\x81\x90UPa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x05\x8C\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP_a\x02\x08`\x01\x01T\x03a\x06FW\x7F\x01&\x98yS_@\xEE\x89W\xE1^\x16\x0B\xF1\x86l^'(\xFF\x0C\xBCX=\x84\x88!\xE2c\x9BNa\x02\x08_\x01_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x069\x93\x92\x91\x90a.\x16V[`@Q\x80\x91\x03\x90\xA1a\x06\xB8V[\x7F\xAF^\x90\xE7 \x15\xF418\xF6kL\xD0\x8B\xD1\xDF\xA2\x83\x900\x10O\"\xA0\n\xF8C\xFE\x84|m\x19a\x02\x08_\x01_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x06\xAF\x93\x92\x91\x90a.\x16V[`@Q\x80\x91\x03\x90\xA1[[PPV[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x07KW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x07B\x90a+$V[`@Q\x80\x91\x03\x90\xFD[\x80a\x02\x07\x81\x81a\x07[\x91\x90a/*V[\x90PPPV[a\x07ia#\xA7V[a\x07qa#\xA7V[___a\x07|a!\xD5V[\x15a\x0B\xB9Wa\x02\x08_\x01_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x84``\x01Q_\x01\x90g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RPPa\x02\x08`\x01\x01T\x84``\x01Q` \x01\x81\x81RPP`\x02`\x01a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x07\xF5\x91\x90a/8V[a\x07\xFF\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x92P_`\x02a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x08/\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90Pa\x08a`\x02\x82`\x02\x81\x10a\x08RWa\x08Qa-cV[[a\x01\x02\x02\x01a\x01\0\x01Ta\"\x0EV[\x91P`\x01\x82a\x08p\x91\x90a/sV[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x08\x89Wa\x08\x88a/\xA6V[[`@Q\x90\x80\x82R\x80` \x02` \x01\x82\x01`@R\x80\x15a\x08\xC2W\x81` \x01[a\x08\xAFa$\x0FV[\x81R` \x01\x90`\x01\x90\x03\x90\x81a\x08\xA7W\x90P[P\x85` \x01Q_\x01\x81\x90RP`\x02\x81`\x02\x81\x10a\x08\xE2Wa\x08\xE1a-cV[[a\x01\x02\x02\x01a\x01\x01\x01_\x90T\x90a\x01\0\n\x90\x04`\xFF\x16\x85` \x01Q` \x01\x90`\xFF\x16\x90\x81`\xFF\x16\x81RPP__\x90P[\x82\x81\x11a\x0B\xB2Wa\tI\x81`\x02\x84`\x02\x81\x10a\t1Wa\t0a-cV[[a\x01\x02\x02\x01a\x01\0\x01Ta!\xE5\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x0B\x9FW`\x02\x82`\x02\x81\x10a\taWa\t`a-cV[[a\x01\x02\x02\x01_\x01\x81a\x01\0\x81\x10a\t{Wa\tza-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x93P\x83\x86` \x01Q_\x01Q\x82\x81Q\x81\x10a\t\xB9Wa\t\xB8a-cV[[` \x02` \x01\x01Q_\x01\x90s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RPPa\n&\x81`\x02\x87`\x02\x81\x10a\n\x0EWa\n\ra-cV[[a\x01\x02\x02\x01a\x01\0\x01Ta!\xE5\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x80a\n\xABWP\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x86`\x02\x81\x10a\nWWa\nVa-cV[[a\x01\x02\x02\x01_\x01\x82a\x01\0\x81\x10a\nqWa\npa-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14\x15[\x15a\x0B\x9EW`\x01_\x85s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ \x80Ta\n\xF8\x90a0\0V[\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01\x82\x80Ta\x0B$\x90a0\0V[\x80\x15a\x0BoW\x80`\x1F\x10a\x0BFWa\x01\0\x80\x83T\x04\x02\x83R\x91` \x01\x91a\x0BoV[\x82\x01\x91\x90_R` _ \x90[\x81T\x81R\x90`\x01\x01\x90` \x01\x80\x83\x11a\x0BRW\x82\x90\x03`\x1F\x16\x82\x01\x91[PPPPP\x86` \x01Q_\x01Q\x82\x81Q\x81\x10a\x0B\x8EWa\x0B\x8Da-cV[[` \x02` \x01\x01Q` \x01\x81\x90RP[[\x80\x80a\x0B\xAA\x90a00V[\x91PPa\t\x12V[PPa\x0B\xE9V[`\x02a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x0B\xDC\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x92P[a\x0C\x0F`\x02\x84`\x02\x81\x10a\x0C\0Wa\x0B\xFFa-cV[[a\x01\x02\x02\x01a\x01\0\x01Ta\"\x0EV[\x90P`\x01\x81a\x0C\x1E\x91\x90a/sV[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x0C7Wa\x0C6a/\xA6V[[`@Q\x90\x80\x82R\x80` \x02` \x01\x82\x01`@R\x80\x15a\x0CpW\x81` \x01[a\x0C]a$\x0FV[\x81R` \x01\x90`\x01\x90\x03\x90\x81a\x0CUW\x90P[P\x84_\x01Q_\x01\x81\x90RP`\x02\x83`\x02\x81\x10a\x0C\x8FWa\x0C\x8Ea-cV[[a\x01\x02\x02\x01a\x01\x01\x01_\x90T\x90a\x01\0\n\x90\x04`\xFF\x16\x84_\x01Q` \x01\x90`\xFF\x16\x90\x81`\xFF\x16\x81RPP__\x90P[\x81\x81\x11a\x0E\xA1Wa\x0C\xF5\x81`\x02\x86`\x02\x81\x10a\x0C\xDDWa\x0C\xDCa-cV[[a\x01\x02\x02\x01a\x01\0\x01Ta!\xE5\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x0E\x8EW`\x02\x84`\x02\x81\x10a\r\rWa\r\x0Ca-cV[[a\x01\x02\x02\x01_\x01\x81a\x01\0\x81\x10a\r'Wa\r&a-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x92P\x82\x85_\x01Q_\x01Q\x82\x81Q\x81\x10a\rdWa\rca-cV[[` \x02` \x01\x01Q_\x01\x90s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RPP`\x01_\x84s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ \x80Ta\r\xE9\x90a0\0V[\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01\x82\x80Ta\x0E\x15\x90a0\0V[\x80\x15a\x0E`W\x80`\x1F\x10a\x0E7Wa\x01\0\x80\x83T\x04\x02\x83R\x91` \x01\x91a\x0E`V[\x82\x01\x91\x90_R` _ \x90[\x81T\x81R\x90`\x01\x01\x90` \x01\x80\x83\x11a\x0ECW\x82\x90\x03`\x1F\x16\x82\x01\x91[PPPPP\x85_\x01Q_\x01Q\x82\x81Q\x81\x10a\x0E~Wa\x0E}a-cV[[` \x02` \x01\x01Q` \x01\x81\x90RP[\x80\x80a\x0E\x99\x90a00V[\x91PPa\x0C\xBEV[Pa\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x84`@\x01\x90g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RPPa\x02\n_\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x84`\x80\x01Q_\x01\x90s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RPPa\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x84`\xA0\x01\x90o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RPP\x83\x94PPPPP\x90V[a\x0F\x9B\x82\x82\x90Pa\"\x1FV[\x81\x81`\x01_3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ \x91\x82a\x0F\xE7\x92\x91\x90a2\x18V[PPPV[a\x0F\xF4a!{V[a\x103W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x10*\x90a+\x8CV[`@Q\x80\x91\x03\x90\xFD[3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x02\n_\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x10\xC5W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x10\xBC\x90a-\xDAV[`@Q\x80\x91\x03\x90\xFD[_a\x02\n_\x01_a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x116\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\xF9\x10g\xEBB\x0C(\xD3\x12He\xFC\x99nj\xA9\xD5A\xB9\xB4\xFE\xF9\x18\x8C\xB9e\xA6\xCCd\x91c\x8E3a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x11\xBC\x92\x91\x90a2\xE5V[`@Q\x80\x91\x03\x90\xA1V[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x12TW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x12K\x90a+$V[`@Q\x80\x91\x03\x90\xFD[a\x12\\a!\xD5V[a\x12\x9BW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x12\x92\x90a,\x80V[`@Q\x80\x91\x03\x90\xFD[a\x02\x06_\x81\x81\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x12\xC1\x90a3\x0CV[\x91\x90a\x01\0\n\x81T\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP_a\x02\x08`\x01\x01\x81\x90UPa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x13!\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\xF72@B\"F\xF6>\xD63\xEF<\xE0rk\x8A\xB8\xFBi\xD4l\x8AN^\xCB\x0B)\"f\x86t\xA1a\x02\x08_\x01_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x13\xBF\x92\x91\x90a33V[`@Q\x80\x91\x03\x90\xA1V[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x14WW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x14N\x90a+$V[`@Q\x80\x91\x03\x90\xFD[a\x14_a!\xD5V[\x15a\x14\x9FW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x14\x96\x90a3\xA4V[`@Q\x80\x91\x03\x90\xFD[a\x14\xA7a!{V[\x15a\x14\xE7W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x14\xDE\x90a4\x0CV[`@Q\x80\x91\x03\x90\xFD[a\x02\x08_\x01_\x81\x81\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x15\x0F\x90a4*V[\x91\x90a\x01\0\n\x81T\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP_`\x02a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x15Z\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90Pa\x02\x06_\x81\x81\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x15\x8C\x90a4*V[\x91\x90a\x01\0\n\x81T\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP_`\x02a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x15\xD7\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90P__\x90P[a\x16\x0E`\x02\x84`\x02\x81\x10a\x15\xFFWa\x15\xFEa-cV[[a\x01\x02\x02\x01a\x01\0\x01Ta\"\x0EV[\x81\x11a\x17\xB2W`\x02\x83`\x02\x81\x10a\x16(Wa\x16'a-cV[[a\x01\x02\x02\x01_\x01\x81a\x01\0\x81\x10a\x16BWa\x16Aa-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x83`\x02\x81\x10a\x16\x8DWa\x16\x8Ca-cV[[a\x01\x02\x02\x01_\x01\x82a\x01\0\x81\x10a\x16\xA7Wa\x16\xA6a-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x17\x9FW`\x02\x83`\x02\x81\x10a\x16\xF7Wa\x16\xF6a-cV[[a\x01\x02\x02\x01_\x01\x81a\x01\0\x81\x10a\x17\x11Wa\x17\x10a-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x83`\x02\x81\x10a\x17FWa\x17Ea-cV[[a\x01\x02\x02\x01_\x01\x82a\x01\0\x81\x10a\x17`Wa\x17_a-cV[[\x01_a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UP[\x80\x80a\x17\xAA\x90a00V[\x91PPa\x15\xE8V[P_`\x02\x83`\x02\x81\x10a\x17\xC8Wa\x17\xC7a-cV[[a\x01\x02\x02\x01a\x01\0\x01T\x90P____\x90P[\x86\x80_\x01\x90a\x17\xEA\x91\x90a4eV[\x90P\x81\x10\x15a\x19FW\x86\x80_\x01\x90a\x18\x02\x91\x90a4eV[\x82\x81\x81\x10a\x18\x13Wa\x18\x12a-cV[[\x90P`@\x02\x01_\x01` \x81\x01\x90a\x18*\x91\x90a)\xEDV[\x92P\x86\x80_\x01\x90a\x18;\x91\x90a4eV[\x82\x81\x81\x10a\x18LWa\x18Ka-cV[[\x90P`@\x02\x01` \x01` \x81\x01\x90a\x18d\x91\x90a*\x9FV[\x91P_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x82s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x03a\x18\xB3Wa\x18\xAC\x83\x85a!\xFA\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x93Pa\x18\xC9V[a\x18\xC6\x83\x85a\"\xBD\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x93P[\x81`\x02\x86`\x02\x81\x10a\x18\xDEWa\x18\xDDa-cV[[a\x01\x02\x02\x01_\x01\x84`\xFF\x16a\x01\0\x81\x10a\x18\xFBWa\x18\xFAa-cV[[\x01_a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UP\x80\x80`\x01\x01\x91PPa\x17\xDBV[P\x82`\x02\x85`\x02\x81\x10a\x19\\Wa\x19[a-cV[[a\x01\x02\x02\x01a\x01\0\x01\x81\x90UP\x85` \x01` \x81\x01\x90a\x19|\x91\x90a)\xEDV[`\x02\x85`\x02\x81\x10a\x19\x90Wa\x19\x8Fa-cV[[a\x01\x02\x02\x01a\x01\x01\x01_a\x01\0\n\x81T\x81`\xFF\x02\x19\x16\x90\x83`\xFF\x16\x02\x17\x90UP\x82a\x02\x08`\x01\x01\x81\x90UPa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x19\xE9\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7Fx\xDA\xD2\xBC\x0BG\xC6\x88\xED\x84\xF3\xFE\xE7\x9A\xBC\x18\xE6\xC9\x82-\xB0Zy\xCA\x19\xDF\xF5E3\xC7G\ra\x02\x08_\x01_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x87a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x1A\x89\x93\x92\x91\x90a6\x8BV[`@Q\x80\x91\x03\x90\xA1PPPPPPV[a\x1A\xA1a!\xD5V[\x15a\x1A\xE1W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x1A\xD8\x90a3\xA4V[`@Q\x80\x91\x03\x90\xFD[a\x1A\xE9a!{V[\x15a\x1B)W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x1B \x90a4\x0CV[`@Q\x80\x91\x03\x90\xFD[3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x80a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x1Bd\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x81\x10a\x1B\x7FWa\x1B~a-cV[[a\x01\x02\x02\x01_\x01\x82`\xFF\x16a\x01\0\x81\x10a\x1B\x9CWa\x1B\x9Ba-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x1C\x13W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x1C\n\x90a-\xDAV[`@Q\x80\x91\x03\x90\xFD[3a\x02\n_\x01_a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x1C\x84\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\xBC'H\xCF\x02\xF7\xA1)\x15%\xE8f\xEF\xC7j\xB3\xB9m2\xD7\xAF\xCB\xB2lS\xDA\xECa{8\xB4y3a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x1D\n\x92\x91\x90a2\xE5V[`@Q\x80\x91\x03\x90\xA1PV[a\x1D!\x82\x82\x90Pa\"\x1FV[__a\x1D+a!\xD5V[\x15a\x1E\xA1W3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x80`\x01a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x1Dm\x91\x90a/8V[a\x1Dw\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x81\x10a\x1D\x92Wa\x1D\x91a-cV[[a\x01\x02\x02\x01_\x01\x86`\xFF\x16a\x01\0\x81\x10a\x1D\xAFWa\x1D\xAEa-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14\x91P\x81a\x1E\x9CW3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x80a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x1E)\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x81\x10a\x1EDWa\x1ECa-cV[[a\x01\x02\x02\x01_\x01\x86`\xFF\x16a\x01\0\x81\x10a\x1EaWa\x1E`a-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14\x90P[a\x1FOV[3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x80a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x1E\xDC\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x81\x10a\x1E\xF7Wa\x1E\xF6a-cV[[a\x01\x02\x02\x01_\x01\x86`\xFF\x16a\x01\0\x81\x10a\x1F\x14Wa\x1F\x13a-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14\x91P[\x81\x80a\x1FXWP\x80[a\x1F\x97W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x1F\x8E\x90a-\xDAV[`@Q\x80\x91\x03\x90\xFD[\x83\x83`\x01_3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ \x91\x82a\x1F\xE3\x92\x91\x90a2\x18V[Pa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a \x12\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\x12Q\x81\xEC!\x88-\xECQ\xA29)\x05\xDF\xF3\xA8,\xBD\x02b\xF1\x8B\\\x0C\x03T\x88g\x1B@\xAF\xB23\x85\x85a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa \x9C\x94\x93\x92\x91\x90a7\x11V[`@Q\x80\x91\x03\x90\xA1PPPPPV[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a!9W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a!0\x90a+$V[`@Q\x80\x91\x03\x90\xFD[\x80__a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPPV[__s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x02\n_\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14\x15\x90P\x90V[__a\x02\x08`\x01\x01T\x14\x15\x90P\x90V[__\x82`\xFF\x16`\x01\x90\x1B\x84\x16\x14\x90P\x92\x91PPV[_\x81`\xFF\x16`\x01\x90\x1B\x19\x83\x16\x90P\x92\x91PPV[_a\"\x18\x82a\"\xD0V[\x90P\x91\x90PV[_\x81\x11a\"aW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\"X\x90a7\x99V[`@Q\x80\x91\x03\x90\xFD[a\x02\x07_\x01_\x90T\x90a\x01\0\n\x90\x04a\xFF\xFF\x16a\xFF\xFF\x16\x81\x11\x15a\"\xBAW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\"\xB1\x90a8\x01V[`@Q\x80\x91\x03\x90\xFD[PV[_\x81`\xFF\x16`\x01\x90\x1B\x83\x17\x90P\x92\x91PPV[_`\x07a\"\xEEo\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x84\x11a#\x9CV[\x90\x1B\x90P`\x06a#\ng\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x83\x85\x90\x1C\x11a#\x9CV[\x90\x1B\x81\x17\x90P`\x05a#$c\xFF\xFF\xFF\xFF\x83\x85\x90\x1C\x11a#\x9CV[\x90\x1B\x81\x17\x90P`\x04a#V[\x81R` \x01a#\xC7a$>V[\x81R` \x01_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01a#\xE4a$ZV[\x81R` \x01a#\xF1a$|V[\x81R` \x01_o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RP\x90V[`@Q\x80`@\x01`@R\x80_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01``\x81RP\x90V[`@Q\x80`@\x01`@R\x80``\x81R` \x01_`\xFF\x16\x81RP\x90V[`@Q\x80`@\x01`@R\x80_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01_\x81RP\x90V[`@Q\x80` \x01`@R\x80_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RP\x90V[__\xFD[__\xFD[_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[a$\xC8\x81a$\xACV[\x81\x14a$\xD2W__\xFD[PV[_\x815\x90Pa$\xE3\x81a$\xBFV[\x92\x91PPV[_`\xFF\x82\x16\x90P\x91\x90PV[a$\xFE\x81a$\xE9V[\x81\x14a%\x08W__\xFD[PV[_\x815\x90Pa%\x19\x81a$\xF5V[\x92\x91PPV[__`@\x83\x85\x03\x12\x15a%5Wa%4a$\xA4V[[_a%B\x85\x82\x86\x01a$\xD5V[\x92PP` a%S\x85\x82\x86\x01a%\x0BV[\x91PP\x92P\x92\x90PV[__\xFD[_` \x82\x84\x03\x12\x15a%vWa%ua%]V[[\x81\x90P\x92\x91PPV[_` \x82\x84\x03\x12\x15a%\x94Wa%\x93a$\xA4V[[_a%\xA1\x84\x82\x85\x01a%aV[\x91PP\x92\x91PPV[_\x81Q\x90P\x91\x90PV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[_\x81\x90P` \x82\x01\x90P\x91\x90PV[_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[_a%\xFC\x82a%\xD3V[\x90P\x91\x90PV[a&\x0C\x81a%\xF2V[\x82RPPV[_\x81Q\x90P\x91\x90PV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[\x82\x81\x83^_\x83\x83\x01RPPPV[_`\x1F\x19`\x1F\x83\x01\x16\x90P\x91\x90PV[_a&T\x82a&\x12V[a&^\x81\x85a&\x1CV[\x93Pa&n\x81\x85` \x86\x01a&,V[a&w\x81a&:V[\x84\x01\x91PP\x92\x91PPV[_`@\x83\x01_\x83\x01Qa&\x97_\x86\x01\x82a&\x03V[P` \x83\x01Q\x84\x82\x03` \x86\x01Ra&\xAF\x82\x82a&JV[\x91PP\x80\x91PP\x92\x91PPV[_a&\xC7\x83\x83a&\x82V[\x90P\x92\x91PPV[_` \x82\x01\x90P\x91\x90PV[_a&\xE5\x82a%\xAAV[a&\xEF\x81\x85a%\xB4V[\x93P\x83` \x82\x02\x85\x01a'\x01\x85a%\xC4V[\x80_[\x85\x81\x10\x15a'\x82a1 V[\x84\x84Ta0\xAEV[\x82UPPPPV[__\x90P\x90V[a1]a1NV[a1h\x81\x84\x84a1)V[PPPV[[\x81\x81\x10\x15a1\x8BWa1\x80_\x82a1UV[`\x01\x81\x01\x90Pa1nV[PPV[`\x1F\x82\x11\x15a1\xD0Wa1\xA1\x81a0\x81V[a1\xAA\x84a0\x93V[\x81\x01` \x85\x10\x15a1\xB9W\x81\x90P[a1\xCDa1\xC5\x85a0\x93V[\x83\x01\x82a1mV[PP[PPPV[_\x82\x82\x1C\x90P\x92\x91PPV[_a1\xF0_\x19\x84`\x08\x02a1\xD5V[\x19\x80\x83\x16\x91PP\x92\x91PPV[_a2\x08\x83\x83a1\xE1V[\x91P\x82`\x02\x02\x82\x17\x90P\x92\x91PPV[a2\"\x83\x83a0wV[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a2;Wa2:a/\xA6V[[a2E\x82Ta0\0V[a2P\x82\x82\x85a1\x8FV[_`\x1F\x83\x11`\x01\x81\x14a2}W_\x84\x15a2kW\x82\x87\x015\x90P[a2u\x85\x82a1\xFDV[\x86UPa2\xDCV[`\x1F\x19\x84\x16a2\x8B\x86a0\x81V[_[\x82\x81\x10\x15a2\xB2W\x84\x89\x015\x82U`\x01\x82\x01\x91P` \x85\x01\x94P` \x81\x01\x90Pa2\x8DV[\x86\x83\x10\x15a2\xCFW\x84\x89\x015a2\xCB`\x1F\x89\x16\x82a1\xE1V[\x83UP[`\x01`\x02\x88\x02\x01\x88UPPP[PPPPPPPV[_`@\x82\x01\x90Pa2\xF8_\x83\x01\x85a.\x07V[a3\x05` \x83\x01\x84a,\x0EV[\x93\x92PPPV[_a3\x16\x82a$\xACV[\x91P_\x82\x03a3(Wa3'a+\xAAV[[`\x01\x82\x03\x90P\x91\x90PV[_`@\x82\x01\x90Pa3F_\x83\x01\x85a-\xF8V[a3S` \x83\x01\x84a,\x0EV[\x93\x92PPPV[\x7Fmigration in progress\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a3\x8E`\x15\x83a*\xCAV[\x91Pa3\x99\x82a3ZV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra3\xBB\x81a3\x82V[\x90P\x91\x90PV[\x7Fmaintenance in progress\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a3\xF6`\x17\x83a*\xCAV[\x91Pa4\x01\x82a3\xC2V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra4#\x81a3\xEAV[\x90P\x91\x90PV[_a44\x82a$\xACV[\x91Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x03a4NWa4Ma+\xAAV[[`\x01\x82\x01\x90P\x91\x90PV[__\xFD[__\xFD[__\xFD[__\x835`\x01` \x03\x846\x03\x03\x81\x12a4\x81Wa4\x80a4YV[[\x80\x84\x01\x92P\x825\x91Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15a4\xA3Wa4\xA2a4]V[[` \x83\x01\x92P`@\x82\x026\x03\x83\x13\x15a4\xBFWa4\xBEa4aV[[P\x92P\x92\x90PV[__\xFD[__\xFD[__\xFD[__\x835`\x01` \x03\x846\x03\x03\x81\x12a4\xEFWa4\xEEa4\xCFV[[\x83\x81\x01\x92P\x825\x91P` \x83\x01\x92Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15a5\x17Wa5\x16a4\xC7V[[`@\x82\x026\x03\x83\x13\x15a5-Wa5,a4\xCBV[[P\x92P\x92\x90PV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[_\x81\x90P\x91\x90PV[_a5\\` \x84\x01\x84a%\x0BV[\x90P\x92\x91PPV[_a5r` \x84\x01\x84a*\x8BV[\x90P\x92\x91PPV[`@\x82\x01a5\x8A_\x83\x01\x83a5NV[a5\x96_\x85\x01\x82a'NV[Pa5\xA4` \x83\x01\x83a5dV[a5\xB1` \x85\x01\x82a&\x03V[PPPPV[_a5\xC2\x83\x83a5zV[`@\x83\x01\x90P\x92\x91PPV[_\x82\x90P\x92\x91PPV[_`@\x82\x01\x90P\x91\x90PV[_a5\xEF\x83\x85a55V[\x93Pa5\xFA\x82a5EV[\x80_[\x85\x81\x10\x15a62Wa6\x0F\x82\x84a5\xCEV[a6\x19\x88\x82a5\xB7V[\x97Pa6$\x83a5\xD8V[\x92PP`\x01\x81\x01\x90Pa5\xFDV[P\x85\x92PPP\x93\x92PPPV[_`@\x83\x01a6P_\x84\x01\x84a4\xD3V[\x85\x83\x03_\x87\x01Ra6b\x83\x82\x84a5\xE4V[\x92PPPa6s` \x84\x01\x84a5NV[a6\x80` \x86\x01\x82a'NV[P\x80\x91PP\x92\x91PPV[_``\x82\x01\x90Pa6\x9E_\x83\x01\x86a-\xF8V[\x81\x81\x03` \x83\x01Ra6\xB0\x81\x85a6?V[\x90Pa6\xBF`@\x83\x01\x84a,\x0EV[\x94\x93PPPPV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[\x82\x81\x837_\x83\x83\x01RPPPV[_a6\xF0\x83\x85a6\xC7V[\x93Pa6\xFD\x83\x85\x84a6\xD7V[a7\x06\x83a&:V[\x84\x01\x90P\x93\x92PPPV[_``\x82\x01\x90Pa7$_\x83\x01\x87a.\x07V[\x81\x81\x03` \x83\x01Ra77\x81\x85\x87a6\xE5V[\x90Pa7F`@\x83\x01\x84a,\x0EV[\x95\x94PPPPPV[\x7Fempty operator data\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a7\x83`\x13\x83a*\xCAV[\x91Pa7\x8E\x82a7OV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra7\xB0\x81a7wV[\x90P\x91\x90PV[\x7Foperator data too large\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a7\xEB`\x17\x83a*\xCAV[\x91Pa7\xF6\x82a7\xB7V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra8\x18\x81a7\xDFV[\x90P\x91\x90PV\xFE\xA2dipfsX\"\x12 Pp\xBF\xB7\x8C\xBAO\xB2\x04\xCE:\x9A\xE2K_q\x0Cbs!v6^\xE88\x9C\xDA\xB1\x8C<-qdsolcC\0\x08\x1C\x003", + b"`\x80`@R4\x80\x15a\0\x0FW__\xFD[P`\x046\x10a\0\xA7W_5`\xE0\x1C\x80c\xAD6\xE6\xD0\x11a\0oW\x80c\xAD6\xE6\xD0\x14a\x01'W\x80c\xC10\x80\x9A\x14a\x011W\x80c\xCD\xBF\xC6-\x14a\x01;W\x80c\xDD?\xD2i\x14a\x01WW\x80c\xF0\x19\xB1T\x14a\x01sW\x80c\xF2\xFD\xE3\x8B\x14a\x01\x8FWa\0\xA7V[\x80c0H\xBF\xBA\x14a\0\xABW\x80cU\xA4}\n\x14a\0\xB5W\x80cepo\x9C\x14a\0\xD1W\x80cuA\x8B\x9D\x14a\0\xEDW\x80c\x8BRR\xD6\x14a\x01\x0BW[__\xFD[a\0\xB3a\x01\xABV[\0[a\0\xCF`\x04\x806\x03\x81\x01\x90a\0\xCA\x91\x90a%\x1FV[a\x03\x7FV[\0[a\0\xEB`\x04\x806\x03\x81\x01\x90a\0\xE6\x91\x90a%\x7FV[a\x06\xBDV[\0[a\0\xF5a\x07aV[`@Qa\x01\x02\x91\x90a(\xBCV[`@Q\x80\x91\x03\x90\xF3[a\x01%`\x04\x806\x03\x81\x01\x90a\x01 \x91\x90a)=V[a\x0F\x8FV[\0[a\x01/a\x0F\xECV[\0[a\x019a\x11\xC6V[\0[a\x01U`\x04\x806\x03\x81\x01\x90a\x01P\x91\x90a)\xA6V[a\x13\xC9V[\0[a\x01q`\x04\x806\x03\x81\x01\x90a\x01l\x91\x90a)\xEDV[a\x1A\x99V[\0[a\x01\x8D`\x04\x806\x03\x81\x01\x90a\x01\x88\x91\x90a*\x18V[a\x1D\x15V[\0[a\x01\xA9`\x04\x806\x03\x81\x01\x90a\x01\xA4\x91\x90a*\x9FV[a \xABV[\0[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x029W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x020\x90a+$V[`@Q\x80\x91\x03\x90\xFD[a\x02Aa!{V[a\x02\x80W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x02w\x90a+\x8CV[`@Q\x80\x91\x03\x90\xFD[_a\x02\n_\x01_a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x02\xF1\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\x8F\xB9\xCD\x05M\n\x02!\x10\xCC\xED#\x9E\x90\x8B\x83NL\xD2\x19Q\x18V\xD4\xEA\xAE0Q\xD92\xD6\x04a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x03u\x91\x90a,\x1DV[`@Q\x80\x91\x03\x90\xA1V[a\x03\x87a!\xD5V[a\x03\xC6W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x03\xBD\x90a,\x80V[`@Q\x80\x91\x03\x90\xFD[a\x02\x08_\x01_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x82g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x044W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x04+\x90a,\xE8V[`@Q\x80\x91\x03\x90\xFD[3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x80a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x04o\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x81\x10a\x04\x8AWa\x04\x89a-cV[[a\x01\x02\x02\x01_\x01\x82`\xFF\x16a\x01\0\x81\x10a\x04\xA7Wa\x04\xA6a-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x05\x1EW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x05\x15\x90a-\xDAV[`@Q\x80\x91\x03\x90\xFD[a\x057\x81a\x02\x08`\x01\x01Ta!\xE5\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x06\xB9Wa\x05T\x81a\x02\x08`\x01\x01Ta!\xFA\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x02\x08`\x01\x01\x81\x90UPa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x05\x8C\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP_a\x02\x08`\x01\x01T\x03a\x06FW\x7F\x01&\x98yS_@\xEE\x89W\xE1^\x16\x0B\xF1\x86l^'(\xFF\x0C\xBCX=\x84\x88!\xE2c\x9BNa\x02\x08_\x01_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x069\x93\x92\x91\x90a.\x16V[`@Q\x80\x91\x03\x90\xA1a\x06\xB8V[\x7F\xAF^\x90\xE7 \x15\xF418\xF6kL\xD0\x8B\xD1\xDF\xA2\x83\x900\x10O\"\xA0\n\xF8C\xFE\x84|m\x19a\x02\x08_\x01_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x06\xAF\x93\x92\x91\x90a.\x16V[`@Q\x80\x91\x03\x90\xA1[[PPV[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x07KW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x07B\x90a+$V[`@Q\x80\x91\x03\x90\xFD[\x80a\x02\x07\x81\x81a\x07[\x91\x90a/*V[\x90PPPV[a\x07ia#\xA7V[a\x07qa#\xA7V[___a\x07|a!\xD5V[\x15a\x0B\xB9Wa\x02\x08_\x01_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x84` \x01Q_\x01\x90g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RPPa\x02\x08`\x01\x01T\x84` \x01Q` \x01\x81\x81RPP`\x02`\x01a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x07\xF5\x91\x90a/8V[a\x07\xFF\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x92P_`\x02a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x08/\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90Pa\x08a`\x02\x82`\x02\x81\x10a\x08RWa\x08Qa-cV[[a\x01\x02\x02\x01a\x01\0\x01Ta\"\x0EV[\x91P`\x01\x82a\x08p\x91\x90a/sV[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x08\x89Wa\x08\x88a/\xA6V[[`@Q\x90\x80\x82R\x80` \x02` \x01\x82\x01`@R\x80\x15a\x08\xC2W\x81` \x01[a\x08\xAFa$\x0FV[\x81R` \x01\x90`\x01\x90\x03\x90\x81a\x08\xA7W\x90P[P\x85`@\x01Q_\x01\x81\x90RP`\x02\x81`\x02\x81\x10a\x08\xE2Wa\x08\xE1a-cV[[a\x01\x02\x02\x01a\x01\x01\x01_\x90T\x90a\x01\0\n\x90\x04`\xFF\x16\x85`@\x01Q` \x01\x90`\xFF\x16\x90\x81`\xFF\x16\x81RPP__\x90P[\x82\x81\x11a\x0B\xB2Wa\tI\x81`\x02\x84`\x02\x81\x10a\t1Wa\t0a-cV[[a\x01\x02\x02\x01a\x01\0\x01Ta!\xE5\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x0B\x9FW`\x02\x82`\x02\x81\x10a\taWa\t`a-cV[[a\x01\x02\x02\x01_\x01\x81a\x01\0\x81\x10a\t{Wa\tza-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x93P\x83\x86`@\x01Q_\x01Q\x82\x81Q\x81\x10a\t\xB9Wa\t\xB8a-cV[[` \x02` \x01\x01Q_\x01\x90s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RPPa\n&\x81`\x02\x87`\x02\x81\x10a\n\x0EWa\n\ra-cV[[a\x01\x02\x02\x01a\x01\0\x01Ta!\xE5\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x80a\n\xABWP\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x86`\x02\x81\x10a\nWWa\nVa-cV[[a\x01\x02\x02\x01_\x01\x82a\x01\0\x81\x10a\nqWa\npa-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14\x15[\x15a\x0B\x9EW`\x01_\x85s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ \x80Ta\n\xF8\x90a0\0V[\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01\x82\x80Ta\x0B$\x90a0\0V[\x80\x15a\x0BoW\x80`\x1F\x10a\x0BFWa\x01\0\x80\x83T\x04\x02\x83R\x91` \x01\x91a\x0BoV[\x82\x01\x91\x90_R` _ \x90[\x81T\x81R\x90`\x01\x01\x90` \x01\x80\x83\x11a\x0BRW\x82\x90\x03`\x1F\x16\x82\x01\x91[PPPPP\x86`@\x01Q_\x01Q\x82\x81Q\x81\x10a\x0B\x8EWa\x0B\x8Da-cV[[` \x02` \x01\x01Q` \x01\x81\x90RP[[\x80\x80a\x0B\xAA\x90a00V[\x91PPa\t\x12V[PPa\x0B\xE9V[`\x02a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x0B\xDC\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x92P[a\x0C\x0F`\x02\x84`\x02\x81\x10a\x0C\0Wa\x0B\xFFa-cV[[a\x01\x02\x02\x01a\x01\0\x01Ta\"\x0EV[\x90P`\x01\x81a\x0C\x1E\x91\x90a/sV[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x0C7Wa\x0C6a/\xA6V[[`@Q\x90\x80\x82R\x80` \x02` \x01\x82\x01`@R\x80\x15a\x0CpW\x81` \x01[a\x0C]a$\x0FV[\x81R` \x01\x90`\x01\x90\x03\x90\x81a\x0CUW\x90P[P\x84_\x01Q_\x01\x81\x90RP`\x02\x83`\x02\x81\x10a\x0C\x8FWa\x0C\x8Ea-cV[[a\x01\x02\x02\x01a\x01\x01\x01_\x90T\x90a\x01\0\n\x90\x04`\xFF\x16\x84_\x01Q` \x01\x90`\xFF\x16\x90\x81`\xFF\x16\x81RPP__\x90P[\x81\x81\x11a\x0E\xA1Wa\x0C\xF5\x81`\x02\x86`\x02\x81\x10a\x0C\xDDWa\x0C\xDCa-cV[[a\x01\x02\x02\x01a\x01\0\x01Ta!\xE5\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x0E\x8EW`\x02\x84`\x02\x81\x10a\r\rWa\r\x0Ca-cV[[a\x01\x02\x02\x01_\x01\x81a\x01\0\x81\x10a\r'Wa\r&a-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x92P\x82\x85_\x01Q_\x01Q\x82\x81Q\x81\x10a\rdWa\rca-cV[[` \x02` \x01\x01Q_\x01\x90s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RPP`\x01_\x84s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ \x80Ta\r\xE9\x90a0\0V[\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01\x82\x80Ta\x0E\x15\x90a0\0V[\x80\x15a\x0E`W\x80`\x1F\x10a\x0E7Wa\x01\0\x80\x83T\x04\x02\x83R\x91` \x01\x91a\x0E`V[\x82\x01\x91\x90_R` _ \x90[\x81T\x81R\x90`\x01\x01\x90` \x01\x80\x83\x11a\x0ECW\x82\x90\x03`\x1F\x16\x82\x01\x91[PPPPP\x85_\x01Q_\x01Q\x82\x81Q\x81\x10a\x0E~Wa\x0E}a-cV[[` \x02` \x01\x01Q` \x01\x81\x90RP[\x80\x80a\x0E\x99\x90a00V[\x91PPa\x0C\xBEV[Pa\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x84`\x80\x01\x90g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RPPa\x02\n_\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x84``\x01Q_\x01\x90s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RPPa\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x84`\xA0\x01\x90o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RPP\x83\x94PPPPP\x90V[a\x0F\x9B\x82\x82\x90Pa\"\x1FV[\x81\x81`\x01_3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ \x91\x82a\x0F\xE7\x92\x91\x90a2\x18V[PPPV[a\x0F\xF4a!{V[a\x103W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x10*\x90a+\x8CV[`@Q\x80\x91\x03\x90\xFD[3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x02\n_\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x10\xC5W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x10\xBC\x90a-\xDAV[`@Q\x80\x91\x03\x90\xFD[_a\x02\n_\x01_a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x116\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\xF9\x10g\xEBB\x0C(\xD3\x12He\xFC\x99nj\xA9\xD5A\xB9\xB4\xFE\xF9\x18\x8C\xB9e\xA6\xCCd\x91c\x8E3a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x11\xBC\x92\x91\x90a2\xE5V[`@Q\x80\x91\x03\x90\xA1V[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x12TW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x12K\x90a+$V[`@Q\x80\x91\x03\x90\xFD[a\x12\\a!\xD5V[a\x12\x9BW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x12\x92\x90a,\x80V[`@Q\x80\x91\x03\x90\xFD[a\x02\x06_\x81\x81\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x12\xC1\x90a3\x0CV[\x91\x90a\x01\0\n\x81T\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP_a\x02\x08`\x01\x01\x81\x90UPa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x13!\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\xF72@B\"F\xF6>\xD63\xEF<\xE0rk\x8A\xB8\xFBi\xD4l\x8AN^\xCB\x0B)\"f\x86t\xA1a\x02\x08_\x01_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x13\xBF\x92\x91\x90a33V[`@Q\x80\x91\x03\x90\xA1V[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x14WW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x14N\x90a+$V[`@Q\x80\x91\x03\x90\xFD[a\x14_a!\xD5V[\x15a\x14\x9FW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x14\x96\x90a3\xA4V[`@Q\x80\x91\x03\x90\xFD[a\x14\xA7a!{V[\x15a\x14\xE7W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x14\xDE\x90a4\x0CV[`@Q\x80\x91\x03\x90\xFD[a\x02\x08_\x01_\x81\x81\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x15\x0F\x90a4*V[\x91\x90a\x01\0\n\x81T\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP_`\x02a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x15Z\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90Pa\x02\x06_\x81\x81\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x15\x8C\x90a4*V[\x91\x90a\x01\0\n\x81T\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP_`\x02a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x15\xD7\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90P__\x90P[a\x16\x0E`\x02\x84`\x02\x81\x10a\x15\xFFWa\x15\xFEa-cV[[a\x01\x02\x02\x01a\x01\0\x01Ta\"\x0EV[\x81\x11a\x17\xB2W`\x02\x83`\x02\x81\x10a\x16(Wa\x16'a-cV[[a\x01\x02\x02\x01_\x01\x81a\x01\0\x81\x10a\x16BWa\x16Aa-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x83`\x02\x81\x10a\x16\x8DWa\x16\x8Ca-cV[[a\x01\x02\x02\x01_\x01\x82a\x01\0\x81\x10a\x16\xA7Wa\x16\xA6a-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x17\x9FW`\x02\x83`\x02\x81\x10a\x16\xF7Wa\x16\xF6a-cV[[a\x01\x02\x02\x01_\x01\x81a\x01\0\x81\x10a\x17\x11Wa\x17\x10a-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x83`\x02\x81\x10a\x17FWa\x17Ea-cV[[a\x01\x02\x02\x01_\x01\x82a\x01\0\x81\x10a\x17`Wa\x17_a-cV[[\x01_a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UP[\x80\x80a\x17\xAA\x90a00V[\x91PPa\x15\xE8V[P_`\x02\x83`\x02\x81\x10a\x17\xC8Wa\x17\xC7a-cV[[a\x01\x02\x02\x01a\x01\0\x01T\x90P____\x90P[\x86\x80_\x01\x90a\x17\xEA\x91\x90a4eV[\x90P\x81\x10\x15a\x19FW\x86\x80_\x01\x90a\x18\x02\x91\x90a4eV[\x82\x81\x81\x10a\x18\x13Wa\x18\x12a-cV[[\x90P`@\x02\x01_\x01` \x81\x01\x90a\x18*\x91\x90a)\xEDV[\x92P\x86\x80_\x01\x90a\x18;\x91\x90a4eV[\x82\x81\x81\x10a\x18LWa\x18Ka-cV[[\x90P`@\x02\x01` \x01` \x81\x01\x90a\x18d\x91\x90a*\x9FV[\x91P_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x82s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x03a\x18\xB3Wa\x18\xAC\x83\x85a!\xFA\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x93Pa\x18\xC9V[a\x18\xC6\x83\x85a\"\xBD\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x93P[\x81`\x02\x86`\x02\x81\x10a\x18\xDEWa\x18\xDDa-cV[[a\x01\x02\x02\x01_\x01\x84`\xFF\x16a\x01\0\x81\x10a\x18\xFBWa\x18\xFAa-cV[[\x01_a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UP\x80\x80`\x01\x01\x91PPa\x17\xDBV[P\x82`\x02\x85`\x02\x81\x10a\x19\\Wa\x19[a-cV[[a\x01\x02\x02\x01a\x01\0\x01\x81\x90UP\x85` \x01` \x81\x01\x90a\x19|\x91\x90a)\xEDV[`\x02\x85`\x02\x81\x10a\x19\x90Wa\x19\x8Fa-cV[[a\x01\x02\x02\x01a\x01\x01\x01_a\x01\0\n\x81T\x81`\xFF\x02\x19\x16\x90\x83`\xFF\x16\x02\x17\x90UP\x82a\x02\x08`\x01\x01\x81\x90UPa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x19\xE9\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7Fx\xDA\xD2\xBC\x0BG\xC6\x88\xED\x84\xF3\xFE\xE7\x9A\xBC\x18\xE6\xC9\x82-\xB0Zy\xCA\x19\xDF\xF5E3\xC7G\ra\x02\x08_\x01_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x87a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x1A\x89\x93\x92\x91\x90a6\x8BV[`@Q\x80\x91\x03\x90\xA1PPPPPPV[a\x1A\xA1a!\xD5V[\x15a\x1A\xE1W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x1A\xD8\x90a3\xA4V[`@Q\x80\x91\x03\x90\xFD[a\x1A\xE9a!{V[\x15a\x1B)W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x1B \x90a4\x0CV[`@Q\x80\x91\x03\x90\xFD[3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x80a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x1Bd\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x81\x10a\x1B\x7FWa\x1B~a-cV[[a\x01\x02\x02\x01_\x01\x82`\xFF\x16a\x01\0\x81\x10a\x1B\x9CWa\x1B\x9Ba-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x1C\x13W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x1C\n\x90a-\xDAV[`@Q\x80\x91\x03\x90\xFD[3a\x02\n_\x01_a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x1C\x84\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\xBC'H\xCF\x02\xF7\xA1)\x15%\xE8f\xEF\xC7j\xB3\xB9m2\xD7\xAF\xCB\xB2lS\xDA\xECa{8\xB4y3a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x1D\n\x92\x91\x90a2\xE5V[`@Q\x80\x91\x03\x90\xA1PV[a\x1D!\x82\x82\x90Pa\"\x1FV[__a\x1D+a!\xD5V[\x15a\x1E\xA1W3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x80`\x01a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x1Dm\x91\x90a/8V[a\x1Dw\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x81\x10a\x1D\x92Wa\x1D\x91a-cV[[a\x01\x02\x02\x01_\x01\x86`\xFF\x16a\x01\0\x81\x10a\x1D\xAFWa\x1D\xAEa-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14\x91P\x81a\x1E\x9CW3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x80a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x1E)\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x81\x10a\x1EDWa\x1ECa-cV[[a\x01\x02\x02\x01_\x01\x86`\xFF\x16a\x01\0\x81\x10a\x1EaWa\x1E`a-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14\x90P[a\x1FOV[3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x80a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x1E\xDC\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x81\x10a\x1E\xF7Wa\x1E\xF6a-cV[[a\x01\x02\x02\x01_\x01\x86`\xFF\x16a\x01\0\x81\x10a\x1F\x14Wa\x1F\x13a-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14\x91P[\x81\x80a\x1FXWP\x80[a\x1F\x97W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x1F\x8E\x90a-\xDAV[`@Q\x80\x91\x03\x90\xFD[\x83\x83`\x01_3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ \x91\x82a\x1F\xE3\x92\x91\x90a2\x18V[Pa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a \x12\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\x12Q\x81\xEC!\x88-\xECQ\xA29)\x05\xDF\xF3\xA8,\xBD\x02b\xF1\x8B\\\x0C\x03T\x88g\x1B@\xAF\xB23\x85\x85a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa \x9C\x94\x93\x92\x91\x90a7\x11V[`@Q\x80\x91\x03\x90\xA1PPPPPV[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a!9W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a!0\x90a+$V[`@Q\x80\x91\x03\x90\xFD[\x80__a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPPV[__s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x02\n_\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14\x15\x90P\x90V[__a\x02\x08`\x01\x01T\x14\x15\x90P\x90V[__\x82`\xFF\x16`\x01\x90\x1B\x84\x16\x14\x90P\x92\x91PPV[_\x81`\xFF\x16`\x01\x90\x1B\x19\x83\x16\x90P\x92\x91PPV[_a\"\x18\x82a\"\xD0V[\x90P\x91\x90PV[_\x81\x11a\"aW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\"X\x90a7\x99V[`@Q\x80\x91\x03\x90\xFD[a\x02\x07_\x01_\x90T\x90a\x01\0\n\x90\x04a\xFF\xFF\x16a\xFF\xFF\x16\x81\x11\x15a\"\xBAW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\"\xB1\x90a8\x01V[`@Q\x80\x91\x03\x90\xFD[PV[_\x81`\xFF\x16`\x01\x90\x1B\x83\x17\x90P\x92\x91PPV[_`\x07a\"\xEEo\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x84\x11a#\x9CV[\x90\x1B\x90P`\x06a#\ng\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x83\x85\x90\x1C\x11a#\x9CV[\x90\x1B\x81\x17\x90P`\x05a#$c\xFF\xFF\xFF\xFF\x83\x85\x90\x1C\x11a#\x9CV[\x90\x1B\x81\x17\x90P`\x04a#V[\x81R` \x01a#\xC7a$ZV[\x81R` \x01a#\xD4a$>V[\x81R` \x01a#\xE1a$|V[\x81R` \x01_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01_o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RP\x90V[`@Q\x80`@\x01`@R\x80_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01``\x81RP\x90V[`@Q\x80`@\x01`@R\x80``\x81R` \x01_`\xFF\x16\x81RP\x90V[`@Q\x80`@\x01`@R\x80_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01_\x81RP\x90V[`@Q\x80` \x01`@R\x80_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RP\x90V[__\xFD[__\xFD[_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[a$\xC8\x81a$\xACV[\x81\x14a$\xD2W__\xFD[PV[_\x815\x90Pa$\xE3\x81a$\xBFV[\x92\x91PPV[_`\xFF\x82\x16\x90P\x91\x90PV[a$\xFE\x81a$\xE9V[\x81\x14a%\x08W__\xFD[PV[_\x815\x90Pa%\x19\x81a$\xF5V[\x92\x91PPV[__`@\x83\x85\x03\x12\x15a%5Wa%4a$\xA4V[[_a%B\x85\x82\x86\x01a$\xD5V[\x92PP` a%S\x85\x82\x86\x01a%\x0BV[\x91PP\x92P\x92\x90PV[__\xFD[_` \x82\x84\x03\x12\x15a%vWa%ua%]V[[\x81\x90P\x92\x91PPV[_` \x82\x84\x03\x12\x15a%\x94Wa%\x93a$\xA4V[[_a%\xA1\x84\x82\x85\x01a%aV[\x91PP\x92\x91PPV[_\x81Q\x90P\x91\x90PV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[_\x81\x90P` \x82\x01\x90P\x91\x90PV[_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[_a%\xFC\x82a%\xD3V[\x90P\x91\x90PV[a&\x0C\x81a%\xF2V[\x82RPPV[_\x81Q\x90P\x91\x90PV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[\x82\x81\x83^_\x83\x83\x01RPPPV[_`\x1F\x19`\x1F\x83\x01\x16\x90P\x91\x90PV[_a&T\x82a&\x12V[a&^\x81\x85a&\x1CV[\x93Pa&n\x81\x85` \x86\x01a&,V[a&w\x81a&:V[\x84\x01\x91PP\x92\x91PPV[_`@\x83\x01_\x83\x01Qa&\x97_\x86\x01\x82a&\x03V[P` \x83\x01Q\x84\x82\x03` \x86\x01Ra&\xAF\x82\x82a&JV[\x91PP\x80\x91PP\x92\x91PPV[_a&\xC7\x83\x83a&\x82V[\x90P\x92\x91PPV[_` \x82\x01\x90P\x91\x90PV[_a&\xE5\x82a%\xAAV[a&\xEF\x81\x85a%\xB4V[\x93P\x83` \x82\x02\x85\x01a'\x01\x85a%\xC4V[\x80_[\x85\x81\x10\x15a'\x82a1 V[\x84\x84Ta0\xAEV[\x82UPPPPV[__\x90P\x90V[a1]a1NV[a1h\x81\x84\x84a1)V[PPPV[[\x81\x81\x10\x15a1\x8BWa1\x80_\x82a1UV[`\x01\x81\x01\x90Pa1nV[PPV[`\x1F\x82\x11\x15a1\xD0Wa1\xA1\x81a0\x81V[a1\xAA\x84a0\x93V[\x81\x01` \x85\x10\x15a1\xB9W\x81\x90P[a1\xCDa1\xC5\x85a0\x93V[\x83\x01\x82a1mV[PP[PPPV[_\x82\x82\x1C\x90P\x92\x91PPV[_a1\xF0_\x19\x84`\x08\x02a1\xD5V[\x19\x80\x83\x16\x91PP\x92\x91PPV[_a2\x08\x83\x83a1\xE1V[\x91P\x82`\x02\x02\x82\x17\x90P\x92\x91PPV[a2\"\x83\x83a0wV[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a2;Wa2:a/\xA6V[[a2E\x82Ta0\0V[a2P\x82\x82\x85a1\x8FV[_`\x1F\x83\x11`\x01\x81\x14a2}W_\x84\x15a2kW\x82\x87\x015\x90P[a2u\x85\x82a1\xFDV[\x86UPa2\xDCV[`\x1F\x19\x84\x16a2\x8B\x86a0\x81V[_[\x82\x81\x10\x15a2\xB2W\x84\x89\x015\x82U`\x01\x82\x01\x91P` \x85\x01\x94P` \x81\x01\x90Pa2\x8DV[\x86\x83\x10\x15a2\xCFW\x84\x89\x015a2\xCB`\x1F\x89\x16\x82a1\xE1V[\x83UP[`\x01`\x02\x88\x02\x01\x88UPPP[PPPPPPPV[_`@\x82\x01\x90Pa2\xF8_\x83\x01\x85a.\x07V[a3\x05` \x83\x01\x84a,\x0EV[\x93\x92PPPV[_a3\x16\x82a$\xACV[\x91P_\x82\x03a3(Wa3'a+\xAAV[[`\x01\x82\x03\x90P\x91\x90PV[_`@\x82\x01\x90Pa3F_\x83\x01\x85a-\xF8V[a3S` \x83\x01\x84a,\x0EV[\x93\x92PPPV[\x7Fmigration in progress\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a3\x8E`\x15\x83a*\xCAV[\x91Pa3\x99\x82a3ZV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra3\xBB\x81a3\x82V[\x90P\x91\x90PV[\x7Fmaintenance in progress\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a3\xF6`\x17\x83a*\xCAV[\x91Pa4\x01\x82a3\xC2V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra4#\x81a3\xEAV[\x90P\x91\x90PV[_a44\x82a$\xACV[\x91Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x03a4NWa4Ma+\xAAV[[`\x01\x82\x01\x90P\x91\x90PV[__\xFD[__\xFD[__\xFD[__\x835`\x01` \x03\x846\x03\x03\x81\x12a4\x81Wa4\x80a4YV[[\x80\x84\x01\x92P\x825\x91Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15a4\xA3Wa4\xA2a4]V[[` \x83\x01\x92P`@\x82\x026\x03\x83\x13\x15a4\xBFWa4\xBEa4aV[[P\x92P\x92\x90PV[__\xFD[__\xFD[__\xFD[__\x835`\x01` \x03\x846\x03\x03\x81\x12a4\xEFWa4\xEEa4\xCFV[[\x83\x81\x01\x92P\x825\x91P` \x83\x01\x92Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15a5\x17Wa5\x16a4\xC7V[[`@\x82\x026\x03\x83\x13\x15a5-Wa5,a4\xCBV[[P\x92P\x92\x90PV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[_\x81\x90P\x91\x90PV[_a5\\` \x84\x01\x84a%\x0BV[\x90P\x92\x91PPV[_a5r` \x84\x01\x84a*\x8BV[\x90P\x92\x91PPV[`@\x82\x01a5\x8A_\x83\x01\x83a5NV[a5\x96_\x85\x01\x82a'NV[Pa5\xA4` \x83\x01\x83a5dV[a5\xB1` \x85\x01\x82a&\x03V[PPPPV[_a5\xC2\x83\x83a5zV[`@\x83\x01\x90P\x92\x91PPV[_\x82\x90P\x92\x91PPV[_`@\x82\x01\x90P\x91\x90PV[_a5\xEF\x83\x85a55V[\x93Pa5\xFA\x82a5EV[\x80_[\x85\x81\x10\x15a62Wa6\x0F\x82\x84a5\xCEV[a6\x19\x88\x82a5\xB7V[\x97Pa6$\x83a5\xD8V[\x92PP`\x01\x81\x01\x90Pa5\xFDV[P\x85\x92PPP\x93\x92PPPV[_`@\x83\x01a6P_\x84\x01\x84a4\xD3V[\x85\x83\x03_\x87\x01Ra6b\x83\x82\x84a5\xE4V[\x92PPPa6s` \x84\x01\x84a5NV[a6\x80` \x86\x01\x82a'NV[P\x80\x91PP\x92\x91PPV[_``\x82\x01\x90Pa6\x9E_\x83\x01\x86a-\xF8V[\x81\x81\x03` \x83\x01Ra6\xB0\x81\x85a6?V[\x90Pa6\xBF`@\x83\x01\x84a,\x0EV[\x94\x93PPPPV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[\x82\x81\x837_\x83\x83\x01RPPPV[_a6\xF0\x83\x85a6\xC7V[\x93Pa6\xFD\x83\x85\x84a6\xD7V[a7\x06\x83a&:V[\x84\x01\x90P\x93\x92PPPV[_``\x82\x01\x90Pa7$_\x83\x01\x87a.\x07V[\x81\x81\x03` \x83\x01Ra77\x81\x85\x87a6\xE5V[\x90Pa7F`@\x83\x01\x84a,\x0EV[\x95\x94PPPPPV[\x7Fempty operator data\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a7\x83`\x13\x83a*\xCAV[\x91Pa7\x8E\x82a7OV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra7\xB0\x81a7wV[\x90P\x91\x90PV[\x7Foperator data too large\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a7\xEB`\x17\x83a*\xCAV[\x91Pa7\xF6\x82a7\xB7V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra8\x18\x81a7\xDFV[\x90P\x91\x90PV\xFE\xA2dipfsX\"\x12 \xFA\x04\xDE\xADB^j\xA2\xEEQe+w\xCD\x8B\xEC4O\x89\xD5\xA5\xD1\x8BB\xF4\x88\x9Bz\xBA\xD1s\"dsolcC\0\x08\x1C\x003", ); /**```solidity -struct ClusterView { KeyspaceView primaryKeyspace; KeyspaceView secondaryKeyspace; uint64 keyspaceVersion; Migration migration; Maintenance maintenance; uint128 version; } +struct ClusterView { KeyspaceView keyspace; Migration migration; KeyspaceView migrationKeyspace; Maintenance maintenance; uint64 keyspaceVersion; uint128 version; } ```*/ #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] pub struct ClusterView { #[allow(missing_docs)] - pub primaryKeyspace: ::RustType, - #[allow(missing_docs)] - pub secondaryKeyspace: ::RustType, - #[allow(missing_docs)] - pub keyspaceVersion: u64, + pub keyspace: ::RustType, #[allow(missing_docs)] pub migration: ::RustType, #[allow(missing_docs)] + pub migrationKeyspace: ::RustType, + #[allow(missing_docs)] pub maintenance: ::RustType, #[allow(missing_docs)] + pub keyspaceVersion: u64, + #[allow(missing_docs)] pub version: u128, } #[allow( @@ -615,19 +615,19 @@ struct ClusterView { KeyspaceView primaryKeyspace; KeyspaceView secondaryKeyspac #[doc(hidden)] type UnderlyingSolTuple<'a> = ( KeyspaceView, - KeyspaceView, - alloy::sol_types::sol_data::Uint<64>, Migration, + KeyspaceView, Maintenance, + alloy::sol_types::sol_data::Uint<64>, alloy::sol_types::sol_data::Uint<128>, ); #[doc(hidden)] type UnderlyingRustTuple<'a> = ( ::RustType, - ::RustType, - u64, ::RustType, + ::RustType, ::RustType, + u64, u128, ); #[cfg(test)] @@ -646,11 +646,11 @@ struct ClusterView { KeyspaceView primaryKeyspace; KeyspaceView secondaryKeyspac impl ::core::convert::From for UnderlyingRustTuple<'_> { fn from(value: ClusterView) -> Self { ( - value.primaryKeyspace, - value.secondaryKeyspace, - value.keyspaceVersion, + value.keyspace, value.migration, + value.migrationKeyspace, value.maintenance, + value.keyspaceVersion, value.version, ) } @@ -660,11 +660,11 @@ struct ClusterView { KeyspaceView primaryKeyspace; KeyspaceView secondaryKeyspac impl ::core::convert::From> for ClusterView { fn from(tuple: UnderlyingRustTuple<'_>) -> Self { Self { - primaryKeyspace: tuple.0, - secondaryKeyspace: tuple.1, - keyspaceVersion: tuple.2, - migration: tuple.3, - maintenance: tuple.4, + keyspace: tuple.0, + migration: tuple.1, + migrationKeyspace: tuple.2, + maintenance: tuple.3, + keyspaceVersion: tuple.4, version: tuple.5, } } @@ -678,19 +678,17 @@ struct ClusterView { KeyspaceView primaryKeyspace; KeyspaceView secondaryKeyspac #[inline] fn stv_to_tokens(&self) -> ::Token<'_> { ( + ::tokenize(&self.keyspace), + ::tokenize(&self.migration), ::tokenize( - &self.primaryKeyspace, + &self.migrationKeyspace, ), - ::tokenize( - &self.secondaryKeyspace, + ::tokenize( + &self.maintenance, ), as alloy_sol_types::SolType>::tokenize(&self.keyspaceVersion), - ::tokenize(&self.migration), - ::tokenize( - &self.maintenance, - ), as alloy_sol_types::SolType>::tokenize(&self.version), @@ -768,7 +766,7 @@ struct ClusterView { KeyspaceView primaryKeyspace; KeyspaceView secondaryKeyspac #[inline] fn eip712_root_type() -> alloy_sol_types::private::Cow<'static, str> { alloy_sol_types::private::Cow::Borrowed( - "ClusterView(KeyspaceView primaryKeyspace,KeyspaceView secondaryKeyspace,uint64 keyspaceVersion,Migration migration,Maintenance maintenance,uint128 version)", + "ClusterView(KeyspaceView keyspace,Migration migration,KeyspaceView migrationKeyspace,Maintenance maintenance,uint64 keyspaceVersion,uint128 version)", ) } #[inline] @@ -785,18 +783,18 @@ struct ClusterView { KeyspaceView primaryKeyspace; KeyspaceView secondaryKeyspac ::eip712_components(), ); components - .push( - ::eip712_root_type(), - ); + .push(::eip712_root_type()); components .extend( - ::eip712_components(), + ::eip712_components(), ); components - .push(::eip712_root_type()); + .push( + ::eip712_root_type(), + ); components .extend( - ::eip712_components(), + ::eip712_components(), ); components .push( @@ -812,11 +810,19 @@ struct ClusterView { KeyspaceView primaryKeyspace; KeyspaceView secondaryKeyspac fn eip712_encode_data(&self) -> alloy_sol_types::private::Vec { [ ::eip712_data_word( - &self.primaryKeyspace, + &self.keyspace, + ) + .0, + ::eip712_data_word( + &self.migration, ) .0, ::eip712_data_word( - &self.secondaryKeyspace, + &self.migrationKeyspace, + ) + .0, + ::eip712_data_word( + &self.maintenance, ) .0, ::eip712_data_word( - &self.migration, - ) - .0, - ::eip712_data_word( - &self.maintenance, - ) - .0, as alloy_sol_types::SolType>::eip712_data_word(&self.version) @@ -847,22 +845,22 @@ struct ClusterView { KeyspaceView primaryKeyspace; KeyspaceView secondaryKeyspac fn topic_preimage_length(rust: &Self::RustType) -> usize { 0usize + ::topic_preimage_length( - &rust.primaryKeyspace, + &rust.keyspace, + ) + + ::topic_preimage_length( + &rust.migration, ) + ::topic_preimage_length( - &rust.secondaryKeyspace, + &rust.migrationKeyspace, + ) + + ::topic_preimage_length( + &rust.maintenance, ) + as alloy_sol_types::EventTopic>::topic_preimage_length( &rust.keyspaceVersion, ) - + ::topic_preimage_length( - &rust.migration, - ) - + ::topic_preimage_length( - &rust.maintenance, - ) + as alloy_sol_types::EventTopic>::topic_preimage_length( @@ -878,11 +876,19 @@ struct ClusterView { KeyspaceView primaryKeyspace; KeyspaceView secondaryKeyspac ::topic_preimage_length(rust), ); ::encode_topic_preimage( - &rust.primaryKeyspace, + &rust.keyspace, + out, + ); + ::encode_topic_preimage( + &rust.migration, out, ); ::encode_topic_preimage( - &rust.secondaryKeyspace, + &rust.migrationKeyspace, + out, + ); + ::encode_topic_preimage( + &rust.maintenance, out, ); ::encode_topic_preimage( - &rust.migration, - out, - ); - ::encode_topic_preimage( - &rust.maintenance, - out, - ); as alloy_sol_types::EventTopic>::encode_topic_preimage( @@ -1787,13 +1785,13 @@ struct Migration { uint64 id; uint256 pullingOperatorsBitmask; } } }; /**```solidity -struct MigrationPlan { KeyspaceSlot[] slotsToUpdate; uint8 replicationStrategy; } +struct MigrationPlan { KeyspaceSlot[] slots; uint8 replicationStrategy; } ```*/ #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] pub struct MigrationPlan { #[allow(missing_docs)] - pub slotsToUpdate: alloy::sol_types::private::Vec< + pub slots: alloy::sol_types::private::Vec< ::RustType, >, #[allow(missing_docs)] @@ -1834,7 +1832,7 @@ struct MigrationPlan { KeyspaceSlot[] slotsToUpdate; uint8 replicationStrategy; #[doc(hidden)] impl ::core::convert::From for UnderlyingRustTuple<'_> { fn from(value: MigrationPlan) -> Self { - (value.slotsToUpdate, value.replicationStrategy) + (value.slots, value.replicationStrategy) } } #[automatically_derived] @@ -1842,7 +1840,7 @@ struct MigrationPlan { KeyspaceSlot[] slotsToUpdate; uint8 replicationStrategy; impl ::core::convert::From> for MigrationPlan { fn from(tuple: UnderlyingRustTuple<'_>) -> Self { Self { - slotsToUpdate: tuple.0, + slots: tuple.0, replicationStrategy: tuple.1, } } @@ -1858,7 +1856,7 @@ struct MigrationPlan { KeyspaceSlot[] slotsToUpdate; uint8 replicationStrategy; ( as alloy_sol_types::SolType>::tokenize(&self.slotsToUpdate), + > as alloy_sol_types::SolType>::tokenize(&self.slots), as alloy_sol_types::SolType>::tokenize(&self.replicationStrategy), @@ -1936,7 +1934,7 @@ struct MigrationPlan { KeyspaceSlot[] slotsToUpdate; uint8 replicationStrategy; #[inline] fn eip712_root_type() -> alloy_sol_types::private::Cow<'static, str> { alloy_sol_types::private::Cow::Borrowed( - "MigrationPlan(KeyspaceSlot[] slotsToUpdate,uint8 replicationStrategy)", + "MigrationPlan(KeyspaceSlot[] slots,uint8 replicationStrategy)", ) } #[inline] @@ -1959,7 +1957,7 @@ struct MigrationPlan { KeyspaceSlot[] slotsToUpdate; uint8 replicationStrategy; [ as alloy_sol_types::SolType>::eip712_data_word(&self.slotsToUpdate) + > as alloy_sol_types::SolType>::eip712_data_word(&self.slots) .0, as alloy_sol_types::EventTopic>::topic_preimage_length( - &rust.slotsToUpdate, - ) + > as alloy_sol_types::EventTopic>::topic_preimage_length(&rust.slots) + as alloy_sol_types::EventTopic>::topic_preimage_length( @@ -1998,7 +1994,7 @@ struct MigrationPlan { KeyspaceSlot[] slotsToUpdate; uint8 replicationStrategy; as alloy_sol_types::EventTopic>::encode_topic_preimage( - &rust.slotsToUpdate, + &rust.slots, out, ); Date: Tue, 20 May 2025 20:37:01 +0000 Subject: [PATCH 19/79] WIP --- Cargo.lock | 62 +++++++ crates/cluster/Cargo.toml | 17 +- crates/cluster/src/contract/evm/mod.rs | 23 ++- .../cluster/src/contract/evm/operator_data.rs | 72 ++++++++ crates/cluster/src/contract/mod.rs | 11 +- crates/cluster/src/event.rs | 40 ----- crates/cluster/src/keyspace.rs | 51 ++++++ crates/cluster/src/lib.rs | 42 +++-- crates/cluster/src/migration.rs | 86 ++++++++++ crates/cluster/src/node.rs | 157 ++++-------------- 10 files changed, 364 insertions(+), 197 deletions(-) create mode 100644 crates/cluster/src/contract/evm/operator_data.rs delete mode 100644 crates/cluster/src/event.rs create mode 100644 crates/cluster/src/keyspace.rs create mode 100644 crates/cluster/src/migration.rs diff --git a/Cargo.lock b/Cargo.lock index 8e0b0e40..738361c9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,6 +23,17 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + [[package]] name = "ahash" version = "0.8.11" @@ -1476,6 +1487,15 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" +[[package]] +name = "cbc" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6" +dependencies = [ + "cipher", +] + [[package]] name = "cc" version = "1.2.22" @@ -1556,6 +1576,16 @@ dependencies = [ "half", ] +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + [[package]] name = "clang-sys" version = "1.7.0" @@ -1628,11 +1658,20 @@ checksum = "b8191fa7302e03607ff0e237d4246cc043ff5b3cb9409d995172ba3bea16b807" name = "cluster" version = "0.1.0" dependencies = [ + "aes", "alloy", + "anyhow", + "arc-swap", + "derive_more 1.0.0", + "fpe", "libp2p", + "postcard", + "serde", "sharding", + "tap", "thiserror 1.0.64", "tokio", + "tracing", ] [[package]] @@ -2581,6 +2620,20 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fpe" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26c4b37de5ae15812a764c958297cfc50f5c010438f60c6ce75d11b802abd404" +dependencies = [ + "cbc", + "cipher", + "libm", + "num-bigint", + "num-integer", + "num-traits", +] + [[package]] name = "fs_extra" version = "1.3.0" @@ -3747,6 +3800,15 @@ dependencies = [ "libc", ] +[[package]] +name = "inout" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" +dependencies = [ + "generic-array", +] + [[package]] name = "instant" version = "0.1.12" diff --git a/crates/cluster/Cargo.toml b/crates/cluster/Cargo.toml index 1343c37b..e1fa8dd0 100644 --- a/crates/cluster/Cargo.toml +++ b/crates/cluster/Cargo.toml @@ -11,11 +11,26 @@ default = ["evm"] evm = ["alloy"] [dependencies] +derive_more = { workspace = true } +libp2p = { workspace = true } + sharding = { path = "../sharding" } alloy = { version = "0.13", default-features = false, features = ["sol-types", "contract", "signer-local", "network"], optional = true } + +anyhow = "1" thiserror = "1" -libp2p = { workspace = true } + +tap = "1.0" +tracing = "0.1" +serde = { version = "1", features = ["derive"] } +postcard = { version = "1.0", default-features = false, features = ["alloc"] } + +fpe = "0.6" +aes = "0.8" + +tokio = { version = "1", features = ["full"] } +arc-swap = "1.7" [dev-dependencies] alloy = { version = "0.13", default-features = false, features = ["provider-anvil-node"] } diff --git a/crates/cluster/src/contract/evm/mod.rs b/crates/cluster/src/contract/evm/mod.rs index 00e09773..5cf90781 100644 --- a/crates/cluster/src/contract/evm/mod.rs +++ b/crates/cluster/src/contract/evm/mod.rs @@ -1,6 +1,8 @@ #[rustfmt::skip] mod bindings; +mod operator_data; + use { alloy::{ network::EthereumWallet, @@ -12,8 +14,7 @@ use { }; pub struct ContractSettings { - pub min_operators: u8, - pub min_nodes: u8, + pub max_operator_data_bytes: u16, } pub struct ContractManager { @@ -79,8 +80,7 @@ impl FromStr for RpcUrl { impl From for bindings::Cluster::Settings { fn from(s: ContractSettings) -> Self { Self { - minOperators: s.min_operators, - minNodes: s.min_nodes, + maxOperatorDataBytes: s.max_operator_data_bytes, } } } @@ -96,3 +96,18 @@ pub struct InvalidPrivateKey(String); #[derive(Debug, thiserror::Error)] #[error("Invalid address: {0:?}")] pub struct InvalidAddress(String); + +impl From
for super::PublicKey { + fn from(addr: Address) -> Self { + // using `Debug` for raw non-checksummed format + Self(format!("{addr:?}")) + } +} + +#[cfg(test)] +mod test { + #[test] + fn address_to_from_public_key_conversion() { + todo!() + } +} diff --git a/crates/cluster/src/contract/evm/operator_data.rs b/crates/cluster/src/contract/evm/operator_data.rs new file mode 100644 index 00000000..76abe14b --- /dev/null +++ b/crates/cluster/src/contract/evm/operator_data.rs @@ -0,0 +1,72 @@ +//! De/serialization for on-chain node operator data. +//! +//! IMPORTANT: The serialization is non self-describing! Every change to the +//! schema should be handled by creating a new version of the schema and bumping +//! the version byte. + +use { + super::Address, + crate::{contract, node}, + aes::Aes256, + anyhow::Context, + fpe::ff1::FF1, + libp2p::PeerId, + serde::{Deserialize, Serialize}, + std::net::SocketAddrV4, +}; + +#[derive(Serialize, Deserialize)] +struct Operator { + name: node::OperatorName, + nodes: Vec, + clients: Vec, +} + +#[derive(Serialize, Deserialize)] +struct Node { + peer_id: PeerId, + addr: SocketAddrV4, +} + +pub(super) fn serialize(operator: node::Operator) -> anyhow::Result> { + let op = Operator { + name: operator.name, + nodes: operator + .nodes + .into_iter() + .map(|node| Node { + peer_id: node.peer_id, + addr: node.addr, + }) + .collect(), + clients: operator.clients, + }; + + // reserve first byte for versioning + let size = postcard::experimental::serialized_size(&op).context("serialize_size")? + 1; + let mut buf = Vec::with_capacity(size); + postcard::to_slice(&op, &mut buf[1..]).context("to_slice")?; + Ok(buf) +} + +pub(super) fn deserialize(operator_addr: Address, buf: &[u8]) -> anyhow::Result { + if buf.is_empty() { + return Err(anyhow::anyhow!("empty buf")); + } + + let operator: Operator = postcard::from_bytes(&buf[1..]).context("from_bytes")?; + + Ok(node::Operator { + id: operator_addr.into(), + name: operator.name, + nodes: operator + .nodes + .into_iter() + .map(|node| crate::Node { + peer_id: node.peer_id, + addr: node.addr, + }) + .collect(), + clients: operator.clients, + }) +} diff --git a/crates/cluster/src/contract/mod.rs b/crates/cluster/src/contract/mod.rs index 53137d9c..a5c8e2e5 100644 --- a/crates/cluster/src/contract/mod.rs +++ b/crates/cluster/src/contract/mod.rs @@ -1,10 +1,15 @@ -use {crate::node, std::future::Future}; +use { + crate::{node, View}, + derive_more::Display, + serde::{Deserialize, Serialize}, + std::{future::Future, sync::Arc}, +}; #[cfg(feature = "evm")] pub mod evm; /// Public key on a chain hosting the [`SmartContract`]. -#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Debug, Display, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct PublicKey(String); pub struct Settings { @@ -33,6 +38,8 @@ pub enum Call { pub trait SmartContract { fn call(&self, call: Call) -> impl Future> + Send; + + fn view(&self) -> Arc; } pub struct Error(String); diff --git a/crates/cluster/src/event.rs b/crates/cluster/src/event.rs deleted file mode 100644 index 5cc94059..00000000 --- a/crates/cluster/src/event.rs +++ /dev/null @@ -1,40 +0,0 @@ -use crate::{NodeOperator, PublicKey}; - -pub struct MigrationStarted { - pub operators_to_remove: Vec, - pub operators_to_add: Vec<(K, NodeOperator)>, - pub version: u128, -} - -pub struct MigrationDataPullCompleted { - pub operator: K, - pub version: u128, -} - -pub struct MigrationCompleted { - pub version: u128, -} - -pub struct MigrationAborted { - pub version: u128, -} - -pub struct MaintenanceStarted { - pub operator: K, - pub version: u8, -} - -pub struct MaintenanceCompleted { - pub operator: K, - pub version: u8, -} - -pub struct MaintenanceAborted { - pub operator: K, - pub version: u8, -} - -pub struct NodeOperatorUpdated { - pub key: K, - pub operator: NodeOperator, -} diff --git a/crates/cluster/src/keyspace.rs b/crates/cluster/src/keyspace.rs new file mode 100644 index 00000000..4ab011da --- /dev/null +++ b/crates/cluster/src/keyspace.rs @@ -0,0 +1,51 @@ +use {crate::node, sharding::ShardId, tap::TapOptional}; + +const REPLICATION_FACTOR: usize = 5; + +/// Strategy of replicating data within a [`Keyspace`] across a set of +/// [`node::Operator`]s. +#[repr(u8)] +#[derive(Clone, Copy, Debug, Default)] +pub enum ReplicationStrategy { + /// Keys are being uniformly distributed across [`node::Operator`]s. + #[default] + UniformDistribution = 0, +} + +/// Continuous space of `u64` keys, where each key is assigned to a set of +/// [`node::Operator`]s. +pub struct Keyspace { + operators: node::Operators, + sharding: sharding::Keyspace, + replication_strategy: ReplicationStrategy, + + version: u64, +} + +impl Keyspace { + /// Required number of [`node::Operator`]s a data should be replicated to. + pub fn replication_factor(&self) -> usize { + REPLICATION_FACTOR + } + + /// Returns the set of [`node::Operator`]s the data under the specified key + /// should be replicated to. + pub fn replicas(&self, key: u64) -> impl Iterator + '_ { + self.sharding + .shard_replicas(ShardId::from_key(key)) + .iter() + .filter_map(|&idx| { + self.operators + .get(idx as usize)? + .as_ref() + .tap_none(|| tracing::warn!("Missing node operator {idx}")) + }) + } + + /// Get [`node::Operators`] map of this [`Kespace`]. + pub(super) fn operators(&self) -> &node::Operators { + &self.operators + } +} + +struct Snapshot {} diff --git a/crates/cluster/src/lib.rs b/crates/cluster/src/lib.rs index f84994a5..d8cc99bd 100644 --- a/crates/cluster/src/lib.rs +++ b/crates/cluster/src/lib.rs @@ -1,4 +1,4 @@ -use std::collections::HashSet; +use std::{collections::HashSet, sync::Arc}; pub mod contract; pub use contract::SmartContract; @@ -6,42 +6,38 @@ pub use contract::SmartContract; pub mod node; pub use node::Node; -const REPLICATION_FACTOR: usize = 5; +mod keyspace; +pub use keyspace::Keyspace; -type Keyspace = sharding::Keyspace; +pub mod migration; +pub use migration::Migration; /// Read-only view of a WCN cluster. pub struct View { - /// - pub operators: node::Operators, - - migration: Migration, - maintenance: Maintenance, - keyspace: Keyspace, - keyspace_version: u64, - + migration: Option, + maintenance: Maintenance, version: u128, } -/// Data migration process within a regional WCN cluster. -pub struct Migration { - /// List of [`node::Operator`]s to be removed from the cluster. - pub operators_to_remove: Vec, - - /// List of [`node::Operator`]s to be added to the cluster. - pub operators_to_add: Vec, +impl View { + /// Returns the primary [`Keyspace`] of this WCN cluster. + pub fn keyspace(&self) -> &Keyspace { + &self.keyspace + } - /// List of [`node::Operator`]s still pulling the data. - pub pulling_operators: HashSet, + /// Returns the ongoing data [`Migration`] of this WCN cluster. + pub fn migration(&self) -> Option<&Migration> { + self.migration.as_ref() + } } -/// Maintenance process within a regional WCN cluster. +/// Maintenance process within a WCN cluster. /// /// Only a single [`node::Operator`] at a time is allowed to be under /// maintenance. -pub struct Maintenance { +struct Maintenance { /// [`node::OperatorId`] of the [`node::Operator`] currently under /// maintenance (if any). - pub slot: Option, + slot: Option, } diff --git a/crates/cluster/src/migration.rs b/crates/cluster/src/migration.rs new file mode 100644 index 00000000..c5719cd0 --- /dev/null +++ b/crates/cluster/src/migration.rs @@ -0,0 +1,86 @@ +use { + crate::{ + keyspace::{self, ReplicationStrategy}, + node, + Keyspace, + View as ClusterView, + }, + std::{collections::HashSet, sync::Arc}, +}; + +/// Data migration process within a WCN cluster. +pub struct Migration { + id: u64, + keyspace: Keyspace, + pulling_operators: HashSet, +} + +impl Migration { + /// Returns the new [`Keyspace`] this [`Migration`] is migrating to. + pub fn keyspace(&self) -> &Keyspace { + &self.keyspace + } +} + +/// [`Migration`] plan. +pub struct Plan { + cluster_view: Arc, + + slots: Vec<(node::OperatorIdx, Option)>, + replication_strategy: ReplicationStrategy, +} + +impl Plan { + /// Creates a new migration [`Plan`]. + pub fn new( + cluster_view: Arc, + remove: Vec, + add: Vec, + ) -> Result { + if cluster_view.migration.is_some() { + return Err(PlanError::MigrationInProgress); + } + + let mut plan = Self { + cluster_view, + slots: Vec::with_capacity(remove.len() + add.len()), + replication_strategy: keyspace::ReplicationStrategy::default(), + }; + + let operators = cluster_view.keyspace.operators(); + + for id in remove { + if !operators.contains(&id) { + return Err(PlanError::UnknownOperator(id)); + } + + plan.push_slot() + } + + Ok() + } + + fn push_slot(&mut self, idx: usize, id: Option) -> Result<(), PlanError> { + let idx = node::OperatorIdx::try_from(idx).map_err(|_| PlanError::IndexOverflow)?; + self.slots.push((idx, id)); + Ok(()) + } +} + +#[derive(Debug, thiserror::Error)] +pub enum PlanError { + #[error("Another migration is already in progress")] + MigrationInProgress, + + #[error("Unknown operator: {0}")] + UnknownOperator(node::OperatorId), + + #[error("Operator already exists: {0}")] + OperatorAlreadyExists(node::OperatorId), + + #[error("Too many operators")] + TooManyOperators, + + #[error("Index overflow")] + IndexOverflow, +} diff --git a/crates/cluster/src/node.rs b/crates/cluster/src/node.rs index 513e8876..55e1be46 100644 --- a/crates/cluster/src/node.rs +++ b/crates/cluster/src/node.rs @@ -1,14 +1,14 @@ use { crate::contract, libp2p::identity::PeerId, - std::{collections::HashMap, mem, net::SocketAddrV4}, + serde::{Deserialize, Serialize}, + std::{collections::HashMap, net::SocketAddrV4}, }; /// Globally unique identifier of an [`Operator`]; pub type OperatorId = contract::PublicKey; -/// Locally unique identifier of an [`Operator`] within a regional WCN cluster -/// keyspace. +/// Locally unique identifier of an [`Operator`] within a WCN cluster. /// /// Refers to a position within the [`Operators`] slot map. pub type OperatorIdx = u8; @@ -17,7 +17,7 @@ pub type OperatorIdx = u8; /// /// Used for informational purposes only. /// Expected to be unique within the cluster, but not enforced to. -#[derive(Debug)] +#[derive(Debug, Serialize, Deserialize)] pub struct OperatorName(String); impl OperatorName { @@ -39,7 +39,7 @@ impl OperatorName { } /// Entity operating a set of WCN nodes within a regional WCN cluster. -#[derive(Debug)] +#[derive(Debug, Serialize, Deserialize)] pub struct Operator { /// ID of this [`Operator`]. pub id: OperatorId, @@ -58,7 +58,7 @@ pub struct Operator { } /// Node within a WCN network. -#[derive(Debug)] +#[derive(Debug, Serialize, Deserialize)] pub struct Node { /// [`PeerId`] of this [`Node`]. /// @@ -70,138 +70,41 @@ pub struct Node { pub addr: SocketAddrV4, } -/// Collection of [`Operator`]s within a regional WCN cluster. -/// -/// Allows to retrieve stored [`Operator`]s using both [`OperatorIdx`]es -/// and [`OperatorId`]s. -/// -/// Guarantees stable ordering on removal -- doesn't shift any elements -/// therefore preserving [`OperatorIdx`] validity. -#[derive(Debug)] -pub struct Operators { - id_to_slot_idx: HashMap, - slots: Vec>, -} +impl Node { + pub fn decrypt(&mut self) { + // FF1::new(key, radix); -impl Default for Operators { - fn default() -> Self { - Self { - id_to_slot_idx: HashMap::new(), - slots: Vec::new(), - } + // let fpe_ff = FF1::::new(&[0; 32], 256).unwrap(); } } -impl Operators { - /// Maximum allowed number of slots in this collection. - pub const MAX_SLOTS: usize = u8::MAX as usize + 1; - - // Creates a new empty collection. - pub fn new() -> Self { - Self::default() - } - - /// Tries to create a new collection out of the provided list of existing - /// slots. - /// - /// Returns `None` if the number of slots exceeds [`Self::MAX_SLOTS`]. - pub fn from_slots(slots: Vec>) -> Option { - if slots.len() > Self::MAX_SLOTS { - return None; - } - - let mut key_to_slot_idx = HashMap::new(); - for (idx, value) in slots.iter().enumerate() { - if let Some(v) = value { - key_to_slot_idx.insert(v.id.clone(), idx as u8); - } - } - - Some(Self { - id_to_slot_idx: key_to_slot_idx, - slots, - }) - } +/// Slot map of [`Operator`]s. +pub(super) struct Operators { + id_to_idx: HashMap, - /// Returns the list of [`Operator] slots. - pub fn slots(&self) -> &[Option] { - &self.slots - } - - /// Gets [`Operator`] by [`OperatorId`]. - pub fn get(&self, id: &OperatorId) -> Option<&Operator> { - self.id_to_slot_idx - .get(id) - .and_then(|&idx| self.slots[idx as usize].as_ref()) - } - - /// Gets [`Operator`] by [`OperatorIdx`]. - pub fn get_by_idx(&self, idx: OperatorIdx) -> Option<&Operator> { - let idx = idx as usize; - if idx >= self.slots.len() { - return None; - } - - self.slots[idx].as_ref() - } - - /// Indicates whether this collection contains the [`Operator`] with the - /// specified [`OperatorId`]. - pub fn contains(&self, id: &OperatorId) -> bool { - self.id_to_slot_idx.contains_key(id) - } + // TODO: assert length + slots: Vec>, +} - /// Returns an [`Iterator`] over the [`Operator`] slots in this collection. - pub fn iter(&self) -> impl Iterator { - self.slots - .iter() - .enumerate() - .filter_map(|(idx, n)| n.as_ref().map(|n| (idx as u8, n))) +impl Operators { + /// Returns whether this map contains the [`Operator`] with the provided + /// [`OperatorId`]. + pub(super) fn contains(&self, id: &OperatorId) -> bool { + self.get(id).is_some() } - fn allocate_slot(&mut self) -> Option { - if let Some(idx) = self.slots.iter().position(|n| n.is_none()) { - return Some(idx as u8); - }; - - if self.slots.len() == Self::MAX_SLOTS { - return None; - } - - self.slots.push(None); - Some((self.slots.len() - 1) as u8) + /// Gets an [`Operator`] by [`OperatorId`]. + pub(super) fn get(&self, id: &OperatorId) -> Option<&Operator> { + self.get_by_idx(*self.id_to_idx.get(id)?) } - /// Inserts an [`Operator`] into the collection. - pub fn insert( - &mut self, - operator: Operator, - ) -> Result, TooManyOperatorsError> { - let idx = if let Some(idx) = self.id_to_slot_idx.get(&operator.id) { - *idx - } else { - let idx = self.allocate_slot().ok_or(TooManyOperatorsError)?; - let _ = self.id_to_slot_idx.insert(operator.id.clone(), idx); - idx - }; - - let mut operator = Some(operator); - mem::swap(&mut operator, &mut self.slots[idx as usize]); - Ok(operator) + /// Gets an [`Operator`] by [`OperatorIdx`]. + pub(super) fn get_by_idx(&self, idx: OperatorIdx) -> Option<&Operator> { + self.slots.get(idx as usize)?.as_ref() } - /// Removes the [`Operator`] with the specified [`OperatorId`] from this - /// collection. - pub fn remove(&mut self, id: &OperatorId) -> Option { - if let Some(idx) = self.id_to_slot_idx.remove(id) { - return self.slots[idx as usize].take(); - } - - None + /// Returns the list of [`Operator`] slots. + pub(super) fn slots(&self) -> &[Option] { + &self.slots } } - -/// Error of trying to insert too many elements into [`Operators`] collection. -#[derive(Clone, Debug, thiserror::Error)] -#[error("Maximum number of node operator reached: {}", Operators::MAX_SLOTS)] -pub struct TooManyOperatorsError; From 8a971b56e6fef83e4ae897f6715e1b97414102ed Mon Sep 17 00:00:00 2001 From: Darksome Date: Mon, 26 May 2025 21:37:32 +0000 Subject: [PATCH 20/79] WIP --- Cargo.lock | 101 + Cargo.toml | 1 + crates/cluster/Cargo.toml | 9 +- crates/cluster/src/client.rs | 70 + crates/cluster/src/contract/evm/mod.rs | 113 - .../cluster/src/contract/evm/operator_data.rs | 72 - crates/cluster/src/contract/mod.rs | 45 - crates/cluster/src/keyspace.rs | 47 +- crates/cluster/src/lib.rs | 438 +- crates/cluster/src/maintenance.rs | 41 + crates/cluster/src/migration.rs | 141 +- crates/cluster/src/node.rs | 151 +- crates/cluster/src/node_operator.rs | 216 + .../evm/bindings/mod.rs | 3975 +++++++---------- crates/cluster/src/smart_contract/evm/mod.rs | 119 + crates/cluster/src/smart_contract/mod.rs | 237 + .../src/smart_contract/operator_data.rs | 1 + 17 files changed, 2938 insertions(+), 2839 deletions(-) create mode 100644 crates/cluster/src/client.rs delete mode 100644 crates/cluster/src/contract/evm/mod.rs delete mode 100644 crates/cluster/src/contract/evm/operator_data.rs delete mode 100644 crates/cluster/src/contract/mod.rs create mode 100644 crates/cluster/src/maintenance.rs create mode 100644 crates/cluster/src/node_operator.rs rename crates/cluster/src/{contract => smart_contract}/evm/bindings/mod.rs (77%) create mode 100644 crates/cluster/src/smart_contract/evm/mod.rs create mode 100644 crates/cluster/src/smart_contract/mod.rs create mode 100644 crates/cluster/src/smart_contract/operator_data.rs diff --git a/Cargo.lock b/Cargo.lock index 738361c9..a0a2f2d5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1664,6 +1664,7 @@ dependencies = [ "arc-swap", "derive_more 1.0.0", "fpe", + "itertools 0.12.1", "libp2p", "postcard", "serde", @@ -2602,6 +2603,21 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + [[package]] name = "fork" version = "0.1.23" @@ -3663,6 +3679,22 @@ dependencies = [ "tower-service", ] +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper 1.3.1", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + [[package]] name = "hyper-util" version = "0.1.3" @@ -4532,6 +4564,23 @@ dependencies = [ "unsigned-varint 0.7.2", ] +[[package]] +name = "native-tls" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework 2.11.1", + "security-framework-sys", + "tempfile", +] + [[package]] name = "nix" version = "0.28.0" @@ -4742,12 +4791,50 @@ dependencies = [ "validit", ] +[[package]] +name = "openssl" +version = "0.10.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fedfea7d58a1f73118430a55da6a286e7b044961736ce96a16a17068ea25e5da" +dependencies = [ + "bitflags 2.6.0", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + [[package]] name = "openssl-probe" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" +[[package]] +name = "openssl-sys" +version = "0.9.108" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e145e1651e858e820e4860f7b9c5e169bc1d8ce1c86043be79fa7b7634821847" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "overload" version = "0.1.1" @@ -5549,19 +5636,23 @@ dependencies = [ "http-body 1.0.0", "http-body-util", "hyper 1.3.1", + "hyper-tls", "hyper-util", "ipnet", "js-sys", "log", "mime", + "native-tls", "once_cell", "percent-encoding", "pin-project-lite", + "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", "sync_wrapper 0.1.2", "tokio", + "tokio-native-tls", "tower-service", "url", "wasm-bindgen", @@ -6739,6 +6830,16 @@ dependencies = [ "syn 2.0.101", ] +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + [[package]] name = "tokio-rustls" version = "0.26.2" diff --git a/Cargo.toml b/Cargo.toml index 8e6b4baf..ae4fcb6e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -49,6 +49,7 @@ time = "0.3" libp2p = { version = "0.54", default-features = false, features = ["serde"] } tokio-serde = { git = "https://github.com/xDarksome/tokio-serde.git", rev = "6df9ff9" } tokio-serde-postcard = { git = "https://github.com/xDarksome/tokio-serde-postcard.git", rev = "5e1b77a" } +itertools = "0.12" [workspace.lints.clippy] all = { level = "deny", priority = -1 } diff --git a/crates/cluster/Cargo.toml b/crates/cluster/Cargo.toml index e1fa8dd0..c739fdc0 100644 --- a/crates/cluster/Cargo.toml +++ b/crates/cluster/Cargo.toml @@ -6,17 +6,14 @@ edition = "2021" [lints] workspace = true -[features] -default = ["evm"] -evm = ["alloy"] - [dependencies] -derive_more = { workspace = true } +derive_more = { workspace = true, features = ["try_from"] } libp2p = { workspace = true } +itertools = { workspace = true } sharding = { path = "../sharding" } -alloy = { version = "0.13", default-features = false, features = ["sol-types", "contract", "signer-local", "network"], optional = true } +alloy = { version = "0.13", default-features = false, features = ["sol-types", "contract", "signer-local", "network", "reqwest"] } anyhow = "1" thiserror = "1" diff --git a/crates/cluster/src/client.rs b/crates/cluster/src/client.rs new file mode 100644 index 00000000..ddd98898 --- /dev/null +++ b/crates/cluster/src/client.rs @@ -0,0 +1,70 @@ +//! Client of a WCN cluster. + +use { + libp2p::identity::PeerId, + serde::{Deserialize, Serialize}, +}; + +/// On-chain data of a [`Client`]. +#[derive(Debug)] +pub struct Data { + /// [`PeerId`] of the [`Client`]. Used for authentication. + pub peer_id: PeerId, +} + +/// Client of a WCN cluster. +#[derive(Debug)] +pub struct Client { + data: VersionedData, +} + +impl Client { + /// Returns [`PeerId`] of this [`Client`]. + pub fn peer_id(&self) -> &PeerId { + match &self.data { + VersionedData::V0(data) => &data.peer_id, + } + } +} + +/// Borrowed [`Client`]. +#[derive(Debug)] +pub struct ClientRef<'a> { + data: VersionedDataRef<'a>, +} + +impl<'a> ClientRef<'a> { + /// Converts this [`ClientRef`] into an owned [`Client`]. + pub fn to_owned(self) -> Client { + Client { + data: match self.data { + VersionedDataRef::V0(data) => VersionedData::V0(*data), + }, + } + } +} + +#[derive(Clone, Copy, Debug)] +enum VersionedData { + V0(DataV0), +} + +#[derive(Debug)] +enum VersionedDataRef<'a> { + V0(&'a DataV0), +} + +// NOTE: The on-chain serialization is non self-describing! Every change to +// the schema should be handled by creating a new version. +#[derive(Clone, Copy, Debug, Serialize, Deserialize)] +pub(crate) struct DataV0 { + pub peer_id: PeerId, +} + +impl From for DataV0 { + fn from(data: Data) -> Self { + Self { + peer_id: data.peer_id, + } + } +} diff --git a/crates/cluster/src/contract/evm/mod.rs b/crates/cluster/src/contract/evm/mod.rs deleted file mode 100644 index 5cf90781..00000000 --- a/crates/cluster/src/contract/evm/mod.rs +++ /dev/null @@ -1,113 +0,0 @@ -#[rustfmt::skip] -mod bindings; - -mod operator_data; - -use { - alloy::{ - network::EthereumWallet, - providers::{Provider, ProviderBuilder}, - signers::local::PrivateKeySigner, - transports::http::reqwest, - }, - std::{str::FromStr, sync::Arc}, -}; - -pub struct ContractSettings { - pub max_operator_data_bytes: u16, -} - -pub struct ContractManager { - provider: Arc, -} - -impl ContractManager { - pub fn new(signer: Signer, rpc_url: RpcUrl) -> Self { - let wallet: EthereumWallet = match signer.inner { - SignerInner::PrivateKey(key) => key.into(), - }; - - Self { - provider: Arc::new(ProviderBuilder::new().wallet(wallet).on_http(rpc_url.0)), - } - } - - pub fn deploy_contract(&self, settings: ContractSettings) {} -} - -#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] -pub struct Address(alloy::primitives::Address); - -impl FromStr for Address { - type Err = InvalidAddress; - - fn from_str(s: &str) -> Result { - alloy::primitives::Address::from_str(s) - .map(Address) - .map_err(|err| InvalidAddress(err.to_string())) - } -} - -pub struct Signer { - inner: SignerInner, -} - -impl Signer { - pub fn try_from_private_key(hex: &str) -> Result { - PrivateKeySigner::from_str(hex) - .map(SignerInner::PrivateKey) - .map(|inner| Self { inner }) - .map_err(|err| InvalidPrivateKey(err.to_string())) - } -} - -pub enum SignerInner { - PrivateKey(PrivateKeySigner), -} - -pub struct RpcUrl(reqwest::Url); - -impl FromStr for RpcUrl { - type Err = InvalidRpcUrl; - - fn from_str(s: &str) -> Result { - reqwest::Url::from_str(s) - .map(Self) - .map_err(|err| InvalidRpcUrl(err.to_string())) - } -} - -impl From for bindings::Cluster::Settings { - fn from(s: ContractSettings) -> Self { - Self { - maxOperatorDataBytes: s.max_operator_data_bytes, - } - } -} - -#[derive(Debug, thiserror::Error)] -#[error("Invalid RPC URL: {0:?}")] -pub struct InvalidRpcUrl(String); - -#[derive(Debug, thiserror::Error)] -#[error("Invalid private key: {0:?}")] -pub struct InvalidPrivateKey(String); - -#[derive(Debug, thiserror::Error)] -#[error("Invalid address: {0:?}")] -pub struct InvalidAddress(String); - -impl From
for super::PublicKey { - fn from(addr: Address) -> Self { - // using `Debug` for raw non-checksummed format - Self(format!("{addr:?}")) - } -} - -#[cfg(test)] -mod test { - #[test] - fn address_to_from_public_key_conversion() { - todo!() - } -} diff --git a/crates/cluster/src/contract/evm/operator_data.rs b/crates/cluster/src/contract/evm/operator_data.rs deleted file mode 100644 index 76abe14b..00000000 --- a/crates/cluster/src/contract/evm/operator_data.rs +++ /dev/null @@ -1,72 +0,0 @@ -//! De/serialization for on-chain node operator data. -//! -//! IMPORTANT: The serialization is non self-describing! Every change to the -//! schema should be handled by creating a new version of the schema and bumping -//! the version byte. - -use { - super::Address, - crate::{contract, node}, - aes::Aes256, - anyhow::Context, - fpe::ff1::FF1, - libp2p::PeerId, - serde::{Deserialize, Serialize}, - std::net::SocketAddrV4, -}; - -#[derive(Serialize, Deserialize)] -struct Operator { - name: node::OperatorName, - nodes: Vec, - clients: Vec, -} - -#[derive(Serialize, Deserialize)] -struct Node { - peer_id: PeerId, - addr: SocketAddrV4, -} - -pub(super) fn serialize(operator: node::Operator) -> anyhow::Result> { - let op = Operator { - name: operator.name, - nodes: operator - .nodes - .into_iter() - .map(|node| Node { - peer_id: node.peer_id, - addr: node.addr, - }) - .collect(), - clients: operator.clients, - }; - - // reserve first byte for versioning - let size = postcard::experimental::serialized_size(&op).context("serialize_size")? + 1; - let mut buf = Vec::with_capacity(size); - postcard::to_slice(&op, &mut buf[1..]).context("to_slice")?; - Ok(buf) -} - -pub(super) fn deserialize(operator_addr: Address, buf: &[u8]) -> anyhow::Result { - if buf.is_empty() { - return Err(anyhow::anyhow!("empty buf")); - } - - let operator: Operator = postcard::from_bytes(&buf[1..]).context("from_bytes")?; - - Ok(node::Operator { - id: operator_addr.into(), - name: operator.name, - nodes: operator - .nodes - .into_iter() - .map(|node| crate::Node { - peer_id: node.peer_id, - addr: node.addr, - }) - .collect(), - clients: operator.clients, - }) -} diff --git a/crates/cluster/src/contract/mod.rs b/crates/cluster/src/contract/mod.rs deleted file mode 100644 index a5c8e2e5..00000000 --- a/crates/cluster/src/contract/mod.rs +++ /dev/null @@ -1,45 +0,0 @@ -use { - crate::{node, View}, - derive_more::Display, - serde::{Deserialize, Serialize}, - std::{future::Future, sync::Arc}, -}; - -#[cfg(feature = "evm")] -pub mod evm; - -/// Public key on a chain hosting the [`SmartContract`]. -#[derive(Clone, Debug, Display, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub struct PublicKey(String); - -pub struct Settings { - pub min_operators: u8, - pub max_operator_data_bytes: u32, -} - -pub enum Call { - StartMigration { - operators_to_remove: Vec, - operators_to_add: Vec<(PublicKey, node::Operator)>, - }, - CompleteMigration, - AbortMigration, - - StartMaintenance, - CompleteMaintenance, - AbortMaintenance, - - UpdateNodeOperator(node::Operator), - - UpdateSettings(Settings), - - TransferOwnership(PublicKey), -} - -pub trait SmartContract { - fn call(&self, call: Call) -> impl Future> + Send; - - fn view(&self) -> Arc; -} - -pub struct Error(String); diff --git a/crates/cluster/src/keyspace.rs b/crates/cluster/src/keyspace.rs index 4ab011da..77f0ef34 100644 --- a/crates/cluster/src/keyspace.rs +++ b/crates/cluster/src/keyspace.rs @@ -1,49 +1,74 @@ -use {crate::node, sharding::ShardId, tap::TapOptional}; +use { + crate::{ + node_operator::{self, NodeOperators}, + NodeOperator, + }, + derive_more::TryFrom, + sharding::ShardId, + tap::TapOptional, +}; const REPLICATION_FACTOR: usize = 5; /// Strategy of replicating data within a [`Keyspace`] across a set of /// [`node::Operator`]s. #[repr(u8)] -#[derive(Clone, Copy, Debug, Default)] +#[derive(Clone, Copy, Debug, Default, TryFrom)] +#[try_from(repr)] pub enum ReplicationStrategy { /// Keys are being uniformly distributed across [`node::Operator`]s. #[default] UniformDistribution = 0, } +// impl ReplicationStrategy { +// pub(super) fn try_from(repr: u8) -> Option { +// match repr { +// 0 => Some(Self::UniformDistribution), +// _ => None, +// } +// } +// } + /// Continuous space of `u64` keys, where each key is assigned to a set of /// [`node::Operator`]s. pub struct Keyspace { - operators: node::Operators, - sharding: sharding::Keyspace, + operators: NodeOperators, + sharding: sharding::Keyspace, replication_strategy: ReplicationStrategy, version: u64, } impl Keyspace { - /// Required number of [`node::Operator`]s a data should be replicated to. + pub(super) fn new( + operators: NodeOperators, + replication_strategy: ReplicationStrategy, + version: u64, + ) -> Self { + todo!() + } + + /// Required number of [`NodeOperator`]s a data should be replicated to. pub fn replication_factor(&self) -> usize { REPLICATION_FACTOR } - /// Returns the set of [`node::Operator`]s the data under the specified key + /// Returns the set of [`NodeOperator`]s the data under the specified key /// should be replicated to. - pub fn replicas(&self, key: u64) -> impl Iterator + '_ { + pub fn replicas(&self, key: u64) -> impl Iterator + '_ { self.sharding .shard_replicas(ShardId::from_key(key)) .iter() .filter_map(|&idx| { self.operators - .get(idx as usize)? - .as_ref() + .get_by_idx(idx) .tap_none(|| tracing::warn!("Missing node operator {idx}")) }) } - /// Get [`node::Operators`] map of this [`Kespace`]. - pub(super) fn operators(&self) -> &node::Operators { + /// Get [`NodeOperators`] of this [`Keyspace`]. + pub(super) fn operators(&self) -> &NodeOperators { &self.operators } } diff --git a/crates/cluster/src/lib.rs b/crates/cluster/src/lib.rs index d8cc99bd..868c45ca 100644 --- a/crates/cluster/src/lib.rs +++ b/crates/cluster/src/lib.rs @@ -1,22 +1,422 @@ -use std::{collections::HashSet, sync::Arc}; +use { + arc_swap::ArcSwap, + itertools::Itertools, + smart_contract::evm, + std::{collections::HashSet, future::Future, sync::Arc}, +}; -pub mod contract; -pub use contract::SmartContract; +pub mod smart_contract; +pub use smart_contract::SmartContract; + +pub mod client; +pub use client::{Client, ClientRef}; pub mod node; -pub use node::Node; +pub use node::{Node, NodeRef}; + +pub mod node_operator; +pub use node_operator::{NewNodeOperator, NodeOperator}; -mod keyspace; +pub mod keyspace; pub use keyspace::Keyspace; pub mod migration; pub use migration::Migration; +pub mod maintenance; +pub use maintenance::Maintenance; + +/// Maximum number of [`NodeOperator`]s within a WCN [`Cluster`]. +pub const MAX_OPERATORS: usize = 256; + +/// WCN cluster. +/// +/// Thin wrapper around the underlying [`SmartContract`] implementation. +/// +/// Performs preliminary invariant validation before calling the actual +/// [`SmartContract`] methods. +pub struct Cluster { + smart_contract: SC, + view: ArcSwap>, +} + +/// WCN [`Cluster`] settings. +pub struct Settings { + /// Maximum number of on-chain bytes stored for a single [`NodeOperator`]. + pub max_node_operator_data_bytes: u16, +} + +/// Version of a WCN [`Cluster`]. +/// +/// Should only monotonically increase. If you observe a jump backwards it means +/// that a chain reorg has occured on the underlying [`SmartContract`] chain. +/// +/// For each version bump a corresponding [`Event`] should be emitted. +pub type Version = u128; + +/// Events happening within a WCN [`Cluster`]. +pub enum Event { + /// [`Migration`] has started. + MigrationStarted(migration::Started), + + /// [`NodeOperator`] has completed the data pull. + MigrationDataPullCompleted(migration::DataPullCompleted), + + /// [`Migration`] has been completed. + MigrationCompleted(migration::Completed), + + /// [`Migration`] has been aborted. + MigrationAborted(migration::Aborted), + + /// [`Maintenance`] has started. + MaintenanceStarted(maintenance::Started), + + /// [`Maintenance`] has been completed. + MaintenanceCompleted(maintenance::Completed), + + /// [`Maintenance`] has been aborted. + MaintenanceAborted(maintenance::Aborted), + + /// On-chain state of an [`NodeOperator`] has been updated. + NodeOperatorUpdated(node_operator::Updated), +} + +impl Cluster { + /// Deploys a new WCN [`Cluster`]. + pub async fn deploy( + signer: smart_contract::Signer, + rpc_url: smart_contract::RpcUrl, + initial_settings: Settings, + initial_operators: Vec, + ) -> Result { + if initial_operators.iter().map(|op| &op.id).dedup().count() != initial_operators.len() { + return Err(DeploymentError::OperatorIdDuplicate); + } + + if initial_operators.len() > MAX_OPERATORS { + return Err(DeploymentError::TooManyOperators); + } + + let contract = SC::deploy(signer, rpc_url, initial_settings, initial_operators).await?; + + let view = contract.cluster_view().await?; + + Ok(Self { + smart_contract: contract, + view: ArcSwap::new(Arc::new(Arc::new(view))), + }) + } + + /// Prepares a new [`migration::Plan`] and calls + /// [`SmartContract::start_migration`] using the prepared plan. + pub async fn start_migration( + &self, + remove: Vec, + add: Vec, + ) -> Result<(), StartMigrationError> { + let plan = self.using_view(move |view| { + if self.smart_contract.signer() != view.owner { + return Err(StartMigrationError::NotOwner); + } + + if view.migration().is_some() { + return Err(StartMigrationError::MigrationInProgress); + } + + if view.maintenance().is_some() { + return Err(StartMigrationError::MaintenanceInProgress); + } + + migration::Plan::new(view, remove, add).map_err(Into::into) + })?; + + self.smart_contract.start_migration(plan).await?; + + Ok(()) + } + + /// Calls [`SmartContract::complete_migration`]. + pub async fn complete_migration( + &self, + id: migration::Id, + ) -> Result<(), CompleteMigrationError> { + let signer = self.smart_contract.signer(); + + let operator_idx = self.using_view(|view| { + let migration = view + .migration() + .ok_or(CompleteMigrationError::NoMigration)?; + + if migration.id() != id { + return Err(CompleteMigrationError::WrongMigrationId); + } + + let operator_idx = migration + .keyspace() + .operators() + .get_idx(&signer) + .ok_or(CompleteMigrationError::NotOperator)?; + + if !migration.is_pulling(&signer) { + return Err(CompleteMigrationError::NotPulling); + } + + Ok(operator_idx) + })?; + + self.smart_contract + .complete_migration(id, operator_idx) + .await + .map_err(Into::into) + } + + /// Calls [`SmartContract::abort_migration`]. + pub async fn abort_migration(&self, id: migration::Id) -> Result<(), AbortMigrationError> { + self.using_view(|view| { + if self.smart_contract.signer() != view.owner { + return Err(AbortMigrationError::NotOwner); + } + + let migration = view.migration().ok_or(AbortMigrationError::NoMigration)?; + + if migration.id() != id { + return Err(AbortMigrationError::WrongMigrationId); + } + + Ok(()) + })?; + + self.smart_contract + .abort_migration(id) + .await + .map_err(Into::into) + } + + /// Calls [`SmartContract::start_maintenance`]. + pub async fn start_maintenance(&self) -> Result<(), StartMaintenanceError> { + let operator_idx = self.using_view(move |view| { + if view.migration().is_some() { + return Err(StartMaintenanceError::MigrationInProgress); + } + + if view.maintenance().is_some() { + return Err(StartMaintenanceError::MaintenanceInProgress); + } + + view.keyspace() + .operators() + .get_idx(&self.smart_contract.signer()) + .ok_or(StartMaintenanceError::NotOperator) + })?; + + self.smart_contract.start_maintenance(operator_idx).await?; + + Ok(()) + } + + /// Calls [`SmartContract::complete_maintenance`]. + pub async fn complete_maintenance(&self) -> Result<(), CompleteMaintenanceError> { + self.using_view(|view| { + let maintenance = view + .maintenance() + .ok_or(CompleteMaintenanceError::NoMaintenance)?; + + if maintenance.operator() != &self.smart_contract.signer() { + return Err(CompleteMaintenanceError::WrongOperator); + } + + Ok(()) + })?; + + self.smart_contract.complete_maintenance().await?; + + Ok(()) + } + + /// Calls [`SmartContract::abort_maintenance`]. + pub async fn abort_maintenance(&self) -> Result<(), AbortMaintenanceError> { + self.using_view(|view| { + if self.smart_contract.signer() != view.owner { + return Err(AbortMaintenanceError::NotOwner); + } + + view.maintenance() + .ok_or(AbortMaintenanceError::NoMaintenance)?; + + Ok(()) + })?; + + self.smart_contract + .abort_maintenance() + .await + .map_err(Into::into) + } + + /// Updates on-chain data of a [`NodeOperator`]. + /// + /// Emits [`node_operator::Updated`] event on success. + pub async fn update_node_operator( + &self, + id: node_operator::Id, + data: node_operator::Data, + ) -> Result<(), UpdateNodeOperatorError> { + let idx = self + .view + .load() + .operator_idx(&id) + .ok_or(UpdateNodeOperatorError::UnknownOperator)?; + + let data = data.serialize()?; + + if data.len() > self.view.load().settings.max_node_operator_data_bytes as usize { + return Err(UpdateNodeOperatorError::DataTooLarge); + } + + self.smart_contract + .update_node_operator(id, idx, data) + .await + .map_err(Into::into) + } + + fn using_view(&self, f: impl FnOnce(&View) -> T) -> T { + f(&self.view.load()) + } +} + +/// [`Cluster::deploy`] error. +#[derive(Debug, thiserror::Error)] +pub enum DeploymentError { + #[error("Too many initial operators provided, should be <= {MAX_OPERATORS}")] + TooManyOperators, + + #[error("Initial operator list contains duplicates")] + OperatorIdDuplicate, + + #[error("Smart-contract: {0}")] + SmartContract(#[from] smart_contract::Error), +} + +/// [`Cluster::start_migration`] error. +#[derive(Debug, thiserror::Error)] +pub enum StartMigrationError { + #[error("Signer is not the owner of the smart-contract")] + NotOwner, + + #[error("Another migration in progress")] + MigrationInProgress, + + #[error("Maintenance in progress")] + MaintenanceInProgress, + + #[error("Plan: {0}")] + Plan(#[from] migration::PlanError), + + #[error("Smart-contract: {0}")] + SmartContract(#[from] smart_contract::Error), +} + +/// [`Cluster::complete_migration`] error. +#[derive(Debug, thiserror::Error)] +pub enum CompleteMigrationError { + #[error("No migration is currently in progress")] + NoMigration, + + #[error("Provided migration id doesn't match the actual one")] + WrongMigrationId, + + #[error("Signer is not a node operator")] + NotOperator, + + #[error("Signer has already completed the data pull")] + NotPulling, + + #[error("Smart-contract: {0}")] + SmartContract(#[from] smart_contract::Error), +} + +/// [`Cluster::abort_migration`] error. +#[derive(Debug, thiserror::Error)] +pub enum AbortMigrationError { + #[error("Signer is not the owner of the smart-contract")] + NotOwner, + + #[error("No migration is currently in progress")] + NoMigration, + + #[error("Provided migration id doesn't match the actual one")] + WrongMigrationId, + + #[error("Smart-contract: {0}")] + SmartContract(#[from] smart_contract::Error), +} + +/// [`Cluster::start_maintenance`] error. +#[derive(Debug, thiserror::Error)] +pub enum StartMaintenanceError { + #[error("Migration in progress")] + MigrationInProgress, + + #[error("Another maintenance in progress")] + MaintenanceInProgress, + + #[error("Signer is not a node operator")] + NotOperator, + + #[error("Smart-contract: {0}")] + SmartContract(#[from] smart_contract::Error), +} + +/// [`Cluster::complete_maintenance`] error. +#[derive(Debug, thiserror::Error)] +pub enum CompleteMaintenanceError { + #[error("No maintenance is currently in progress")] + NoMaintenance, + + #[error("Signer is not under maintenance")] + WrongOperator, + + #[error("Smart-contract: {0}")] + SmartContract(#[from] smart_contract::Error), +} + +/// [`Cluster::abort_maintenance`] error. +#[derive(Debug, thiserror::Error)] +pub enum AbortMaintenanceError { + #[error("Signer is not the owner of the smart-contract")] + NotOwner, + + #[error("No maintenance is currently in progress")] + NoMaintenance, + + #[error("Smart-contract: {0}")] + SmartContract(#[from] smart_contract::Error), +} + +/// [`Cluster::update_node_operator`] error. +#[derive(Debug, thiserror::Error)] +pub enum UpdateNodeOperatorError { + #[error("Provided node operator is not a member of this cluster")] + UnknownOperator, + + #[error("Data serialization: {0}")] + DataSerialization(#[from] node_operator::DataSerializationError), + + #[error("Size of the provided operator data exceeds the configured setting")] + DataTooLarge, + + #[error("Smart-contract: {0}")] + SmartContract(#[from] smart_contract::Error), +} + /// Read-only view of a WCN cluster. pub struct View { + owner: smart_contract::PublicKey, + settings: Settings, + keyspace: Keyspace, migration: Option, - maintenance: Maintenance, + maintenance: Option, + version: u128, } @@ -30,14 +430,22 @@ impl View { pub fn migration(&self) -> Option<&Migration> { self.migration.as_ref() } -} -/// Maintenance process within a WCN cluster. -/// -/// Only a single [`node::Operator`] at a time is allowed to be under -/// maintenance. -struct Maintenance { - /// [`node::OperatorId`] of the [`node::Operator`] currently under - /// maintenance (if any). - slot: Option, + /// Returns the ongoing [`Maintenance`] of this WCN cluster. + pub fn maintenance(&self) -> Option<&Maintenance> { + self.maintenance.as_ref() + } + + /// Indicates whether the [`NodeOperator`] is a member of the [`Cluster`]. + pub fn is_member(&self, id: &node_operator::Id) -> bool { + self.operator_idx(id).is_some() + } + + fn operator_idx(&self, id: &node_operator::Id) -> Option { + self.keyspace.operators().get_idx(&id).or_else(|| { + self.migration + .as_ref() + .and_then(|migration| migration.keyspace().operators().get_idx(&id)) + }) + } } diff --git a/crates/cluster/src/maintenance.rs b/crates/cluster/src/maintenance.rs new file mode 100644 index 00000000..f4dac84a --- /dev/null +++ b/crates/cluster/src/maintenance.rs @@ -0,0 +1,41 @@ +use crate::{node, node_operator, Version}; + +/// Maintenance process within a WCN cluster. +/// +/// Only a single [`node_operator`] at a time is allowed to be under +/// maintenance. +pub struct Maintenance { + operator: node_operator::Id, +} + +impl Maintenance { + /// Returns [`node_operator::Id`] of the node operator currently under + /// [`Maintenance`]. + pub fn operator(&self) -> &node_operator::Id { + &self.operator + } +} + +/// [`Maintenance`] has started. +pub struct Started { + /// ID of the [`node_operator`] that started the [`Maintenance`]. + pub operator_id: node_operator::Id, + + /// Updated cluster [`Version`]. + pub version: Version, +} + +/// [`Maintenance`] has been completed. +pub struct Completed { + /// ID of the [`node_operator`] that completed the [`Maintenance`]. + pub operator_id: node_operator::Id, + + /// Updated cluster [`Version`]. + pub version: Version, +} + +/// [`Maintenance`] has been aborted. +pub struct Aborted { + /// Updated cluster [`Version`]. + pub version: Version, +} diff --git a/crates/cluster/src/migration.rs b/crates/cluster/src/migration.rs index c5719cd0..b8e7c1b3 100644 --- a/crates/cluster/src/migration.rs +++ b/crates/cluster/src/migration.rs @@ -1,69 +1,103 @@ use { crate::{ keyspace::{self, ReplicationStrategy}, - node, + node_operator, Keyspace, + NewNodeOperator, + Version, View as ClusterView, }, - std::{collections::HashSet, sync::Arc}, + itertools::Itertools, + std::collections::HashSet, }; +/// Identifier of a [`Migration`]. +pub type Id = u64; + /// Data migration process within a WCN cluster. pub struct Migration { - id: u64, + id: Id, keyspace: Keyspace, - pulling_operators: HashSet, + pulling_operators: HashSet, } impl Migration { + /// Returns [`Id`] of this [`Migration`]. + pub fn id(&self) -> Id { + self.id + } + /// Returns the new [`Keyspace`] this [`Migration`] is migrating to. pub fn keyspace(&self) -> &Keyspace { &self.keyspace } + + /// Indicates whether the specified [`node_operator`] is still in process of + /// pulling the data. + pub fn is_pulling(&self, id: &node_operator::Id) -> bool { + self.pulling_operators.contains(&id) + } } /// [`Migration`] plan. pub struct Plan { - cluster_view: Arc, - - slots: Vec<(node::OperatorIdx, Option)>, + slots: Vec<(node_operator::Idx, Option)>, replication_strategy: ReplicationStrategy, } impl Plan { /// Creates a new migration [`Plan`]. - pub fn new( - cluster_view: Arc, - remove: Vec, - add: Vec, + pub(super) fn new( + cluster_view: &ClusterView, + remove: Vec, + add: Vec, ) -> Result { + let slot_count = remove + .iter() + .chain(add.iter().map(|op| &op.id)) + .dedup() + .count(); + + if slot_count != remove.len() + add.len() { + return Err(PlanError::DuplicateIds); + } + if cluster_view.migration.is_some() { return Err(PlanError::MigrationInProgress); } - let mut plan = Self { - cluster_view, - slots: Vec::with_capacity(remove.len() + add.len()), - replication_strategy: keyspace::ReplicationStrategy::default(), - }; - + let mut slots = Vec::with_capacity(slot_count); let operators = cluster_view.keyspace.operators(); for id in remove { - if !operators.contains(&id) { - return Err(PlanError::UnknownOperator(id)); - } + operators + .get_idx(&id) + .map(|idx| slots.push((idx, None))) + .ok_or_else(|| PlanError::UnknownOperator(id))?; + } + + let add = &mut add.into_iter(); - plan.push_slot() + // First populate the slots that were cleared just now. + for (id, slot) in add.zip(slots.iter_mut()) { + slot.1 = Some(id); } - Ok() - } + for item in add.zip_longest(operators.freeSlots()) { + match item.left_and_right() { + (Some(_), None) => return Err(PlanError::TooManyOperators), + (None, _) => break, + (Some(operator), _) if operators.contains(&operator.id) => { + return Err(PlanError::OperatorAlreadyExists(operator.id)) + } + (Some(id), Some(idx)) => slots.push((idx, Some(id))), + }; + } - fn push_slot(&mut self, idx: usize, id: Option) -> Result<(), PlanError> { - let idx = node::OperatorIdx::try_from(idx).map_err(|_| PlanError::IndexOverflow)?; - self.slots.push((idx, id)); - Ok(()) + Ok(Self { + slots, + replication_strategy: keyspace::ReplicationStrategy::default(), + }) } } @@ -72,15 +106,60 @@ pub enum PlanError { #[error("Another migration is already in progress")] MigrationInProgress, + #[error("Duplicate operator IDs provided")] + DuplicateIds, + #[error("Unknown operator: {0}")] - UnknownOperator(node::OperatorId), + UnknownOperator(node_operator::Id), #[error("Operator already exists: {0}")] - OperatorAlreadyExists(node::OperatorId), + OperatorAlreadyExists(node_operator::Id), #[error("Too many operators")] TooManyOperators, +} + +/// [`Migration`] has started. +pub struct Started { + /// [`Id`] of the [`Migration`] being started. + pub id: Id, + + /// Migration [`Plan`] being used. + pub plan: Plan, + + /// Updated cluster [`Version`]. + pub version: Version, +} + +/// [`NodeOperator`](crate::NodeOperator) has completed the data pull. +pub struct DataPullCompleted { + /// [`Id`] of the [`Migration`]. + pub id: Id, + + /// ID of the [`node_operator`] that completed the pull. + pub operator_id: node_operator::Id, + + /// Updated cluster [`Version`]. + pub version: u128, +} + +/// [`Migration`] has been completed. +pub struct Completed { + /// [`Id`] of the completed [`Migration`]. + pub id: Id, + + /// ID of the [`node_operator`] that completed the last data pull. + pub operator_id: node_operator::Id, + + /// Updated cluster [`Version`]. + pub version: u128, +} + +/// [`Migration`] has been aborted. +pub struct Aborted { + /// [`Id`] of the [`Migration`]. + pub id: Id, - #[error("Index overflow")] - IndexOverflow, + /// Updated cluster [`Version`]. + pub version: u128, } diff --git a/crates/cluster/src/node.rs b/crates/cluster/src/node.rs index 55e1be46..820f5526 100644 --- a/crates/cluster/src/node.rs +++ b/crates/cluster/src/node.rs @@ -1,65 +1,88 @@ +//! Node within a WCN cluster. + use { - crate::contract, libp2p::identity::PeerId, serde::{Deserialize, Serialize}, - std::{collections::HashMap, net::SocketAddrV4}, + std::net::SocketAddrV4, }; -/// Globally unique identifier of an [`Operator`]; -pub type OperatorId = contract::PublicKey; - -/// Locally unique identifier of an [`Operator`] within a WCN cluster. +/// On-chain data of a [`Node`]. /// -/// Refers to a position within the [`Operators`] slot map. -pub type OperatorIdx = u8; +/// The IP address is currently being encrypted using a format-preserving +/// encryption algorithm. +#[derive(Debug)] +pub struct Data { + /// [`PeerId`] of the [`Node`]. + /// + /// Used for authentication. Multiple nodes managed by the same + /// node operator are allowed to have the same [`PeerId`]. + pub peer_id: PeerId, -/// Name of an [`Operator`]. -/// -/// Used for informational purposes only. -/// Expected to be unique within the cluster, but not enforced to. -#[derive(Debug, Serialize, Deserialize)] -pub struct OperatorName(String); + /// [`SocketAddrV4`] of the [`Node`]. + pub addr: SocketAddrV4, +} + +/// Node within a WCN cluster. +#[derive(Debug)] +pub struct Node { + data: VersionedData, +} -impl OperatorName { - /// Maximum allowed length of an [`OperatorName`] (in bytes). - pub const MAX_LENGTH: usize = 32; +impl Node { + /// Returns [`PeerId`] of this [`Node`]. + pub fn peer_id(&self) -> &PeerId { + match &self.data { + VersionedData::V0(data) => &data.peer_id, + } + } - /// Tries to create a new [`OperatorName`] out of the provided [`ToString`]. - /// - /// Returns `None` if the string length exceeds [`Self::MAX_LENGTH`]. - pub fn new(s: impl ToString) -> Option { - let s = s.to_string(); - (s.len() <= Self::MAX_LENGTH).then_some(Self(s)) + /// Returns [`SocketAddrV4`] of this [`Node`]. + pub fn addr(&self) -> SocketAddrV4 { + match self.data { + VersionedData::V0(data) => data.addr, + } } - /// Returns a reference to the underlying string. - pub fn as_str(&self) -> &str { - &self.0 + pub(super) fn encrypt(&mut self) {} + + pub(super) fn decrypt(&mut self) { + // FF1::new(key, radix); + + // let fpe_ff = FF1::::new(&[0; 32], 256).unwrap(); } } -/// Entity operating a set of WCN nodes within a regional WCN cluster. -#[derive(Debug, Serialize, Deserialize)] -pub struct Operator { - /// ID of this [`Operator`]. - pub id: OperatorId, +/// Borrowed [`Node`]. +#[derive(Debug)] +pub struct NodeRef<'a> { + data: VersionedDataRef<'a>, +} - /// Name of this [`Operator`]. - pub name: OperatorName, +impl<'a> NodeRef<'a> { + /// Converts this [`NodeRef`] into an owned [`Node`]. + pub fn to_owned(self) -> Node { + Node { + data: match self.data { + VersionedDataRef::V0(data) => VersionedData::V0(*data), + }, + } + } +} - /// List of [`Node`]s being operated by this [`Operator`]. - pub nodes: Vec, +#[derive(Clone, Copy, Debug)] +enum VersionedData { + V0(DataV0), +} - /// List of clients of this [`Operator`]. - /// - /// Those clients are allowed to use the WCN network on behalf of this - /// [`Operator`]. - pub clients: Vec, +#[derive(Debug)] +enum VersionedDataRef<'a> { + V0(&'a DataV0), } -/// Node within a WCN network. -#[derive(Debug, Serialize, Deserialize)] -pub struct Node { +// NOTE: The on-chain serialization is non self-describing! Every change to +// the schema should be handled by creating a new version. +#[derive(Clone, Copy, Debug, Serialize, Deserialize)] +pub(crate) struct DataV0 { /// [`PeerId`] of this [`Node`]. /// /// Used for authentication. Multiple nodes managed by the same @@ -70,41 +93,11 @@ pub struct Node { pub addr: SocketAddrV4, } -impl Node { - pub fn decrypt(&mut self) { - // FF1::new(key, radix); - - // let fpe_ff = FF1::::new(&[0; 32], 256).unwrap(); - } -} - -/// Slot map of [`Operator`]s. -pub(super) struct Operators { - id_to_idx: HashMap, - - // TODO: assert length - slots: Vec>, -} - -impl Operators { - /// Returns whether this map contains the [`Operator`] with the provided - /// [`OperatorId`]. - pub(super) fn contains(&self, id: &OperatorId) -> bool { - self.get(id).is_some() - } - - /// Gets an [`Operator`] by [`OperatorId`]. - pub(super) fn get(&self, id: &OperatorId) -> Option<&Operator> { - self.get_by_idx(*self.id_to_idx.get(id)?) - } - - /// Gets an [`Operator`] by [`OperatorIdx`]. - pub(super) fn get_by_idx(&self, idx: OperatorIdx) -> Option<&Operator> { - self.slots.get(idx as usize)?.as_ref() - } - - /// Returns the list of [`Operator`] slots. - pub(super) fn slots(&self) -> &[Option] { - &self.slots +impl From for DataV0 { + fn from(data: Data) -> Self { + Self { + peer_id: data.peer_id, + addr: data.addr, + } } } diff --git a/crates/cluster/src/node_operator.rs b/crates/cluster/src/node_operator.rs new file mode 100644 index 00000000..77bafb54 --- /dev/null +++ b/crates/cluster/src/node_operator.rs @@ -0,0 +1,216 @@ +//! Entity operating a set of nodes within a WCN cluster. + +use { + crate::{client, node, smart_contract, Node}, + serde::{Deserialize, Serialize}, + std::collections::HashMap, +}; + +/// Globally unique identifier of a [`NodeOperator`]; +pub type Id = smart_contract::PublicKey; + +/// Locally unique identifier of a [`NodeOperator`] within a WCN cluster. +/// +/// Refers to a position within the [`NodeOperators`] slot map. +pub type Idx = u8; + +/// Name of a [`NodeOperator`]. +/// +/// Used for informational purposes only. +/// Expected to be unique within the cluster, but not enforced to. +#[derive(Debug, Serialize, Deserialize)] +pub struct Name(String); + +impl Name { + /// Maximum allowed length of a [`Name`] (in bytes). + pub const MAX_LENGTH: usize = 32; + + /// Tries to create a new [`Name`] out of the provided [`ToString`]. + /// + /// Returns `None` if the string length exceeds [`Self::MAX_LENGTH`]. + pub fn new(s: impl ToString) -> Option { + let s = s.to_string(); + (s.len() <= Self::MAX_LENGTH).then_some(Self(s)) + } + + /// Returns a reference to the underlying string. + pub fn as_str(&self) -> &str { + &self.0 + } +} + +/// On-chain data of a [`NodeOperator`]. +#[derive(Debug)] +pub struct Data { + /// Name of the [`NodeOperator`]. + pub name: Name, + + /// List of [`node`]s of the [`NodeOperator`]. + pub nodes: Vec, + + /// List of [`client`]s authorized to use the WCN cluster on behalf of the + /// [`NodeOperator`]. + pub clients: Vec, +} + +/// [`NodeOperator`] [`Data`] serialized for on-chain storage. +#[derive(Debug)] +pub struct SerializedData(Vec); + +impl SerializedData { + pub(super) fn len(&self) -> usize { + self.0.len() + } +} + +/// New [`NodeOperator`] that is not a member of WCN cluster yet. +pub struct NewNodeOperator { + /// [`Id`] of this [`NewNodeOperator`]. + pub id: Id, + + /// [`Data`] of this [`NewNodeOperator`]. + pub data: Data, +} + +/// Entity operating a set of [`Node`]s within a WCN cluster. +#[derive(Debug)] +pub struct NodeOperator { + id: Id, + data: VersionedData, +} + +/// On-chain state of an [`NodeOperator`] has been updated. +pub struct Updated { + /// Updated [`NodeOperator`]. + pub operator: NodeOperator, +} + +impl Data { + pub(super) fn serialize(self) -> Result { + use DataSerializationError as Error; + + // TODO: encrypt + + let data = DataV0 { + name: self.name, + nodes: self.nodes.into_iter().map(Into::into).collect(), + clients: self.clients.into_iter().map(Into::into).collect(), + }; + + let size = postcard::experimental::serialized_size(&data).map_err(Error::from_postcard)?; + + // reserve first byte for versioning + let mut buf = Vec::with_capacity(size + 1); + buf[0] = 0; // current schema version + postcard::to_slice(&data, &mut buf[1..]).map_err(Error::from_postcard)?; + Ok(SerializedData(buf)) + } +} + +#[derive(Debug)] +enum VersionedData { + V0(DataV0), +} + +impl NodeOperator { + fn deserialize(id: Id, data_bytes: &[u8]) -> Result { + use DataDeserializationError as Error; + + if data_bytes.is_empty() { + return Err(DataDeserializationError::EmptyBuffer); + } + + let schema_version = data_bytes[0]; + let bytes = &data_bytes[1..]; + + let data = match schema_version { + 0 => postcard::from_bytes(bytes).map(VersionedData::V0), + ver => return Err(Error::UnknownSchemaVersion(ver)), + } + .map_err(Error::from_postcard)?; + + Ok(Self { id, data }) + } +} + +// NOTE: The on-chain serialization is non self-describing! Every change to +// the schema should be handled by creating a new version. +#[derive(Debug, Deserialize, Serialize)] +struct DataV0 { + name: Name, + nodes: Vec, + clients: Vec, +} + +#[derive(Debug, thiserror::Error)] +pub enum DataSerializationError { + #[error("Codec: {0}")] + Codec(String), +} + +impl DataSerializationError { + fn from_postcard(err: postcard::Error) -> Self { + Self::Codec(format!("{err:?}")) + } +} + +#[derive(Debug, thiserror::Error)] +pub enum DataDeserializationError { + #[error("Empty data buffer")] + EmptyBuffer, + + #[error("Codec: {0}")] + Codec(String), + + #[error("Unknown schema version: {0}")] + UnknownSchemaVersion(u8), +} + +impl DataDeserializationError { + fn from_postcard(err: postcard::Error) -> Self { + Self::Codec(format!("{err:?}")) + } +} + +/// Slot map of [`NodeOperator`]s. +pub(super) struct NodeOperators { + id_to_idx: HashMap, + + // TODO: assert length + slots: Vec>, +} + +impl NodeOperators { + /// Returns whether this map contains the [`NodeOperator`] with the provided + /// [`Id`]. + pub(super) fn contains(&self, id: &Id) -> bool { + self.get(id).is_some() + } + + /// Gets an [`NodeOperator`] by [`Id`]. + pub(super) fn get(&self, id: &Id) -> Option<&NodeOperator> { + self.get_by_idx(self.get_idx(id)?) + } + + /// Gets an [`NodeOperator`] by [`Idx`]. + pub(super) fn get_by_idx(&self, idx: Idx) -> Option<&NodeOperator> { + self.slots.get(idx as usize)?.as_ref() + } + + /// Gets an [`Idx`] by [`Id`]. + pub(super) fn get_idx(&self, id: &Id) -> Option { + self.id_to_idx.get(id).copied() + } + + /// Returns the list of [`NodeOperator`] slots. + pub(super) fn slots(&self) -> &[Option] { + &self.slots + } + + pub(super) fn freeSlots(&self) -> impl Iterator + '_ { + self.slots + .iter() + .enumerate() + .filter_map(|(idx, slot)| slot.is_none().then_some(idx.try_into().unwrap())) + } +} diff --git a/crates/cluster/src/contract/evm/bindings/mod.rs b/crates/cluster/src/smart_contract/evm/bindings/mod.rs similarity index 77% rename from crates/cluster/src/contract/evm/bindings/mod.rs rename to crates/cluster/src/smart_contract/evm/bindings/mod.rs index 56143058..5f4872e6 100644 --- a/crates/cluster/src/contract/evm/bindings/mod.rs +++ b/crates/cluster/src/smart_contract/evm/bindings/mod.rs @@ -3,558 +3,556 @@ //! This is autogenerated code. //! Do not manually edit these files. //! These files may be overwritten by the codegen system at any time. -/** - -Generated by the following Solidity interface... -```solidity -interface Cluster { - struct ClusterView { - KeyspaceView keyspace; - Migration migration; - KeyspaceView migrationKeyspace; - Maintenance maintenance; - uint64 keyspaceVersion; - uint128 version; - } - struct KeyspaceSlot { - uint8 idx; - address operator; - } - struct KeyspaceView { - NodeOperator[] operators; - uint8 replicationStrategy; - } - struct Maintenance { - address slot; - } - struct Migration { - uint64 id; - uint256 pullingOperatorsBitmask; - } - struct MigrationPlan { - KeyspaceSlot[] slots; - uint8 replicationStrategy; - } - struct NodeOperator { - address addr; - bytes data; - } - struct Settings { - uint16 maxOperatorDataBytes; - } - - event MaintenanceAborted(uint128 clusterVersion); - event MaintenanceCompleted(address operatorAddress, uint128 clusterVersion); - event MaintenanceStarted(address operatorAddress, uint128 clusterVersion); - event MigrationAborted(uint64 id, uint128 clusterVersion); - event MigrationCompleted(uint64 id, address operatorAddress, uint128 clusterVersion); - event MigrationDataPullCompleted(uint64 id, address operatorAddress, uint128 clusterVersion); - event MigrationStarted(uint64 id, MigrationPlan plan, uint128 clusterVersion); - event NodeOperatorDataUpdated(address operatorAddress, bytes data, uint128 clusterVersion); - - constructor(Settings initialSettings, address[] initialOperators); - - function abortMaintenance() external; - function abortMigration() external; - function completeMaintenance() external; - function completeMigration(uint64 id, uint8 operatorIdx) external; - function getView() external view returns (ClusterView memory); - function registerNodeOperator(bytes memory data) external; - function startMaintenance(uint8 operatorIdx) external; - function startMigration(MigrationPlan memory plan) external; - function transferOwnership(address newOwner) external; - function updateNodeOperatorData(uint8 operatorIdx, bytes memory data) external; - function updateSettings(Settings memory newSettings) external; -} -``` - -...which was generated by the following JSON ABI: -```json -[ - { - "type": "constructor", - "inputs": [ - { - "name": "initialSettings", - "type": "tuple", - "internalType": "struct Settings", - "components": [ - { - "name": "maxOperatorDataBytes", - "type": "uint16", - "internalType": "uint16" - } - ] - }, - { - "name": "initialOperators", - "type": "address[]", - "internalType": "address[]" - } - ], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "abortMaintenance", - "inputs": [], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "abortMigration", - "inputs": [], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "completeMaintenance", - "inputs": [], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "completeMigration", - "inputs": [ - { - "name": "id", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "operatorIdx", - "type": "uint8", - "internalType": "uint8" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "getView", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "tuple", - "internalType": "struct ClusterView", - "components": [ - { - "name": "keyspace", - "type": "tuple", - "internalType": "struct KeyspaceView", - "components": [ - { - "name": "operators", - "type": "tuple[]", - "internalType": "struct NodeOperator[]", - "components": [ - { - "name": "addr", - "type": "address", - "internalType": "address" - }, - { - "name": "data", - "type": "bytes", - "internalType": "bytes" - } - ] - }, - { - "name": "replicationStrategy", - "type": "uint8", - "internalType": "uint8" - } - ] - }, - { - "name": "migration", - "type": "tuple", - "internalType": "struct Migration", - "components": [ - { - "name": "id", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "pullingOperatorsBitmask", - "type": "uint256", - "internalType": "uint256" - } - ] - }, - { - "name": "migrationKeyspace", - "type": "tuple", - "internalType": "struct KeyspaceView", - "components": [ - { - "name": "operators", - "type": "tuple[]", - "internalType": "struct NodeOperator[]", - "components": [ - { - "name": "addr", - "type": "address", - "internalType": "address" - }, - { - "name": "data", - "type": "bytes", - "internalType": "bytes" - } - ] - }, - { - "name": "replicationStrategy", - "type": "uint8", - "internalType": "uint8" - } - ] - }, - { - "name": "maintenance", - "type": "tuple", - "internalType": "struct Maintenance", - "components": [ - { - "name": "slot", - "type": "address", - "internalType": "address" - } - ] - }, - { - "name": "keyspaceVersion", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "version", - "type": "uint128", - "internalType": "uint128" - } - ] - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "registerNodeOperator", - "inputs": [ - { - "name": "data", - "type": "bytes", - "internalType": "bytes" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "startMaintenance", - "inputs": [ - { - "name": "operatorIdx", - "type": "uint8", - "internalType": "uint8" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "startMigration", - "inputs": [ - { - "name": "plan", - "type": "tuple", - "internalType": "struct MigrationPlan", - "components": [ - { - "name": "slots", - "type": "tuple[]", - "internalType": "struct KeyspaceSlot[]", - "components": [ - { - "name": "idx", - "type": "uint8", - "internalType": "uint8" - }, - { - "name": "operator", - "type": "address", - "internalType": "address" - } - ] - }, - { - "name": "replicationStrategy", - "type": "uint8", - "internalType": "uint8" - } - ] - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "transferOwnership", - "inputs": [ - { - "name": "newOwner", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "updateNodeOperatorData", - "inputs": [ - { - "name": "operatorIdx", - "type": "uint8", - "internalType": "uint8" - }, - { - "name": "data", - "type": "bytes", - "internalType": "bytes" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "updateSettings", - "inputs": [ - { - "name": "newSettings", - "type": "tuple", - "internalType": "struct Settings", - "components": [ - { - "name": "maxOperatorDataBytes", - "type": "uint16", - "internalType": "uint16" - } - ] - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "event", - "name": "MaintenanceAborted", - "inputs": [ - { - "name": "clusterVersion", - "type": "uint128", - "indexed": false, - "internalType": "uint128" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "MaintenanceCompleted", - "inputs": [ - { - "name": "operatorAddress", - "type": "address", - "indexed": false, - "internalType": "address" - }, - { - "name": "clusterVersion", - "type": "uint128", - "indexed": false, - "internalType": "uint128" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "MaintenanceStarted", - "inputs": [ - { - "name": "operatorAddress", - "type": "address", - "indexed": false, - "internalType": "address" - }, - { - "name": "clusterVersion", - "type": "uint128", - "indexed": false, - "internalType": "uint128" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "MigrationAborted", - "inputs": [ - { - "name": "id", - "type": "uint64", - "indexed": false, - "internalType": "uint64" - }, - { - "name": "clusterVersion", - "type": "uint128", - "indexed": false, - "internalType": "uint128" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "MigrationCompleted", - "inputs": [ - { - "name": "id", - "type": "uint64", - "indexed": false, - "internalType": "uint64" - }, - { - "name": "operatorAddress", - "type": "address", - "indexed": false, - "internalType": "address" - }, - { - "name": "clusterVersion", - "type": "uint128", - "indexed": false, - "internalType": "uint128" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "MigrationDataPullCompleted", - "inputs": [ - { - "name": "id", - "type": "uint64", - "indexed": false, - "internalType": "uint64" - }, - { - "name": "operatorAddress", - "type": "address", - "indexed": false, - "internalType": "address" - }, - { - "name": "clusterVersion", - "type": "uint128", - "indexed": false, - "internalType": "uint128" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "MigrationStarted", - "inputs": [ - { - "name": "id", - "type": "uint64", - "indexed": false, - "internalType": "uint64" - }, - { - "name": "plan", - "type": "tuple", - "indexed": false, - "internalType": "struct MigrationPlan", - "components": [ - { - "name": "slots", - "type": "tuple[]", - "internalType": "struct KeyspaceSlot[]", - "components": [ - { - "name": "idx", - "type": "uint8", - "internalType": "uint8" - }, - { - "name": "operator", - "type": "address", - "internalType": "address" - } - ] - }, - { - "name": "replicationStrategy", - "type": "uint8", - "internalType": "uint8" - } - ] - }, - { - "name": "clusterVersion", - "type": "uint128", - "indexed": false, - "internalType": "uint128" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "NodeOperatorDataUpdated", - "inputs": [ - { - "name": "operatorAddress", - "type": "address", - "indexed": false, - "internalType": "address" - }, - { - "name": "data", - "type": "bytes", - "indexed": false, - "internalType": "bytes" - }, - { - "name": "clusterVersion", - "type": "uint128", - "indexed": false, - "internalType": "uint128" - } - ], - "anonymous": false - } -] -```*/ +/// Generated by the following Solidity interface... +/// ```solidity +/// interface Cluster { +/// struct ClusterView { +/// KeyspaceView keyspace; +/// Migration migration; +/// KeyspaceView migrationKeyspace; +/// Maintenance maintenance; +/// uint64 keyspaceVersion; +/// uint128 version; +/// } +/// struct KeyspaceSlot { +/// uint8 idx; +/// address operator; +/// } +/// struct KeyspaceView { +/// NodeOperator[] operators; +/// uint8 replicationStrategy; +/// } +/// struct Maintenance { +/// address slot; +/// } +/// struct Migration { +/// uint64 id; +/// uint256 pullingOperatorsBitmask; +/// } +/// struct MigrationPlan { +/// KeyspaceSlot[] slots; +/// uint8 replicationStrategy; +/// } +/// struct NodeOperator { +/// address addr; +/// bytes data; +/// } +/// struct Settings { +/// uint16 maxOperatorDataBytes; +/// } +/// +/// event MaintenanceAborted(uint128 clusterVersion); +/// event MaintenanceCompleted(address operatorAddress, uint128 clusterVersion); +/// event MaintenanceStarted(address operatorAddress, uint128 clusterVersion); +/// event MigrationAborted(uint64 id, uint128 clusterVersion); +/// event MigrationCompleted(uint64 id, address operatorAddress, uint128 clusterVersion); +/// event MigrationDataPullCompleted(uint64 id, address operatorAddress, uint128 clusterVersion); +/// event MigrationStarted(uint64 id, MigrationPlan plan, uint128 clusterVersion); +/// event NodeOperatorDataUpdated(address operatorAddress, bytes data, uint128 clusterVersion); +/// +/// constructor(Settings initialSettings, address[] initialOperators); +/// +/// function abortMaintenance() external; +/// function abortMigration() external; +/// function completeMaintenance() external; +/// function completeMigration(uint64 id, uint8 operatorIdx) external; +/// function getView() external view returns (ClusterView memory); +/// function registerNodeOperator(bytes memory data) external; +/// function startMaintenance(uint8 operatorIdx) external; +/// function startMigration(MigrationPlan memory plan) external; +/// function transferOwnership(address newOwner) external; +/// function updateNodeOperatorData(uint8 operatorIdx, bytes memory data) external; +/// function updateSettings(Settings memory newSettings) external; +/// } +/// ``` +/// +/// ...which was generated by the following JSON ABI: +/// ```json +/// [ +/// { +/// "type": "constructor", +/// "inputs": [ +/// { +/// "name": "initialSettings", +/// "type": "tuple", +/// "internalType": "struct Settings", +/// "components": [ +/// { +/// "name": "maxOperatorDataBytes", +/// "type": "uint16", +/// "internalType": "uint16" +/// } +/// ] +/// }, +/// { +/// "name": "initialOperators", +/// "type": "address[]", +/// "internalType": "address[]" +/// } +/// ], +/// "stateMutability": "nonpayable" +/// }, +/// { +/// "type": "function", +/// "name": "abortMaintenance", +/// "inputs": [], +/// "outputs": [], +/// "stateMutability": "nonpayable" +/// }, +/// { +/// "type": "function", +/// "name": "abortMigration", +/// "inputs": [], +/// "outputs": [], +/// "stateMutability": "nonpayable" +/// }, +/// { +/// "type": "function", +/// "name": "completeMaintenance", +/// "inputs": [], +/// "outputs": [], +/// "stateMutability": "nonpayable" +/// }, +/// { +/// "type": "function", +/// "name": "completeMigration", +/// "inputs": [ +/// { +/// "name": "id", +/// "type": "uint64", +/// "internalType": "uint64" +/// }, +/// { +/// "name": "operatorIdx", +/// "type": "uint8", +/// "internalType": "uint8" +/// } +/// ], +/// "outputs": [], +/// "stateMutability": "nonpayable" +/// }, +/// { +/// "type": "function", +/// "name": "getView", +/// "inputs": [], +/// "outputs": [ +/// { +/// "name": "", +/// "type": "tuple", +/// "internalType": "struct ClusterView", +/// "components": [ +/// { +/// "name": "keyspace", +/// "type": "tuple", +/// "internalType": "struct KeyspaceView", +/// "components": [ +/// { +/// "name": "operators", +/// "type": "tuple[]", +/// "internalType": "struct NodeOperator[]", +/// "components": [ +/// { +/// "name": "addr", +/// "type": "address", +/// "internalType": "address" +/// }, +/// { +/// "name": "data", +/// "type": "bytes", +/// "internalType": "bytes" +/// } +/// ] +/// }, +/// { +/// "name": "replicationStrategy", +/// "type": "uint8", +/// "internalType": "uint8" +/// } +/// ] +/// }, +/// { +/// "name": "migration", +/// "type": "tuple", +/// "internalType": "struct Migration", +/// "components": [ +/// { +/// "name": "id", +/// "type": "uint64", +/// "internalType": "uint64" +/// }, +/// { +/// "name": "pullingOperatorsBitmask", +/// "type": "uint256", +/// "internalType": "uint256" +/// } +/// ] +/// }, +/// { +/// "name": "migrationKeyspace", +/// "type": "tuple", +/// "internalType": "struct KeyspaceView", +/// "components": [ +/// { +/// "name": "operators", +/// "type": "tuple[]", +/// "internalType": "struct NodeOperator[]", +/// "components": [ +/// { +/// "name": "addr", +/// "type": "address", +/// "internalType": "address" +/// }, +/// { +/// "name": "data", +/// "type": "bytes", +/// "internalType": "bytes" +/// } +/// ] +/// }, +/// { +/// "name": "replicationStrategy", +/// "type": "uint8", +/// "internalType": "uint8" +/// } +/// ] +/// }, +/// { +/// "name": "maintenance", +/// "type": "tuple", +/// "internalType": "struct Maintenance", +/// "components": [ +/// { +/// "name": "slot", +/// "type": "address", +/// "internalType": "address" +/// } +/// ] +/// }, +/// { +/// "name": "keyspaceVersion", +/// "type": "uint64", +/// "internalType": "uint64" +/// }, +/// { +/// "name": "version", +/// "type": "uint128", +/// "internalType": "uint128" +/// } +/// ] +/// } +/// ], +/// "stateMutability": "view" +/// }, +/// { +/// "type": "function", +/// "name": "registerNodeOperator", +/// "inputs": [ +/// { +/// "name": "data", +/// "type": "bytes", +/// "internalType": "bytes" +/// } +/// ], +/// "outputs": [], +/// "stateMutability": "nonpayable" +/// }, +/// { +/// "type": "function", +/// "name": "startMaintenance", +/// "inputs": [ +/// { +/// "name": "operatorIdx", +/// "type": "uint8", +/// "internalType": "uint8" +/// } +/// ], +/// "outputs": [], +/// "stateMutability": "nonpayable" +/// }, +/// { +/// "type": "function", +/// "name": "startMigration", +/// "inputs": [ +/// { +/// "name": "plan", +/// "type": "tuple", +/// "internalType": "struct MigrationPlan", +/// "components": [ +/// { +/// "name": "slots", +/// "type": "tuple[]", +/// "internalType": "struct KeyspaceSlot[]", +/// "components": [ +/// { +/// "name": "idx", +/// "type": "uint8", +/// "internalType": "uint8" +/// }, +/// { +/// "name": "operator", +/// "type": "address", +/// "internalType": "address" +/// } +/// ] +/// }, +/// { +/// "name": "replicationStrategy", +/// "type": "uint8", +/// "internalType": "uint8" +/// } +/// ] +/// } +/// ], +/// "outputs": [], +/// "stateMutability": "nonpayable" +/// }, +/// { +/// "type": "function", +/// "name": "transferOwnership", +/// "inputs": [ +/// { +/// "name": "newOwner", +/// "type": "address", +/// "internalType": "address" +/// } +/// ], +/// "outputs": [], +/// "stateMutability": "nonpayable" +/// }, +/// { +/// "type": "function", +/// "name": "updateNodeOperatorData", +/// "inputs": [ +/// { +/// "name": "operatorIdx", +/// "type": "uint8", +/// "internalType": "uint8" +/// }, +/// { +/// "name": "data", +/// "type": "bytes", +/// "internalType": "bytes" +/// } +/// ], +/// "outputs": [], +/// "stateMutability": "nonpayable" +/// }, +/// { +/// "type": "function", +/// "name": "updateSettings", +/// "inputs": [ +/// { +/// "name": "newSettings", +/// "type": "tuple", +/// "internalType": "struct Settings", +/// "components": [ +/// { +/// "name": "maxOperatorDataBytes", +/// "type": "uint16", +/// "internalType": "uint16" +/// } +/// ] +/// } +/// ], +/// "outputs": [], +/// "stateMutability": "nonpayable" +/// }, +/// { +/// "type": "event", +/// "name": "MaintenanceAborted", +/// "inputs": [ +/// { +/// "name": "clusterVersion", +/// "type": "uint128", +/// "indexed": false, +/// "internalType": "uint128" +/// } +/// ], +/// "anonymous": false +/// }, +/// { +/// "type": "event", +/// "name": "MaintenanceCompleted", +/// "inputs": [ +/// { +/// "name": "operatorAddress", +/// "type": "address", +/// "indexed": false, +/// "internalType": "address" +/// }, +/// { +/// "name": "clusterVersion", +/// "type": "uint128", +/// "indexed": false, +/// "internalType": "uint128" +/// } +/// ], +/// "anonymous": false +/// }, +/// { +/// "type": "event", +/// "name": "MaintenanceStarted", +/// "inputs": [ +/// { +/// "name": "operatorAddress", +/// "type": "address", +/// "indexed": false, +/// "internalType": "address" +/// }, +/// { +/// "name": "clusterVersion", +/// "type": "uint128", +/// "indexed": false, +/// "internalType": "uint128" +/// } +/// ], +/// "anonymous": false +/// }, +/// { +/// "type": "event", +/// "name": "MigrationAborted", +/// "inputs": [ +/// { +/// "name": "id", +/// "type": "uint64", +/// "indexed": false, +/// "internalType": "uint64" +/// }, +/// { +/// "name": "clusterVersion", +/// "type": "uint128", +/// "indexed": false, +/// "internalType": "uint128" +/// } +/// ], +/// "anonymous": false +/// }, +/// { +/// "type": "event", +/// "name": "MigrationCompleted", +/// "inputs": [ +/// { +/// "name": "id", +/// "type": "uint64", +/// "indexed": false, +/// "internalType": "uint64" +/// }, +/// { +/// "name": "operatorAddress", +/// "type": "address", +/// "indexed": false, +/// "internalType": "address" +/// }, +/// { +/// "name": "clusterVersion", +/// "type": "uint128", +/// "indexed": false, +/// "internalType": "uint128" +/// } +/// ], +/// "anonymous": false +/// }, +/// { +/// "type": "event", +/// "name": "MigrationDataPullCompleted", +/// "inputs": [ +/// { +/// "name": "id", +/// "type": "uint64", +/// "indexed": false, +/// "internalType": "uint64" +/// }, +/// { +/// "name": "operatorAddress", +/// "type": "address", +/// "indexed": false, +/// "internalType": "address" +/// }, +/// { +/// "name": "clusterVersion", +/// "type": "uint128", +/// "indexed": false, +/// "internalType": "uint128" +/// } +/// ], +/// "anonymous": false +/// }, +/// { +/// "type": "event", +/// "name": "MigrationStarted", +/// "inputs": [ +/// { +/// "name": "id", +/// "type": "uint64", +/// "indexed": false, +/// "internalType": "uint64" +/// }, +/// { +/// "name": "plan", +/// "type": "tuple", +/// "indexed": false, +/// "internalType": "struct MigrationPlan", +/// "components": [ +/// { +/// "name": "slots", +/// "type": "tuple[]", +/// "internalType": "struct KeyspaceSlot[]", +/// "components": [ +/// { +/// "name": "idx", +/// "type": "uint8", +/// "internalType": "uint8" +/// }, +/// { +/// "name": "operator", +/// "type": "address", +/// "internalType": "address" +/// } +/// ] +/// }, +/// { +/// "name": "replicationStrategy", +/// "type": "uint8", +/// "internalType": "uint8" +/// } +/// ] +/// }, +/// { +/// "name": "clusterVersion", +/// "type": "uint128", +/// "indexed": false, +/// "internalType": "uint128" +/// } +/// ], +/// "anonymous": false +/// }, +/// { +/// "type": "event", +/// "name": "NodeOperatorDataUpdated", +/// "inputs": [ +/// { +/// "name": "operatorAddress", +/// "type": "address", +/// "indexed": false, +/// "internalType": "address" +/// }, +/// { +/// "name": "data", +/// "type": "bytes", +/// "indexed": false, +/// "internalType": "bytes" +/// }, +/// { +/// "name": "clusterVersion", +/// "type": "uint128", +/// "indexed": false, +/// "internalType": "uint128" +/// } +/// ], +/// "anonymous": false +/// } +/// ] +/// ``` #[allow( non_camel_case_types, non_snake_case, @@ -563,8 +561,7 @@ interface Cluster { clippy::empty_structs_with_brackets )] pub mod Cluster { - use super::*; - use alloy::sol_types as alloy_sol_types; + use {super::*, alloy::sol_types as alloy_sol_types}; /// The creation / init bytecode of the contract. /// /// ```text @@ -585,9 +582,9 @@ pub mod Cluster { pub static DEPLOYED_BYTECODE: alloy_sol_types::private::Bytes = alloy_sol_types::private::Bytes::from_static( b"`\x80`@R4\x80\x15a\0\x0FW__\xFD[P`\x046\x10a\0\xA7W_5`\xE0\x1C\x80c\xAD6\xE6\xD0\x11a\0oW\x80c\xAD6\xE6\xD0\x14a\x01'W\x80c\xC10\x80\x9A\x14a\x011W\x80c\xCD\xBF\xC6-\x14a\x01;W\x80c\xDD?\xD2i\x14a\x01WW\x80c\xF0\x19\xB1T\x14a\x01sW\x80c\xF2\xFD\xE3\x8B\x14a\x01\x8FWa\0\xA7V[\x80c0H\xBF\xBA\x14a\0\xABW\x80cU\xA4}\n\x14a\0\xB5W\x80cepo\x9C\x14a\0\xD1W\x80cuA\x8B\x9D\x14a\0\xEDW\x80c\x8BRR\xD6\x14a\x01\x0BW[__\xFD[a\0\xB3a\x01\xABV[\0[a\0\xCF`\x04\x806\x03\x81\x01\x90a\0\xCA\x91\x90a%\x1FV[a\x03\x7FV[\0[a\0\xEB`\x04\x806\x03\x81\x01\x90a\0\xE6\x91\x90a%\x7FV[a\x06\xBDV[\0[a\0\xF5a\x07aV[`@Qa\x01\x02\x91\x90a(\xBCV[`@Q\x80\x91\x03\x90\xF3[a\x01%`\x04\x806\x03\x81\x01\x90a\x01 \x91\x90a)=V[a\x0F\x8FV[\0[a\x01/a\x0F\xECV[\0[a\x019a\x11\xC6V[\0[a\x01U`\x04\x806\x03\x81\x01\x90a\x01P\x91\x90a)\xA6V[a\x13\xC9V[\0[a\x01q`\x04\x806\x03\x81\x01\x90a\x01l\x91\x90a)\xEDV[a\x1A\x99V[\0[a\x01\x8D`\x04\x806\x03\x81\x01\x90a\x01\x88\x91\x90a*\x18V[a\x1D\x15V[\0[a\x01\xA9`\x04\x806\x03\x81\x01\x90a\x01\xA4\x91\x90a*\x9FV[a \xABV[\0[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x029W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x020\x90a+$V[`@Q\x80\x91\x03\x90\xFD[a\x02Aa!{V[a\x02\x80W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x02w\x90a+\x8CV[`@Q\x80\x91\x03\x90\xFD[_a\x02\n_\x01_a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x02\xF1\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\x8F\xB9\xCD\x05M\n\x02!\x10\xCC\xED#\x9E\x90\x8B\x83NL\xD2\x19Q\x18V\xD4\xEA\xAE0Q\xD92\xD6\x04a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x03u\x91\x90a,\x1DV[`@Q\x80\x91\x03\x90\xA1V[a\x03\x87a!\xD5V[a\x03\xC6W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x03\xBD\x90a,\x80V[`@Q\x80\x91\x03\x90\xFD[a\x02\x08_\x01_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x82g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x044W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x04+\x90a,\xE8V[`@Q\x80\x91\x03\x90\xFD[3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x80a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x04o\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x81\x10a\x04\x8AWa\x04\x89a-cV[[a\x01\x02\x02\x01_\x01\x82`\xFF\x16a\x01\0\x81\x10a\x04\xA7Wa\x04\xA6a-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x05\x1EW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x05\x15\x90a-\xDAV[`@Q\x80\x91\x03\x90\xFD[a\x057\x81a\x02\x08`\x01\x01Ta!\xE5\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x06\xB9Wa\x05T\x81a\x02\x08`\x01\x01Ta!\xFA\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x02\x08`\x01\x01\x81\x90UPa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x05\x8C\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP_a\x02\x08`\x01\x01T\x03a\x06FW\x7F\x01&\x98yS_@\xEE\x89W\xE1^\x16\x0B\xF1\x86l^'(\xFF\x0C\xBCX=\x84\x88!\xE2c\x9BNa\x02\x08_\x01_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x069\x93\x92\x91\x90a.\x16V[`@Q\x80\x91\x03\x90\xA1a\x06\xB8V[\x7F\xAF^\x90\xE7 \x15\xF418\xF6kL\xD0\x8B\xD1\xDF\xA2\x83\x900\x10O\"\xA0\n\xF8C\xFE\x84|m\x19a\x02\x08_\x01_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x06\xAF\x93\x92\x91\x90a.\x16V[`@Q\x80\x91\x03\x90\xA1[[PPV[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x07KW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x07B\x90a+$V[`@Q\x80\x91\x03\x90\xFD[\x80a\x02\x07\x81\x81a\x07[\x91\x90a/*V[\x90PPPV[a\x07ia#\xA7V[a\x07qa#\xA7V[___a\x07|a!\xD5V[\x15a\x0B\xB9Wa\x02\x08_\x01_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x84` \x01Q_\x01\x90g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RPPa\x02\x08`\x01\x01T\x84` \x01Q` \x01\x81\x81RPP`\x02`\x01a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x07\xF5\x91\x90a/8V[a\x07\xFF\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x92P_`\x02a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x08/\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90Pa\x08a`\x02\x82`\x02\x81\x10a\x08RWa\x08Qa-cV[[a\x01\x02\x02\x01a\x01\0\x01Ta\"\x0EV[\x91P`\x01\x82a\x08p\x91\x90a/sV[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x08\x89Wa\x08\x88a/\xA6V[[`@Q\x90\x80\x82R\x80` \x02` \x01\x82\x01`@R\x80\x15a\x08\xC2W\x81` \x01[a\x08\xAFa$\x0FV[\x81R` \x01\x90`\x01\x90\x03\x90\x81a\x08\xA7W\x90P[P\x85`@\x01Q_\x01\x81\x90RP`\x02\x81`\x02\x81\x10a\x08\xE2Wa\x08\xE1a-cV[[a\x01\x02\x02\x01a\x01\x01\x01_\x90T\x90a\x01\0\n\x90\x04`\xFF\x16\x85`@\x01Q` \x01\x90`\xFF\x16\x90\x81`\xFF\x16\x81RPP__\x90P[\x82\x81\x11a\x0B\xB2Wa\tI\x81`\x02\x84`\x02\x81\x10a\t1Wa\t0a-cV[[a\x01\x02\x02\x01a\x01\0\x01Ta!\xE5\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x0B\x9FW`\x02\x82`\x02\x81\x10a\taWa\t`a-cV[[a\x01\x02\x02\x01_\x01\x81a\x01\0\x81\x10a\t{Wa\tza-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x93P\x83\x86`@\x01Q_\x01Q\x82\x81Q\x81\x10a\t\xB9Wa\t\xB8a-cV[[` \x02` \x01\x01Q_\x01\x90s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RPPa\n&\x81`\x02\x87`\x02\x81\x10a\n\x0EWa\n\ra-cV[[a\x01\x02\x02\x01a\x01\0\x01Ta!\xE5\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x80a\n\xABWP\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x86`\x02\x81\x10a\nWWa\nVa-cV[[a\x01\x02\x02\x01_\x01\x82a\x01\0\x81\x10a\nqWa\npa-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14\x15[\x15a\x0B\x9EW`\x01_\x85s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ \x80Ta\n\xF8\x90a0\0V[\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01\x82\x80Ta\x0B$\x90a0\0V[\x80\x15a\x0BoW\x80`\x1F\x10a\x0BFWa\x01\0\x80\x83T\x04\x02\x83R\x91` \x01\x91a\x0BoV[\x82\x01\x91\x90_R` _ \x90[\x81T\x81R\x90`\x01\x01\x90` \x01\x80\x83\x11a\x0BRW\x82\x90\x03`\x1F\x16\x82\x01\x91[PPPPP\x86`@\x01Q_\x01Q\x82\x81Q\x81\x10a\x0B\x8EWa\x0B\x8Da-cV[[` \x02` \x01\x01Q` \x01\x81\x90RP[[\x80\x80a\x0B\xAA\x90a00V[\x91PPa\t\x12V[PPa\x0B\xE9V[`\x02a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x0B\xDC\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x92P[a\x0C\x0F`\x02\x84`\x02\x81\x10a\x0C\0Wa\x0B\xFFa-cV[[a\x01\x02\x02\x01a\x01\0\x01Ta\"\x0EV[\x90P`\x01\x81a\x0C\x1E\x91\x90a/sV[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x0C7Wa\x0C6a/\xA6V[[`@Q\x90\x80\x82R\x80` \x02` \x01\x82\x01`@R\x80\x15a\x0CpW\x81` \x01[a\x0C]a$\x0FV[\x81R` \x01\x90`\x01\x90\x03\x90\x81a\x0CUW\x90P[P\x84_\x01Q_\x01\x81\x90RP`\x02\x83`\x02\x81\x10a\x0C\x8FWa\x0C\x8Ea-cV[[a\x01\x02\x02\x01a\x01\x01\x01_\x90T\x90a\x01\0\n\x90\x04`\xFF\x16\x84_\x01Q` \x01\x90`\xFF\x16\x90\x81`\xFF\x16\x81RPP__\x90P[\x81\x81\x11a\x0E\xA1Wa\x0C\xF5\x81`\x02\x86`\x02\x81\x10a\x0C\xDDWa\x0C\xDCa-cV[[a\x01\x02\x02\x01a\x01\0\x01Ta!\xE5\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x0E\x8EW`\x02\x84`\x02\x81\x10a\r\rWa\r\x0Ca-cV[[a\x01\x02\x02\x01_\x01\x81a\x01\0\x81\x10a\r'Wa\r&a-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x92P\x82\x85_\x01Q_\x01Q\x82\x81Q\x81\x10a\rdWa\rca-cV[[` \x02` \x01\x01Q_\x01\x90s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RPP`\x01_\x84s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ \x80Ta\r\xE9\x90a0\0V[\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01\x82\x80Ta\x0E\x15\x90a0\0V[\x80\x15a\x0E`W\x80`\x1F\x10a\x0E7Wa\x01\0\x80\x83T\x04\x02\x83R\x91` \x01\x91a\x0E`V[\x82\x01\x91\x90_R` _ \x90[\x81T\x81R\x90`\x01\x01\x90` \x01\x80\x83\x11a\x0ECW\x82\x90\x03`\x1F\x16\x82\x01\x91[PPPPP\x85_\x01Q_\x01Q\x82\x81Q\x81\x10a\x0E~Wa\x0E}a-cV[[` \x02` \x01\x01Q` \x01\x81\x90RP[\x80\x80a\x0E\x99\x90a00V[\x91PPa\x0C\xBEV[Pa\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x84`\x80\x01\x90g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RPPa\x02\n_\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x84``\x01Q_\x01\x90s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RPPa\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x84`\xA0\x01\x90o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RPP\x83\x94PPPPP\x90V[a\x0F\x9B\x82\x82\x90Pa\"\x1FV[\x81\x81`\x01_3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ \x91\x82a\x0F\xE7\x92\x91\x90a2\x18V[PPPV[a\x0F\xF4a!{V[a\x103W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x10*\x90a+\x8CV[`@Q\x80\x91\x03\x90\xFD[3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x02\n_\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x10\xC5W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x10\xBC\x90a-\xDAV[`@Q\x80\x91\x03\x90\xFD[_a\x02\n_\x01_a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x116\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\xF9\x10g\xEBB\x0C(\xD3\x12He\xFC\x99nj\xA9\xD5A\xB9\xB4\xFE\xF9\x18\x8C\xB9e\xA6\xCCd\x91c\x8E3a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x11\xBC\x92\x91\x90a2\xE5V[`@Q\x80\x91\x03\x90\xA1V[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x12TW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x12K\x90a+$V[`@Q\x80\x91\x03\x90\xFD[a\x12\\a!\xD5V[a\x12\x9BW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x12\x92\x90a,\x80V[`@Q\x80\x91\x03\x90\xFD[a\x02\x06_\x81\x81\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x12\xC1\x90a3\x0CV[\x91\x90a\x01\0\n\x81T\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP_a\x02\x08`\x01\x01\x81\x90UPa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x13!\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\xF72@B\"F\xF6>\xD63\xEF<\xE0rk\x8A\xB8\xFBi\xD4l\x8AN^\xCB\x0B)\"f\x86t\xA1a\x02\x08_\x01_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x13\xBF\x92\x91\x90a33V[`@Q\x80\x91\x03\x90\xA1V[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x14WW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x14N\x90a+$V[`@Q\x80\x91\x03\x90\xFD[a\x14_a!\xD5V[\x15a\x14\x9FW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x14\x96\x90a3\xA4V[`@Q\x80\x91\x03\x90\xFD[a\x14\xA7a!{V[\x15a\x14\xE7W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x14\xDE\x90a4\x0CV[`@Q\x80\x91\x03\x90\xFD[a\x02\x08_\x01_\x81\x81\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x15\x0F\x90a4*V[\x91\x90a\x01\0\n\x81T\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP_`\x02a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x15Z\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90Pa\x02\x06_\x81\x81\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x15\x8C\x90a4*V[\x91\x90a\x01\0\n\x81T\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP_`\x02a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x15\xD7\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90P__\x90P[a\x16\x0E`\x02\x84`\x02\x81\x10a\x15\xFFWa\x15\xFEa-cV[[a\x01\x02\x02\x01a\x01\0\x01Ta\"\x0EV[\x81\x11a\x17\xB2W`\x02\x83`\x02\x81\x10a\x16(Wa\x16'a-cV[[a\x01\x02\x02\x01_\x01\x81a\x01\0\x81\x10a\x16BWa\x16Aa-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x83`\x02\x81\x10a\x16\x8DWa\x16\x8Ca-cV[[a\x01\x02\x02\x01_\x01\x82a\x01\0\x81\x10a\x16\xA7Wa\x16\xA6a-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x17\x9FW`\x02\x83`\x02\x81\x10a\x16\xF7Wa\x16\xF6a-cV[[a\x01\x02\x02\x01_\x01\x81a\x01\0\x81\x10a\x17\x11Wa\x17\x10a-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x83`\x02\x81\x10a\x17FWa\x17Ea-cV[[a\x01\x02\x02\x01_\x01\x82a\x01\0\x81\x10a\x17`Wa\x17_a-cV[[\x01_a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UP[\x80\x80a\x17\xAA\x90a00V[\x91PPa\x15\xE8V[P_`\x02\x83`\x02\x81\x10a\x17\xC8Wa\x17\xC7a-cV[[a\x01\x02\x02\x01a\x01\0\x01T\x90P____\x90P[\x86\x80_\x01\x90a\x17\xEA\x91\x90a4eV[\x90P\x81\x10\x15a\x19FW\x86\x80_\x01\x90a\x18\x02\x91\x90a4eV[\x82\x81\x81\x10a\x18\x13Wa\x18\x12a-cV[[\x90P`@\x02\x01_\x01` \x81\x01\x90a\x18*\x91\x90a)\xEDV[\x92P\x86\x80_\x01\x90a\x18;\x91\x90a4eV[\x82\x81\x81\x10a\x18LWa\x18Ka-cV[[\x90P`@\x02\x01` \x01` \x81\x01\x90a\x18d\x91\x90a*\x9FV[\x91P_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x82s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x03a\x18\xB3Wa\x18\xAC\x83\x85a!\xFA\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x93Pa\x18\xC9V[a\x18\xC6\x83\x85a\"\xBD\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x93P[\x81`\x02\x86`\x02\x81\x10a\x18\xDEWa\x18\xDDa-cV[[a\x01\x02\x02\x01_\x01\x84`\xFF\x16a\x01\0\x81\x10a\x18\xFBWa\x18\xFAa-cV[[\x01_a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UP\x80\x80`\x01\x01\x91PPa\x17\xDBV[P\x82`\x02\x85`\x02\x81\x10a\x19\\Wa\x19[a-cV[[a\x01\x02\x02\x01a\x01\0\x01\x81\x90UP\x85` \x01` \x81\x01\x90a\x19|\x91\x90a)\xEDV[`\x02\x85`\x02\x81\x10a\x19\x90Wa\x19\x8Fa-cV[[a\x01\x02\x02\x01a\x01\x01\x01_a\x01\0\n\x81T\x81`\xFF\x02\x19\x16\x90\x83`\xFF\x16\x02\x17\x90UP\x82a\x02\x08`\x01\x01\x81\x90UPa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x19\xE9\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7Fx\xDA\xD2\xBC\x0BG\xC6\x88\xED\x84\xF3\xFE\xE7\x9A\xBC\x18\xE6\xC9\x82-\xB0Zy\xCA\x19\xDF\xF5E3\xC7G\ra\x02\x08_\x01_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x87a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x1A\x89\x93\x92\x91\x90a6\x8BV[`@Q\x80\x91\x03\x90\xA1PPPPPPV[a\x1A\xA1a!\xD5V[\x15a\x1A\xE1W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x1A\xD8\x90a3\xA4V[`@Q\x80\x91\x03\x90\xFD[a\x1A\xE9a!{V[\x15a\x1B)W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x1B \x90a4\x0CV[`@Q\x80\x91\x03\x90\xFD[3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x80a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x1Bd\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x81\x10a\x1B\x7FWa\x1B~a-cV[[a\x01\x02\x02\x01_\x01\x82`\xFF\x16a\x01\0\x81\x10a\x1B\x9CWa\x1B\x9Ba-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x1C\x13W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x1C\n\x90a-\xDAV[`@Q\x80\x91\x03\x90\xFD[3a\x02\n_\x01_a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x1C\x84\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\xBC'H\xCF\x02\xF7\xA1)\x15%\xE8f\xEF\xC7j\xB3\xB9m2\xD7\xAF\xCB\xB2lS\xDA\xECa{8\xB4y3a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x1D\n\x92\x91\x90a2\xE5V[`@Q\x80\x91\x03\x90\xA1PV[a\x1D!\x82\x82\x90Pa\"\x1FV[__a\x1D+a!\xD5V[\x15a\x1E\xA1W3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x80`\x01a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x1Dm\x91\x90a/8V[a\x1Dw\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x81\x10a\x1D\x92Wa\x1D\x91a-cV[[a\x01\x02\x02\x01_\x01\x86`\xFF\x16a\x01\0\x81\x10a\x1D\xAFWa\x1D\xAEa-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14\x91P\x81a\x1E\x9CW3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x80a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x1E)\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x81\x10a\x1EDWa\x1ECa-cV[[a\x01\x02\x02\x01_\x01\x86`\xFF\x16a\x01\0\x81\x10a\x1EaWa\x1E`a-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14\x90P[a\x1FOV[3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x80a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x1E\xDC\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x81\x10a\x1E\xF7Wa\x1E\xF6a-cV[[a\x01\x02\x02\x01_\x01\x86`\xFF\x16a\x01\0\x81\x10a\x1F\x14Wa\x1F\x13a-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14\x91P[\x81\x80a\x1FXWP\x80[a\x1F\x97W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x1F\x8E\x90a-\xDAV[`@Q\x80\x91\x03\x90\xFD[\x83\x83`\x01_3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ \x91\x82a\x1F\xE3\x92\x91\x90a2\x18V[Pa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a \x12\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\x12Q\x81\xEC!\x88-\xECQ\xA29)\x05\xDF\xF3\xA8,\xBD\x02b\xF1\x8B\\\x0C\x03T\x88g\x1B@\xAF\xB23\x85\x85a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa \x9C\x94\x93\x92\x91\x90a7\x11V[`@Q\x80\x91\x03\x90\xA1PPPPPV[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a!9W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a!0\x90a+$V[`@Q\x80\x91\x03\x90\xFD[\x80__a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPPV[__s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x02\n_\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14\x15\x90P\x90V[__a\x02\x08`\x01\x01T\x14\x15\x90P\x90V[__\x82`\xFF\x16`\x01\x90\x1B\x84\x16\x14\x90P\x92\x91PPV[_\x81`\xFF\x16`\x01\x90\x1B\x19\x83\x16\x90P\x92\x91PPV[_a\"\x18\x82a\"\xD0V[\x90P\x91\x90PV[_\x81\x11a\"aW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\"X\x90a7\x99V[`@Q\x80\x91\x03\x90\xFD[a\x02\x07_\x01_\x90T\x90a\x01\0\n\x90\x04a\xFF\xFF\x16a\xFF\xFF\x16\x81\x11\x15a\"\xBAW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\"\xB1\x90a8\x01V[`@Q\x80\x91\x03\x90\xFD[PV[_\x81`\xFF\x16`\x01\x90\x1B\x83\x17\x90P\x92\x91PPV[_`\x07a\"\xEEo\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x84\x11a#\x9CV[\x90\x1B\x90P`\x06a#\ng\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x83\x85\x90\x1C\x11a#\x9CV[\x90\x1B\x81\x17\x90P`\x05a#$c\xFF\xFF\xFF\xFF\x83\x85\x90\x1C\x11a#\x9CV[\x90\x1B\x81\x17\x90P`\x04a#V[\x81R` \x01a#\xC7a$ZV[\x81R` \x01a#\xD4a$>V[\x81R` \x01a#\xE1a$|V[\x81R` \x01_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01_o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RP\x90V[`@Q\x80`@\x01`@R\x80_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01``\x81RP\x90V[`@Q\x80`@\x01`@R\x80``\x81R` \x01_`\xFF\x16\x81RP\x90V[`@Q\x80`@\x01`@R\x80_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01_\x81RP\x90V[`@Q\x80` \x01`@R\x80_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RP\x90V[__\xFD[__\xFD[_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[a$\xC8\x81a$\xACV[\x81\x14a$\xD2W__\xFD[PV[_\x815\x90Pa$\xE3\x81a$\xBFV[\x92\x91PPV[_`\xFF\x82\x16\x90P\x91\x90PV[a$\xFE\x81a$\xE9V[\x81\x14a%\x08W__\xFD[PV[_\x815\x90Pa%\x19\x81a$\xF5V[\x92\x91PPV[__`@\x83\x85\x03\x12\x15a%5Wa%4a$\xA4V[[_a%B\x85\x82\x86\x01a$\xD5V[\x92PP` a%S\x85\x82\x86\x01a%\x0BV[\x91PP\x92P\x92\x90PV[__\xFD[_` \x82\x84\x03\x12\x15a%vWa%ua%]V[[\x81\x90P\x92\x91PPV[_` \x82\x84\x03\x12\x15a%\x94Wa%\x93a$\xA4V[[_a%\xA1\x84\x82\x85\x01a%aV[\x91PP\x92\x91PPV[_\x81Q\x90P\x91\x90PV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[_\x81\x90P` \x82\x01\x90P\x91\x90PV[_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[_a%\xFC\x82a%\xD3V[\x90P\x91\x90PV[a&\x0C\x81a%\xF2V[\x82RPPV[_\x81Q\x90P\x91\x90PV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[\x82\x81\x83^_\x83\x83\x01RPPPV[_`\x1F\x19`\x1F\x83\x01\x16\x90P\x91\x90PV[_a&T\x82a&\x12V[a&^\x81\x85a&\x1CV[\x93Pa&n\x81\x85` \x86\x01a&,V[a&w\x81a&:V[\x84\x01\x91PP\x92\x91PPV[_`@\x83\x01_\x83\x01Qa&\x97_\x86\x01\x82a&\x03V[P` \x83\x01Q\x84\x82\x03` \x86\x01Ra&\xAF\x82\x82a&JV[\x91PP\x80\x91PP\x92\x91PPV[_a&\xC7\x83\x83a&\x82V[\x90P\x92\x91PPV[_` \x82\x01\x90P\x91\x90PV[_a&\xE5\x82a%\xAAV[a&\xEF\x81\x85a%\xB4V[\x93P\x83` \x82\x02\x85\x01a'\x01\x85a%\xC4V[\x80_[\x85\x81\x10\x15a'\x82a1 V[\x84\x84Ta0\xAEV[\x82UPPPPV[__\x90P\x90V[a1]a1NV[a1h\x81\x84\x84a1)V[PPPV[[\x81\x81\x10\x15a1\x8BWa1\x80_\x82a1UV[`\x01\x81\x01\x90Pa1nV[PPV[`\x1F\x82\x11\x15a1\xD0Wa1\xA1\x81a0\x81V[a1\xAA\x84a0\x93V[\x81\x01` \x85\x10\x15a1\xB9W\x81\x90P[a1\xCDa1\xC5\x85a0\x93V[\x83\x01\x82a1mV[PP[PPPV[_\x82\x82\x1C\x90P\x92\x91PPV[_a1\xF0_\x19\x84`\x08\x02a1\xD5V[\x19\x80\x83\x16\x91PP\x92\x91PPV[_a2\x08\x83\x83a1\xE1V[\x91P\x82`\x02\x02\x82\x17\x90P\x92\x91PPV[a2\"\x83\x83a0wV[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a2;Wa2:a/\xA6V[[a2E\x82Ta0\0V[a2P\x82\x82\x85a1\x8FV[_`\x1F\x83\x11`\x01\x81\x14a2}W_\x84\x15a2kW\x82\x87\x015\x90P[a2u\x85\x82a1\xFDV[\x86UPa2\xDCV[`\x1F\x19\x84\x16a2\x8B\x86a0\x81V[_[\x82\x81\x10\x15a2\xB2W\x84\x89\x015\x82U`\x01\x82\x01\x91P` \x85\x01\x94P` \x81\x01\x90Pa2\x8DV[\x86\x83\x10\x15a2\xCFW\x84\x89\x015a2\xCB`\x1F\x89\x16\x82a1\xE1V[\x83UP[`\x01`\x02\x88\x02\x01\x88UPPP[PPPPPPPV[_`@\x82\x01\x90Pa2\xF8_\x83\x01\x85a.\x07V[a3\x05` \x83\x01\x84a,\x0EV[\x93\x92PPPV[_a3\x16\x82a$\xACV[\x91P_\x82\x03a3(Wa3'a+\xAAV[[`\x01\x82\x03\x90P\x91\x90PV[_`@\x82\x01\x90Pa3F_\x83\x01\x85a-\xF8V[a3S` \x83\x01\x84a,\x0EV[\x93\x92PPPV[\x7Fmigration in progress\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a3\x8E`\x15\x83a*\xCAV[\x91Pa3\x99\x82a3ZV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra3\xBB\x81a3\x82V[\x90P\x91\x90PV[\x7Fmaintenance in progress\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a3\xF6`\x17\x83a*\xCAV[\x91Pa4\x01\x82a3\xC2V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra4#\x81a3\xEAV[\x90P\x91\x90PV[_a44\x82a$\xACV[\x91Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x03a4NWa4Ma+\xAAV[[`\x01\x82\x01\x90P\x91\x90PV[__\xFD[__\xFD[__\xFD[__\x835`\x01` \x03\x846\x03\x03\x81\x12a4\x81Wa4\x80a4YV[[\x80\x84\x01\x92P\x825\x91Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15a4\xA3Wa4\xA2a4]V[[` \x83\x01\x92P`@\x82\x026\x03\x83\x13\x15a4\xBFWa4\xBEa4aV[[P\x92P\x92\x90PV[__\xFD[__\xFD[__\xFD[__\x835`\x01` \x03\x846\x03\x03\x81\x12a4\xEFWa4\xEEa4\xCFV[[\x83\x81\x01\x92P\x825\x91P` \x83\x01\x92Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15a5\x17Wa5\x16a4\xC7V[[`@\x82\x026\x03\x83\x13\x15a5-Wa5,a4\xCBV[[P\x92P\x92\x90PV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[_\x81\x90P\x91\x90PV[_a5\\` \x84\x01\x84a%\x0BV[\x90P\x92\x91PPV[_a5r` \x84\x01\x84a*\x8BV[\x90P\x92\x91PPV[`@\x82\x01a5\x8A_\x83\x01\x83a5NV[a5\x96_\x85\x01\x82a'NV[Pa5\xA4` \x83\x01\x83a5dV[a5\xB1` \x85\x01\x82a&\x03V[PPPPV[_a5\xC2\x83\x83a5zV[`@\x83\x01\x90P\x92\x91PPV[_\x82\x90P\x92\x91PPV[_`@\x82\x01\x90P\x91\x90PV[_a5\xEF\x83\x85a55V[\x93Pa5\xFA\x82a5EV[\x80_[\x85\x81\x10\x15a62Wa6\x0F\x82\x84a5\xCEV[a6\x19\x88\x82a5\xB7V[\x97Pa6$\x83a5\xD8V[\x92PP`\x01\x81\x01\x90Pa5\xFDV[P\x85\x92PPP\x93\x92PPPV[_`@\x83\x01a6P_\x84\x01\x84a4\xD3V[\x85\x83\x03_\x87\x01Ra6b\x83\x82\x84a5\xE4V[\x92PPPa6s` \x84\x01\x84a5NV[a6\x80` \x86\x01\x82a'NV[P\x80\x91PP\x92\x91PPV[_``\x82\x01\x90Pa6\x9E_\x83\x01\x86a-\xF8V[\x81\x81\x03` \x83\x01Ra6\xB0\x81\x85a6?V[\x90Pa6\xBF`@\x83\x01\x84a,\x0EV[\x94\x93PPPPV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[\x82\x81\x837_\x83\x83\x01RPPPV[_a6\xF0\x83\x85a6\xC7V[\x93Pa6\xFD\x83\x85\x84a6\xD7V[a7\x06\x83a&:V[\x84\x01\x90P\x93\x92PPPV[_``\x82\x01\x90Pa7$_\x83\x01\x87a.\x07V[\x81\x81\x03` \x83\x01Ra77\x81\x85\x87a6\xE5V[\x90Pa7F`@\x83\x01\x84a,\x0EV[\x95\x94PPPPPV[\x7Fempty operator data\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a7\x83`\x13\x83a*\xCAV[\x91Pa7\x8E\x82a7OV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra7\xB0\x81a7wV[\x90P\x91\x90PV[\x7Foperator data too large\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a7\xEB`\x17\x83a*\xCAV[\x91Pa7\xF6\x82a7\xB7V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra8\x18\x81a7\xDFV[\x90P\x91\x90PV\xFE\xA2dipfsX\"\x12 \xFA\x04\xDE\xADB^j\xA2\xEEQe+w\xCD\x8B\xEC4O\x89\xD5\xA5\xD1\x8BB\xF4\x88\x9Bz\xBA\xD1s\"dsolcC\0\x08\x1C\x003", ); - /**```solidity -struct ClusterView { KeyspaceView keyspace; Migration migration; KeyspaceView migrationKeyspace; Maintenance maintenance; uint64 keyspaceVersion; uint128 version; } -```*/ + /// ```solidity + /// struct ClusterView { KeyspaceView keyspace; Migration migration; KeyspaceView migrationKeyspace; Maintenance maintenance; uint64 keyspaceVersion; uint128 version; } + /// ``` #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] pub struct ClusterView { @@ -632,9 +629,7 @@ struct ClusterView { KeyspaceView keyspace; Migration migration; KeyspaceView mi ); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] - fn _type_assertion( - _t: alloy_sol_types::private::AssertTypeEq, - ) { + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { match _t { alloy_sol_types::private::AssertTypeEq::< ::RustType, @@ -680,18 +675,14 @@ struct ClusterView { KeyspaceView keyspace; Migration migration; KeyspaceView mi ( ::tokenize(&self.keyspace), ::tokenize(&self.migration), - ::tokenize( - &self.migrationKeyspace, + ::tokenize(&self.migrationKeyspace), + ::tokenize(&self.maintenance), + as alloy_sol_types::SolType>::tokenize( + &self.keyspaceVersion, ), - ::tokenize( - &self.maintenance, + as alloy_sol_types::SolType>::tokenize( + &self.version, ), - as alloy_sol_types::SolType>::tokenize(&self.keyspaceVersion), - as alloy_sol_types::SolType>::tokenize(&self.version), ) } #[inline] @@ -699,64 +690,50 @@ struct ClusterView { KeyspaceView keyspace; Migration migration; KeyspaceView mi if let Some(size) = ::ENCODED_SIZE { return size; } - let tuple = as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_encoded_size(&tuple) + let tuple = + as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encoded_size(&tuple) } #[inline] fn stv_eip712_data_word(&self) -> alloy_sol_types::Word { ::eip712_hash_struct(self) } #[inline] - fn stv_abi_encode_packed_to( - &self, - out: &mut alloy_sol_types::private::Vec, - ) { - let tuple = as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_encode_packed_to(&tuple, out) + fn stv_abi_encode_packed_to(&self, out: &mut alloy_sol_types::private::Vec) { + let tuple = + as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encode_packed_to( + &tuple, out, + ) } #[inline] fn stv_abi_packed_encoded_size(&self) -> usize { if let Some(size) = ::PACKED_ENCODED_SIZE { return size; } - let tuple = as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_packed_encoded_size(&tuple) + let tuple = + as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_packed_encoded_size( + &tuple, + ) } } #[automatically_derived] impl alloy_sol_types::SolType for ClusterView { type RustType = Self; - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; const SOL_NAME: &'static str = ::NAME; - const ENCODED_SIZE: Option = as alloy_sol_types::SolType>::ENCODED_SIZE; - const PACKED_ENCODED_SIZE: Option = as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; + const ENCODED_SIZE: Option = + as alloy_sol_types::SolType>::ENCODED_SIZE; + const PACKED_ENCODED_SIZE: Option = + as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; #[inline] fn valid_token(token: &Self::Token<'_>) -> bool { as alloy_sol_types::SolType>::valid_token(token) } #[inline] fn detokenize(token: Self::Token<'_>) -> Self::RustType { - let tuple = as alloy_sol_types::SolType>::detokenize(token); + let tuple = as alloy_sol_types::SolType>::detokenize(token); >>::from(tuple) } } @@ -766,44 +743,26 @@ struct ClusterView { KeyspaceView keyspace; Migration migration; KeyspaceView mi #[inline] fn eip712_root_type() -> alloy_sol_types::private::Cow<'static, str> { alloy_sol_types::private::Cow::Borrowed( - "ClusterView(KeyspaceView keyspace,Migration migration,KeyspaceView migrationKeyspace,Maintenance maintenance,uint64 keyspaceVersion,uint128 version)", + "ClusterView(KeyspaceView keyspace,Migration migration,KeyspaceView \ + migrationKeyspace,Maintenance maintenance,uint64 keyspaceVersion,uint128 \ + version)", ) } #[inline] - fn eip712_components() -> alloy_sol_types::private::Vec< - alloy_sol_types::private::Cow<'static, str>, - > { + fn eip712_components( + ) -> alloy_sol_types::private::Vec> + { let mut components = alloy_sol_types::private::Vec::with_capacity(4); + components.push(::eip712_root_type()); components - .push( - ::eip712_root_type(), - ); - components - .extend( - ::eip712_components(), - ); - components - .push(::eip712_root_type()); + .extend(::eip712_components()); + components.push(::eip712_root_type()); + components.extend(::eip712_components()); + components.push(::eip712_root_type()); components - .extend( - ::eip712_components(), - ); - components - .push( - ::eip712_root_type(), - ); - components - .extend( - ::eip712_components(), - ); - components - .push( - ::eip712_root_type(), - ); - components - .extend( - ::eip712_components(), - ); + .extend(::eip712_components()); + components.push(::eip712_root_type()); + components.extend(::eip712_components()); components } #[inline] @@ -872,9 +831,7 @@ struct ClusterView { KeyspaceView keyspace; Migration migration; KeyspaceView mi rust: &Self::RustType, out: &mut alloy_sol_types::private::Vec, ) { - out.reserve( - ::topic_preimage_length(rust), - ); + out.reserve(::topic_preimage_length(rust)); ::encode_topic_preimage( &rust.keyspace, out, @@ -905,23 +862,16 @@ struct ClusterView { KeyspaceView keyspace; Migration migration; KeyspaceView mi ); } #[inline] - fn encode_topic( - rust: &Self::RustType, - ) -> alloy_sol_types::abi::token::WordToken { + fn encode_topic(rust: &Self::RustType) -> alloy_sol_types::abi::token::WordToken { let mut out = alloy_sol_types::private::Vec::new(); - ::encode_topic_preimage( - rust, - &mut out, - ); - alloy_sol_types::abi::token::WordToken( - alloy_sol_types::private::keccak256(out), - ) + ::encode_topic_preimage(rust, &mut out); + alloy_sol_types::abi::token::WordToken(alloy_sol_types::private::keccak256(out)) } } }; - /**```solidity -struct KeyspaceSlot { uint8 idx; address operator; } -```*/ + /// ```solidity + /// struct KeyspaceSlot { uint8 idx; address operator; } + /// ``` #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] pub struct KeyspaceSlot { @@ -947,9 +897,7 @@ struct KeyspaceSlot { uint8 idx; address operator; } type UnderlyingRustTuple<'a> = (u8, alloy::sol_types::private::Address); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] - fn _type_assertion( - _t: alloy_sol_types::private::AssertTypeEq, - ) { + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { match _t { alloy_sol_types::private::AssertTypeEq::< ::RustType, @@ -982,9 +930,9 @@ struct KeyspaceSlot { uint8 idx; address operator; } #[inline] fn stv_to_tokens(&self) -> ::Token<'_> { ( - as alloy_sol_types::SolType>::tokenize(&self.idx), + as alloy_sol_types::SolType>::tokenize( + &self.idx, + ), ::tokenize( &self.operator, ), @@ -995,64 +943,50 @@ struct KeyspaceSlot { uint8 idx; address operator; } if let Some(size) = ::ENCODED_SIZE { return size; } - let tuple = as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_encoded_size(&tuple) + let tuple = + as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encoded_size(&tuple) } #[inline] fn stv_eip712_data_word(&self) -> alloy_sol_types::Word { ::eip712_hash_struct(self) } #[inline] - fn stv_abi_encode_packed_to( - &self, - out: &mut alloy_sol_types::private::Vec, - ) { - let tuple = as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_encode_packed_to(&tuple, out) + fn stv_abi_encode_packed_to(&self, out: &mut alloy_sol_types::private::Vec) { + let tuple = + as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encode_packed_to( + &tuple, out, + ) } #[inline] fn stv_abi_packed_encoded_size(&self) -> usize { if let Some(size) = ::PACKED_ENCODED_SIZE { return size; } - let tuple = as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_packed_encoded_size(&tuple) + let tuple = + as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_packed_encoded_size( + &tuple, + ) } } #[automatically_derived] impl alloy_sol_types::SolType for KeyspaceSlot { type RustType = Self; - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; const SOL_NAME: &'static str = ::NAME; - const ENCODED_SIZE: Option = as alloy_sol_types::SolType>::ENCODED_SIZE; - const PACKED_ENCODED_SIZE: Option = as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; + const ENCODED_SIZE: Option = + as alloy_sol_types::SolType>::ENCODED_SIZE; + const PACKED_ENCODED_SIZE: Option = + as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; #[inline] fn valid_token(token: &Self::Token<'_>) -> bool { as alloy_sol_types::SolType>::valid_token(token) } #[inline] fn detokenize(token: Self::Token<'_>) -> Self::RustType { - let tuple = as alloy_sol_types::SolType>::detokenize(token); + let tuple = as alloy_sol_types::SolType>::detokenize(token); >>::from(tuple) } } @@ -1061,14 +995,12 @@ struct KeyspaceSlot { uint8 idx; address operator; } const NAME: &'static str = "KeyspaceSlot"; #[inline] fn eip712_root_type() -> alloy_sol_types::private::Cow<'static, str> { - alloy_sol_types::private::Cow::Borrowed( - "KeyspaceSlot(uint8 idx,address operator)", - ) + alloy_sol_types::private::Cow::Borrowed("KeyspaceSlot(uint8 idx,address operator)") } #[inline] - fn eip712_components() -> alloy_sol_types::private::Vec< - alloy_sol_types::private::Cow<'static, str>, - > { + fn eip712_components( + ) -> alloy_sol_types::private::Vec> + { alloy_sol_types::private::Vec::new() } #[inline] @@ -1107,9 +1039,7 @@ struct KeyspaceSlot { uint8 idx; address operator; } rust: &Self::RustType, out: &mut alloy_sol_types::private::Vec, ) { - out.reserve( - ::topic_preimage_length(rust), - ); + out.reserve(::topic_preimage_length(rust)); as alloy_sol_types::EventTopic>::encode_topic_preimage(&rust.idx, out); @@ -1119,30 +1049,22 @@ struct KeyspaceSlot { uint8 idx; address operator; } ); } #[inline] - fn encode_topic( - rust: &Self::RustType, - ) -> alloy_sol_types::abi::token::WordToken { + fn encode_topic(rust: &Self::RustType) -> alloy_sol_types::abi::token::WordToken { let mut out = alloy_sol_types::private::Vec::new(); - ::encode_topic_preimage( - rust, - &mut out, - ); - alloy_sol_types::abi::token::WordToken( - alloy_sol_types::private::keccak256(out), - ) + ::encode_topic_preimage(rust, &mut out); + alloy_sol_types::abi::token::WordToken(alloy_sol_types::private::keccak256(out)) } } }; - /**```solidity -struct KeyspaceView { NodeOperator[] operators; uint8 replicationStrategy; } -```*/ + /// ```solidity + /// struct KeyspaceView { NodeOperator[] operators; uint8 replicationStrategy; } + /// ``` #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] pub struct KeyspaceView { #[allow(missing_docs)] - pub operators: alloy::sol_types::private::Vec< - ::RustType, - >, + pub operators: + alloy::sol_types::private::Vec<::RustType>, #[allow(missing_docs)] pub replicationStrategy: u8, } @@ -1161,16 +1083,12 @@ struct KeyspaceView { NodeOperator[] operators; uint8 replicationStrategy; } ); #[doc(hidden)] type UnderlyingRustTuple<'a> = ( - alloy::sol_types::private::Vec< - ::RustType, - >, + alloy::sol_types::private::Vec<::RustType>, u8, ); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] - fn _type_assertion( - _t: alloy_sol_types::private::AssertTypeEq, - ) { + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { match _t { alloy_sol_types::private::AssertTypeEq::< ::RustType, @@ -1216,64 +1134,50 @@ struct KeyspaceView { NodeOperator[] operators; uint8 replicationStrategy; } if let Some(size) = ::ENCODED_SIZE { return size; } - let tuple = as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_encoded_size(&tuple) + let tuple = + as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encoded_size(&tuple) } #[inline] fn stv_eip712_data_word(&self) -> alloy_sol_types::Word { ::eip712_hash_struct(self) } #[inline] - fn stv_abi_encode_packed_to( - &self, - out: &mut alloy_sol_types::private::Vec, - ) { - let tuple = as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_encode_packed_to(&tuple, out) + fn stv_abi_encode_packed_to(&self, out: &mut alloy_sol_types::private::Vec) { + let tuple = + as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encode_packed_to( + &tuple, out, + ) } #[inline] fn stv_abi_packed_encoded_size(&self) -> usize { if let Some(size) = ::PACKED_ENCODED_SIZE { return size; } - let tuple = as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_packed_encoded_size(&tuple) + let tuple = + as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_packed_encoded_size( + &tuple, + ) } } #[automatically_derived] impl alloy_sol_types::SolType for KeyspaceView { type RustType = Self; - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; const SOL_NAME: &'static str = ::NAME; - const ENCODED_SIZE: Option = as alloy_sol_types::SolType>::ENCODED_SIZE; - const PACKED_ENCODED_SIZE: Option = as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; + const ENCODED_SIZE: Option = + as alloy_sol_types::SolType>::ENCODED_SIZE; + const PACKED_ENCODED_SIZE: Option = + as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; #[inline] fn valid_token(token: &Self::Token<'_>) -> bool { as alloy_sol_types::SolType>::valid_token(token) } #[inline] fn detokenize(token: Self::Token<'_>) -> Self::RustType { - let tuple = as alloy_sol_types::SolType>::detokenize(token); + let tuple = as alloy_sol_types::SolType>::detokenize(token); >>::from(tuple) } } @@ -1287,18 +1191,13 @@ struct KeyspaceView { NodeOperator[] operators; uint8 replicationStrategy; } ) } #[inline] - fn eip712_components() -> alloy_sol_types::private::Vec< - alloy_sol_types::private::Cow<'static, str>, - > { + fn eip712_components( + ) -> alloy_sol_types::private::Vec> + { let mut components = alloy_sol_types::private::Vec::with_capacity(1); + components.push(::eip712_root_type()); components - .push( - ::eip712_root_type(), - ); - components - .extend( - ::eip712_components(), - ); + .extend(::eip712_components()); components } #[inline] @@ -1339,9 +1238,7 @@ struct KeyspaceView { NodeOperator[] operators; uint8 replicationStrategy; } rust: &Self::RustType, out: &mut alloy_sol_types::private::Vec, ) { - out.reserve( - ::topic_preimage_length(rust), - ); + out.reserve(::topic_preimage_length(rust)); as alloy_sol_types::EventTopic>::encode_topic_preimage( @@ -1356,23 +1253,16 @@ struct KeyspaceView { NodeOperator[] operators; uint8 replicationStrategy; } ); } #[inline] - fn encode_topic( - rust: &Self::RustType, - ) -> alloy_sol_types::abi::token::WordToken { + fn encode_topic(rust: &Self::RustType) -> alloy_sol_types::abi::token::WordToken { let mut out = alloy_sol_types::private::Vec::new(); - ::encode_topic_preimage( - rust, - &mut out, - ); - alloy_sol_types::abi::token::WordToken( - alloy_sol_types::private::keccak256(out), - ) + ::encode_topic_preimage(rust, &mut out); + alloy_sol_types::abi::token::WordToken(alloy_sol_types::private::keccak256(out)) } } }; - /**```solidity -struct Maintenance { address slot; } -```*/ + /// ```solidity + /// struct Maintenance { address slot; } + /// ``` #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] pub struct Maintenance { @@ -1393,9 +1283,7 @@ struct Maintenance { address slot; } type UnderlyingRustTuple<'a> = (alloy::sol_types::private::Address,); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] - fn _type_assertion( - _t: alloy_sol_types::private::AssertTypeEq, - ) { + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { match _t { alloy_sol_types::private::AssertTypeEq::< ::RustType, @@ -1435,64 +1323,50 @@ struct Maintenance { address slot; } if let Some(size) = ::ENCODED_SIZE { return size; } - let tuple = as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_encoded_size(&tuple) + let tuple = + as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encoded_size(&tuple) } #[inline] fn stv_eip712_data_word(&self) -> alloy_sol_types::Word { ::eip712_hash_struct(self) } #[inline] - fn stv_abi_encode_packed_to( - &self, - out: &mut alloy_sol_types::private::Vec, - ) { - let tuple = as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_encode_packed_to(&tuple, out) + fn stv_abi_encode_packed_to(&self, out: &mut alloy_sol_types::private::Vec) { + let tuple = + as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encode_packed_to( + &tuple, out, + ) } #[inline] fn stv_abi_packed_encoded_size(&self) -> usize { if let Some(size) = ::PACKED_ENCODED_SIZE { return size; } - let tuple = as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_packed_encoded_size(&tuple) + let tuple = + as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_packed_encoded_size( + &tuple, + ) } } #[automatically_derived] impl alloy_sol_types::SolType for Maintenance { type RustType = Self; - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; const SOL_NAME: &'static str = ::NAME; - const ENCODED_SIZE: Option = as alloy_sol_types::SolType>::ENCODED_SIZE; - const PACKED_ENCODED_SIZE: Option = as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; + const ENCODED_SIZE: Option = + as alloy_sol_types::SolType>::ENCODED_SIZE; + const PACKED_ENCODED_SIZE: Option = + as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; #[inline] fn valid_token(token: &Self::Token<'_>) -> bool { as alloy_sol_types::SolType>::valid_token(token) } #[inline] fn detokenize(token: Self::Token<'_>) -> Self::RustType { - let tuple = as alloy_sol_types::SolType>::detokenize(token); + let tuple = as alloy_sol_types::SolType>::detokenize(token); >>::from(tuple) } } @@ -1504,9 +1378,9 @@ struct Maintenance { address slot; } alloy_sol_types::private::Cow::Borrowed("Maintenance(address slot)") } #[inline] - fn eip712_components() -> alloy_sol_types::private::Vec< - alloy_sol_types::private::Cow<'static, str>, - > { + fn eip712_components( + ) -> alloy_sol_types::private::Vec> + { alloy_sol_types::private::Vec::new() } #[inline] @@ -1516,10 +1390,10 @@ struct Maintenance { address slot; } #[inline] fn eip712_encode_data(&self) -> alloy_sol_types::private::Vec { ::eip712_data_word( - &self.slot, - ) - .0 - .to_vec() + &self.slot, + ) + .0 + .to_vec() } } #[automatically_derived] @@ -1536,32 +1410,23 @@ struct Maintenance { address slot; } rust: &Self::RustType, out: &mut alloy_sol_types::private::Vec, ) { - out.reserve( - ::topic_preimage_length(rust), - ); + out.reserve(::topic_preimage_length(rust)); ::encode_topic_preimage( &rust.slot, out, ); } #[inline] - fn encode_topic( - rust: &Self::RustType, - ) -> alloy_sol_types::abi::token::WordToken { + fn encode_topic(rust: &Self::RustType) -> alloy_sol_types::abi::token::WordToken { let mut out = alloy_sol_types::private::Vec::new(); - ::encode_topic_preimage( - rust, - &mut out, - ); - alloy_sol_types::abi::token::WordToken( - alloy_sol_types::private::keccak256(out), - ) + ::encode_topic_preimage(rust, &mut out); + alloy_sol_types::abi::token::WordToken(alloy_sol_types::private::keccak256(out)) } } }; - /**```solidity -struct Migration { uint64 id; uint256 pullingOperatorsBitmask; } -```*/ + /// ```solidity + /// struct Migration { uint64 id; uint256 pullingOperatorsBitmask; } + /// ``` #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] pub struct Migration { @@ -1584,15 +1449,10 @@ struct Migration { uint64 id; uint256 pullingOperatorsBitmask; } alloy::sol_types::sol_data::Uint<256>, ); #[doc(hidden)] - type UnderlyingRustTuple<'a> = ( - u64, - alloy::sol_types::private::primitives::aliases::U256, - ); + type UnderlyingRustTuple<'a> = (u64, alloy::sol_types::private::primitives::aliases::U256); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] - fn _type_assertion( - _t: alloy_sol_types::private::AssertTypeEq, - ) { + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { match _t { alloy_sol_types::private::AssertTypeEq::< ::RustType, @@ -1625,12 +1485,10 @@ struct Migration { uint64 id; uint256 pullingOperatorsBitmask; } #[inline] fn stv_to_tokens(&self) -> ::Token<'_> { ( - as alloy_sol_types::SolType>::tokenize(&self.id), - as alloy_sol_types::SolType>::tokenize( + as alloy_sol_types::SolType>::tokenize( + &self.id, + ), + as alloy_sol_types::SolType>::tokenize( &self.pullingOperatorsBitmask, ), ) @@ -1640,64 +1498,50 @@ struct Migration { uint64 id; uint256 pullingOperatorsBitmask; } if let Some(size) = ::ENCODED_SIZE { return size; } - let tuple = as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_encoded_size(&tuple) + let tuple = + as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encoded_size(&tuple) } #[inline] fn stv_eip712_data_word(&self) -> alloy_sol_types::Word { ::eip712_hash_struct(self) } #[inline] - fn stv_abi_encode_packed_to( - &self, - out: &mut alloy_sol_types::private::Vec, - ) { - let tuple = as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_encode_packed_to(&tuple, out) + fn stv_abi_encode_packed_to(&self, out: &mut alloy_sol_types::private::Vec) { + let tuple = + as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encode_packed_to( + &tuple, out, + ) } #[inline] fn stv_abi_packed_encoded_size(&self) -> usize { if let Some(size) = ::PACKED_ENCODED_SIZE { return size; } - let tuple = as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_packed_encoded_size(&tuple) + let tuple = + as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_packed_encoded_size( + &tuple, + ) } } #[automatically_derived] impl alloy_sol_types::SolType for Migration { type RustType = Self; - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; const SOL_NAME: &'static str = ::NAME; - const ENCODED_SIZE: Option = as alloy_sol_types::SolType>::ENCODED_SIZE; - const PACKED_ENCODED_SIZE: Option = as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; + const ENCODED_SIZE: Option = + as alloy_sol_types::SolType>::ENCODED_SIZE; + const PACKED_ENCODED_SIZE: Option = + as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; #[inline] fn valid_token(token: &Self::Token<'_>) -> bool { as alloy_sol_types::SolType>::valid_token(token) } #[inline] fn detokenize(token: Self::Token<'_>) -> Self::RustType { - let tuple = as alloy_sol_types::SolType>::detokenize(token); + let tuple = as alloy_sol_types::SolType>::detokenize(token); >>::from(tuple) } } @@ -1711,9 +1555,9 @@ struct Migration { uint64 id; uint256 pullingOperatorsBitmask; } ) } #[inline] - fn eip712_components() -> alloy_sol_types::private::Vec< - alloy_sol_types::private::Cow<'static, str>, - > { + fn eip712_components( + ) -> alloy_sol_types::private::Vec> + { alloy_sol_types::private::Vec::new() } #[inline] @@ -1756,9 +1600,7 @@ struct Migration { uint64 id; uint256 pullingOperatorsBitmask; } rust: &Self::RustType, out: &mut alloy_sol_types::private::Vec, ) { - out.reserve( - ::topic_preimage_length(rust), - ); + out.reserve(::topic_preimage_length(rust)); as alloy_sol_types::EventTopic>::encode_topic_preimage(&rust.id, out); @@ -1770,30 +1612,22 @@ struct Migration { uint64 id; uint256 pullingOperatorsBitmask; } ); } #[inline] - fn encode_topic( - rust: &Self::RustType, - ) -> alloy_sol_types::abi::token::WordToken { + fn encode_topic(rust: &Self::RustType) -> alloy_sol_types::abi::token::WordToken { let mut out = alloy_sol_types::private::Vec::new(); - ::encode_topic_preimage( - rust, - &mut out, - ); - alloy_sol_types::abi::token::WordToken( - alloy_sol_types::private::keccak256(out), - ) + ::encode_topic_preimage(rust, &mut out); + alloy_sol_types::abi::token::WordToken(alloy_sol_types::private::keccak256(out)) } } }; - /**```solidity -struct MigrationPlan { KeyspaceSlot[] slots; uint8 replicationStrategy; } -```*/ + /// ```solidity + /// struct MigrationPlan { KeyspaceSlot[] slots; uint8 replicationStrategy; } + /// ``` #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] pub struct MigrationPlan { #[allow(missing_docs)] - pub slots: alloy::sol_types::private::Vec< - ::RustType, - >, + pub slots: + alloy::sol_types::private::Vec<::RustType>, #[allow(missing_docs)] pub replicationStrategy: u8, } @@ -1812,16 +1646,12 @@ struct MigrationPlan { KeyspaceSlot[] slots; uint8 replicationStrategy; } ); #[doc(hidden)] type UnderlyingRustTuple<'a> = ( - alloy::sol_types::private::Vec< - ::RustType, - >, + alloy::sol_types::private::Vec<::RustType>, u8, ); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] - fn _type_assertion( - _t: alloy_sol_types::private::AssertTypeEq, - ) { + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { match _t { alloy_sol_types::private::AssertTypeEq::< ::RustType, @@ -1867,64 +1697,50 @@ struct MigrationPlan { KeyspaceSlot[] slots; uint8 replicationStrategy; } if let Some(size) = ::ENCODED_SIZE { return size; } - let tuple = as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_encoded_size(&tuple) + let tuple = + as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encoded_size(&tuple) } #[inline] fn stv_eip712_data_word(&self) -> alloy_sol_types::Word { ::eip712_hash_struct(self) } #[inline] - fn stv_abi_encode_packed_to( - &self, - out: &mut alloy_sol_types::private::Vec, - ) { - let tuple = as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_encode_packed_to(&tuple, out) + fn stv_abi_encode_packed_to(&self, out: &mut alloy_sol_types::private::Vec) { + let tuple = + as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encode_packed_to( + &tuple, out, + ) } #[inline] fn stv_abi_packed_encoded_size(&self) -> usize { if let Some(size) = ::PACKED_ENCODED_SIZE { return size; } - let tuple = as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_packed_encoded_size(&tuple) + let tuple = + as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_packed_encoded_size( + &tuple, + ) } } #[automatically_derived] impl alloy_sol_types::SolType for MigrationPlan { type RustType = Self; - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; const SOL_NAME: &'static str = ::NAME; - const ENCODED_SIZE: Option = as alloy_sol_types::SolType>::ENCODED_SIZE; - const PACKED_ENCODED_SIZE: Option = as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; + const ENCODED_SIZE: Option = + as alloy_sol_types::SolType>::ENCODED_SIZE; + const PACKED_ENCODED_SIZE: Option = + as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; #[inline] fn valid_token(token: &Self::Token<'_>) -> bool { as alloy_sol_types::SolType>::valid_token(token) } #[inline] fn detokenize(token: Self::Token<'_>) -> Self::RustType { - let tuple = as alloy_sol_types::SolType>::detokenize(token); + let tuple = as alloy_sol_types::SolType>::detokenize(token); >>::from(tuple) } } @@ -1938,18 +1754,13 @@ struct MigrationPlan { KeyspaceSlot[] slots; uint8 replicationStrategy; } ) } #[inline] - fn eip712_components() -> alloy_sol_types::private::Vec< - alloy_sol_types::private::Cow<'static, str>, - > { + fn eip712_components( + ) -> alloy_sol_types::private::Vec> + { let mut components = alloy_sol_types::private::Vec::with_capacity(1); + components.push(::eip712_root_type()); components - .push( - ::eip712_root_type(), - ); - components - .extend( - ::eip712_components(), - ); + .extend(::eip712_components()); components } #[inline] @@ -1988,9 +1799,7 @@ struct MigrationPlan { KeyspaceSlot[] slots; uint8 replicationStrategy; } rust: &Self::RustType, out: &mut alloy_sol_types::private::Vec, ) { - out.reserve( - ::topic_preimage_length(rust), - ); + out.reserve(::topic_preimage_length(rust)); as alloy_sol_types::EventTopic>::encode_topic_preimage( @@ -2005,23 +1814,16 @@ struct MigrationPlan { KeyspaceSlot[] slots; uint8 replicationStrategy; } ); } #[inline] - fn encode_topic( - rust: &Self::RustType, - ) -> alloy_sol_types::abi::token::WordToken { + fn encode_topic(rust: &Self::RustType) -> alloy_sol_types::abi::token::WordToken { let mut out = alloy_sol_types::private::Vec::new(); - ::encode_topic_preimage( - rust, - &mut out, - ); - alloy_sol_types::abi::token::WordToken( - alloy_sol_types::private::keccak256(out), - ) + ::encode_topic_preimage(rust, &mut out); + alloy_sol_types::abi::token::WordToken(alloy_sol_types::private::keccak256(out)) } } }; - /**```solidity -struct NodeOperator { address addr; bytes data; } -```*/ + /// ```solidity + /// struct NodeOperator { address addr; bytes data; } + /// ``` #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] pub struct NodeOperator { @@ -2050,9 +1852,7 @@ struct NodeOperator { address addr; bytes data; } ); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] - fn _type_assertion( - _t: alloy_sol_types::private::AssertTypeEq, - ) { + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { match _t { alloy_sol_types::private::AssertTypeEq::< ::RustType, @@ -2098,64 +1898,50 @@ struct NodeOperator { address addr; bytes data; } if let Some(size) = ::ENCODED_SIZE { return size; } - let tuple = as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_encoded_size(&tuple) + let tuple = + as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encoded_size(&tuple) } #[inline] fn stv_eip712_data_word(&self) -> alloy_sol_types::Word { ::eip712_hash_struct(self) } #[inline] - fn stv_abi_encode_packed_to( - &self, - out: &mut alloy_sol_types::private::Vec, - ) { - let tuple = as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_encode_packed_to(&tuple, out) + fn stv_abi_encode_packed_to(&self, out: &mut alloy_sol_types::private::Vec) { + let tuple = + as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encode_packed_to( + &tuple, out, + ) } #[inline] fn stv_abi_packed_encoded_size(&self) -> usize { if let Some(size) = ::PACKED_ENCODED_SIZE { return size; } - let tuple = as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_packed_encoded_size(&tuple) + let tuple = + as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_packed_encoded_size( + &tuple, + ) } } #[automatically_derived] impl alloy_sol_types::SolType for NodeOperator { type RustType = Self; - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; const SOL_NAME: &'static str = ::NAME; - const ENCODED_SIZE: Option = as alloy_sol_types::SolType>::ENCODED_SIZE; - const PACKED_ENCODED_SIZE: Option = as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; + const ENCODED_SIZE: Option = + as alloy_sol_types::SolType>::ENCODED_SIZE; + const PACKED_ENCODED_SIZE: Option = + as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; #[inline] fn valid_token(token: &Self::Token<'_>) -> bool { as alloy_sol_types::SolType>::valid_token(token) } #[inline] fn detokenize(token: Self::Token<'_>) -> Self::RustType { - let tuple = as alloy_sol_types::SolType>::detokenize(token); + let tuple = as alloy_sol_types::SolType>::detokenize(token); >>::from(tuple) } } @@ -2164,14 +1950,12 @@ struct NodeOperator { address addr; bytes data; } const NAME: &'static str = "NodeOperator"; #[inline] fn eip712_root_type() -> alloy_sol_types::private::Cow<'static, str> { - alloy_sol_types::private::Cow::Borrowed( - "NodeOperator(address addr,bytes data)", - ) + alloy_sol_types::private::Cow::Borrowed("NodeOperator(address addr,bytes data)") } #[inline] - fn eip712_components() -> alloy_sol_types::private::Vec< - alloy_sol_types::private::Cow<'static, str>, - > { + fn eip712_components( + ) -> alloy_sol_types::private::Vec> + { alloy_sol_types::private::Vec::new() } #[inline] @@ -2210,9 +1994,7 @@ struct NodeOperator { address addr; bytes data; } rust: &Self::RustType, out: &mut alloy_sol_types::private::Vec, ) { - out.reserve( - ::topic_preimage_length(rust), - ); + out.reserve(::topic_preimage_length(rust)); ::encode_topic_preimage( &rust.addr, out, @@ -2223,23 +2005,16 @@ struct NodeOperator { address addr; bytes data; } ); } #[inline] - fn encode_topic( - rust: &Self::RustType, - ) -> alloy_sol_types::abi::token::WordToken { + fn encode_topic(rust: &Self::RustType) -> alloy_sol_types::abi::token::WordToken { let mut out = alloy_sol_types::private::Vec::new(); - ::encode_topic_preimage( - rust, - &mut out, - ); - alloy_sol_types::abi::token::WordToken( - alloy_sol_types::private::keccak256(out), - ) + ::encode_topic_preimage(rust, &mut out); + alloy_sol_types::abi::token::WordToken(alloy_sol_types::private::keccak256(out)) } } }; - /**```solidity -struct Settings { uint16 maxOperatorDataBytes; } -```*/ + /// ```solidity + /// struct Settings { uint16 maxOperatorDataBytes; } + /// ``` #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] pub struct Settings { @@ -2260,9 +2035,7 @@ struct Settings { uint16 maxOperatorDataBytes; } type UnderlyingRustTuple<'a> = (u16,); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] - fn _type_assertion( - _t: alloy_sol_types::private::AssertTypeEq, - ) { + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { match _t { alloy_sol_types::private::AssertTypeEq::< ::RustType, @@ -2294,9 +2067,9 @@ struct Settings { uint16 maxOperatorDataBytes; } #[inline] fn stv_to_tokens(&self) -> ::Token<'_> { ( - as alloy_sol_types::SolType>::tokenize(&self.maxOperatorDataBytes), + as alloy_sol_types::SolType>::tokenize( + &self.maxOperatorDataBytes, + ), ) } #[inline] @@ -2304,64 +2077,50 @@ struct Settings { uint16 maxOperatorDataBytes; } if let Some(size) = ::ENCODED_SIZE { return size; } - let tuple = as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_encoded_size(&tuple) + let tuple = + as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encoded_size(&tuple) } #[inline] fn stv_eip712_data_word(&self) -> alloy_sol_types::Word { ::eip712_hash_struct(self) } #[inline] - fn stv_abi_encode_packed_to( - &self, - out: &mut alloy_sol_types::private::Vec, - ) { - let tuple = as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_encode_packed_to(&tuple, out) + fn stv_abi_encode_packed_to(&self, out: &mut alloy_sol_types::private::Vec) { + let tuple = + as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encode_packed_to( + &tuple, out, + ) } #[inline] fn stv_abi_packed_encoded_size(&self) -> usize { if let Some(size) = ::PACKED_ENCODED_SIZE { return size; } - let tuple = as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_packed_encoded_size(&tuple) + let tuple = + as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_packed_encoded_size( + &tuple, + ) } } #[automatically_derived] impl alloy_sol_types::SolType for Settings { type RustType = Self; - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; const SOL_NAME: &'static str = ::NAME; - const ENCODED_SIZE: Option = as alloy_sol_types::SolType>::ENCODED_SIZE; - const PACKED_ENCODED_SIZE: Option = as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; + const ENCODED_SIZE: Option = + as alloy_sol_types::SolType>::ENCODED_SIZE; + const PACKED_ENCODED_SIZE: Option = + as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; #[inline] fn valid_token(token: &Self::Token<'_>) -> bool { as alloy_sol_types::SolType>::valid_token(token) } #[inline] fn detokenize(token: Self::Token<'_>) -> Self::RustType { - let tuple = as alloy_sol_types::SolType>::detokenize(token); + let tuple = as alloy_sol_types::SolType>::detokenize(token); >>::from(tuple) } } @@ -2370,14 +2129,12 @@ struct Settings { uint16 maxOperatorDataBytes; } const NAME: &'static str = "Settings"; #[inline] fn eip712_root_type() -> alloy_sol_types::private::Cow<'static, str> { - alloy_sol_types::private::Cow::Borrowed( - "Settings(uint16 maxOperatorDataBytes)", - ) + alloy_sol_types::private::Cow::Borrowed("Settings(uint16 maxOperatorDataBytes)") } #[inline] - fn eip712_components() -> alloy_sol_types::private::Vec< - alloy_sol_types::private::Cow<'static, str>, - > { + fn eip712_components( + ) -> alloy_sol_types::private::Vec> + { alloy_sol_types::private::Vec::new() } #[inline] @@ -2411,9 +2168,7 @@ struct Settings { uint16 maxOperatorDataBytes; } rust: &Self::RustType, out: &mut alloy_sol_types::private::Vec, ) { - out.reserve( - ::topic_preimage_length(rust), - ); + out.reserve(::topic_preimage_length(rust)); as alloy_sol_types::EventTopic>::encode_topic_preimage( @@ -2422,24 +2177,18 @@ struct Settings { uint16 maxOperatorDataBytes; } ); } #[inline] - fn encode_topic( - rust: &Self::RustType, - ) -> alloy_sol_types::abi::token::WordToken { + fn encode_topic(rust: &Self::RustType) -> alloy_sol_types::abi::token::WordToken { let mut out = alloy_sol_types::private::Vec::new(); - ::encode_topic_preimage( - rust, - &mut out, - ); - alloy_sol_types::abi::token::WordToken( - alloy_sol_types::private::keccak256(out), - ) + ::encode_topic_preimage(rust, &mut out); + alloy_sol_types::abi::token::WordToken(alloy_sol_types::private::keccak256(out)) } } }; - /**Event with signature `MaintenanceAborted(uint128)` and selector `0x8fb9cd054d0a022110cced239e908b834e4cd219511856d4eaae3051d932d604`. -```solidity -event MaintenanceAborted(uint128 clusterVersion); -```*/ + /// Event with signature `MaintenanceAborted(uint128)` and selector + /// `0x8fb9cd054d0a022110cced239e908b834e4cd219511856d4eaae3051d932d604`. + /// ```solidity + /// event MaintenanceAborted(uint128 clusterVersion); + /// ``` #[allow( non_camel_case_types, non_snake_case, @@ -2462,45 +2211,15 @@ event MaintenanceAborted(uint128 clusterVersion); #[automatically_derived] impl alloy_sol_types::SolEvent for MaintenanceAborted { type DataTuple<'a> = (alloy::sol_types::sol_data::Uint<128>,); - type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); const SIGNATURE: &'static str = "MaintenanceAborted(uint128)"; - const SIGNATURE_HASH: alloy_sol_types::private::B256 = alloy_sol_types::private::B256::new([ - 143u8, - 185u8, - 205u8, - 5u8, - 77u8, - 10u8, - 2u8, - 33u8, - 16u8, - 204u8, - 237u8, - 35u8, - 158u8, - 144u8, - 139u8, - 131u8, - 78u8, - 76u8, - 210u8, - 25u8, - 81u8, - 24u8, - 86u8, - 212u8, - 234u8, - 174u8, - 48u8, - 81u8, - 217u8, - 50u8, - 214u8, - 4u8, - ]); + const SIGNATURE_HASH: alloy_sol_types::private::B256 = + alloy_sol_types::private::B256::new([ + 143u8, 185u8, 205u8, 5u8, 77u8, 10u8, 2u8, 33u8, 16u8, 204u8, 237u8, 35u8, + 158u8, 144u8, 139u8, 131u8, 78u8, 76u8, 210u8, 25u8, 81u8, 24u8, 86u8, 212u8, + 234u8, 174u8, 48u8, 81u8, 217u8, 50u8, 214u8, 4u8, + ]); const ANONYMOUS: bool = false; #[allow(unused_variables)] #[inline] @@ -2508,29 +2227,29 @@ event MaintenanceAborted(uint128 clusterVersion); topics: ::RustType, data: as alloy_sol_types::SolType>::RustType, ) -> Self { - Self { clusterVersion: data.0 } + Self { + clusterVersion: data.0, + } } #[inline] fn check_signature( topics: &::RustType, ) -> alloy_sol_types::Result<()> { if topics.0 != Self::SIGNATURE_HASH { - return Err( - alloy_sol_types::Error::invalid_event_signature_hash( - Self::SIGNATURE, - topics.0, - Self::SIGNATURE_HASH, - ), - ); + return Err(alloy_sol_types::Error::invalid_event_signature_hash( + Self::SIGNATURE, + topics.0, + Self::SIGNATURE_HASH, + )); } Ok(()) } #[inline] fn tokenize_body(&self) -> Self::DataToken<'_> { ( - as alloy_sol_types::SolType>::tokenize(&self.clusterVersion), + as alloy_sol_types::SolType>::tokenize( + &self.clusterVersion, + ), ) } #[inline] @@ -2545,9 +2264,7 @@ event MaintenanceAborted(uint128 clusterVersion); if out.len() < ::COUNT { return Err(alloy_sol_types::Error::Overrun); } - out[0usize] = alloy_sol_types::abi::token::WordToken( - Self::SIGNATURE_HASH, - ); + out[0usize] = alloy_sol_types::abi::token::WordToken(Self::SIGNATURE_HASH); Ok(()) } } @@ -2568,10 +2285,11 @@ event MaintenanceAborted(uint128 clusterVersion); } } }; - /**Event with signature `MaintenanceCompleted(address,uint128)` and selector `0xf91067eb420c28d3124865fc996e6aa9d541b9b4fef9188cb965a6cc6491638e`. -```solidity -event MaintenanceCompleted(address operatorAddress, uint128 clusterVersion); -```*/ + /// Event with signature `MaintenanceCompleted(address,uint128)` and + /// selector `0xf91067eb420c28d3124865fc996e6aa9d541b9b4fef9188cb965a6cc6491638e`. + /// ```solidity + /// event MaintenanceCompleted(address operatorAddress, uint128 clusterVersion); + /// ``` #[allow( non_camel_case_types, non_snake_case, @@ -2599,45 +2317,15 @@ event MaintenanceCompleted(address operatorAddress, uint128 clusterVersion); alloy::sol_types::sol_data::Address, alloy::sol_types::sol_data::Uint<128>, ); - type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); const SIGNATURE: &'static str = "MaintenanceCompleted(address,uint128)"; - const SIGNATURE_HASH: alloy_sol_types::private::B256 = alloy_sol_types::private::B256::new([ - 249u8, - 16u8, - 103u8, - 235u8, - 66u8, - 12u8, - 40u8, - 211u8, - 18u8, - 72u8, - 101u8, - 252u8, - 153u8, - 110u8, - 106u8, - 169u8, - 213u8, - 65u8, - 185u8, - 180u8, - 254u8, - 249u8, - 24u8, - 140u8, - 185u8, - 101u8, - 166u8, - 204u8, - 100u8, - 145u8, - 99u8, - 142u8, - ]); + const SIGNATURE_HASH: alloy_sol_types::private::B256 = + alloy_sol_types::private::B256::new([ + 249u8, 16u8, 103u8, 235u8, 66u8, 12u8, 40u8, 211u8, 18u8, 72u8, 101u8, 252u8, + 153u8, 110u8, 106u8, 169u8, 213u8, 65u8, 185u8, 180u8, 254u8, 249u8, 24u8, + 140u8, 185u8, 101u8, 166u8, 204u8, 100u8, 145u8, 99u8, 142u8, + ]); const ANONYMOUS: bool = false; #[allow(unused_variables)] #[inline] @@ -2655,13 +2343,11 @@ event MaintenanceCompleted(address operatorAddress, uint128 clusterVersion); topics: &::RustType, ) -> alloy_sol_types::Result<()> { if topics.0 != Self::SIGNATURE_HASH { - return Err( - alloy_sol_types::Error::invalid_event_signature_hash( - Self::SIGNATURE, - topics.0, - Self::SIGNATURE_HASH, - ), - ); + return Err(alloy_sol_types::Error::invalid_event_signature_hash( + Self::SIGNATURE, + topics.0, + Self::SIGNATURE_HASH, + )); } Ok(()) } @@ -2671,9 +2357,9 @@ event MaintenanceCompleted(address operatorAddress, uint128 clusterVersion); ::tokenize( &self.operatorAddress, ), - as alloy_sol_types::SolType>::tokenize(&self.clusterVersion), + as alloy_sol_types::SolType>::tokenize( + &self.clusterVersion, + ), ) } #[inline] @@ -2688,9 +2374,7 @@ event MaintenanceCompleted(address operatorAddress, uint128 clusterVersion); if out.len() < ::COUNT { return Err(alloy_sol_types::Error::Overrun); } - out[0usize] = alloy_sol_types::abi::token::WordToken( - Self::SIGNATURE_HASH, - ); + out[0usize] = alloy_sol_types::abi::token::WordToken(Self::SIGNATURE_HASH); Ok(()) } } @@ -2711,10 +2395,11 @@ event MaintenanceCompleted(address operatorAddress, uint128 clusterVersion); } } }; - /**Event with signature `MaintenanceStarted(address,uint128)` and selector `0xbc2748cf02f7a1291525e866efc76ab3b96d32d7afcbb26c53daec617b38b479`. -```solidity -event MaintenanceStarted(address operatorAddress, uint128 clusterVersion); -```*/ + /// Event with signature `MaintenanceStarted(address,uint128)` and selector + /// `0xbc2748cf02f7a1291525e866efc76ab3b96d32d7afcbb26c53daec617b38b479`. + /// ```solidity + /// event MaintenanceStarted(address operatorAddress, uint128 clusterVersion); + /// ``` #[allow( non_camel_case_types, non_snake_case, @@ -2742,45 +2427,15 @@ event MaintenanceStarted(address operatorAddress, uint128 clusterVersion); alloy::sol_types::sol_data::Address, alloy::sol_types::sol_data::Uint<128>, ); - type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); const SIGNATURE: &'static str = "MaintenanceStarted(address,uint128)"; - const SIGNATURE_HASH: alloy_sol_types::private::B256 = alloy_sol_types::private::B256::new([ - 188u8, - 39u8, - 72u8, - 207u8, - 2u8, - 247u8, - 161u8, - 41u8, - 21u8, - 37u8, - 232u8, - 102u8, - 239u8, - 199u8, - 106u8, - 179u8, - 185u8, - 109u8, - 50u8, - 215u8, - 175u8, - 203u8, - 178u8, - 108u8, - 83u8, - 218u8, - 236u8, - 97u8, - 123u8, - 56u8, - 180u8, - 121u8, - ]); + const SIGNATURE_HASH: alloy_sol_types::private::B256 = + alloy_sol_types::private::B256::new([ + 188u8, 39u8, 72u8, 207u8, 2u8, 247u8, 161u8, 41u8, 21u8, 37u8, 232u8, 102u8, + 239u8, 199u8, 106u8, 179u8, 185u8, 109u8, 50u8, 215u8, 175u8, 203u8, 178u8, + 108u8, 83u8, 218u8, 236u8, 97u8, 123u8, 56u8, 180u8, 121u8, + ]); const ANONYMOUS: bool = false; #[allow(unused_variables)] #[inline] @@ -2798,13 +2453,11 @@ event MaintenanceStarted(address operatorAddress, uint128 clusterVersion); topics: &::RustType, ) -> alloy_sol_types::Result<()> { if topics.0 != Self::SIGNATURE_HASH { - return Err( - alloy_sol_types::Error::invalid_event_signature_hash( - Self::SIGNATURE, - topics.0, - Self::SIGNATURE_HASH, - ), - ); + return Err(alloy_sol_types::Error::invalid_event_signature_hash( + Self::SIGNATURE, + topics.0, + Self::SIGNATURE_HASH, + )); } Ok(()) } @@ -2814,9 +2467,9 @@ event MaintenanceStarted(address operatorAddress, uint128 clusterVersion); ::tokenize( &self.operatorAddress, ), - as alloy_sol_types::SolType>::tokenize(&self.clusterVersion), + as alloy_sol_types::SolType>::tokenize( + &self.clusterVersion, + ), ) } #[inline] @@ -2831,9 +2484,7 @@ event MaintenanceStarted(address operatorAddress, uint128 clusterVersion); if out.len() < ::COUNT { return Err(alloy_sol_types::Error::Overrun); } - out[0usize] = alloy_sol_types::abi::token::WordToken( - Self::SIGNATURE_HASH, - ); + out[0usize] = alloy_sol_types::abi::token::WordToken(Self::SIGNATURE_HASH); Ok(()) } } @@ -2854,10 +2505,11 @@ event MaintenanceStarted(address operatorAddress, uint128 clusterVersion); } } }; - /**Event with signature `MigrationAborted(uint64,uint128)` and selector `0xf73240422246f63ed633ef3ce0726b8ab8fb69d46c8a4e5ecb0b2922668674a1`. -```solidity -event MigrationAborted(uint64 id, uint128 clusterVersion); -```*/ + /// Event with signature `MigrationAborted(uint64,uint128)` and selector + /// `0xf73240422246f63ed633ef3ce0726b8ab8fb69d46c8a4e5ecb0b2922668674a1`. + /// ```solidity + /// event MigrationAborted(uint64 id, uint128 clusterVersion); + /// ``` #[allow( non_camel_case_types, non_snake_case, @@ -2885,45 +2537,15 @@ event MigrationAborted(uint64 id, uint128 clusterVersion); alloy::sol_types::sol_data::Uint<64>, alloy::sol_types::sol_data::Uint<128>, ); - type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); const SIGNATURE: &'static str = "MigrationAborted(uint64,uint128)"; - const SIGNATURE_HASH: alloy_sol_types::private::B256 = alloy_sol_types::private::B256::new([ - 247u8, - 50u8, - 64u8, - 66u8, - 34u8, - 70u8, - 246u8, - 62u8, - 214u8, - 51u8, - 239u8, - 60u8, - 224u8, - 114u8, - 107u8, - 138u8, - 184u8, - 251u8, - 105u8, - 212u8, - 108u8, - 138u8, - 78u8, - 94u8, - 203u8, - 11u8, - 41u8, - 34u8, - 102u8, - 134u8, - 116u8, - 161u8, - ]); + const SIGNATURE_HASH: alloy_sol_types::private::B256 = + alloy_sol_types::private::B256::new([ + 247u8, 50u8, 64u8, 66u8, 34u8, 70u8, 246u8, 62u8, 214u8, 51u8, 239u8, 60u8, + 224u8, 114u8, 107u8, 138u8, 184u8, 251u8, 105u8, 212u8, 108u8, 138u8, 78u8, + 94u8, 203u8, 11u8, 41u8, 34u8, 102u8, 134u8, 116u8, 161u8, + ]); const ANONYMOUS: bool = false; #[allow(unused_variables)] #[inline] @@ -2941,25 +2563,23 @@ event MigrationAborted(uint64 id, uint128 clusterVersion); topics: &::RustType, ) -> alloy_sol_types::Result<()> { if topics.0 != Self::SIGNATURE_HASH { - return Err( - alloy_sol_types::Error::invalid_event_signature_hash( - Self::SIGNATURE, - topics.0, - Self::SIGNATURE_HASH, - ), - ); + return Err(alloy_sol_types::Error::invalid_event_signature_hash( + Self::SIGNATURE, + topics.0, + Self::SIGNATURE_HASH, + )); } Ok(()) } #[inline] fn tokenize_body(&self) -> Self::DataToken<'_> { ( - as alloy_sol_types::SolType>::tokenize(&self.id), - as alloy_sol_types::SolType>::tokenize(&self.clusterVersion), + as alloy_sol_types::SolType>::tokenize( + &self.id, + ), + as alloy_sol_types::SolType>::tokenize( + &self.clusterVersion, + ), ) } #[inline] @@ -2974,9 +2594,7 @@ event MigrationAborted(uint64 id, uint128 clusterVersion); if out.len() < ::COUNT { return Err(alloy_sol_types::Error::Overrun); } - out[0usize] = alloy_sol_types::abi::token::WordToken( - Self::SIGNATURE_HASH, - ); + out[0usize] = alloy_sol_types::abi::token::WordToken(Self::SIGNATURE_HASH); Ok(()) } } @@ -2997,10 +2615,11 @@ event MigrationAborted(uint64 id, uint128 clusterVersion); } } }; - /**Event with signature `MigrationCompleted(uint64,address,uint128)` and selector `0x01269879535f40ee8957e15e160bf1866c5e2728ff0cbc583d848821e2639b4e`. -```solidity -event MigrationCompleted(uint64 id, address operatorAddress, uint128 clusterVersion); -```*/ + /// Event with signature `MigrationCompleted(uint64,address,uint128)` and + /// selector `0x01269879535f40ee8957e15e160bf1866c5e2728ff0cbc583d848821e2639b4e`. + /// ```solidity + /// event MigrationCompleted(uint64 id, address operatorAddress, uint128 clusterVersion); + /// ``` #[allow( non_camel_case_types, non_snake_case, @@ -3031,45 +2650,15 @@ event MigrationCompleted(uint64 id, address operatorAddress, uint128 clusterVers alloy::sol_types::sol_data::Address, alloy::sol_types::sol_data::Uint<128>, ); - type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); const SIGNATURE: &'static str = "MigrationCompleted(uint64,address,uint128)"; - const SIGNATURE_HASH: alloy_sol_types::private::B256 = alloy_sol_types::private::B256::new([ - 1u8, - 38u8, - 152u8, - 121u8, - 83u8, - 95u8, - 64u8, - 238u8, - 137u8, - 87u8, - 225u8, - 94u8, - 22u8, - 11u8, - 241u8, - 134u8, - 108u8, - 94u8, - 39u8, - 40u8, - 255u8, - 12u8, - 188u8, - 88u8, - 61u8, - 132u8, - 136u8, - 33u8, - 226u8, - 99u8, - 155u8, - 78u8, - ]); + const SIGNATURE_HASH: alloy_sol_types::private::B256 = + alloy_sol_types::private::B256::new([ + 1u8, 38u8, 152u8, 121u8, 83u8, 95u8, 64u8, 238u8, 137u8, 87u8, 225u8, 94u8, + 22u8, 11u8, 241u8, 134u8, 108u8, 94u8, 39u8, 40u8, 255u8, 12u8, 188u8, 88u8, + 61u8, 132u8, 136u8, 33u8, 226u8, 99u8, 155u8, 78u8, + ]); const ANONYMOUS: bool = false; #[allow(unused_variables)] #[inline] @@ -3088,28 +2677,26 @@ event MigrationCompleted(uint64 id, address operatorAddress, uint128 clusterVers topics: &::RustType, ) -> alloy_sol_types::Result<()> { if topics.0 != Self::SIGNATURE_HASH { - return Err( - alloy_sol_types::Error::invalid_event_signature_hash( - Self::SIGNATURE, - topics.0, - Self::SIGNATURE_HASH, - ), - ); + return Err(alloy_sol_types::Error::invalid_event_signature_hash( + Self::SIGNATURE, + topics.0, + Self::SIGNATURE_HASH, + )); } Ok(()) } #[inline] fn tokenize_body(&self) -> Self::DataToken<'_> { ( - as alloy_sol_types::SolType>::tokenize(&self.id), + as alloy_sol_types::SolType>::tokenize( + &self.id, + ), ::tokenize( &self.operatorAddress, ), - as alloy_sol_types::SolType>::tokenize(&self.clusterVersion), + as alloy_sol_types::SolType>::tokenize( + &self.clusterVersion, + ), ) } #[inline] @@ -3124,9 +2711,7 @@ event MigrationCompleted(uint64 id, address operatorAddress, uint128 clusterVers if out.len() < ::COUNT { return Err(alloy_sol_types::Error::Overrun); } - out[0usize] = alloy_sol_types::abi::token::WordToken( - Self::SIGNATURE_HASH, - ); + out[0usize] = alloy_sol_types::abi::token::WordToken(Self::SIGNATURE_HASH); Ok(()) } } @@ -3147,10 +2732,12 @@ event MigrationCompleted(uint64 id, address operatorAddress, uint128 clusterVers } } }; - /**Event with signature `MigrationDataPullCompleted(uint64,address,uint128)` and selector `0xaf5e90e72015f43138f66b4cd08bd1dfa2839030104f22a00af843fe847c6d19`. -```solidity -event MigrationDataPullCompleted(uint64 id, address operatorAddress, uint128 clusterVersion); -```*/ + /// Event with signature + /// `MigrationDataPullCompleted(uint64,address,uint128)` and selector + /// `0xaf5e90e72015f43138f66b4cd08bd1dfa2839030104f22a00af843fe847c6d19`. + /// ```solidity + /// event MigrationDataPullCompleted(uint64 id, address operatorAddress, uint128 clusterVersion); + /// ``` #[allow( non_camel_case_types, non_snake_case, @@ -3181,45 +2768,15 @@ event MigrationDataPullCompleted(uint64 id, address operatorAddress, uint128 clu alloy::sol_types::sol_data::Address, alloy::sol_types::sol_data::Uint<128>, ); - type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); const SIGNATURE: &'static str = "MigrationDataPullCompleted(uint64,address,uint128)"; - const SIGNATURE_HASH: alloy_sol_types::private::B256 = alloy_sol_types::private::B256::new([ - 175u8, - 94u8, - 144u8, - 231u8, - 32u8, - 21u8, - 244u8, - 49u8, - 56u8, - 246u8, - 107u8, - 76u8, - 208u8, - 139u8, - 209u8, - 223u8, - 162u8, - 131u8, - 144u8, - 48u8, - 16u8, - 79u8, - 34u8, - 160u8, - 10u8, - 248u8, - 67u8, - 254u8, - 132u8, - 124u8, - 109u8, - 25u8, - ]); + const SIGNATURE_HASH: alloy_sol_types::private::B256 = + alloy_sol_types::private::B256::new([ + 175u8, 94u8, 144u8, 231u8, 32u8, 21u8, 244u8, 49u8, 56u8, 246u8, 107u8, 76u8, + 208u8, 139u8, 209u8, 223u8, 162u8, 131u8, 144u8, 48u8, 16u8, 79u8, 34u8, 160u8, + 10u8, 248u8, 67u8, 254u8, 132u8, 124u8, 109u8, 25u8, + ]); const ANONYMOUS: bool = false; #[allow(unused_variables)] #[inline] @@ -3238,28 +2795,26 @@ event MigrationDataPullCompleted(uint64 id, address operatorAddress, uint128 clu topics: &::RustType, ) -> alloy_sol_types::Result<()> { if topics.0 != Self::SIGNATURE_HASH { - return Err( - alloy_sol_types::Error::invalid_event_signature_hash( - Self::SIGNATURE, - topics.0, - Self::SIGNATURE_HASH, - ), - ); + return Err(alloy_sol_types::Error::invalid_event_signature_hash( + Self::SIGNATURE, + topics.0, + Self::SIGNATURE_HASH, + )); } Ok(()) } #[inline] fn tokenize_body(&self) -> Self::DataToken<'_> { ( - as alloy_sol_types::SolType>::tokenize(&self.id), + as alloy_sol_types::SolType>::tokenize( + &self.id, + ), ::tokenize( &self.operatorAddress, ), - as alloy_sol_types::SolType>::tokenize(&self.clusterVersion), + as alloy_sol_types::SolType>::tokenize( + &self.clusterVersion, + ), ) } #[inline] @@ -3274,9 +2829,7 @@ event MigrationDataPullCompleted(uint64 id, address operatorAddress, uint128 clu if out.len() < ::COUNT { return Err(alloy_sol_types::Error::Overrun); } - out[0usize] = alloy_sol_types::abi::token::WordToken( - Self::SIGNATURE_HASH, - ); + out[0usize] = alloy_sol_types::abi::token::WordToken(Self::SIGNATURE_HASH); Ok(()) } } @@ -3292,17 +2845,17 @@ event MigrationDataPullCompleted(uint64 id, address operatorAddress, uint128 clu #[automatically_derived] impl From<&MigrationDataPullCompleted> for alloy_sol_types::private::LogData { #[inline] - fn from( - this: &MigrationDataPullCompleted, - ) -> alloy_sol_types::private::LogData { + fn from(this: &MigrationDataPullCompleted) -> alloy_sol_types::private::LogData { alloy_sol_types::SolEvent::encode_log_data(this) } } }; - /**Event with signature `MigrationStarted(uint64,((uint8,address)[],uint8),uint128)` and selector `0x78dad2bc0b47c688ed84f3fee79abc18e6c9822db05a79ca19dff54533c7470d`. -```solidity -event MigrationStarted(uint64 id, MigrationPlan plan, uint128 clusterVersion); -```*/ + /// Event with signature + /// `MigrationStarted(uint64,((uint8,address)[],uint8),uint128)` and + /// selector `0x78dad2bc0b47c688ed84f3fee79abc18e6c9822db05a79ca19dff54533c7470d`. + /// ```solidity + /// event MigrationStarted(uint64 id, MigrationPlan plan, uint128 clusterVersion); + /// ``` #[allow( non_camel_case_types, non_snake_case, @@ -3333,45 +2886,16 @@ event MigrationStarted(uint64 id, MigrationPlan plan, uint128 clusterVersion); MigrationPlan, alloy::sol_types::sol_data::Uint<128>, ); - type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); - const SIGNATURE: &'static str = "MigrationStarted(uint64,((uint8,address)[],uint8),uint128)"; - const SIGNATURE_HASH: alloy_sol_types::private::B256 = alloy_sol_types::private::B256::new([ - 120u8, - 218u8, - 210u8, - 188u8, - 11u8, - 71u8, - 198u8, - 136u8, - 237u8, - 132u8, - 243u8, - 254u8, - 231u8, - 154u8, - 188u8, - 24u8, - 230u8, - 201u8, - 130u8, - 45u8, - 176u8, - 90u8, - 121u8, - 202u8, - 25u8, - 223u8, - 245u8, - 69u8, - 51u8, - 199u8, - 71u8, - 13u8, - ]); + const SIGNATURE: &'static str = + "MigrationStarted(uint64,((uint8,address)[],uint8),uint128)"; + const SIGNATURE_HASH: alloy_sol_types::private::B256 = + alloy_sol_types::private::B256::new([ + 120u8, 218u8, 210u8, 188u8, 11u8, 71u8, 198u8, 136u8, 237u8, 132u8, 243u8, + 254u8, 231u8, 154u8, 188u8, 24u8, 230u8, 201u8, 130u8, 45u8, 176u8, 90u8, + 121u8, 202u8, 25u8, 223u8, 245u8, 69u8, 51u8, 199u8, 71u8, 13u8, + ]); const ANONYMOUS: bool = false; #[allow(unused_variables)] #[inline] @@ -3390,26 +2914,24 @@ event MigrationStarted(uint64 id, MigrationPlan plan, uint128 clusterVersion); topics: &::RustType, ) -> alloy_sol_types::Result<()> { if topics.0 != Self::SIGNATURE_HASH { - return Err( - alloy_sol_types::Error::invalid_event_signature_hash( - Self::SIGNATURE, - topics.0, - Self::SIGNATURE_HASH, - ), - ); + return Err(alloy_sol_types::Error::invalid_event_signature_hash( + Self::SIGNATURE, + topics.0, + Self::SIGNATURE_HASH, + )); } Ok(()) } #[inline] fn tokenize_body(&self) -> Self::DataToken<'_> { ( - as alloy_sol_types::SolType>::tokenize(&self.id), + as alloy_sol_types::SolType>::tokenize( + &self.id, + ), ::tokenize(&self.plan), - as alloy_sol_types::SolType>::tokenize(&self.clusterVersion), + as alloy_sol_types::SolType>::tokenize( + &self.clusterVersion, + ), ) } #[inline] @@ -3424,9 +2946,7 @@ event MigrationStarted(uint64 id, MigrationPlan plan, uint128 clusterVersion); if out.len() < ::COUNT { return Err(alloy_sol_types::Error::Overrun); } - out[0usize] = alloy_sol_types::abi::token::WordToken( - Self::SIGNATURE_HASH, - ); + out[0usize] = alloy_sol_types::abi::token::WordToken(Self::SIGNATURE_HASH); Ok(()) } } @@ -3447,10 +2967,12 @@ event MigrationStarted(uint64 id, MigrationPlan plan, uint128 clusterVersion); } } }; - /**Event with signature `NodeOperatorDataUpdated(address,bytes,uint128)` and selector `0x125181ec21882dec51a2392905dff3a82cbd0262f18b5c0c035488671b40afb2`. -```solidity -event NodeOperatorDataUpdated(address operatorAddress, bytes data, uint128 clusterVersion); -```*/ + /// Event with signature `NodeOperatorDataUpdated(address,bytes,uint128)` + /// and selector + /// `0x125181ec21882dec51a2392905dff3a82cbd0262f18b5c0c035488671b40afb2`. + /// ```solidity + /// event NodeOperatorDataUpdated(address operatorAddress, bytes data, uint128 clusterVersion); + /// ``` #[allow( non_camel_case_types, non_snake_case, @@ -3481,45 +3003,15 @@ event NodeOperatorDataUpdated(address operatorAddress, bytes data, uint128 clust alloy::sol_types::sol_data::Bytes, alloy::sol_types::sol_data::Uint<128>, ); - type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); const SIGNATURE: &'static str = "NodeOperatorDataUpdated(address,bytes,uint128)"; - const SIGNATURE_HASH: alloy_sol_types::private::B256 = alloy_sol_types::private::B256::new([ - 18u8, - 81u8, - 129u8, - 236u8, - 33u8, - 136u8, - 45u8, - 236u8, - 81u8, - 162u8, - 57u8, - 41u8, - 5u8, - 223u8, - 243u8, - 168u8, - 44u8, - 189u8, - 2u8, - 98u8, - 241u8, - 139u8, - 92u8, - 12u8, - 3u8, - 84u8, - 136u8, - 103u8, - 27u8, - 64u8, - 175u8, - 178u8, - ]); + const SIGNATURE_HASH: alloy_sol_types::private::B256 = + alloy_sol_types::private::B256::new([ + 18u8, 81u8, 129u8, 236u8, 33u8, 136u8, 45u8, 236u8, 81u8, 162u8, 57u8, 41u8, + 5u8, 223u8, 243u8, 168u8, 44u8, 189u8, 2u8, 98u8, 241u8, 139u8, 92u8, 12u8, + 3u8, 84u8, 136u8, 103u8, 27u8, 64u8, 175u8, 178u8, + ]); const ANONYMOUS: bool = false; #[allow(unused_variables)] #[inline] @@ -3538,13 +3030,11 @@ event NodeOperatorDataUpdated(address operatorAddress, bytes data, uint128 clust topics: &::RustType, ) -> alloy_sol_types::Result<()> { if topics.0 != Self::SIGNATURE_HASH { - return Err( - alloy_sol_types::Error::invalid_event_signature_hash( - Self::SIGNATURE, - topics.0, - Self::SIGNATURE_HASH, - ), - ); + return Err(alloy_sol_types::Error::invalid_event_signature_hash( + Self::SIGNATURE, + topics.0, + Self::SIGNATURE_HASH, + )); } Ok(()) } @@ -3557,9 +3047,9 @@ event NodeOperatorDataUpdated(address operatorAddress, bytes data, uint128 clust ::tokenize( &self.data, ), - as alloy_sol_types::SolType>::tokenize(&self.clusterVersion), + as alloy_sol_types::SolType>::tokenize( + &self.clusterVersion, + ), ) } #[inline] @@ -3574,9 +3064,7 @@ event NodeOperatorDataUpdated(address operatorAddress, bytes data, uint128 clust if out.len() < ::COUNT { return Err(alloy_sol_types::Error::Overrun); } - out[0usize] = alloy_sol_types::abi::token::WordToken( - Self::SIGNATURE_HASH, - ); + out[0usize] = alloy_sol_types::abi::token::WordToken(Self::SIGNATURE_HASH); Ok(()) } } @@ -3592,26 +3080,22 @@ event NodeOperatorDataUpdated(address operatorAddress, bytes data, uint128 clust #[automatically_derived] impl From<&NodeOperatorDataUpdated> for alloy_sol_types::private::LogData { #[inline] - fn from( - this: &NodeOperatorDataUpdated, - ) -> alloy_sol_types::private::LogData { + fn from(this: &NodeOperatorDataUpdated) -> alloy_sol_types::private::LogData { alloy_sol_types::SolEvent::encode_log_data(this) } } }; - /**Constructor`. -```solidity -constructor(Settings initialSettings, address[] initialOperators); -```*/ + /// Constructor`. + /// ```solidity + /// constructor(Settings initialSettings, address[] initialOperators); + /// ``` #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] pub struct constructorCall { #[allow(missing_docs)] pub initialSettings: ::RustType, #[allow(missing_docs)] - pub initialOperators: alloy::sol_types::private::Vec< - alloy::sol_types::private::Address, - >, + pub initialOperators: alloy::sol_types::private::Vec, } const _: () = { use alloy::sol_types as alloy_sol_types; @@ -3628,9 +3112,7 @@ constructor(Settings initialSettings, address[] initialOperators); ); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] - fn _type_assertion( - _t: alloy_sol_types::private::AssertTypeEq, - ) { + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { match _t { alloy_sol_types::private::AssertTypeEq::< ::RustType, @@ -3661,9 +3143,7 @@ constructor(Settings initialSettings, address[] initialOperators); Settings, alloy::sol_types::sol_data::Array, ); - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; #[inline] fn new<'a>( tuple: as alloy_sol_types::SolType>::RustType, @@ -3683,14 +3163,15 @@ constructor(Settings initialSettings, address[] initialOperators); } } }; - /**Function with signature `abortMaintenance()` and selector `0x3048bfba`. -```solidity -function abortMaintenance() external; -```*/ + /// Function with signature `abortMaintenance()` and selector `0x3048bfba`. + /// ```solidity + /// function abortMaintenance() external; + /// ``` #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] pub struct abortMaintenanceCall {} - ///Container type for the return parameters of the [`abortMaintenance()`](abortMaintenanceCall) function. + /// Container type for the return parameters of the + /// [`abortMaintenance()`](abortMaintenanceCall) function. #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] pub struct abortMaintenanceReturn {} @@ -3709,9 +3190,7 @@ function abortMaintenance() external; type UnderlyingRustTuple<'a> = (); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] - fn _type_assertion( - _t: alloy_sol_types::private::AssertTypeEq, - ) { + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { match _t { alloy_sol_types::private::AssertTypeEq::< ::RustType, @@ -3720,16 +3199,14 @@ function abortMaintenance() external; } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From - for UnderlyingRustTuple<'_> { + impl ::core::convert::From for UnderlyingRustTuple<'_> { fn from(value: abortMaintenanceCall) -> Self { () } } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From> - for abortMaintenanceCall { + impl ::core::convert::From> for abortMaintenanceCall { fn from(tuple: UnderlyingRustTuple<'_>) -> Self { Self {} } @@ -3742,9 +3219,7 @@ function abortMaintenance() external; type UnderlyingRustTuple<'a> = (); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] - fn _type_assertion( - _t: alloy_sol_types::private::AssertTypeEq, - ) { + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { match _t { alloy_sol_types::private::AssertTypeEq::< ::RustType, @@ -3753,16 +3228,14 @@ function abortMaintenance() external; } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From - for UnderlyingRustTuple<'_> { + impl ::core::convert::From for UnderlyingRustTuple<'_> { fn from(value: abortMaintenanceReturn) -> Self { () } } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From> - for abortMaintenanceReturn { + impl ::core::convert::From> for abortMaintenanceReturn { fn from(tuple: UnderlyingRustTuple<'_>) -> Self { Self {} } @@ -3771,14 +3244,10 @@ function abortMaintenance() external; #[automatically_derived] impl alloy_sol_types::SolCall for abortMaintenanceCall { type Parameters<'a> = (); - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; type Return = abortMaintenanceReturn; type ReturnTuple<'a> = (); - type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; const SIGNATURE: &'static str = "abortMaintenance()"; const SELECTOR: [u8; 4] = [48u8, 72u8, 191u8, 186u8]; #[inline] @@ -3796,21 +3265,22 @@ function abortMaintenance() external; data: &[u8], validate: bool, ) -> alloy_sol_types::Result { - as alloy_sol_types::SolType>::abi_decode_sequence(data, validate) - .map(Into::into) + as alloy_sol_types::SolType>::abi_decode_sequence( + data, validate, + ) + .map(Into::into) } } }; - /**Function with signature `abortMigration()` and selector `0xc130809a`. -```solidity -function abortMigration() external; -```*/ + /// Function with signature `abortMigration()` and selector `0xc130809a`. + /// ```solidity + /// function abortMigration() external; + /// ``` #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] pub struct abortMigrationCall {} - ///Container type for the return parameters of the [`abortMigration()`](abortMigrationCall) function. + /// Container type for the return parameters of the + /// [`abortMigration()`](abortMigrationCall) function. #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] pub struct abortMigrationReturn {} @@ -3829,9 +3299,7 @@ function abortMigration() external; type UnderlyingRustTuple<'a> = (); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] - fn _type_assertion( - _t: alloy_sol_types::private::AssertTypeEq, - ) { + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { match _t { alloy_sol_types::private::AssertTypeEq::< ::RustType, @@ -3860,9 +3328,7 @@ function abortMigration() external; type UnderlyingRustTuple<'a> = (); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] - fn _type_assertion( - _t: alloy_sol_types::private::AssertTypeEq, - ) { + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { match _t { alloy_sol_types::private::AssertTypeEq::< ::RustType, @@ -3871,16 +3337,14 @@ function abortMigration() external; } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From - for UnderlyingRustTuple<'_> { + impl ::core::convert::From for UnderlyingRustTuple<'_> { fn from(value: abortMigrationReturn) -> Self { () } } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From> - for abortMigrationReturn { + impl ::core::convert::From> for abortMigrationReturn { fn from(tuple: UnderlyingRustTuple<'_>) -> Self { Self {} } @@ -3889,14 +3353,10 @@ function abortMigration() external; #[automatically_derived] impl alloy_sol_types::SolCall for abortMigrationCall { type Parameters<'a> = (); - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; type Return = abortMigrationReturn; type ReturnTuple<'a> = (); - type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; const SIGNATURE: &'static str = "abortMigration()"; const SELECTOR: [u8; 4] = [193u8, 48u8, 128u8, 154u8]; #[inline] @@ -3914,21 +3374,22 @@ function abortMigration() external; data: &[u8], validate: bool, ) -> alloy_sol_types::Result { - as alloy_sol_types::SolType>::abi_decode_sequence(data, validate) - .map(Into::into) + as alloy_sol_types::SolType>::abi_decode_sequence( + data, validate, + ) + .map(Into::into) } } }; - /**Function with signature `completeMaintenance()` and selector `0xad36e6d0`. -```solidity -function completeMaintenance() external; -```*/ + /// Function with signature `completeMaintenance()` and selector + /// `0xad36e6d0`. ```solidity + /// function completeMaintenance() external; + /// ``` #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] pub struct completeMaintenanceCall {} - ///Container type for the return parameters of the [`completeMaintenance()`](completeMaintenanceCall) function. + /// Container type for the return parameters of the + /// [`completeMaintenance()`](completeMaintenanceCall) function. #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] pub struct completeMaintenanceReturn {} @@ -3947,9 +3408,7 @@ function completeMaintenance() external; type UnderlyingRustTuple<'a> = (); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] - fn _type_assertion( - _t: alloy_sol_types::private::AssertTypeEq, - ) { + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { match _t { alloy_sol_types::private::AssertTypeEq::< ::RustType, @@ -3958,16 +3417,14 @@ function completeMaintenance() external; } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From - for UnderlyingRustTuple<'_> { + impl ::core::convert::From for UnderlyingRustTuple<'_> { fn from(value: completeMaintenanceCall) -> Self { () } } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From> - for completeMaintenanceCall { + impl ::core::convert::From> for completeMaintenanceCall { fn from(tuple: UnderlyingRustTuple<'_>) -> Self { Self {} } @@ -3980,9 +3437,7 @@ function completeMaintenance() external; type UnderlyingRustTuple<'a> = (); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] - fn _type_assertion( - _t: alloy_sol_types::private::AssertTypeEq, - ) { + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { match _t { alloy_sol_types::private::AssertTypeEq::< ::RustType, @@ -3991,16 +3446,14 @@ function completeMaintenance() external; } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From - for UnderlyingRustTuple<'_> { + impl ::core::convert::From for UnderlyingRustTuple<'_> { fn from(value: completeMaintenanceReturn) -> Self { () } } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From> - for completeMaintenanceReturn { + impl ::core::convert::From> for completeMaintenanceReturn { fn from(tuple: UnderlyingRustTuple<'_>) -> Self { Self {} } @@ -4009,14 +3462,10 @@ function completeMaintenance() external; #[automatically_derived] impl alloy_sol_types::SolCall for completeMaintenanceCall { type Parameters<'a> = (); - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; type Return = completeMaintenanceReturn; type ReturnTuple<'a> = (); - type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; const SIGNATURE: &'static str = "completeMaintenance()"; const SELECTOR: [u8; 4] = [173u8, 54u8, 230u8, 208u8]; #[inline] @@ -4034,17 +3483,17 @@ function completeMaintenance() external; data: &[u8], validate: bool, ) -> alloy_sol_types::Result { - as alloy_sol_types::SolType>::abi_decode_sequence(data, validate) - .map(Into::into) + as alloy_sol_types::SolType>::abi_decode_sequence( + data, validate, + ) + .map(Into::into) } } }; - /**Function with signature `completeMigration(uint64,uint8)` and selector `0x55a47d0a`. -```solidity -function completeMigration(uint64 id, uint8 operatorIdx) external; -```*/ + /// Function with signature `completeMigration(uint64,uint8)` and selector + /// `0x55a47d0a`. ```solidity + /// function completeMigration(uint64 id, uint8 operatorIdx) external; + /// ``` #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] pub struct completeMigrationCall { @@ -4053,7 +3502,8 @@ function completeMigration(uint64 id, uint8 operatorIdx) external; #[allow(missing_docs)] pub operatorIdx: u8, } - ///Container type for the return parameters of the [`completeMigration(uint64,uint8)`](completeMigrationCall) function. + /// Container type for the return parameters of the + /// [`completeMigration(uint64,uint8)`](completeMigrationCall) function. #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] pub struct completeMigrationReturn {} @@ -4075,9 +3525,7 @@ function completeMigration(uint64 id, uint8 operatorIdx) external; type UnderlyingRustTuple<'a> = (u64, u8); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] - fn _type_assertion( - _t: alloy_sol_types::private::AssertTypeEq, - ) { + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { match _t { alloy_sol_types::private::AssertTypeEq::< ::RustType, @@ -4086,16 +3534,14 @@ function completeMigration(uint64 id, uint8 operatorIdx) external; } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From - for UnderlyingRustTuple<'_> { + impl ::core::convert::From for UnderlyingRustTuple<'_> { fn from(value: completeMigrationCall) -> Self { (value.id, value.operatorIdx) } } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From> - for completeMigrationCall { + impl ::core::convert::From> for completeMigrationCall { fn from(tuple: UnderlyingRustTuple<'_>) -> Self { Self { id: tuple.0, @@ -4111,9 +3557,7 @@ function completeMigration(uint64 id, uint8 operatorIdx) external; type UnderlyingRustTuple<'a> = (); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] - fn _type_assertion( - _t: alloy_sol_types::private::AssertTypeEq, - ) { + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { match _t { alloy_sol_types::private::AssertTypeEq::< ::RustType, @@ -4122,16 +3566,14 @@ function completeMigration(uint64 id, uint8 operatorIdx) external; } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From - for UnderlyingRustTuple<'_> { + impl ::core::convert::From for UnderlyingRustTuple<'_> { fn from(value: completeMigrationReturn) -> Self { () } } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From> - for completeMigrationReturn { + impl ::core::convert::From> for completeMigrationReturn { fn from(tuple: UnderlyingRustTuple<'_>) -> Self { Self {} } @@ -4143,14 +3585,10 @@ function completeMigration(uint64 id, uint8 operatorIdx) external; alloy::sol_types::sol_data::Uint<64>, alloy::sol_types::sol_data::Uint<8>, ); - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; type Return = completeMigrationReturn; type ReturnTuple<'a> = (); - type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; const SIGNATURE: &'static str = "completeMigration(uint64,uint8)"; const SELECTOR: [u8; 4] = [85u8, 164u8, 125u8, 10u8]; #[inline] @@ -4162,12 +3600,12 @@ function completeMigration(uint64 id, uint8 operatorIdx) external; #[inline] fn tokenize(&self) -> Self::Token<'_> { ( - as alloy_sol_types::SolType>::tokenize(&self.id), - as alloy_sol_types::SolType>::tokenize(&self.operatorIdx), + as alloy_sol_types::SolType>::tokenize( + &self.id, + ), + as alloy_sol_types::SolType>::tokenize( + &self.operatorIdx, + ), ) } #[inline] @@ -4175,21 +3613,22 @@ function completeMigration(uint64 id, uint8 operatorIdx) external; data: &[u8], validate: bool, ) -> alloy_sol_types::Result { - as alloy_sol_types::SolType>::abi_decode_sequence(data, validate) - .map(Into::into) + as alloy_sol_types::SolType>::abi_decode_sequence( + data, validate, + ) + .map(Into::into) } } }; - /**Function with signature `getView()` and selector `0x75418b9d`. -```solidity -function getView() external view returns (ClusterView memory); -```*/ + /// Function with signature `getView()` and selector `0x75418b9d`. + /// ```solidity + /// function getView() external view returns (ClusterView memory); + /// ``` #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] pub struct getViewCall {} - ///Container type for the return parameters of the [`getView()`](getViewCall) function. + /// Container type for the return parameters of the + /// [`getView()`](getViewCall) function. #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] pub struct getViewReturn { @@ -4211,9 +3650,7 @@ function getView() external view returns (ClusterView memory); type UnderlyingRustTuple<'a> = (); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] - fn _type_assertion( - _t: alloy_sol_types::private::AssertTypeEq, - ) { + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { match _t { alloy_sol_types::private::AssertTypeEq::< ::RustType, @@ -4239,14 +3676,10 @@ function getView() external view returns (ClusterView memory); #[doc(hidden)] type UnderlyingSolTuple<'a> = (ClusterView,); #[doc(hidden)] - type UnderlyingRustTuple<'a> = ( - ::RustType, - ); + type UnderlyingRustTuple<'a> = (::RustType,); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] - fn _type_assertion( - _t: alloy_sol_types::private::AssertTypeEq, - ) { + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { match _t { alloy_sol_types::private::AssertTypeEq::< ::RustType, @@ -4271,14 +3704,10 @@ function getView() external view returns (ClusterView memory); #[automatically_derived] impl alloy_sol_types::SolCall for getViewCall { type Parameters<'a> = (); - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; type Return = getViewReturn; type ReturnTuple<'a> = (ClusterView,); - type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; const SIGNATURE: &'static str = "getView()"; const SELECTOR: [u8; 4] = [117u8, 65u8, 139u8, 157u8]; #[inline] @@ -4296,24 +3725,25 @@ function getView() external view returns (ClusterView memory); data: &[u8], validate: bool, ) -> alloy_sol_types::Result { - as alloy_sol_types::SolType>::abi_decode_sequence(data, validate) - .map(Into::into) + as alloy_sol_types::SolType>::abi_decode_sequence( + data, validate, + ) + .map(Into::into) } } }; - /**Function with signature `registerNodeOperator(bytes)` and selector `0x8b5252d6`. -```solidity -function registerNodeOperator(bytes memory data) external; -```*/ + /// Function with signature `registerNodeOperator(bytes)` and selector + /// `0x8b5252d6`. ```solidity + /// function registerNodeOperator(bytes memory data) external; + /// ``` #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] pub struct registerNodeOperatorCall { #[allow(missing_docs)] pub data: alloy::sol_types::private::Bytes, } - ///Container type for the return parameters of the [`registerNodeOperator(bytes)`](registerNodeOperatorCall) function. + /// Container type for the return parameters of the + /// [`registerNodeOperator(bytes)`](registerNodeOperatorCall) function. #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] pub struct registerNodeOperatorReturn {} @@ -4332,9 +3762,7 @@ function registerNodeOperator(bytes memory data) external; type UnderlyingRustTuple<'a> = (alloy::sol_types::private::Bytes,); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] - fn _type_assertion( - _t: alloy_sol_types::private::AssertTypeEq, - ) { + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { match _t { alloy_sol_types::private::AssertTypeEq::< ::RustType, @@ -4343,16 +3771,14 @@ function registerNodeOperator(bytes memory data) external; } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From - for UnderlyingRustTuple<'_> { + impl ::core::convert::From for UnderlyingRustTuple<'_> { fn from(value: registerNodeOperatorCall) -> Self { (value.data,) } } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From> - for registerNodeOperatorCall { + impl ::core::convert::From> for registerNodeOperatorCall { fn from(tuple: UnderlyingRustTuple<'_>) -> Self { Self { data: tuple.0 } } @@ -4365,9 +3791,7 @@ function registerNodeOperator(bytes memory data) external; type UnderlyingRustTuple<'a> = (); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] - fn _type_assertion( - _t: alloy_sol_types::private::AssertTypeEq, - ) { + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { match _t { alloy_sol_types::private::AssertTypeEq::< ::RustType, @@ -4376,16 +3800,14 @@ function registerNodeOperator(bytes memory data) external; } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From - for UnderlyingRustTuple<'_> { + impl ::core::convert::From for UnderlyingRustTuple<'_> { fn from(value: registerNodeOperatorReturn) -> Self { () } } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From> - for registerNodeOperatorReturn { + impl ::core::convert::From> for registerNodeOperatorReturn { fn from(tuple: UnderlyingRustTuple<'_>) -> Self { Self {} } @@ -4394,14 +3816,10 @@ function registerNodeOperator(bytes memory data) external; #[automatically_derived] impl alloy_sol_types::SolCall for registerNodeOperatorCall { type Parameters<'a> = (alloy::sol_types::sol_data::Bytes,); - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; type Return = registerNodeOperatorReturn; type ReturnTuple<'a> = (); - type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; const SIGNATURE: &'static str = "registerNodeOperator(bytes)"; const SELECTOR: [u8; 4] = [139u8, 82u8, 82u8, 214u8]; #[inline] @@ -4423,24 +3841,25 @@ function registerNodeOperator(bytes memory data) external; data: &[u8], validate: bool, ) -> alloy_sol_types::Result { - as alloy_sol_types::SolType>::abi_decode_sequence(data, validate) - .map(Into::into) + as alloy_sol_types::SolType>::abi_decode_sequence( + data, validate, + ) + .map(Into::into) } } }; - /**Function with signature `startMaintenance(uint8)` and selector `0xdd3fd269`. -```solidity -function startMaintenance(uint8 operatorIdx) external; -```*/ + /// Function with signature `startMaintenance(uint8)` and selector + /// `0xdd3fd269`. ```solidity + /// function startMaintenance(uint8 operatorIdx) external; + /// ``` #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] pub struct startMaintenanceCall { #[allow(missing_docs)] pub operatorIdx: u8, } - ///Container type for the return parameters of the [`startMaintenance(uint8)`](startMaintenanceCall) function. + /// Container type for the return parameters of the + /// [`startMaintenance(uint8)`](startMaintenanceCall) function. #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] pub struct startMaintenanceReturn {} @@ -4459,9 +3878,7 @@ function startMaintenance(uint8 operatorIdx) external; type UnderlyingRustTuple<'a> = (u8,); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] - fn _type_assertion( - _t: alloy_sol_types::private::AssertTypeEq, - ) { + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { match _t { alloy_sol_types::private::AssertTypeEq::< ::RustType, @@ -4470,18 +3887,18 @@ function startMaintenance(uint8 operatorIdx) external; } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From - for UnderlyingRustTuple<'_> { + impl ::core::convert::From for UnderlyingRustTuple<'_> { fn from(value: startMaintenanceCall) -> Self { (value.operatorIdx,) } } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From> - for startMaintenanceCall { + impl ::core::convert::From> for startMaintenanceCall { fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self { operatorIdx: tuple.0 } + Self { + operatorIdx: tuple.0, + } } } } @@ -4492,9 +3909,7 @@ function startMaintenance(uint8 operatorIdx) external; type UnderlyingRustTuple<'a> = (); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] - fn _type_assertion( - _t: alloy_sol_types::private::AssertTypeEq, - ) { + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { match _t { alloy_sol_types::private::AssertTypeEq::< ::RustType, @@ -4503,16 +3918,14 @@ function startMaintenance(uint8 operatorIdx) external; } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From - for UnderlyingRustTuple<'_> { + impl ::core::convert::From for UnderlyingRustTuple<'_> { fn from(value: startMaintenanceReturn) -> Self { () } } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From> - for startMaintenanceReturn { + impl ::core::convert::From> for startMaintenanceReturn { fn from(tuple: UnderlyingRustTuple<'_>) -> Self { Self {} } @@ -4521,14 +3934,10 @@ function startMaintenance(uint8 operatorIdx) external; #[automatically_derived] impl alloy_sol_types::SolCall for startMaintenanceCall { type Parameters<'a> = (alloy::sol_types::sol_data::Uint<8>,); - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; type Return = startMaintenanceReturn; type ReturnTuple<'a> = (); - type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; const SIGNATURE: &'static str = "startMaintenance(uint8)"; const SELECTOR: [u8; 4] = [221u8, 63u8, 210u8, 105u8]; #[inline] @@ -4540,9 +3949,9 @@ function startMaintenance(uint8 operatorIdx) external; #[inline] fn tokenize(&self) -> Self::Token<'_> { ( - as alloy_sol_types::SolType>::tokenize(&self.operatorIdx), + as alloy_sol_types::SolType>::tokenize( + &self.operatorIdx, + ), ) } #[inline] @@ -4550,24 +3959,26 @@ function startMaintenance(uint8 operatorIdx) external; data: &[u8], validate: bool, ) -> alloy_sol_types::Result { - as alloy_sol_types::SolType>::abi_decode_sequence(data, validate) - .map(Into::into) + as alloy_sol_types::SolType>::abi_decode_sequence( + data, validate, + ) + .map(Into::into) } } }; - /**Function with signature `startMigration(((uint8,address)[],uint8))` and selector `0xcdbfc62d`. -```solidity -function startMigration(MigrationPlan memory plan) external; -```*/ + /// Function with signature `startMigration(((uint8,address)[],uint8))` and + /// selector `0xcdbfc62d`. ```solidity + /// function startMigration(MigrationPlan memory plan) external; + /// ``` #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] pub struct startMigrationCall { #[allow(missing_docs)] pub plan: ::RustType, } - ///Container type for the return parameters of the [`startMigration(((uint8,address)[],uint8))`](startMigrationCall) function. + /// Container type for the return parameters of the + /// [`startMigration(((uint8,address)[],uint8))`](startMigrationCall) + /// function. #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] pub struct startMigrationReturn {} @@ -4583,14 +3994,11 @@ function startMigration(MigrationPlan memory plan) external; #[doc(hidden)] type UnderlyingSolTuple<'a> = (MigrationPlan,); #[doc(hidden)] - type UnderlyingRustTuple<'a> = ( - ::RustType, - ); + type UnderlyingRustTuple<'a> = + (::RustType,); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] - fn _type_assertion( - _t: alloy_sol_types::private::AssertTypeEq, - ) { + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { match _t { alloy_sol_types::private::AssertTypeEq::< ::RustType, @@ -4619,9 +4027,7 @@ function startMigration(MigrationPlan memory plan) external; type UnderlyingRustTuple<'a> = (); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] - fn _type_assertion( - _t: alloy_sol_types::private::AssertTypeEq, - ) { + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { match _t { alloy_sol_types::private::AssertTypeEq::< ::RustType, @@ -4630,16 +4036,14 @@ function startMigration(MigrationPlan memory plan) external; } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From - for UnderlyingRustTuple<'_> { + impl ::core::convert::From for UnderlyingRustTuple<'_> { fn from(value: startMigrationReturn) -> Self { () } } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From> - for startMigrationReturn { + impl ::core::convert::From> for startMigrationReturn { fn from(tuple: UnderlyingRustTuple<'_>) -> Self { Self {} } @@ -4648,14 +4052,10 @@ function startMigration(MigrationPlan memory plan) external; #[automatically_derived] impl alloy_sol_types::SolCall for startMigrationCall { type Parameters<'a> = (MigrationPlan,); - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; type Return = startMigrationReturn; type ReturnTuple<'a> = (); - type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; const SIGNATURE: &'static str = "startMigration(((uint8,address)[],uint8))"; const SELECTOR: [u8; 4] = [205u8, 191u8, 198u8, 45u8]; #[inline] @@ -4666,31 +4066,34 @@ function startMigration(MigrationPlan memory plan) external; } #[inline] fn tokenize(&self) -> Self::Token<'_> { - (::tokenize(&self.plan),) + (::tokenize( + &self.plan, + ),) } #[inline] fn abi_decode_returns( data: &[u8], validate: bool, ) -> alloy_sol_types::Result { - as alloy_sol_types::SolType>::abi_decode_sequence(data, validate) - .map(Into::into) + as alloy_sol_types::SolType>::abi_decode_sequence( + data, validate, + ) + .map(Into::into) } } }; - /**Function with signature `transferOwnership(address)` and selector `0xf2fde38b`. -```solidity -function transferOwnership(address newOwner) external; -```*/ + /// Function with signature `transferOwnership(address)` and selector + /// `0xf2fde38b`. ```solidity + /// function transferOwnership(address newOwner) external; + /// ``` #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] pub struct transferOwnershipCall { #[allow(missing_docs)] pub newOwner: alloy::sol_types::private::Address, } - ///Container type for the return parameters of the [`transferOwnership(address)`](transferOwnershipCall) function. + /// Container type for the return parameters of the + /// [`transferOwnership(address)`](transferOwnershipCall) function. #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] pub struct transferOwnershipReturn {} @@ -4709,9 +4112,7 @@ function transferOwnership(address newOwner) external; type UnderlyingRustTuple<'a> = (alloy::sol_types::private::Address,); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] - fn _type_assertion( - _t: alloy_sol_types::private::AssertTypeEq, - ) { + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { match _t { alloy_sol_types::private::AssertTypeEq::< ::RustType, @@ -4720,16 +4121,14 @@ function transferOwnership(address newOwner) external; } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From - for UnderlyingRustTuple<'_> { + impl ::core::convert::From for UnderlyingRustTuple<'_> { fn from(value: transferOwnershipCall) -> Self { (value.newOwner,) } } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From> - for transferOwnershipCall { + impl ::core::convert::From> for transferOwnershipCall { fn from(tuple: UnderlyingRustTuple<'_>) -> Self { Self { newOwner: tuple.0 } } @@ -4742,9 +4141,7 @@ function transferOwnership(address newOwner) external; type UnderlyingRustTuple<'a> = (); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] - fn _type_assertion( - _t: alloy_sol_types::private::AssertTypeEq, - ) { + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { match _t { alloy_sol_types::private::AssertTypeEq::< ::RustType, @@ -4753,16 +4150,14 @@ function transferOwnership(address newOwner) external; } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From - for UnderlyingRustTuple<'_> { + impl ::core::convert::From for UnderlyingRustTuple<'_> { fn from(value: transferOwnershipReturn) -> Self { () } } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From> - for transferOwnershipReturn { + impl ::core::convert::From> for transferOwnershipReturn { fn from(tuple: UnderlyingRustTuple<'_>) -> Self { Self {} } @@ -4771,14 +4166,10 @@ function transferOwnership(address newOwner) external; #[automatically_derived] impl alloy_sol_types::SolCall for transferOwnershipCall { type Parameters<'a> = (alloy::sol_types::sol_data::Address,); - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; type Return = transferOwnershipReturn; type ReturnTuple<'a> = (); - type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; const SIGNATURE: &'static str = "transferOwnership(address)"; const SELECTOR: [u8; 4] = [242u8, 253u8, 227u8, 139u8]; #[inline] @@ -4800,17 +4191,17 @@ function transferOwnership(address newOwner) external; data: &[u8], validate: bool, ) -> alloy_sol_types::Result { - as alloy_sol_types::SolType>::abi_decode_sequence(data, validate) - .map(Into::into) + as alloy_sol_types::SolType>::abi_decode_sequence( + data, validate, + ) + .map(Into::into) } } }; - /**Function with signature `updateNodeOperatorData(uint8,bytes)` and selector `0xf019b154`. -```solidity -function updateNodeOperatorData(uint8 operatorIdx, bytes memory data) external; -```*/ + /// Function with signature `updateNodeOperatorData(uint8,bytes)` and + /// selector `0xf019b154`. ```solidity + /// function updateNodeOperatorData(uint8 operatorIdx, bytes memory data) + /// external; ``` #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] pub struct updateNodeOperatorDataCall { @@ -4819,7 +4210,9 @@ function updateNodeOperatorData(uint8 operatorIdx, bytes memory data) external; #[allow(missing_docs)] pub data: alloy::sol_types::private::Bytes, } - ///Container type for the return parameters of the [`updateNodeOperatorData(uint8,bytes)`](updateNodeOperatorDataCall) function. + /// Container type for the return parameters of the + /// [`updateNodeOperatorData(uint8,bytes)`](updateNodeOperatorDataCall) + /// function. #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] pub struct updateNodeOperatorDataReturn {} @@ -4841,9 +4234,7 @@ function updateNodeOperatorData(uint8 operatorIdx, bytes memory data) external; type UnderlyingRustTuple<'a> = (u8, alloy::sol_types::private::Bytes); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] - fn _type_assertion( - _t: alloy_sol_types::private::AssertTypeEq, - ) { + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { match _t { alloy_sol_types::private::AssertTypeEq::< ::RustType, @@ -4852,16 +4243,14 @@ function updateNodeOperatorData(uint8 operatorIdx, bytes memory data) external; } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From - for UnderlyingRustTuple<'_> { + impl ::core::convert::From for UnderlyingRustTuple<'_> { fn from(value: updateNodeOperatorDataCall) -> Self { (value.operatorIdx, value.data) } } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From> - for updateNodeOperatorDataCall { + impl ::core::convert::From> for updateNodeOperatorDataCall { fn from(tuple: UnderlyingRustTuple<'_>) -> Self { Self { operatorIdx: tuple.0, @@ -4877,9 +4266,7 @@ function updateNodeOperatorData(uint8 operatorIdx, bytes memory data) external; type UnderlyingRustTuple<'a> = (); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] - fn _type_assertion( - _t: alloy_sol_types::private::AssertTypeEq, - ) { + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { match _t { alloy_sol_types::private::AssertTypeEq::< ::RustType, @@ -4888,16 +4275,14 @@ function updateNodeOperatorData(uint8 operatorIdx, bytes memory data) external; } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From - for UnderlyingRustTuple<'_> { + impl ::core::convert::From for UnderlyingRustTuple<'_> { fn from(value: updateNodeOperatorDataReturn) -> Self { () } } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From> - for updateNodeOperatorDataReturn { + impl ::core::convert::From> for updateNodeOperatorDataReturn { fn from(tuple: UnderlyingRustTuple<'_>) -> Self { Self {} } @@ -4909,14 +4294,10 @@ function updateNodeOperatorData(uint8 operatorIdx, bytes memory data) external; alloy::sol_types::sol_data::Uint<8>, alloy::sol_types::sol_data::Bytes, ); - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; type Return = updateNodeOperatorDataReturn; type ReturnTuple<'a> = (); - type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; const SIGNATURE: &'static str = "updateNodeOperatorData(uint8,bytes)"; const SELECTOR: [u8; 4] = [240u8, 25u8, 177u8, 84u8]; #[inline] @@ -4928,9 +4309,9 @@ function updateNodeOperatorData(uint8 operatorIdx, bytes memory data) external; #[inline] fn tokenize(&self) -> Self::Token<'_> { ( - as alloy_sol_types::SolType>::tokenize(&self.operatorIdx), + as alloy_sol_types::SolType>::tokenize( + &self.operatorIdx, + ), ::tokenize( &self.data, ), @@ -4941,24 +4322,25 @@ function updateNodeOperatorData(uint8 operatorIdx, bytes memory data) external; data: &[u8], validate: bool, ) -> alloy_sol_types::Result { - as alloy_sol_types::SolType>::abi_decode_sequence(data, validate) - .map(Into::into) + as alloy_sol_types::SolType>::abi_decode_sequence( + data, validate, + ) + .map(Into::into) } } }; - /**Function with signature `updateSettings((uint16))` and selector `0x65706f9c`. -```solidity -function updateSettings(Settings memory newSettings) external; -```*/ + /// Function with signature `updateSettings((uint16))` and selector + /// `0x65706f9c`. ```solidity + /// function updateSettings(Settings memory newSettings) external; + /// ``` #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] pub struct updateSettingsCall { #[allow(missing_docs)] pub newSettings: ::RustType, } - ///Container type for the return parameters of the [`updateSettings((uint16))`](updateSettingsCall) function. + /// Container type for the return parameters of the + /// [`updateSettings((uint16))`](updateSettingsCall) function. #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] pub struct updateSettingsReturn {} @@ -4974,14 +4356,10 @@ function updateSettings(Settings memory newSettings) external; #[doc(hidden)] type UnderlyingSolTuple<'a> = (Settings,); #[doc(hidden)] - type UnderlyingRustTuple<'a> = ( - ::RustType, - ); + type UnderlyingRustTuple<'a> = (::RustType,); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] - fn _type_assertion( - _t: alloy_sol_types::private::AssertTypeEq, - ) { + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { match _t { alloy_sol_types::private::AssertTypeEq::< ::RustType, @@ -4999,7 +4377,9 @@ function updateSettings(Settings memory newSettings) external; #[doc(hidden)] impl ::core::convert::From> for updateSettingsCall { fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self { newSettings: tuple.0 } + Self { + newSettings: tuple.0, + } } } } @@ -5010,9 +4390,7 @@ function updateSettings(Settings memory newSettings) external; type UnderlyingRustTuple<'a> = (); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] - fn _type_assertion( - _t: alloy_sol_types::private::AssertTypeEq, - ) { + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { match _t { alloy_sol_types::private::AssertTypeEq::< ::RustType, @@ -5021,16 +4399,14 @@ function updateSettings(Settings memory newSettings) external; } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From - for UnderlyingRustTuple<'_> { + impl ::core::convert::From for UnderlyingRustTuple<'_> { fn from(value: updateSettingsReturn) -> Self { () } } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From> - for updateSettingsReturn { + impl ::core::convert::From> for updateSettingsReturn { fn from(tuple: UnderlyingRustTuple<'_>) -> Self { Self {} } @@ -5039,14 +4415,10 @@ function updateSettings(Settings memory newSettings) external; #[automatically_derived] impl alloy_sol_types::SolCall for updateSettingsCall { type Parameters<'a> = (Settings,); - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; type Return = updateSettingsReturn; type ReturnTuple<'a> = (); - type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; const SIGNATURE: &'static str = "updateSettings((uint16))"; const SELECTOR: [u8; 4] = [101u8, 112u8, 111u8, 156u8]; #[inline] @@ -5057,21 +4429,23 @@ function updateSettings(Settings memory newSettings) external; } #[inline] fn tokenize(&self) -> Self::Token<'_> { - (::tokenize(&self.newSettings),) + (::tokenize( + &self.newSettings, + ),) } #[inline] fn abi_decode_returns( data: &[u8], validate: bool, ) -> alloy_sol_types::Result { - as alloy_sol_types::SolType>::abi_decode_sequence(data, validate) - .map(Into::into) + as alloy_sol_types::SolType>::abi_decode_sequence( + data, validate, + ) + .map(Into::into) } } }; - ///Container for all the [`Cluster`](self) function calls. + /// Container for all the [`Cluster`](self) function calls. pub enum ClusterCalls { #[allow(missing_docs)] abortMaintenance(abortMaintenanceCall), @@ -5100,8 +4474,9 @@ function updateSettings(Settings memory newSettings) external; impl ClusterCalls { /// All the selectors of this enum. /// - /// Note that the selectors might not be in the same order as the variants. - /// No guarantees are made about the order of the selectors. + /// Note that the selectors might not be in the same order as the + /// variants. No guarantees are made about the order of the + /// selectors. /// /// Prefer using `SolInterface` methods instead. pub const SELECTORS: &'static [[u8; 4usize]] = &[ @@ -5174,20 +4549,16 @@ function updateSettings(Settings memory newSettings) external; data: &[u8], validate: bool, ) -> alloy_sol_types::Result { - static DECODE_SHIMS: &[fn( - &[u8], - bool, - ) -> alloy_sol_types::Result] = &[ + static DECODE_SHIMS: &[fn(&[u8], bool) -> alloy_sol_types::Result] = &[ { fn abortMaintenance( data: &[u8], validate: bool, ) -> alloy_sol_types::Result { ::abi_decode_raw( - data, - validate, - ) - .map(ClusterCalls::abortMaintenance) + data, validate, + ) + .map(ClusterCalls::abortMaintenance) } abortMaintenance }, @@ -5197,10 +4568,9 @@ function updateSettings(Settings memory newSettings) external; validate: bool, ) -> alloy_sol_types::Result { ::abi_decode_raw( - data, - validate, - ) - .map(ClusterCalls::completeMigration) + data, validate, + ) + .map(ClusterCalls::completeMigration) } completeMigration }, @@ -5210,10 +4580,9 @@ function updateSettings(Settings memory newSettings) external; validate: bool, ) -> alloy_sol_types::Result { ::abi_decode_raw( - data, - validate, - ) - .map(ClusterCalls::updateSettings) + data, validate, + ) + .map(ClusterCalls::updateSettings) } updateSettings }, @@ -5222,10 +4591,7 @@ function updateSettings(Settings memory newSettings) external; data: &[u8], validate: bool, ) -> alloy_sol_types::Result { - ::abi_decode_raw( - data, - validate, - ) + ::abi_decode_raw(data, validate) .map(ClusterCalls::getView) } getView @@ -5236,10 +4602,9 @@ function updateSettings(Settings memory newSettings) external; validate: bool, ) -> alloy_sol_types::Result { ::abi_decode_raw( - data, - validate, - ) - .map(ClusterCalls::registerNodeOperator) + data, validate, + ) + .map(ClusterCalls::registerNodeOperator) } registerNodeOperator }, @@ -5249,10 +4614,9 @@ function updateSettings(Settings memory newSettings) external; validate: bool, ) -> alloy_sol_types::Result { ::abi_decode_raw( - data, - validate, - ) - .map(ClusterCalls::completeMaintenance) + data, validate, + ) + .map(ClusterCalls::completeMaintenance) } completeMaintenance }, @@ -5262,10 +4626,9 @@ function updateSettings(Settings memory newSettings) external; validate: bool, ) -> alloy_sol_types::Result { ::abi_decode_raw( - data, - validate, - ) - .map(ClusterCalls::abortMigration) + data, validate, + ) + .map(ClusterCalls::abortMigration) } abortMigration }, @@ -5275,10 +4638,9 @@ function updateSettings(Settings memory newSettings) external; validate: bool, ) -> alloy_sol_types::Result { ::abi_decode_raw( - data, - validate, - ) - .map(ClusterCalls::startMigration) + data, validate, + ) + .map(ClusterCalls::startMigration) } startMigration }, @@ -5288,10 +4650,9 @@ function updateSettings(Settings memory newSettings) external; validate: bool, ) -> alloy_sol_types::Result { ::abi_decode_raw( - data, - validate, - ) - .map(ClusterCalls::startMaintenance) + data, validate, + ) + .map(ClusterCalls::startMaintenance) } startMaintenance }, @@ -5301,10 +4662,9 @@ function updateSettings(Settings memory newSettings) external; validate: bool, ) -> alloy_sol_types::Result { ::abi_decode_raw( - data, - validate, - ) - .map(ClusterCalls::updateNodeOperatorData) + data, validate, + ) + .map(ClusterCalls::updateNodeOperatorData) } updateNodeOperatorData }, @@ -5314,21 +4674,18 @@ function updateSettings(Settings memory newSettings) external; validate: bool, ) -> alloy_sol_types::Result { ::abi_decode_raw( - data, - validate, - ) - .map(ClusterCalls::transferOwnership) + data, validate, + ) + .map(ClusterCalls::transferOwnership) } transferOwnership }, ]; let Ok(idx) = Self::SELECTORS.binary_search(&selector) else { - return Err( - alloy_sol_types::Error::unknown_selector( - ::NAME, - selector, - ), - ); + return Err(alloy_sol_types::Error::unknown_selector( + ::NAME, + selector, + )); }; DECODE_SHIMS[idx](data, validate) } @@ -5336,47 +4693,31 @@ function updateSettings(Settings memory newSettings) external; fn abi_encoded_size(&self) -> usize { match self { Self::abortMaintenance(inner) => { - ::abi_encoded_size( - inner, - ) + ::abi_encoded_size(inner) } Self::abortMigration(inner) => { - ::abi_encoded_size( - inner, - ) + ::abi_encoded_size(inner) } Self::completeMaintenance(inner) => { - ::abi_encoded_size( - inner, - ) + ::abi_encoded_size(inner) } Self::completeMigration(inner) => { - ::abi_encoded_size( - inner, - ) + ::abi_encoded_size(inner) } Self::getView(inner) => { ::abi_encoded_size(inner) } Self::registerNodeOperator(inner) => { - ::abi_encoded_size( - inner, - ) + ::abi_encoded_size(inner) } Self::startMaintenance(inner) => { - ::abi_encoded_size( - inner, - ) + ::abi_encoded_size(inner) } Self::startMigration(inner) => { - ::abi_encoded_size( - inner, - ) + ::abi_encoded_size(inner) } Self::transferOwnership(inner) => { - ::abi_encoded_size( - inner, - ) + ::abi_encoded_size(inner) } Self::updateNodeOperatorData(inner) => { ::abi_encoded_size( @@ -5384,9 +4725,7 @@ function updateSettings(Settings memory newSettings) external; ) } Self::updateSettings(inner) => { - ::abi_encoded_size( - inner, - ) + ::abi_encoded_size(inner) } } } @@ -5394,72 +4733,48 @@ function updateSettings(Settings memory newSettings) external; fn abi_encode_raw(&self, out: &mut alloy_sol_types::private::Vec) { match self { Self::abortMaintenance(inner) => { - ::abi_encode_raw( - inner, - out, - ) + ::abi_encode_raw(inner, out) } Self::abortMigration(inner) => { - ::abi_encode_raw( - inner, - out, - ) + ::abi_encode_raw(inner, out) } Self::completeMaintenance(inner) => { ::abi_encode_raw( - inner, - out, + inner, out, ) } Self::completeMigration(inner) => { - ::abi_encode_raw( - inner, - out, - ) + ::abi_encode_raw(inner, out) } Self::getView(inner) => { ::abi_encode_raw(inner, out) } Self::registerNodeOperator(inner) => { ::abi_encode_raw( - inner, - out, + inner, out, ) } Self::startMaintenance(inner) => { - ::abi_encode_raw( - inner, - out, - ) + ::abi_encode_raw(inner, out) } Self::startMigration(inner) => { - ::abi_encode_raw( - inner, - out, - ) + ::abi_encode_raw(inner, out) } Self::transferOwnership(inner) => { - ::abi_encode_raw( - inner, - out, - ) + ::abi_encode_raw(inner, out) } Self::updateNodeOperatorData(inner) => { ::abi_encode_raw( - inner, - out, + inner, out, ) } Self::updateSettings(inner) => { - ::abi_encode_raw( - inner, - out, - ) + ::abi_encode_raw(inner, out) } } } } - ///Container for all the [`Cluster`](self) events. + /// Container for all the [`Cluster`](self) events. pub enum ClusterEvents { #[allow(missing_docs)] MaintenanceAborted(MaintenanceAborted), @@ -5482,282 +4797,51 @@ function updateSettings(Settings memory newSettings) external; impl ClusterEvents { /// All the selectors of this enum. /// - /// Note that the selectors might not be in the same order as the variants. - /// No guarantees are made about the order of the selectors. + /// Note that the selectors might not be in the same order as the + /// variants. No guarantees are made about the order of the + /// selectors. /// /// Prefer using `SolInterface` methods instead. pub const SELECTORS: &'static [[u8; 32usize]] = &[ [ - 1u8, - 38u8, - 152u8, - 121u8, - 83u8, - 95u8, - 64u8, - 238u8, - 137u8, - 87u8, - 225u8, - 94u8, - 22u8, - 11u8, - 241u8, - 134u8, - 108u8, - 94u8, - 39u8, - 40u8, - 255u8, - 12u8, - 188u8, - 88u8, - 61u8, - 132u8, - 136u8, - 33u8, - 226u8, - 99u8, - 155u8, - 78u8, + 1u8, 38u8, 152u8, 121u8, 83u8, 95u8, 64u8, 238u8, 137u8, 87u8, 225u8, 94u8, 22u8, + 11u8, 241u8, 134u8, 108u8, 94u8, 39u8, 40u8, 255u8, 12u8, 188u8, 88u8, 61u8, 132u8, + 136u8, 33u8, 226u8, 99u8, 155u8, 78u8, ], [ - 18u8, - 81u8, - 129u8, - 236u8, - 33u8, - 136u8, - 45u8, - 236u8, - 81u8, - 162u8, - 57u8, - 41u8, - 5u8, - 223u8, - 243u8, - 168u8, - 44u8, - 189u8, - 2u8, - 98u8, - 241u8, - 139u8, - 92u8, - 12u8, - 3u8, - 84u8, - 136u8, - 103u8, - 27u8, - 64u8, - 175u8, - 178u8, + 18u8, 81u8, 129u8, 236u8, 33u8, 136u8, 45u8, 236u8, 81u8, 162u8, 57u8, 41u8, 5u8, + 223u8, 243u8, 168u8, 44u8, 189u8, 2u8, 98u8, 241u8, 139u8, 92u8, 12u8, 3u8, 84u8, + 136u8, 103u8, 27u8, 64u8, 175u8, 178u8, ], [ - 120u8, - 218u8, - 210u8, - 188u8, - 11u8, - 71u8, - 198u8, - 136u8, - 237u8, - 132u8, - 243u8, - 254u8, - 231u8, - 154u8, - 188u8, - 24u8, - 230u8, - 201u8, - 130u8, - 45u8, - 176u8, - 90u8, - 121u8, - 202u8, - 25u8, - 223u8, - 245u8, - 69u8, - 51u8, - 199u8, - 71u8, - 13u8, + 120u8, 218u8, 210u8, 188u8, 11u8, 71u8, 198u8, 136u8, 237u8, 132u8, 243u8, 254u8, + 231u8, 154u8, 188u8, 24u8, 230u8, 201u8, 130u8, 45u8, 176u8, 90u8, 121u8, 202u8, + 25u8, 223u8, 245u8, 69u8, 51u8, 199u8, 71u8, 13u8, ], [ - 143u8, - 185u8, - 205u8, - 5u8, - 77u8, - 10u8, - 2u8, - 33u8, - 16u8, - 204u8, - 237u8, - 35u8, - 158u8, - 144u8, - 139u8, - 131u8, - 78u8, - 76u8, - 210u8, - 25u8, - 81u8, - 24u8, - 86u8, - 212u8, - 234u8, - 174u8, - 48u8, - 81u8, - 217u8, - 50u8, - 214u8, - 4u8, + 143u8, 185u8, 205u8, 5u8, 77u8, 10u8, 2u8, 33u8, 16u8, 204u8, 237u8, 35u8, 158u8, + 144u8, 139u8, 131u8, 78u8, 76u8, 210u8, 25u8, 81u8, 24u8, 86u8, 212u8, 234u8, + 174u8, 48u8, 81u8, 217u8, 50u8, 214u8, 4u8, ], [ - 175u8, - 94u8, - 144u8, - 231u8, - 32u8, - 21u8, - 244u8, - 49u8, - 56u8, - 246u8, - 107u8, - 76u8, - 208u8, - 139u8, - 209u8, - 223u8, - 162u8, - 131u8, - 144u8, - 48u8, - 16u8, - 79u8, - 34u8, - 160u8, - 10u8, - 248u8, - 67u8, - 254u8, - 132u8, - 124u8, - 109u8, - 25u8, + 175u8, 94u8, 144u8, 231u8, 32u8, 21u8, 244u8, 49u8, 56u8, 246u8, 107u8, 76u8, + 208u8, 139u8, 209u8, 223u8, 162u8, 131u8, 144u8, 48u8, 16u8, 79u8, 34u8, 160u8, + 10u8, 248u8, 67u8, 254u8, 132u8, 124u8, 109u8, 25u8, ], [ - 188u8, - 39u8, - 72u8, - 207u8, - 2u8, - 247u8, - 161u8, - 41u8, - 21u8, - 37u8, - 232u8, - 102u8, - 239u8, - 199u8, - 106u8, - 179u8, - 185u8, - 109u8, - 50u8, - 215u8, - 175u8, - 203u8, - 178u8, - 108u8, - 83u8, - 218u8, - 236u8, - 97u8, - 123u8, - 56u8, - 180u8, - 121u8, + 188u8, 39u8, 72u8, 207u8, 2u8, 247u8, 161u8, 41u8, 21u8, 37u8, 232u8, 102u8, 239u8, + 199u8, 106u8, 179u8, 185u8, 109u8, 50u8, 215u8, 175u8, 203u8, 178u8, 108u8, 83u8, + 218u8, 236u8, 97u8, 123u8, 56u8, 180u8, 121u8, ], [ - 247u8, - 50u8, - 64u8, - 66u8, - 34u8, - 70u8, - 246u8, - 62u8, - 214u8, - 51u8, - 239u8, - 60u8, - 224u8, - 114u8, - 107u8, - 138u8, - 184u8, - 251u8, - 105u8, - 212u8, - 108u8, - 138u8, - 78u8, - 94u8, - 203u8, - 11u8, - 41u8, - 34u8, - 102u8, - 134u8, - 116u8, - 161u8, + 247u8, 50u8, 64u8, 66u8, 34u8, 70u8, 246u8, 62u8, 214u8, 51u8, 239u8, 60u8, 224u8, + 114u8, 107u8, 138u8, 184u8, 251u8, 105u8, 212u8, 108u8, 138u8, 78u8, 94u8, 203u8, + 11u8, 41u8, 34u8, 102u8, 134u8, 116u8, 161u8, ], [ - 249u8, - 16u8, - 103u8, - 235u8, - 66u8, - 12u8, - 40u8, - 211u8, - 18u8, - 72u8, - 101u8, - 252u8, - 153u8, - 110u8, - 106u8, - 169u8, - 213u8, - 65u8, - 185u8, - 180u8, - 254u8, - 249u8, - 24u8, - 140u8, - 185u8, - 101u8, - 166u8, - 204u8, - 100u8, - 145u8, - 99u8, - 142u8, + 249u8, 16u8, 103u8, 235u8, 66u8, 12u8, 40u8, 211u8, 18u8, 72u8, 101u8, 252u8, + 153u8, 110u8, 106u8, 169u8, 213u8, 65u8, 185u8, 180u8, 254u8, 249u8, 24u8, 140u8, + 185u8, 101u8, 166u8, 204u8, 100u8, 145u8, 99u8, 142u8, ], ]; } @@ -5771,93 +4855,63 @@ function updateSettings(Settings memory newSettings) external; validate: bool, ) -> alloy_sol_types::Result { match topics.first().copied() { - Some( - ::SIGNATURE_HASH, - ) => { + Some(::SIGNATURE_HASH) => { ::decode_raw_log( - topics, - data, - validate, - ) - .map(Self::MaintenanceAborted) + topics, data, validate, + ) + .map(Self::MaintenanceAborted) } - Some( - ::SIGNATURE_HASH, - ) => { + Some(::SIGNATURE_HASH) => { ::decode_raw_log( - topics, - data, - validate, - ) - .map(Self::MaintenanceCompleted) + topics, data, validate, + ) + .map(Self::MaintenanceCompleted) } - Some( - ::SIGNATURE_HASH, - ) => { + Some(::SIGNATURE_HASH) => { ::decode_raw_log( - topics, - data, - validate, - ) - .map(Self::MaintenanceStarted) + topics, data, validate, + ) + .map(Self::MaintenanceStarted) } Some(::SIGNATURE_HASH) => { ::decode_raw_log( - topics, - data, - validate, - ) - .map(Self::MigrationAborted) + topics, data, validate, + ) + .map(Self::MigrationAborted) } - Some( - ::SIGNATURE_HASH, - ) => { + Some(::SIGNATURE_HASH) => { ::decode_raw_log( - topics, - data, - validate, - ) - .map(Self::MigrationCompleted) + topics, data, validate, + ) + .map(Self::MigrationCompleted) } - Some( - ::SIGNATURE_HASH, - ) => { + Some(::SIGNATURE_HASH) => { ::decode_raw_log( - topics, - data, - validate, - ) - .map(Self::MigrationDataPullCompleted) + topics, data, validate, + ) + .map(Self::MigrationDataPullCompleted) } Some(::SIGNATURE_HASH) => { ::decode_raw_log( - topics, - data, - validate, - ) - .map(Self::MigrationStarted) + topics, data, validate, + ) + .map(Self::MigrationStarted) } - Some( - ::SIGNATURE_HASH, - ) => { + Some(::SIGNATURE_HASH) => { ::decode_raw_log( - topics, - data, - validate, - ) - .map(Self::NodeOperatorDataUpdated) - } - _ => { - alloy_sol_types::private::Err(alloy_sol_types::Error::InvalidLog { - name: ::NAME, - log: alloy_sol_types::private::Box::new( - alloy_sol_types::private::LogData::new_unchecked( - topics.to_vec(), - data.to_vec().into(), - ), + topics, data, validate, + ) + .map(Self::NodeOperatorDataUpdated) + } + _ => alloy_sol_types::private::Err(alloy_sol_types::Error::InvalidLog { + name: ::NAME, + log: alloy_sol_types::private::Box::new( + alloy_sol_types::private::LogData::new_unchecked( + topics.to_vec(), + data.to_vec().into(), ), - }) - } + ), + }), } } } @@ -5921,9 +4975,10 @@ function updateSettings(Settings memory newSettings) external; } } use alloy::contract as alloy_contract; - /**Creates a new wrapper around an on-chain [`Cluster`](self) contract instance. - -See the [wrapper's documentation](`ClusterInstance`) for more details.*/ + /// Creates a new wrapper around an on-chain [`Cluster`](self) contract + /// instance. + /// + /// See the [wrapper's documentation](`ClusterInstance`) for more details. #[inline] pub const fn new< T: alloy_contract::private::Transport + ::core::clone::Clone, @@ -5935,11 +4990,14 @@ See the [wrapper's documentation](`ClusterInstance`) for more details.*/ ) -> ClusterInstance { ClusterInstance::::new(address, provider) } - /**Deploys this contract using the given `provider` and constructor arguments, if any. - -Returns a new instance of the contract, if the deployment was successful. - -For more fine-grained control over the deployment process, use [`deploy_builder`] instead.*/ + /// Deploys this contract using the given `provider` and constructor + /// arguments, if any. + /// + /// Returns a new instance of the contract, if the deployment was + /// successful. + /// + /// For more fine-grained control over the deployment process, use + /// [`deploy_builder`] instead. #[inline] pub fn deploy< T: alloy_contract::private::Transport + ::core::clone::Clone, @@ -5948,19 +5006,17 @@ For more fine-grained control over the deployment process, use [`deploy_builder` >( provider: P, initialSettings: ::RustType, - initialOperators: alloy::sol_types::private::Vec< - alloy::sol_types::private::Address, - >, - ) -> impl ::core::future::Future< - Output = alloy_contract::Result>, - > { + initialOperators: alloy::sol_types::private::Vec, + ) -> impl ::core::future::Future>> + { ClusterInstance::::deploy(provider, initialSettings, initialOperators) } - /**Creates a `RawCallBuilder` for deploying this contract using the given `provider` -and constructor arguments, if any. - -This is a simple wrapper around creating a `RawCallBuilder` with the data set to -the bytecode concatenated with the constructor's ABI-encoded arguments.*/ + /// Creates a `RawCallBuilder` for deploying this contract using the given + /// `provider` and constructor arguments, if any. + /// + /// This is a simple wrapper around creating a `RawCallBuilder` with the + /// data set to the bytecode concatenated with the constructor's + /// ABI-encoded arguments. #[inline] pub fn deploy_builder< T: alloy_contract::private::Transport + ::core::clone::Clone, @@ -5969,27 +5025,23 @@ the bytecode concatenated with the constructor's ABI-encoded arguments.*/ >( provider: P, initialSettings: ::RustType, - initialOperators: alloy::sol_types::private::Vec< - alloy::sol_types::private::Address, - >, + initialOperators: alloy::sol_types::private::Vec, ) -> alloy_contract::RawCallBuilder { - ClusterInstance::< - T, - P, - N, - >::deploy_builder(provider, initialSettings, initialOperators) + ClusterInstance::::deploy_builder(provider, initialSettings, initialOperators) } - /**A [`Cluster`](self) instance. - -Contains type-safe methods for interacting with an on-chain instance of the -[`Cluster`](self) contract located at a given `address`, using a given -provider `P`. - -If the contract bytecode is available (see the [`sol!`](alloy_sol_types::sol!) -documentation on how to provide it), the `deploy` and `deploy_builder` methods can -be used to deploy a new instance of the contract. - -See the [module-level documentation](self) for all the available methods.*/ + /// A [`Cluster`](self) instance. + /// + /// Contains type-safe methods for interacting with an on-chain instance of + /// the [`Cluster`](self) contract located at a given `address`, using a + /// given provider `P`. + /// + /// If the contract bytecode is available (see the + /// [`sol!`](alloy_sol_types::sol!) documentation on how to provide it), + /// the `deploy` and `deploy_builder` methods can be used to deploy a + /// new instance of the contract. + /// + /// See the [module-level documentation](self) for all the available + /// methods. #[derive(Clone)] pub struct ClusterInstance { address: alloy_sol_types::private::Address, @@ -6000,77 +5052,73 @@ See the [module-level documentation](self) for all the available methods.*/ impl ::core::fmt::Debug for ClusterInstance { #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { - f.debug_tuple("ClusterInstance").field(&self.address).finish() + f.debug_tuple("ClusterInstance") + .field(&self.address) + .finish() } } /// Instantiation and getters/setters. #[automatically_derived] impl< - T: alloy_contract::private::Transport + ::core::clone::Clone, - P: alloy_contract::private::Provider, - N: alloy_contract::private::Network, - > ClusterInstance { - /**Creates a new wrapper around an on-chain [`Cluster`](self) contract instance. - -See the [wrapper's documentation](`ClusterInstance`) for more details.*/ + T: alloy_contract::private::Transport + ::core::clone::Clone, + P: alloy_contract::private::Provider, + N: alloy_contract::private::Network, + > ClusterInstance + { + /// Creates a new wrapper around an on-chain [`Cluster`](self) contract + /// instance. + /// + /// See the [wrapper's documentation](`ClusterInstance`) for more + /// details. #[inline] - pub const fn new( - address: alloy_sol_types::private::Address, - provider: P, - ) -> Self { + pub const fn new(address: alloy_sol_types::private::Address, provider: P) -> Self { Self { address, provider, _network_transport: ::core::marker::PhantomData, } } - /**Deploys this contract using the given `provider` and constructor arguments, if any. - -Returns a new instance of the contract, if the deployment was successful. - -For more fine-grained control over the deployment process, use [`deploy_builder`] instead.*/ + /// Deploys this contract using the given `provider` and constructor + /// arguments, if any. + /// + /// Returns a new instance of the contract, if the deployment was + /// successful. + /// + /// For more fine-grained control over the deployment process, use + /// [`deploy_builder`] instead. #[inline] pub async fn deploy( provider: P, initialSettings: ::RustType, - initialOperators: alloy::sol_types::private::Vec< - alloy::sol_types::private::Address, - >, + initialOperators: alloy::sol_types::private::Vec, ) -> alloy_contract::Result> { - let call_builder = Self::deploy_builder( - provider, - initialSettings, - initialOperators, - ); + let call_builder = Self::deploy_builder(provider, initialSettings, initialOperators); let contract_address = call_builder.deploy().await?; Ok(Self::new(contract_address, call_builder.provider)) } - /**Creates a `RawCallBuilder` for deploying this contract using the given `provider` -and constructor arguments, if any. - -This is a simple wrapper around creating a `RawCallBuilder` with the data set to -the bytecode concatenated with the constructor's ABI-encoded arguments.*/ + /// Creates a `RawCallBuilder` for deploying this contract using the + /// given `provider` and constructor arguments, if any. + /// + /// This is a simple wrapper around creating a `RawCallBuilder` with the + /// data set to the bytecode concatenated with the constructor's + /// ABI-encoded arguments. #[inline] pub fn deploy_builder( provider: P, initialSettings: ::RustType, - initialOperators: alloy::sol_types::private::Vec< - alloy::sol_types::private::Address, - >, + initialOperators: alloy::sol_types::private::Vec, ) -> alloy_contract::RawCallBuilder { alloy_contract::RawCallBuilder::new_raw_deploy( provider, [ &BYTECODE[..], - &alloy_sol_types::SolConstructor::abi_encode( - &constructorCall { - initialSettings, - initialOperators, - }, - )[..], + &alloy_sol_types::SolConstructor::abi_encode(&constructorCall { + initialSettings, + initialOperators, + })[..], ] - .concat() - .into(), + .concat() + .into(), ) } /// Returns a reference to the address. @@ -6095,7 +5143,8 @@ the bytecode concatenated with the constructor's ABI-encoded arguments.*/ } } impl ClusterInstance { - /// Clones the provider and returns a new instance with the cloned provider. + /// Clones the provider and returns a new instance with the cloned + /// provider. #[inline] pub fn with_cloned_provider(self) -> ClusterInstance { ClusterInstance { @@ -6108,101 +5157,92 @@ the bytecode concatenated with the constructor's ABI-encoded arguments.*/ /// Function calls. #[automatically_derived] impl< - T: alloy_contract::private::Transport + ::core::clone::Clone, - P: alloy_contract::private::Provider, - N: alloy_contract::private::Network, - > ClusterInstance { - /// Creates a new call builder using this contract instance's provider and address. + T: alloy_contract::private::Transport + ::core::clone::Clone, + P: alloy_contract::private::Provider, + N: alloy_contract::private::Network, + > ClusterInstance + { + /// Creates a new call builder using this contract instance's provider + /// and address. /// - /// Note that the call can be any function call, not just those defined in this - /// contract. Prefer using the other methods for building type-safe contract calls. + /// Note that the call can be any function call, not just those defined + /// in this contract. Prefer using the other methods for + /// building type-safe contract calls. pub fn call_builder( &self, call: &C, ) -> alloy_contract::SolCallBuilder { alloy_contract::SolCallBuilder::new_sol(&self.provider, &self.address, call) } - ///Creates a new call builder for the [`abortMaintenance`] function. + /// Creates a new call builder for the [`abortMaintenance`] function. pub fn abortMaintenance( &self, ) -> alloy_contract::SolCallBuilder { self.call_builder(&abortMaintenanceCall {}) } - ///Creates a new call builder for the [`abortMigration`] function. + /// Creates a new call builder for the [`abortMigration`] function. pub fn abortMigration( &self, ) -> alloy_contract::SolCallBuilder { self.call_builder(&abortMigrationCall {}) } - ///Creates a new call builder for the [`completeMaintenance`] function. + /// Creates a new call builder for the [`completeMaintenance`] function. pub fn completeMaintenance( &self, ) -> alloy_contract::SolCallBuilder { self.call_builder(&completeMaintenanceCall {}) } - ///Creates a new call builder for the [`completeMigration`] function. + /// Creates a new call builder for the [`completeMigration`] function. pub fn completeMigration( &self, id: u64, operatorIdx: u8, ) -> alloy_contract::SolCallBuilder { - self.call_builder( - &completeMigrationCall { - id, - operatorIdx, - }, - ) + self.call_builder(&completeMigrationCall { id, operatorIdx }) } - ///Creates a new call builder for the [`getView`] function. + /// Creates a new call builder for the [`getView`] function. pub fn getView(&self) -> alloy_contract::SolCallBuilder { self.call_builder(&getViewCall {}) } - ///Creates a new call builder for the [`registerNodeOperator`] function. + /// Creates a new call builder for the [`registerNodeOperator`] + /// function. pub fn registerNodeOperator( &self, data: alloy::sol_types::private::Bytes, ) -> alloy_contract::SolCallBuilder { self.call_builder(®isterNodeOperatorCall { data }) } - ///Creates a new call builder for the [`startMaintenance`] function. + /// Creates a new call builder for the [`startMaintenance`] function. pub fn startMaintenance( &self, operatorIdx: u8, ) -> alloy_contract::SolCallBuilder { - self.call_builder( - &startMaintenanceCall { - operatorIdx, - }, - ) + self.call_builder(&startMaintenanceCall { operatorIdx }) } - ///Creates a new call builder for the [`startMigration`] function. + /// Creates a new call builder for the [`startMigration`] function. pub fn startMigration( &self, plan: ::RustType, ) -> alloy_contract::SolCallBuilder { self.call_builder(&startMigrationCall { plan }) } - ///Creates a new call builder for the [`transferOwnership`] function. + /// Creates a new call builder for the [`transferOwnership`] function. pub fn transferOwnership( &self, newOwner: alloy::sol_types::private::Address, ) -> alloy_contract::SolCallBuilder { self.call_builder(&transferOwnershipCall { newOwner }) } - ///Creates a new call builder for the [`updateNodeOperatorData`] function. + /// Creates a new call builder for the [`updateNodeOperatorData`] + /// function. pub fn updateNodeOperatorData( &self, operatorIdx: u8, data: alloy::sol_types::private::Bytes, ) -> alloy_contract::SolCallBuilder { - self.call_builder( - &updateNodeOperatorDataCall { - operatorIdx, - data, - }, - ) + self.call_builder(&updateNodeOperatorDataCall { operatorIdx, data }) } - ///Creates a new call builder for the [`updateSettings`] function. + /// Creates a new call builder for the [`updateSettings`] function. pub fn updateSettings( &self, newSettings: ::RustType, @@ -6213,62 +5253,63 @@ the bytecode concatenated with the constructor's ABI-encoded arguments.*/ /// Event filters. #[automatically_derived] impl< - T: alloy_contract::private::Transport + ::core::clone::Clone, - P: alloy_contract::private::Provider, - N: alloy_contract::private::Network, - > ClusterInstance { - /// Creates a new event filter using this contract instance's provider and address. + T: alloy_contract::private::Transport + ::core::clone::Clone, + P: alloy_contract::private::Provider, + N: alloy_contract::private::Network, + > ClusterInstance + { + /// Creates a new event filter using this contract instance's provider + /// and address. /// - /// Note that the type can be any event, not just those defined in this contract. - /// Prefer using the other methods for building type-safe event filters. + /// Note that the type can be any event, not just those defined in this + /// contract. Prefer using the other methods for building + /// type-safe event filters. pub fn event_filter( &self, ) -> alloy_contract::Event { alloy_contract::Event::new_sol(&self.provider, &self.address) } - ///Creates a new event filter for the [`MaintenanceAborted`] event. + /// Creates a new event filter for the [`MaintenanceAborted`] event. pub fn MaintenanceAborted_filter( &self, ) -> alloy_contract::Event { self.event_filter::() } - ///Creates a new event filter for the [`MaintenanceCompleted`] event. + /// Creates a new event filter for the [`MaintenanceCompleted`] event. pub fn MaintenanceCompleted_filter( &self, ) -> alloy_contract::Event { self.event_filter::() } - ///Creates a new event filter for the [`MaintenanceStarted`] event. + /// Creates a new event filter for the [`MaintenanceStarted`] event. pub fn MaintenanceStarted_filter( &self, ) -> alloy_contract::Event { self.event_filter::() } - ///Creates a new event filter for the [`MigrationAborted`] event. - pub fn MigrationAborted_filter( - &self, - ) -> alloy_contract::Event { + /// Creates a new event filter for the [`MigrationAborted`] event. + pub fn MigrationAborted_filter(&self) -> alloy_contract::Event { self.event_filter::() } - ///Creates a new event filter for the [`MigrationCompleted`] event. + /// Creates a new event filter for the [`MigrationCompleted`] event. pub fn MigrationCompleted_filter( &self, ) -> alloy_contract::Event { self.event_filter::() } - ///Creates a new event filter for the [`MigrationDataPullCompleted`] event. + /// Creates a new event filter for the [`MigrationDataPullCompleted`] + /// event. pub fn MigrationDataPullCompleted_filter( &self, ) -> alloy_contract::Event { self.event_filter::() } - ///Creates a new event filter for the [`MigrationStarted`] event. - pub fn MigrationStarted_filter( - &self, - ) -> alloy_contract::Event { + /// Creates a new event filter for the [`MigrationStarted`] event. + pub fn MigrationStarted_filter(&self) -> alloy_contract::Event { self.event_filter::() } - ///Creates a new event filter for the [`NodeOperatorDataUpdated`] event. + /// Creates a new event filter for the [`NodeOperatorDataUpdated`] + /// event. pub fn NodeOperatorDataUpdated_filter( &self, ) -> alloy_contract::Event { diff --git a/crates/cluster/src/smart_contract/evm/mod.rs b/crates/cluster/src/smart_contract/evm/mod.rs new file mode 100644 index 00000000..df949e53 --- /dev/null +++ b/crates/cluster/src/smart_contract/evm/mod.rs @@ -0,0 +1,119 @@ +use { + super::{PublicKey, Result, RpcUrl, Signer}, + crate::{node, node_operator, NewNodeOperator, Settings}, + alloy::providers::DynProvider, +}; + +#[rustfmt::skip] +mod bindings; + +#[derive(Clone)] +pub struct SmartContract( + bindings::Cluster::ClusterInstance<(), DynProvider, alloy::network::Ethereum>, +); + +pub(crate) type Address = alloy::primitives::Address; + +impl super::SmartContract for SmartContract { + type ReadOnly = Self; + + async fn deploy( + signer: Signer, + rpc_url: RpcUrl, + initial_settings: Settings, + initial_operators: Vec, + ) -> Result { + todo!() + + // let initial_settings = bindings::Cluster::Settings { + // maxOperatorDataBytes: 4096, + // }; + + // let initial_operators = initial_operators.into_iter().map(|key| + // key.0).collect(); + + // let smart_contract = bindings::Cluster::deploy( + // self.alloy_provider.clone(), + // initial_settings, + // initial_operators, + // ) + // .await?; + + // Ok(Manager { + // smart_contract, + // alloy_provider: self.alloy_provider, + // }) + } + + async fn connect(signer: Signer, rpc_url: RpcUrl) -> super::Result { + // let wallet: EthereumWallet = match signer.inner { + // SignerInner::PrivateKey(key) => key.into(), + // }; + + // let provider = ProviderBuilder::new().wallet(wallet).on_http(rpc_url.0); + + // Self { + // smart_contract: (), + // alloy_provider: DynProvider::new(provider), + // } + + todo!() + } + + async fn connect_ro(rpc_url: RpcUrl) -> Result { + todo!() + } + + fn signer(&self) -> PublicKey { + todo!() + } + + async fn start_migration(&self, plan: crate::migration::Plan) -> Result<()> { + todo!() + } + + async fn complete_migration( + &self, + id: crate::migration::Id, + operator_idx: node_operator::Idx, + ) -> super::Result<()> { + todo!() + } + + async fn abort_migration(&self, id: crate::migration::Id) -> Result<()> { + todo!() + } + + async fn start_maintenance(&self, operator_idx: node_operator::Idx) -> Result<()> { + todo!() + } + + async fn complete_maintenance(&self) -> Result<()> { + todo!() + } + + async fn abort_maintenance(&self) -> Result<()> { + todo!() + } + + async fn update_node_operator( + &self, + id: node_operator::Id, + idx: node_operator::Idx, + data: node_operator::SerializedData, + ) -> super::Result<()> { + todo!() + } +} + +impl super::ReadOnlySmartContract for SmartContract { + async fn cluster_view(&self) -> super::Result { + std::todo!() + // let view = self.inner.getView().call().await?._0; + + // Ok(ClusterView { + // keyspace: + // Keyspace::new(view.keyspace.replicationStrategy.try_into().unwrap()), + // }) + } +} diff --git a/crates/cluster/src/smart_contract/mod.rs b/crates/cluster/src/smart_contract/mod.rs new file mode 100644 index 00000000..7a920a2d --- /dev/null +++ b/crates/cluster/src/smart_contract/mod.rs @@ -0,0 +1,237 @@ +pub mod evm; + +mod operator_data; + +use { + crate::{migration, node_operator, NewNodeOperator, Settings, View as ClusterView}, + alloy::{signers::local::PrivateKeySigner, transports::http::reqwest}, + derive_more::derive::Display, + serde::{Deserialize, Serialize}, + std::str::FromStr, +}; + +/// Handle to a smart-contract managing the state of a WCN cluster. +/// +/// Logic invariants documented on the methods of this trait MUST be +/// implemented inside the on-chain implementation of the smart-contract itself. +pub trait SmartContract: ReadOnlySmartContract { + type ReadOnly: ReadOnlySmartContract; + + /// Deploys a new smart-contract. + async fn deploy( + signer: Signer, + rpc_url: RpcUrl, + initial_settings: Settings, + initial_operators: Vec, + ) -> Result; + + /// Connects to an existing smart-contract. + async fn connect(signer: Signer, rpc_url: RpcUrl) -> Result; + + /// Connects to an existing smart-contract in read-only mode. + async fn connect_ro(rpc_url: RpcUrl) -> Result; + + /// Returns the [`PublicKey`] of the [`Signer`] which is currently being + /// used for this [`SmartContract`] handle. + fn signer(&self) -> PublicKey; + + /// Starts a new data [`migration`] process using the provided + /// [`migration::Plan`]. + /// + /// The implementation MUST validate the following invariants: + /// - there's no ongoing data migration + /// - there's no ongoing maintenance + /// - [`signer`](SmartContract::signer) is the owner of the + /// [`SmartContract`] + /// + /// The implementation MUST emit [`migration::Started`] event on success. + async fn start_migration(&self, plan: migration::Plan) -> Result<()>; + + /// Marks that the [`signer`](SmartContract::signer) has completed the data + /// pull required for completion of the current [`migration`]. + /// + /// The implementation MUST validate the following invariants: + /// - there's an ongoing data migration + /// - the provided [`migration::Id`] matches the ID of the migration + /// - [`signer`](Smart::signer) is a [`node::Operator`] under the provided + /// [`node::OperatorIdx`] + /// + /// If this [`node::Operator`] is the last remaining one left to complete + /// the data pull then the migration MUST be completed and + /// [`migration::Completed`] event MUST be emitted. + /// Otherwise the data pull MUST be marked as completed for the + /// [`node::Operator`] and [`migration::DataPullCompleted`] MUST be emitted. + /// + /// The implementation MAY be idempotent. In case of an idempotent + /// execution the event MUST not be emitted. + async fn complete_migration( + &self, + id: migration::Id, + operator_idx: node_operator::Idx, + ) -> Result<()>; + + /// Aborts the ongoing data [`migration`] process restoring the WCN cluster + /// to the original state it had before the migration had started. + /// + /// The implementation MUST validate the following invariants: + /// - there's an ongoing data migration + /// - [`signer`](SmartContract::signer) is the owner of the + /// [`SmartContract`] + /// + /// The implementation MUST emit [`migration::Aborted`] event on success. + async fn abort_migration(&self, id: migration::Id) -> Result<()>; + + /// Starts a [`maintenance`] process for the [`node::Operator`] being the + /// current [`signer`](Manager::signer). + /// + /// The implementation MUST validate the following invariants: + /// - there's no ongoing data migration + /// - there's no ongoing maintenance + /// - [`signer`](SmartContract::signer) is a [`node::Operator`] under the + /// provided [`node::OperatorIdx`] + /// + /// The implementation MUST emit [`maintenance::Started`] event on success. + async fn start_maintenance(&self, operator_idx: node_operator::Idx) -> Result<()>; + + /// Completes the ongoing [`maintenance`] process. + /// + /// The implementation MUST validate the following invariants: + /// - there's an ongoing maintenance + /// - [`signer`](SmartContract::signer) is the one who + /// [started](Manager::start_maintenance) the maintenance + /// + /// The implementation MUST emit [`maintenance::Completed`] event on + /// success. + async fn complete_maintenance(&self) -> Result<()>; + + /// Aborts the ongoing [`maintenance`] process. + /// + /// The implementation MUST validate the following invariants: + /// - there's an ongoing maintenance + /// - [`signer`](SmartContract::signer) is the owner of the + /// [`SmartContract`] + /// + /// The implementation MUST emit [`maintenance::Aborted`] event on success. + async fn abort_maintenance(&self) -> Result<()>; + + /// Updates on-chain data of a [`node::Operator`]. + /// + /// The implementation MUST validate the following invariants: + /// - [`signer`](SmartContract::signer) is a [`node::Operator`] under the + /// provided [`node::OperatorIdx`] + /// + /// The implementation MUST emit [`node::OperatorUpdated`] event on success. + async fn update_node_operator( + &self, + id: node_operator::Id, + idx: node_operator::Idx, + data: node_operator::SerializedData, + ) -> Result<()>; +} + +/// Read-only handle to a smart-contract managing the state of a WCN cluster. +pub trait ReadOnlySmartContract: Sized + Send + Sync + 'static { + /// Returns the current [`ClusterView`]. + async fn cluster_view(&self) -> Result; +} + +// impl From for Error { +// fn from(err: alloy::contract::Error) -> Self { +// Self(format!("{err:?}")) +// } +// } + +/// [`SmartContract`] error. +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("Revert: {0}")] + Revert(String), + + #[error("Other: {0}")] + Other(String), +} + +/// [`ReadOnlySmartContract`] error. +#[derive(Debug, thiserror::Error)] +#[error("{0}")] +pub struct ReadError(String); + +pub type Result = std::result::Result; + +pub type ReadResult = std::result::Result; + +#[derive(Clone, Debug, Display, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub struct PublicKey(evm::Address); + +impl FromStr for PublicKey { + type Err = InvalidPublicKey; + + fn from_str(s: &str) -> Result { + alloy::primitives::Address::from_str(s) + .map(PublicKey) + .map_err(|err| InvalidPublicKey(err.to_string())) + } +} + +pub struct Signer { + inner: SignerInner, +} + +impl Signer { + pub fn try_from_private_key(hex: &str) -> Result { + PrivateKeySigner::from_str(hex) + .map(SignerInner::PrivateKey) + .map(|inner| Self { inner }) + .map_err(|err| InvalidPrivateKey(err.to_string())) + } +} + +enum SignerInner { + PrivateKey(PrivateKeySigner), +} + +pub struct RpcUrl(reqwest::Url); + +impl FromStr for RpcUrl { + type Err = InvalidRpcUrl; + + fn from_str(s: &str) -> Result { + reqwest::Url::from_str(s) + .map(Self) + .map_err(|err| InvalidRpcUrl(err.to_string())) + } +} + +#[derive(Debug, thiserror::Error)] +#[error("Invalid RPC URL: {0:?}")] +pub struct InvalidRpcUrl(String); + +#[derive(Debug, thiserror::Error)] +#[error("Invalid private key: {0:?}")] +pub struct InvalidPrivateKey(String); + +#[derive(Debug, thiserror::Error)] +#[error("Invalid public key: {0:?}")] +pub struct InvalidPublicKey(String); + +// impl TryFrom for Keyspace { +// type Error = Error; + +// fn try_from(view: bindings::Cluster::KeyspaceView) -> Result { +// let replication_strategy = view +// .replicationStrategy +// .try_into() +// .map_err(|err| Error(format!("Invalid ReplicationStrategy: +// {err}")))?; + +// Ok(Keyspace::new(replication_strategy)) +// } +// } + +// #[cfg(test)] +// mod test { +// #[test] +// fn address_to_from_public_key_conversion() { +// todo!() +// } +// } diff --git a/crates/cluster/src/smart_contract/operator_data.rs b/crates/cluster/src/smart_contract/operator_data.rs new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/crates/cluster/src/smart_contract/operator_data.rs @@ -0,0 +1 @@ + From 3c96b1cb20fad94ee28e29c769f712b79958534f Mon Sep 17 00:00:00 2001 From: Github Bot Date: Mon, 26 May 2025 21:38:03 +0000 Subject: [PATCH 21/79] Bump VERSION to 250526.0 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 2dc6aad7..3cb3ed85 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -250520.0 +250526.0 From 1c45587aef81469c40600c8a2f647aaacdd92835 Mon Sep 17 00:00:00 2001 From: Darksome Date: Tue, 27 May 2025 21:26:14 +0000 Subject: [PATCH 22/79] upgrade alloy to 1.0 & use sol! macro to generate bindings --- Cargo.lock | 246 +- contracts/src/Cluster.sol | 2 +- crates/cluster/Cargo.toml | 4 +- .../src/smart_contract/{evm/mod.rs => evm.rs} | 14 +- .../src/smart_contract/evm/bindings/mod.rs | 5319 ----------------- crates/cluster/src/smart_contract/mod.rs | 2 - .../src/smart_contract/operator_data.rs | 1 - 7 files changed, 168 insertions(+), 5420 deletions(-) rename crates/cluster/src/smart_contract/{evm/mod.rs => evm.rs} (91%) delete mode 100644 crates/cluster/src/smart_contract/evm/bindings/mod.rs delete mode 100644 crates/cluster/src/smart_contract/operator_data.rs diff --git a/Cargo.lock b/Cargo.lock index a0a2f2d5..9577016a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -99,9 +99,9 @@ checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" [[package]] name = "alloy" -version = "0.13.0" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "239e728d663a3bdababa24dfdc697faec987593161c5ff54d72ee01df6721d59" +checksum = "ca940218f168ba7dd97c22fccd3055e9f2ff463bd5aededf614f1fba71c90648" dependencies = [ "alloy-consensus", "alloy-contract", @@ -121,9 +121,9 @@ dependencies = [ [[package]] name = "alloy-chains" -version = "0.1.69" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28e2652684758b0d9b389d248b209ed9fd9989ef489a550265fe4bb8454fe7eb" +checksum = "517e5acbd38b6d4c59da380e8bbadc6d365bf001903ce46cf5521c53c647e07b" dependencies = [ "alloy-primitives", "num_enum", @@ -132,9 +132,9 @@ dependencies = [ [[package]] name = "alloy-consensus" -version = "0.13.0" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27d301f5bcfd37e3aac727c360d8b50c33ddff9169ce0370198dedda36a9927d" +checksum = "78090ff96d0d1b648dbcebc63b5305296b76ad4b5d4810f755d7d1224ced6247" dependencies = [ "alloy-eips", "alloy-primitives", @@ -148,6 +148,7 @@ dependencies = [ "k256", "once_cell", "rand 0.8.5", + "secp256k1", "serde", "serde_with", "thiserror 2.0.12", @@ -155,9 +156,9 @@ dependencies = [ [[package]] name = "alloy-consensus-any" -version = "0.13.0" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f4f97a85a45965e0e4f9f5b94bbafaa3e4ee6868bdbcf2e4a9acb4b358038fe" +checksum = "bcdfc3b2f202e3c6284685e6d3dcfbb532b39552d9e1021276e68e2389037616" dependencies = [ "alloy-consensus", "alloy-eips", @@ -169,9 +170,9 @@ dependencies = [ [[package]] name = "alloy-contract" -version = "0.13.0" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f39e8b96c9e25dde7222372332489075f7e750e4fd3e81c11eec0939b78b71b8" +checksum = "6f4a5b6c7829e8aa048f5b23defa21706b675e68e612cf88d9f509771fecc806" dependencies = [ "alloy-consensus", "alloy-dyn-abi", @@ -190,9 +191,9 @@ dependencies = [ [[package]] name = "alloy-core" -version = "0.8.25" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d8bcce99ad10fe02640cfaec1c6bc809b837c783c1d52906aa5af66e2a196f6" +checksum = "a3c5a28f166629752f2e7246b813cdea3243cca59aab2d4264b1fd68392c10eb" dependencies = [ "alloy-dyn-abi", "alloy-json-abi", @@ -202,15 +203,14 @@ dependencies = [ [[package]] name = "alloy-dyn-abi" -version = "0.8.25" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb8e762aefd39a397ff485bc86df673465c4ad3ec8819cc60833a8a3ba5cdc87" +checksum = "18cc14d832bc3331ca22a1c7819de1ede99f58f61a7d123952af7dde8de124a6" dependencies = [ "alloy-json-abi", "alloy-primitives", "alloy-sol-type-parser", "alloy-sol-types", - "const-hex", "itoa", "serde", "serde_json", @@ -219,9 +219,9 @@ dependencies = [ [[package]] name = "alloy-eip2124" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "675264c957689f0fd75f5993a73123c2cc3b5c235a38f5b9037fe6c826bfb2c0" +checksum = "741bdd7499908b3aa0b159bba11e71c8cddd009a2c2eb7a06e825f1ec87900a5" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -232,9 +232,9 @@ dependencies = [ [[package]] name = "alloy-eip2930" -version = "0.1.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0069cf0642457f87a01a014f6dc29d5d893cd4fd8fddf0c3cdfad1bb3ebafc41" +checksum = "7b82752a889170df67bbb36d42ca63c531eb16274f0d7299ae2a680facba17bd" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -243,9 +243,9 @@ dependencies = [ [[package]] name = "alloy-eip7702" -version = "0.5.1" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b15b13d38b366d01e818fe8e710d4d702ef7499eacd44926a06171dd9585d0c" +checksum = "9d4769c6ffddca380b0070d71c8b7f30bed375543fe76bb2f74ec0acf4b7cd16" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -255,9 +255,9 @@ dependencies = [ [[package]] name = "alloy-eips" -version = "0.13.0" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10b11c382ca8075128d1ae6822b60921cf484c911d9a5831797a01218f98125f" +checksum = "5fb7646210355c36b07886c91cac52e4727191e2b0ee1415cce8f953f6019dd2" dependencies = [ "alloy-eip2124", "alloy-eip2930", @@ -275,9 +275,9 @@ dependencies = [ [[package]] name = "alloy-genesis" -version = "0.13.0" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bd9e75c5dd40319ebbe807ebe9dfb10c24e4a70d9c7d638e62921d8dd093c8b" +checksum = "85b14b506d7a4f739dd57ad5026d65eb64d842f4e971f71da5e9be5067ecbdc9" dependencies = [ "alloy-eips", "alloy-primitives", @@ -288,9 +288,9 @@ dependencies = [ [[package]] name = "alloy-hardforks" -version = "0.1.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "473ee2ab7f5262b36e8fbc1b5327d5c9d488ab247e31ac739b929dbe2444ae79" +checksum = "fbff8445282ec080c2673692062bd4930d7a0d6bda257caf138cfc650c503000" dependencies = [ "alloy-chains", "alloy-eip2124", @@ -301,9 +301,9 @@ dependencies = [ [[package]] name = "alloy-json-abi" -version = "0.8.25" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe6beff64ad0aa6ad1019a3db26fef565aefeb011736150ab73ed3366c3cfd1b" +checksum = "3ccaa79753d7bf15f06399ea76922afbfaf8d18bebed9e8fc452984b4a90dcc9" dependencies = [ "alloy-primitives", "alloy-sol-type-parser", @@ -313,9 +313,9 @@ dependencies = [ [[package]] name = "alloy-json-rpc" -version = "0.13.0" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbcf26d02a72e23d5bc245425ea403c93ba17d254f20f9c23556a249c6c7e143" +checksum = "7a7ed339a633ba1a2af3eb9847dc90936d1b3c380a223cfca7a45be1713d8ab0" dependencies = [ "alloy-primitives", "alloy-sol-types", @@ -327,9 +327,9 @@ dependencies = [ [[package]] name = "alloy-network" -version = "0.13.0" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b44dd4429e190f727358571175ebf323db360a303bf4e1731213f510ced1c2e6" +checksum = "691a4825b3d08f031b49aae3c11cb35abf2af376fc11146bf8e5930a432dbf40" dependencies = [ "alloy-consensus", "alloy-consensus-any", @@ -353,9 +353,9 @@ dependencies = [ [[package]] name = "alloy-network-primitives" -version = "0.13.0" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86f736e1d1eb1b770dbd32919bdf46d4dcd4617f2eed07947dfb32649962baba" +checksum = "5713f40f9cbe4428292d095e8bbb38af82e63ad4247418b7f6d6fb7ef2d9d68b" dependencies = [ "alloy-consensus", "alloy-eips", @@ -366,9 +366,9 @@ dependencies = [ [[package]] name = "alloy-node-bindings" -version = "0.13.0" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10f33291f6b969268b04b8f96ffab5071b3c241e593dd462372288b069787375" +checksum = "88c4a039f33025c4f4a88c121ce59f0b09a7ec159ac76c843dfb96a663cc48e8" dependencies = [ "alloy-genesis", "alloy-hardforks", @@ -387,9 +387,9 @@ dependencies = [ [[package]] name = "alloy-primitives" -version = "0.8.25" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c77490fe91a0ce933a1f219029521f20fc28c2c0ca95d53fa4da9c00b8d9d4e" +checksum = "18c35fc4b03ace65001676358ffbbaefe2a2b27ee50fe777c345082c7c888be8" dependencies = [ "alloy-rlp", "bytes", @@ -404,7 +404,7 @@ dependencies = [ "keccak-asm", "paste", "proptest", - "rand 0.8.5", + "rand 0.9.1", "ruint", "rustc-hash 2.1.1", "serde", @@ -414,9 +414,9 @@ dependencies = [ [[package]] name = "alloy-provider" -version = "0.13.0" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a557f9e3ec89437b06db3bfc97d20782b1f7cc55b5b602b6a82bf3f64d7efb0e" +checksum = "1382ef9e0fa1ab3f5a3dbc0a0fa1193f3794d5c9d75fc22654bb6da1cf7a59cc" dependencies = [ "alloy-chains", "alloy-consensus", @@ -477,9 +477,9 @@ dependencies = [ [[package]] name = "alloy-rpc-client" -version = "0.13.0" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cec6dc89c4c3ef166f9fa436d1831f8142c16cf2e637647c936a6aaaabd8d898" +checksum = "859ec46fb132175969a0101bdd2fe9ecd413c40feeb0383e98710a4a089cee77" dependencies = [ "alloy-json-rpc", "alloy-primitives", @@ -502,9 +502,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types" -version = "0.13.0" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3849f8131a18cc5d7f95f301d68a6af5aa2db28ad8522fb9db1f27b3794e8b68" +checksum = "9f1512ec542339a72c263570644a56d685f20ce77be465fbd3f3f33fb772bcbd" dependencies = [ "alloy-primitives", "alloy-rpc-types-anvil", @@ -515,9 +515,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-anvil" -version = "0.13.0" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19051fd5e8de7e1f95ec228c9303debd776dcc7caf8d1ece3191f711f5c06541" +checksum = "e284bffcdd934f924c710fdec402b7482f9fa1c6e9923fdfb6069106e832d525" dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", @@ -527,9 +527,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-any" -version = "0.13.0" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecd6d480e4e6e456f30eeeb3aef1512aaecb68df2a35d1f78865dbc4d20dc0fd" +checksum = "d87236623aafabbf7196bcde37a4d626c3e56b3b22d787310e6d5ea25239c5d8" dependencies = [ "alloy-consensus-any", "alloy-rpc-types-eth", @@ -538,9 +538,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-eth" -version = "0.13.0" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a8b6d55bdaa0c4a08650d4b32f174494cbade56adf6f2fcfa2a4f3490cb5511" +checksum = "9b8acc64d23e484a0a27375b57caba34569729560a29aa366933f0ae07b7786f" dependencies = [ "alloy-consensus", "alloy-consensus-any", @@ -558,9 +558,9 @@ dependencies = [ [[package]] name = "alloy-serde" -version = "0.13.0" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1824791912f468a481dedc1db50feef3e85a078f6d743a62db2ee9c2ca674882" +checksum = "114c287eb4595f1e0844800efb0860dd7228fcf9bc77d52e303fb7a43eb766b2" dependencies = [ "alloy-primitives", "serde", @@ -569,9 +569,9 @@ dependencies = [ [[package]] name = "alloy-signer" -version = "0.13.0" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d087fe5aea96a93fbe71be8aaed5c57c3caac303c09e674bc5b1647990d648b" +checksum = "afebd60fa84d9ce793326941509d8f26ce7b383f2aabd7a42ba215c1b92ea96b" dependencies = [ "alloy-primitives", "async-trait", @@ -584,9 +584,9 @@ dependencies = [ [[package]] name = "alloy-signer-local" -version = "0.13.0" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2940353d2425bb75965cd5101075334e6271051e35610f903bf8099a52b0b1a9" +checksum = "f551042c11c4fa7cb8194d488250b8dc58035241c418d79f07980c4aee4fa5c9" dependencies = [ "alloy-consensus", "alloy-network", @@ -600,9 +600,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro" -version = "0.8.25" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e10ae8e9a91d328ae954c22542415303919aabe976fe7a92eb06db1b68fd59f2" +checksum = "8612e0658964d616344f199ab251a49d48113992d81b92dab93ed855faa66383" dependencies = [ "alloy-sol-macro-expander", "alloy-sol-macro-input", @@ -614,9 +614,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro-expander" -version = "0.8.25" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83ad5da86c127751bc607c174d6c9fe9b85ef0889a9ca0c641735d77d4f98f26" +checksum = "7a384edac7283bc4c010a355fb648082860c04b826bb7a814c45263c8f304c74" dependencies = [ "alloy-json-abi", "alloy-sol-macro-input", @@ -633,9 +633,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro-input" -version = "0.8.25" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3d30f0d3f9ba3b7686f3ff1de9ee312647aac705604417a2f40c604f409a9e" +checksum = "0dd588c2d516da7deb421b8c166dc60b7ae31bca5beea29ab6621fcfa53d6ca5" dependencies = [ "alloy-json-abi", "const-hex", @@ -651,9 +651,9 @@ dependencies = [ [[package]] name = "alloy-sol-type-parser" -version = "0.8.25" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d162f8524adfdfb0e4bd0505c734c985f3e2474eb022af32eef0d52a4f3935c" +checksum = "e86ddeb70792c7ceaad23e57d52250107ebbb86733e52f4a25d8dc1abc931837" dependencies = [ "serde", "winnow 0.7.10", @@ -661,24 +661,24 @@ dependencies = [ [[package]] name = "alloy-sol-types" -version = "0.8.25" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d43d5e60466a440230c07761aa67671d4719d46f43be8ea6e7ed334d8db4a9ab" +checksum = "584cb97bfc5746cb9dcc4def77da11694b5d6d7339be91b7480a6a68dc129387" dependencies = [ "alloy-json-abi", "alloy-primitives", "alloy-sol-macro", - "const-hex", "serde", ] [[package]] name = "alloy-transport" -version = "0.13.0" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6818b4c82a474cc01ac9e88ccfcd9f9b7bc893b2f8aea7e890a28dcd55c0a7aa" +checksum = "46fb766c0bce9f62779a83048ca6d998c2ced4153d694027c66e537629f4fd61" dependencies = [ "alloy-json-rpc", + "alloy-primitives", "base64 0.22.1", "derive_more 2.0.1", "futures", @@ -696,9 +696,9 @@ dependencies = [ [[package]] name = "alloy-transport-http" -version = "0.13.0" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cc3079a33483afa1b1365a3add3ea3e21c75b10f704870198ba7846627d10f2" +checksum = "254bd59ca1abaf2da3e3201544a41924163b019414cce16f0dc6bc75d20c6612" dependencies = [ "alloy-json-rpc", "alloy-transport", @@ -711,14 +711,14 @@ dependencies = [ [[package]] name = "alloy-trie" -version = "0.7.9" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d95a94854e420f07e962f7807485856cde359ab99ab6413883e15235ad996e8b" +checksum = "983d99aa81f586cef9dae38443245e585840fcf0fc58b09aee0b1f27aed1d500" dependencies = [ "alloy-primitives", "alloy-rlp", "arrayvec", - "derive_more 1.0.0", + "derive_more 2.0.1", "nybbles", "serde", "smallvec", @@ -1284,6 +1284,22 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" +[[package]] +name = "bitcoin-io" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b47c4ab7a93edb0c7198c5535ed9b52b63095f4e9b45279c6736cec4b856baf" + +[[package]] +name = "bitcoin_hashes" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb18c03d0db0247e147a21a6faafd5a7eb851c743db062de72018b6b7e8e4d16" +dependencies = [ + "bitcoin-io", + "hex-conservative", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -2480,9 +2496,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.8" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18" dependencies = [ "libc", "windows-sys 0.52.0", @@ -2515,9 +2531,9 @@ checksum = "a2a2b11eda1d40935b26cf18f6833c526845ae8c41e58d09af6adeb6f0269183" [[package]] name = "fastrand" -version = "2.0.2" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "fastrlp" @@ -3100,7 +3116,7 @@ dependencies = [ "itoa", "libc", "memmap2", - "rustix", + "rustix 0.38.32", "smallvec", "thiserror 1.0.64", ] @@ -3508,6 +3524,15 @@ dependencies = [ "serde", ] +[[package]] +name = "hex-conservative" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5313b072ce3c597065a808dbf612c4c8e8590bdbf8b579508bf7a762c5eae6cd" +dependencies = [ + "arrayvec", +] + [[package]] name = "hex_fmt" version = "0.3.0" @@ -4283,6 +4308,12 @@ version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +[[package]] +name = "linux-raw-sys" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" + [[package]] name = "lock_api" version = "0.4.11" @@ -5411,6 +5442,7 @@ checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.3", + "serde", ] [[package]] @@ -5468,6 +5500,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ "getrandom 0.3.3", + "serde", ] [[package]] @@ -5865,7 +5898,20 @@ dependencies = [ "bitflags 2.6.0", "errno", "libc", - "linux-raw-sys", + "linux-raw-sys 0.4.13", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustix" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" +dependencies = [ + "bitflags 2.6.0", + "errno", + "libc", + "linux-raw-sys 0.9.4", "windows-sys 0.52.0", ] @@ -6049,6 +6095,27 @@ dependencies = [ "zeroize", ] +[[package]] +name = "secp256k1" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b50c5943d326858130af85e049f2661ba3c78b26589b8ab98e65e80ae44a1252" +dependencies = [ + "bitcoin_hashes", + "rand 0.8.5", + "secp256k1-sys", + "serde", +] + +[[package]] +name = "secp256k1-sys" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4387882333d3aa8cb20530a17c69a3752e97837832f34f6dccc760e715001d9" +dependencies = [ + "cc", +] + [[package]] name = "security-framework" version = "2.11.1" @@ -6506,9 +6573,9 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "0.8.25" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4560533fbd6914b94a8fb5cc803ed6801c3455668db3b810702c57612bac9412" +checksum = "1b5d879005cc1b5ba4e18665be9e9501d9da3a9b95f625497c4cb7ee082b532e" dependencies = [ "paste", "proc-macro2", @@ -6568,13 +6635,14 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.10.1" +version = "3.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" dependencies = [ - "cfg-if", "fastrand", - "rustix", + "getrandom 0.3.3", + "once_cell", + "rustix 1.0.7", "windows-sys 0.52.0", ] @@ -7839,7 +7907,7 @@ dependencies = [ "either", "home", "once_cell", - "rustix", + "rustix 0.38.32", ] [[package]] diff --git a/contracts/src/Cluster.sol b/contracts/src/Cluster.sol index 45afef62..7e24f80d 100644 --- a/contracts/src/Cluster.sol +++ b/contracts/src/Cluster.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; -import '../dependencies/openzeppelin-contracts/contracts/utils/math/Math.sol'; +// import '../dependencies/openzeppelin-contracts/contracts/utils/math/Math.sol'; struct Settings { uint16 maxOperatorDataBytes; diff --git a/crates/cluster/Cargo.toml b/crates/cluster/Cargo.toml index c739fdc0..c9efe68c 100644 --- a/crates/cluster/Cargo.toml +++ b/crates/cluster/Cargo.toml @@ -13,7 +13,7 @@ itertools = { workspace = true } sharding = { path = "../sharding" } -alloy = { version = "0.13", default-features = false, features = ["sol-types", "contract", "signer-local", "network", "reqwest"] } +alloy = { version = "1.0", default-features = false, features = ["sol-types", "contract", "signer-local", "network", "reqwest"] } anyhow = "1" thiserror = "1" @@ -30,5 +30,5 @@ tokio = { version = "1", features = ["full"] } arc-swap = "1.7" [dev-dependencies] -alloy = { version = "0.13", default-features = false, features = ["provider-anvil-node"] } +alloy = { version = "1.0", default-features = false, features = ["provider-anvil-node"] } tokio = { version = "1", default-features = false } diff --git a/crates/cluster/src/smart_contract/evm/mod.rs b/crates/cluster/src/smart_contract/evm.rs similarity index 91% rename from crates/cluster/src/smart_contract/evm/mod.rs rename to crates/cluster/src/smart_contract/evm.rs index df949e53..8b4dc197 100644 --- a/crates/cluster/src/smart_contract/evm/mod.rs +++ b/crates/cluster/src/smart_contract/evm.rs @@ -1,16 +1,18 @@ use { super::{PublicKey, Result, RpcUrl, Signer}, crate::{node, node_operator, NewNodeOperator, Settings}, - alloy::providers::DynProvider, + alloy::{providers::DynProvider, sol, sol_types::SolConstructor}, }; -#[rustfmt::skip] -mod bindings; +mod bindings { + alloy::sol!( + #[sol(rpc)] + "../../contracts/src/Cluster.sol" + ); +} #[derive(Clone)] -pub struct SmartContract( - bindings::Cluster::ClusterInstance<(), DynProvider, alloy::network::Ethereum>, -); +pub struct SmartContract(bindings::Cluster::ClusterInstance); pub(crate) type Address = alloy::primitives::Address; diff --git a/crates/cluster/src/smart_contract/evm/bindings/mod.rs b/crates/cluster/src/smart_contract/evm/bindings/mod.rs deleted file mode 100644 index 5f4872e6..00000000 --- a/crates/cluster/src/smart_contract/evm/bindings/mod.rs +++ /dev/null @@ -1,5319 +0,0 @@ -#![allow(unused_imports, clippy::all, rustdoc::all)] -//! This module contains the sol! generated bindings for solidity contracts. -//! This is autogenerated code. -//! Do not manually edit these files. -//! These files may be overwritten by the codegen system at any time. -/// Generated by the following Solidity interface... -/// ```solidity -/// interface Cluster { -/// struct ClusterView { -/// KeyspaceView keyspace; -/// Migration migration; -/// KeyspaceView migrationKeyspace; -/// Maintenance maintenance; -/// uint64 keyspaceVersion; -/// uint128 version; -/// } -/// struct KeyspaceSlot { -/// uint8 idx; -/// address operator; -/// } -/// struct KeyspaceView { -/// NodeOperator[] operators; -/// uint8 replicationStrategy; -/// } -/// struct Maintenance { -/// address slot; -/// } -/// struct Migration { -/// uint64 id; -/// uint256 pullingOperatorsBitmask; -/// } -/// struct MigrationPlan { -/// KeyspaceSlot[] slots; -/// uint8 replicationStrategy; -/// } -/// struct NodeOperator { -/// address addr; -/// bytes data; -/// } -/// struct Settings { -/// uint16 maxOperatorDataBytes; -/// } -/// -/// event MaintenanceAborted(uint128 clusterVersion); -/// event MaintenanceCompleted(address operatorAddress, uint128 clusterVersion); -/// event MaintenanceStarted(address operatorAddress, uint128 clusterVersion); -/// event MigrationAborted(uint64 id, uint128 clusterVersion); -/// event MigrationCompleted(uint64 id, address operatorAddress, uint128 clusterVersion); -/// event MigrationDataPullCompleted(uint64 id, address operatorAddress, uint128 clusterVersion); -/// event MigrationStarted(uint64 id, MigrationPlan plan, uint128 clusterVersion); -/// event NodeOperatorDataUpdated(address operatorAddress, bytes data, uint128 clusterVersion); -/// -/// constructor(Settings initialSettings, address[] initialOperators); -/// -/// function abortMaintenance() external; -/// function abortMigration() external; -/// function completeMaintenance() external; -/// function completeMigration(uint64 id, uint8 operatorIdx) external; -/// function getView() external view returns (ClusterView memory); -/// function registerNodeOperator(bytes memory data) external; -/// function startMaintenance(uint8 operatorIdx) external; -/// function startMigration(MigrationPlan memory plan) external; -/// function transferOwnership(address newOwner) external; -/// function updateNodeOperatorData(uint8 operatorIdx, bytes memory data) external; -/// function updateSettings(Settings memory newSettings) external; -/// } -/// ``` -/// -/// ...which was generated by the following JSON ABI: -/// ```json -/// [ -/// { -/// "type": "constructor", -/// "inputs": [ -/// { -/// "name": "initialSettings", -/// "type": "tuple", -/// "internalType": "struct Settings", -/// "components": [ -/// { -/// "name": "maxOperatorDataBytes", -/// "type": "uint16", -/// "internalType": "uint16" -/// } -/// ] -/// }, -/// { -/// "name": "initialOperators", -/// "type": "address[]", -/// "internalType": "address[]" -/// } -/// ], -/// "stateMutability": "nonpayable" -/// }, -/// { -/// "type": "function", -/// "name": "abortMaintenance", -/// "inputs": [], -/// "outputs": [], -/// "stateMutability": "nonpayable" -/// }, -/// { -/// "type": "function", -/// "name": "abortMigration", -/// "inputs": [], -/// "outputs": [], -/// "stateMutability": "nonpayable" -/// }, -/// { -/// "type": "function", -/// "name": "completeMaintenance", -/// "inputs": [], -/// "outputs": [], -/// "stateMutability": "nonpayable" -/// }, -/// { -/// "type": "function", -/// "name": "completeMigration", -/// "inputs": [ -/// { -/// "name": "id", -/// "type": "uint64", -/// "internalType": "uint64" -/// }, -/// { -/// "name": "operatorIdx", -/// "type": "uint8", -/// "internalType": "uint8" -/// } -/// ], -/// "outputs": [], -/// "stateMutability": "nonpayable" -/// }, -/// { -/// "type": "function", -/// "name": "getView", -/// "inputs": [], -/// "outputs": [ -/// { -/// "name": "", -/// "type": "tuple", -/// "internalType": "struct ClusterView", -/// "components": [ -/// { -/// "name": "keyspace", -/// "type": "tuple", -/// "internalType": "struct KeyspaceView", -/// "components": [ -/// { -/// "name": "operators", -/// "type": "tuple[]", -/// "internalType": "struct NodeOperator[]", -/// "components": [ -/// { -/// "name": "addr", -/// "type": "address", -/// "internalType": "address" -/// }, -/// { -/// "name": "data", -/// "type": "bytes", -/// "internalType": "bytes" -/// } -/// ] -/// }, -/// { -/// "name": "replicationStrategy", -/// "type": "uint8", -/// "internalType": "uint8" -/// } -/// ] -/// }, -/// { -/// "name": "migration", -/// "type": "tuple", -/// "internalType": "struct Migration", -/// "components": [ -/// { -/// "name": "id", -/// "type": "uint64", -/// "internalType": "uint64" -/// }, -/// { -/// "name": "pullingOperatorsBitmask", -/// "type": "uint256", -/// "internalType": "uint256" -/// } -/// ] -/// }, -/// { -/// "name": "migrationKeyspace", -/// "type": "tuple", -/// "internalType": "struct KeyspaceView", -/// "components": [ -/// { -/// "name": "operators", -/// "type": "tuple[]", -/// "internalType": "struct NodeOperator[]", -/// "components": [ -/// { -/// "name": "addr", -/// "type": "address", -/// "internalType": "address" -/// }, -/// { -/// "name": "data", -/// "type": "bytes", -/// "internalType": "bytes" -/// } -/// ] -/// }, -/// { -/// "name": "replicationStrategy", -/// "type": "uint8", -/// "internalType": "uint8" -/// } -/// ] -/// }, -/// { -/// "name": "maintenance", -/// "type": "tuple", -/// "internalType": "struct Maintenance", -/// "components": [ -/// { -/// "name": "slot", -/// "type": "address", -/// "internalType": "address" -/// } -/// ] -/// }, -/// { -/// "name": "keyspaceVersion", -/// "type": "uint64", -/// "internalType": "uint64" -/// }, -/// { -/// "name": "version", -/// "type": "uint128", -/// "internalType": "uint128" -/// } -/// ] -/// } -/// ], -/// "stateMutability": "view" -/// }, -/// { -/// "type": "function", -/// "name": "registerNodeOperator", -/// "inputs": [ -/// { -/// "name": "data", -/// "type": "bytes", -/// "internalType": "bytes" -/// } -/// ], -/// "outputs": [], -/// "stateMutability": "nonpayable" -/// }, -/// { -/// "type": "function", -/// "name": "startMaintenance", -/// "inputs": [ -/// { -/// "name": "operatorIdx", -/// "type": "uint8", -/// "internalType": "uint8" -/// } -/// ], -/// "outputs": [], -/// "stateMutability": "nonpayable" -/// }, -/// { -/// "type": "function", -/// "name": "startMigration", -/// "inputs": [ -/// { -/// "name": "plan", -/// "type": "tuple", -/// "internalType": "struct MigrationPlan", -/// "components": [ -/// { -/// "name": "slots", -/// "type": "tuple[]", -/// "internalType": "struct KeyspaceSlot[]", -/// "components": [ -/// { -/// "name": "idx", -/// "type": "uint8", -/// "internalType": "uint8" -/// }, -/// { -/// "name": "operator", -/// "type": "address", -/// "internalType": "address" -/// } -/// ] -/// }, -/// { -/// "name": "replicationStrategy", -/// "type": "uint8", -/// "internalType": "uint8" -/// } -/// ] -/// } -/// ], -/// "outputs": [], -/// "stateMutability": "nonpayable" -/// }, -/// { -/// "type": "function", -/// "name": "transferOwnership", -/// "inputs": [ -/// { -/// "name": "newOwner", -/// "type": "address", -/// "internalType": "address" -/// } -/// ], -/// "outputs": [], -/// "stateMutability": "nonpayable" -/// }, -/// { -/// "type": "function", -/// "name": "updateNodeOperatorData", -/// "inputs": [ -/// { -/// "name": "operatorIdx", -/// "type": "uint8", -/// "internalType": "uint8" -/// }, -/// { -/// "name": "data", -/// "type": "bytes", -/// "internalType": "bytes" -/// } -/// ], -/// "outputs": [], -/// "stateMutability": "nonpayable" -/// }, -/// { -/// "type": "function", -/// "name": "updateSettings", -/// "inputs": [ -/// { -/// "name": "newSettings", -/// "type": "tuple", -/// "internalType": "struct Settings", -/// "components": [ -/// { -/// "name": "maxOperatorDataBytes", -/// "type": "uint16", -/// "internalType": "uint16" -/// } -/// ] -/// } -/// ], -/// "outputs": [], -/// "stateMutability": "nonpayable" -/// }, -/// { -/// "type": "event", -/// "name": "MaintenanceAborted", -/// "inputs": [ -/// { -/// "name": "clusterVersion", -/// "type": "uint128", -/// "indexed": false, -/// "internalType": "uint128" -/// } -/// ], -/// "anonymous": false -/// }, -/// { -/// "type": "event", -/// "name": "MaintenanceCompleted", -/// "inputs": [ -/// { -/// "name": "operatorAddress", -/// "type": "address", -/// "indexed": false, -/// "internalType": "address" -/// }, -/// { -/// "name": "clusterVersion", -/// "type": "uint128", -/// "indexed": false, -/// "internalType": "uint128" -/// } -/// ], -/// "anonymous": false -/// }, -/// { -/// "type": "event", -/// "name": "MaintenanceStarted", -/// "inputs": [ -/// { -/// "name": "operatorAddress", -/// "type": "address", -/// "indexed": false, -/// "internalType": "address" -/// }, -/// { -/// "name": "clusterVersion", -/// "type": "uint128", -/// "indexed": false, -/// "internalType": "uint128" -/// } -/// ], -/// "anonymous": false -/// }, -/// { -/// "type": "event", -/// "name": "MigrationAborted", -/// "inputs": [ -/// { -/// "name": "id", -/// "type": "uint64", -/// "indexed": false, -/// "internalType": "uint64" -/// }, -/// { -/// "name": "clusterVersion", -/// "type": "uint128", -/// "indexed": false, -/// "internalType": "uint128" -/// } -/// ], -/// "anonymous": false -/// }, -/// { -/// "type": "event", -/// "name": "MigrationCompleted", -/// "inputs": [ -/// { -/// "name": "id", -/// "type": "uint64", -/// "indexed": false, -/// "internalType": "uint64" -/// }, -/// { -/// "name": "operatorAddress", -/// "type": "address", -/// "indexed": false, -/// "internalType": "address" -/// }, -/// { -/// "name": "clusterVersion", -/// "type": "uint128", -/// "indexed": false, -/// "internalType": "uint128" -/// } -/// ], -/// "anonymous": false -/// }, -/// { -/// "type": "event", -/// "name": "MigrationDataPullCompleted", -/// "inputs": [ -/// { -/// "name": "id", -/// "type": "uint64", -/// "indexed": false, -/// "internalType": "uint64" -/// }, -/// { -/// "name": "operatorAddress", -/// "type": "address", -/// "indexed": false, -/// "internalType": "address" -/// }, -/// { -/// "name": "clusterVersion", -/// "type": "uint128", -/// "indexed": false, -/// "internalType": "uint128" -/// } -/// ], -/// "anonymous": false -/// }, -/// { -/// "type": "event", -/// "name": "MigrationStarted", -/// "inputs": [ -/// { -/// "name": "id", -/// "type": "uint64", -/// "indexed": false, -/// "internalType": "uint64" -/// }, -/// { -/// "name": "plan", -/// "type": "tuple", -/// "indexed": false, -/// "internalType": "struct MigrationPlan", -/// "components": [ -/// { -/// "name": "slots", -/// "type": "tuple[]", -/// "internalType": "struct KeyspaceSlot[]", -/// "components": [ -/// { -/// "name": "idx", -/// "type": "uint8", -/// "internalType": "uint8" -/// }, -/// { -/// "name": "operator", -/// "type": "address", -/// "internalType": "address" -/// } -/// ] -/// }, -/// { -/// "name": "replicationStrategy", -/// "type": "uint8", -/// "internalType": "uint8" -/// } -/// ] -/// }, -/// { -/// "name": "clusterVersion", -/// "type": "uint128", -/// "indexed": false, -/// "internalType": "uint128" -/// } -/// ], -/// "anonymous": false -/// }, -/// { -/// "type": "event", -/// "name": "NodeOperatorDataUpdated", -/// "inputs": [ -/// { -/// "name": "operatorAddress", -/// "type": "address", -/// "indexed": false, -/// "internalType": "address" -/// }, -/// { -/// "name": "data", -/// "type": "bytes", -/// "indexed": false, -/// "internalType": "bytes" -/// }, -/// { -/// "name": "clusterVersion", -/// "type": "uint128", -/// "indexed": false, -/// "internalType": "uint128" -/// } -/// ], -/// "anonymous": false -/// } -/// ] -/// ``` -#[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style, - clippy::empty_structs_with_brackets -)] -pub mod Cluster { - use {super::*, alloy::sol_types as alloy_sol_types}; - /// The creation / init bytecode of the contract. - /// - /// ```text - ///0x608060405234801561000f575f5ffd5b50604051613d0f380380613d0f833981810160405281019061003191906103bd565b335f5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550816102075f820151815f015f6101000a81548161ffff021916908361ffff1602179055509050505f5f90505b8151811015610139578181815181106100b8576100b7610417565b5b602002602001015160025f600281106100d4576100d3610417565b5b61010202015f018261010081106100ee576100ed610417565b5b015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808060010191505061009c565b5061014a815161017260201b60201c565b60025f6002811061015e5761015d610417565b5b6101020201610100018190555050506104ad565b5f60018260ff166001901b610187919061047a565b9050919050565b5f604051905090565b5f5ffd5b5f5ffd5b5f5ffd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6101e9826101a3565b810181811067ffffffffffffffff82111715610208576102076101b3565b5b80604052505050565b5f61021a61018e565b905061022682826101e0565b919050565b5f61ffff82169050919050565b6102418161022b565b811461024b575f5ffd5b50565b5f8151905061025c81610238565b92915050565b5f602082840312156102775761027661019f565b5b6102816020610211565b90505f6102908482850161024e565b5f8301525092915050565b5f5ffd5b5f67ffffffffffffffff8211156102b9576102b86101b3565b5b602082029050602081019050919050565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6102f7826102ce565b9050919050565b610307816102ed565b8114610311575f5ffd5b50565b5f81519050610322816102fe565b92915050565b5f61033a6103358461029f565b610211565b9050808382526020820190506020840283018581111561035d5761035c6102ca565b5b835b8181101561038657806103728882610314565b84526020840193505060208101905061035f565b5050509392505050565b5f82601f8301126103a4576103a361029b565b5b81516103b4848260208601610328565b91505092915050565b5f5f604083850312156103d3576103d2610197565b5b5f6103e085828601610262565b925050602083015167ffffffffffffffff8111156104015761040061019b565b5b61040d85828601610390565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f819050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61048482610444565b915061048f83610444565b92508282039050818111156104a7576104a661044d565b5b92915050565b613855806104ba5f395ff3fe608060405234801561000f575f5ffd5b50600436106100a7575f3560e01c8063ad36e6d01161006f578063ad36e6d014610127578063c130809a14610131578063cdbfc62d1461013b578063dd3fd26914610157578063f019b15414610173578063f2fde38b1461018f576100a7565b80633048bfba146100ab57806355a47d0a146100b557806365706f9c146100d157806375418b9d146100ed5780638b5252d61461010b575b5f5ffd5b6100b36101ab565b005b6100cf60048036038101906100ca919061251f565b61037f565b005b6100eb60048036038101906100e6919061257f565b6106bd565b005b6100f5610761565b60405161010291906128bc565b60405180910390f35b6101256004803603810190610120919061293d565b610f8f565b005b61012f610fec565b005b6101396111c6565b005b610155600480360381019061015091906129a6565b6113c9565b005b610171600480360381019061016c91906129ed565b611a99565b005b61018d60048036038101906101889190612a18565b611d15565b005b6101a960048036038101906101a49190612a9f565b6120ab565b005b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610239576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161023090612b24565b60405180910390fd5b61024161217b565b610280576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161027790612b8c565b60405180910390fd5b5f61020a5f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff16809291906102f190612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507f8fb9cd054d0a022110cced239e908b834e4cd219511856d4eaae3051d932d60461020b5f9054906101000a90046fffffffffffffffffffffffffffffffff166040516103759190612c1d565b60405180910390a1565b6103876121d5565b6103c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103bd90612c80565b60405180910390fd5b6102085f015f9054906101000a900467ffffffffffffffff1667ffffffffffffffff168267ffffffffffffffff1614610434576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042b90612ce8565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff166002806102065f9054906101000a900467ffffffffffffffff1661046f9190612d33565b67ffffffffffffffff166002811061048a57610489612d63565b5b61010202015f018260ff1661010081106104a7576104a6612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461051e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161051590612dda565b60405180910390fd5b61053781610208600101546121e590919063ffffffff16565b6106b95761055481610208600101546121fa90919063ffffffff16565b6102086001018190555061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff168092919061058c90612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550505f6102086001015403610646577f01269879535f40ee8957e15e160bf1866c5e2728ff0cbc583d848821e2639b4e6102085f015f9054906101000a900467ffffffffffffffff163361020b5f9054906101000a90046fffffffffffffffffffffffffffffffff1660405161063993929190612e16565b60405180910390a16106b8565b7faf5e90e72015f43138f66b4cd08bd1dfa2839030104f22a00af843fe847c6d196102085f015f9054906101000a900467ffffffffffffffff163361020b5f9054906101000a90046fffffffffffffffffffffffffffffffff166040516106af93929190612e16565b60405180910390a15b5b5050565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461074b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161074290612b24565b60405180910390fd5b80610207818161075b9190612f2a565b90505050565b6107696123a7565b6107716123a7565b5f5f5f61077c6121d5565b15610bb9576102085f015f9054906101000a900467ffffffffffffffff1684602001515f019067ffffffffffffffff16908167ffffffffffffffff16815250506102086001015484602001516020018181525050600260016102065f9054906101000a900467ffffffffffffffff166107f59190612f38565b6107ff9190612d33565b67ffffffffffffffff1692505f60026102065f9054906101000a900467ffffffffffffffff1661082f9190612d33565b67ffffffffffffffff1690506108616002826002811061085257610851612d63565b5b6101020201610100015461220e565b91506001826108709190612f73565b67ffffffffffffffff81111561088957610888612fa6565b5b6040519080825280602002602001820160405280156108c257816020015b6108af61240f565b8152602001906001900390816108a75790505b5085604001515f0181905250600281600281106108e2576108e1612d63565b5b6101020201610101015f9054906101000a900460ff1685604001516020019060ff16908160ff16815250505f5f90505b828111610bb257610949816002846002811061093157610930612d63565b5b610102020161010001546121e590919063ffffffff16565b610b9f576002826002811061096157610960612d63565b5b61010202015f0181610100811061097b5761097a612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1693508386604001515f015182815181106109b9576109b8612d63565b5b60200260200101515f019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050610a268160028760028110610a0e57610a0d612d63565b5b610102020161010001546121e590919063ffffffff16565b80610aab57508373ffffffffffffffffffffffffffffffffffffffff1660028660028110610a5757610a56612d63565b5b61010202015f01826101008110610a7157610a70612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b15610b9e5760015f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f208054610af890613000565b80601f0160208091040260200160405190810160405280929190818152602001828054610b2490613000565b8015610b6f5780601f10610b4657610100808354040283529160200191610b6f565b820191905f5260205f20905b815481529060010190602001808311610b5257829003601f168201915b505050505086604001515f01518281518110610b8e57610b8d612d63565b5b6020026020010151602001819052505b5b8080610baa90613030565b915050610912565b5050610be9565b60026102065f9054906101000a900467ffffffffffffffff16610bdc9190612d33565b67ffffffffffffffff1692505b610c0f60028460028110610c0057610bff612d63565b5b6101020201610100015461220e565b9050600181610c1e9190612f73565b67ffffffffffffffff811115610c3757610c36612fa6565b5b604051908082528060200260200182016040528015610c7057816020015b610c5d61240f565b815260200190600190039081610c555790505b50845f01515f018190525060028360028110610c8f57610c8e612d63565b5b6101020201610101015f9054906101000a900460ff16845f01516020019060ff16908160ff16815250505f5f90505b818111610ea157610cf58160028660028110610cdd57610cdc612d63565b5b610102020161010001546121e590919063ffffffff16565b610e8e5760028460028110610d0d57610d0c612d63565b5b61010202015f01816101008110610d2757610d26612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16925082855f01515f01518281518110610d6457610d63612d63565b5b60200260200101515f019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f208054610de990613000565b80601f0160208091040260200160405190810160405280929190818152602001828054610e1590613000565b8015610e605780601f10610e3757610100808354040283529160200191610e60565b820191905f5260205f20905b815481529060010190602001808311610e4357829003601f168201915b5050505050855f01515f01518281518110610e7e57610e7d612d63565b5b6020026020010151602001819052505b8080610e9990613030565b915050610cbe565b506102065f9054906101000a900467ffffffffffffffff16846080019067ffffffffffffffff16908167ffffffffffffffff168152505061020a5f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684606001515f019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505061020b5f9054906101000a90046fffffffffffffffffffffffffffffffff168460a001906fffffffffffffffffffffffffffffffff1690816fffffffffffffffffffffffffffffffff16815250508394505050505090565b610f9b8282905061221f565b818160015f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f209182610fe7929190613218565b505050565b610ff461217b565b611033576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161102a90612b8c565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff1661020a5f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146110c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110bc90612dda565b60405180910390fd5b5f61020a5f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff168092919061113690612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507ff91067eb420c28d3124865fc996e6aa9d541b9b4fef9188cb965a6cc6491638e3361020b5f9054906101000a90046fffffffffffffffffffffffffffffffff166040516111bc9291906132e5565b60405180910390a1565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611254576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161124b90612b24565b60405180910390fd5b61125c6121d5565b61129b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161129290612c80565b60405180910390fd5b6102065f81819054906101000a900467ffffffffffffffff16809291906112c19061330c565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550505f6102086001018190555061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff168092919061132190612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507ff73240422246f63ed633ef3ce0726b8ab8fb69d46c8a4e5ecb0b2922668674a16102085f015f9054906101000a900467ffffffffffffffff1661020b5f9054906101000a90046fffffffffffffffffffffffffffffffff166040516113bf929190613333565b60405180910390a1565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611457576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161144e90612b24565b60405180910390fd5b61145f6121d5565b1561149f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611496906133a4565b60405180910390fd5b6114a761217b565b156114e7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114de9061340c565b60405180910390fd5b6102085f015f81819054906101000a900467ffffffffffffffff168092919061150f9061342a565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550505f60026102065f9054906101000a900467ffffffffffffffff1661155a9190612d33565b67ffffffffffffffff1690506102065f81819054906101000a900467ffffffffffffffff168092919061158c9061342a565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550505f60026102065f9054906101000a900467ffffffffffffffff166115d79190612d33565b67ffffffffffffffff1690505f5f90505b61160e600284600281106115ff576115fe612d63565b5b6101020201610100015461220e565b81116117b2576002836002811061162857611627612d63565b5b61010202015f0181610100811061164257611641612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166002836002811061168d5761168c612d63565b5b61010202015f018261010081106116a7576116a6612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461179f57600283600281106116f7576116f6612d63565b5b61010202015f0181610100811061171157611710612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff166002836002811061174657611745612d63565b5b61010202015f018261010081106117605761175f612d63565b5b015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b80806117aa90613030565b9150506115e8565b505f600283600281106117c8576117c7612d63565b5b6101020201610100015490505f5f5f5f90505b86805f01906117ea9190613465565b90508110156119465786805f01906118029190613465565b8281811061181357611812612d63565b5b9050604002015f01602081019061182a91906129ed565b925086805f019061183b9190613465565b8281811061184c5761184b612d63565b5b90506040020160200160208101906118649190612a9f565b91505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036118b3576118ac83856121fa90919063ffffffff16565b93506118c9565b6118c683856122bd90919063ffffffff16565b93505b81600286600281106118de576118dd612d63565b5b61010202015f018460ff1661010081106118fb576118fa612d63565b5b015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080806001019150506117db565b50826002856002811061195c5761195b612d63565b5b6101020201610100018190555085602001602081019061197c91906129ed565b600285600281106119905761198f612d63565b5b6101020201610101015f6101000a81548160ff021916908360ff160217905550826102086001018190555061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff16809291906119e990612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507f78dad2bc0b47c688ed84f3fee79abc18e6c9822db05a79ca19dff54533c7470d6102085f015f9054906101000a900467ffffffffffffffff168761020b5f9054906101000a90046fffffffffffffffffffffffffffffffff16604051611a899392919061368b565b60405180910390a1505050505050565b611aa16121d5565b15611ae1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ad8906133a4565b60405180910390fd5b611ae961217b565b15611b29576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b209061340c565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff166002806102065f9054906101000a900467ffffffffffffffff16611b649190612d33565b67ffffffffffffffff1660028110611b7f57611b7e612d63565b5b61010202015f018260ff166101008110611b9c57611b9b612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611c13576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c0a90612dda565b60405180910390fd5b3361020a5f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff1680929190611c8490612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507fbc2748cf02f7a1291525e866efc76ab3b96d32d7afcbb26c53daec617b38b4793361020b5f9054906101000a90046fffffffffffffffffffffffffffffffff16604051611d0a9291906132e5565b60405180910390a150565b611d218282905061221f565b5f5f611d2b6121d5565b15611ea1573373ffffffffffffffffffffffffffffffffffffffff1660028060016102065f9054906101000a900467ffffffffffffffff16611d6d9190612f38565b611d779190612d33565b67ffffffffffffffff1660028110611d9257611d91612d63565b5b61010202015f018660ff166101008110611daf57611dae612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614915081611e9c573373ffffffffffffffffffffffffffffffffffffffff166002806102065f9054906101000a900467ffffffffffffffff16611e299190612d33565b67ffffffffffffffff1660028110611e4457611e43612d63565b5b61010202015f018660ff166101008110611e6157611e60612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161490505b611f4f565b3373ffffffffffffffffffffffffffffffffffffffff166002806102065f9054906101000a900467ffffffffffffffff16611edc9190612d33565b67ffffffffffffffff1660028110611ef757611ef6612d63565b5b61010202015f018660ff166101008110611f1457611f13612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161491505b8180611f585750805b611f97576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f8e90612dda565b60405180910390fd5b838360015f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f209182611fe3929190613218565b5061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff168092919061201290612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507f125181ec21882dec51a2392905dff3a82cbd0262f18b5c0c035488671b40afb233858561020b5f9054906101000a90046fffffffffffffffffffffffffffffffff1660405161209c9493929190613711565b60405180910390a15050505050565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612139576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161213090612b24565b60405180910390fd5b805f5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b5f5f73ffffffffffffffffffffffffffffffffffffffff1661020a5f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415905090565b5f5f610208600101541415905090565b5f5f8260ff166001901b841614905092915050565b5f8160ff166001901b198316905092915050565b5f612218826122d0565b9050919050565b5f8111612261576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161225890613799565b60405180910390fd5b6102075f015f9054906101000a900461ffff1661ffff168111156122ba576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122b190613801565b60405180910390fd5b50565b5f8160ff166001901b8317905092915050565b5f60076122ee6fffffffffffffffffffffffffffffffff841161239c565b901b9050600661230a67ffffffffffffffff8385901c1161239c565b901b81179050600561232463ffffffff8385901c1161239c565b901b81179050600461233c61ffff8385901c1161239c565b901b81179050600361235360ff8385901c1161239c565b901b81179050600261236a600f8385901c1161239c565b901b811790507d01010202020203030303030303030000000000000000000000000000000082821c1a81179050919050565b5f8115159050919050565b6040518060c001604052806123ba61243e565b81526020016123c761245a565b81526020016123d461243e565b81526020016123e161247c565b81526020015f67ffffffffffffffff1681526020015f6fffffffffffffffffffffffffffffffff1681525090565b60405180604001604052805f73ffffffffffffffffffffffffffffffffffffffff168152602001606081525090565b6040518060400160405280606081526020015f60ff1681525090565b60405180604001604052805f67ffffffffffffffff1681526020015f81525090565b60405180602001604052805f73ffffffffffffffffffffffffffffffffffffffff1681525090565b5f5ffd5b5f5ffd5b5f67ffffffffffffffff82169050919050565b6124c8816124ac565b81146124d2575f5ffd5b50565b5f813590506124e3816124bf565b92915050565b5f60ff82169050919050565b6124fe816124e9565b8114612508575f5ffd5b50565b5f81359050612519816124f5565b92915050565b5f5f60408385031215612535576125346124a4565b5b5f612542858286016124d5565b92505060206125538582860161250b565b9150509250929050565b5f5ffd5b5f602082840312156125765761257561255d565b5b81905092915050565b5f60208284031215612594576125936124a4565b5b5f6125a184828501612561565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6125fc826125d3565b9050919050565b61260c816125f2565b82525050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61265482612612565b61265e818561261c565b935061266e81856020860161262c565b6126778161263a565b840191505092915050565b5f604083015f8301516126975f860182612603565b50602083015184820360208601526126af828261264a565b9150508091505092915050565b5f6126c78383612682565b905092915050565b5f602082019050919050565b5f6126e5826125aa565b6126ef81856125b4565b935083602082028501612701856125c4565b805f5b8581101561273c578484038952815161271d85826126bc565b9450612728836126cf565b925060208a01995050600181019050612704565b50829750879550505050505092915050565b612757816124e9565b82525050565b5f604083015f8301518482035f86015261277782826126db565b915050602083015161278c602086018261274e565b508091505092915050565b6127a0816124ac565b82525050565b5f819050919050565b6127b8816127a6565b82525050565b604082015f8201516127d25f850182612797565b5060208201516127e560208501826127af565b50505050565b602082015f8201516127ff5f850182612603565b50505050565b5f6fffffffffffffffffffffffffffffffff82169050919050565b61282981612805565b82525050565b5f60e083015f8301518482035f860152612849828261275d565b915050602083015161285e60208601826127be565b5060408301518482036060860152612876828261275d565b915050606083015161288b60808601826127eb565b50608083015161289e60a0860182612797565b5060a08301516128b160c0860182612820565b508091505092915050565b5f6020820190508181035f8301526128d4818461282f565b905092915050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f83601f8401126128fd576128fc6128dc565b5b8235905067ffffffffffffffff81111561291a576129196128e0565b5b602083019150836001820283011115612936576129356128e4565b5b9250929050565b5f5f60208385031215612953576129526124a4565b5b5f83013567ffffffffffffffff8111156129705761296f6124a8565b5b61297c858286016128e8565b92509250509250929050565b5f6040828403121561299d5761299c61255d565b5b81905092915050565b5f602082840312156129bb576129ba6124a4565b5b5f82013567ffffffffffffffff8111156129d8576129d76124a8565b5b6129e484828501612988565b91505092915050565b5f60208284031215612a0257612a016124a4565b5b5f612a0f8482850161250b565b91505092915050565b5f5f5f60408486031215612a2f57612a2e6124a4565b5b5f612a3c8682870161250b565b935050602084013567ffffffffffffffff811115612a5d57612a5c6124a8565b5b612a69868287016128e8565b92509250509250925092565b612a7e816125f2565b8114612a88575f5ffd5b50565b5f81359050612a9981612a75565b92915050565b5f60208284031215612ab457612ab36124a4565b5b5f612ac184828501612a8b565b91505092915050565b5f82825260208201905092915050565b7f6e6f7420746865206f776e6572000000000000000000000000000000000000005f82015250565b5f612b0e600d83612aca565b9150612b1982612ada565b602082019050919050565b5f6020820190508181035f830152612b3b81612b02565b9050919050565b7f6e6f206d61696e74656e616e63650000000000000000000000000000000000005f82015250565b5f612b76600e83612aca565b9150612b8182612b42565b602082019050919050565b5f6020820190508181035f830152612ba381612b6a565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f612be182612805565b91506fffffffffffffffffffffffffffffffff8203612c0357612c02612baa565b5b600182019050919050565b612c1781612805565b82525050565b5f602082019050612c305f830184612c0e565b92915050565b7f6e6f206d6967726174696f6e00000000000000000000000000000000000000005f82015250565b5f612c6a600c83612aca565b9150612c7582612c36565b602082019050919050565b5f6020820190508181035f830152612c9781612c5e565b9050919050565b7f77726f6e67206d6967726174696f6e20696400000000000000000000000000005f82015250565b5f612cd2601283612aca565b9150612cdd82612c9e565b602082019050919050565b5f6020820190508181035f830152612cff81612cc6565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f612d3d826124ac565b9150612d48836124ac565b925082612d5857612d57612d06565b5b828206905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f77726f6e67206f70657261746f720000000000000000000000000000000000005f82015250565b5f612dc4600e83612aca565b9150612dcf82612d90565b602082019050919050565b5f6020820190508181035f830152612df181612db8565b9050919050565b612e01816124ac565b82525050565b612e10816125f2565b82525050565b5f606082019050612e295f830186612df8565b612e366020830185612e07565b612e436040830184612c0e565b949350505050565b5f61ffff82169050919050565b612e6181612e4b565b8114612e6b575f5ffd5b50565b5f8135612e7a81612e58565b80915050919050565b5f815f1b9050919050565b5f61ffff612e9b84612e83565b9350801983169250808416831791505092915050565b5f819050919050565b5f612ed4612ecf612eca84612e4b565b612eb1565b612e4b565b9050919050565b5f819050919050565b612eed82612eba565b612f00612ef982612edb565b8354612e8e565b8255505050565b5f81015f830180612f1781612e6e565b9050612f238184612ee4565b5050505050565b612f348282612f07565b5050565b5f612f42826124ac565b9150612f4d836124ac565b9250828203905067ffffffffffffffff811115612f6d57612f6c612baa565b5b92915050565b5f612f7d826127a6565b9150612f88836127a6565b9250828201905080821115612fa057612f9f612baa565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061301757607f821691505b60208210810361302a57613029612fd3565b5b50919050565b5f61303a826127a6565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361306c5761306b612baa565b5b600182019050919050565b5f82905092915050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026130dd7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826130a2565b6130e786836130a2565b95508019841693508086168417925050509392505050565b5f61311961311461310f846127a6565b612eb1565b6127a6565b9050919050565b5f819050919050565b613132836130ff565b61314661313e82613120565b8484546130ae565b825550505050565b5f5f905090565b61315d61314e565b613168818484613129565b505050565b5b8181101561318b576131805f82613155565b60018101905061316e565b5050565b601f8211156131d0576131a181613081565b6131aa84613093565b810160208510156131b9578190505b6131cd6131c585613093565b83018261316d565b50505b505050565b5f82821c905092915050565b5f6131f05f19846008026131d5565b1980831691505092915050565b5f61320883836131e1565b9150826002028217905092915050565b6132228383613077565b67ffffffffffffffff81111561323b5761323a612fa6565b5b6132458254613000565b61325082828561318f565b5f601f83116001811461327d575f841561326b578287013590505b61327585826131fd565b8655506132dc565b601f19841661328b86613081565b5f5b828110156132b25784890135825560018201915060208501945060208101905061328d565b868310156132cf57848901356132cb601f8916826131e1565b8355505b6001600288020188555050505b50505050505050565b5f6040820190506132f85f830185612e07565b6133056020830184612c0e565b9392505050565b5f613316826124ac565b91505f820361332857613327612baa565b5b600182039050919050565b5f6040820190506133465f830185612df8565b6133536020830184612c0e565b9392505050565b7f6d6967726174696f6e20696e2070726f677265737300000000000000000000005f82015250565b5f61338e601583612aca565b91506133998261335a565b602082019050919050565b5f6020820190508181035f8301526133bb81613382565b9050919050565b7f6d61696e74656e616e636520696e2070726f67726573730000000000000000005f82015250565b5f6133f6601783612aca565b9150613401826133c2565b602082019050919050565b5f6020820190508181035f830152613423816133ea565b9050919050565b5f613434826124ac565b915067ffffffffffffffff820361344e5761344d612baa565b5b600182019050919050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f8335600160200384360303811261348157613480613459565b5b80840192508235915067ffffffffffffffff8211156134a3576134a261345d565b5b6020830192506040820236038313156134bf576134be613461565b5b509250929050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f833560016020038436030381126134ef576134ee6134cf565b5b83810192508235915060208301925067ffffffffffffffff821115613517576135166134c7565b5b60408202360383131561352d5761352c6134cb565b5b509250929050565b5f82825260208201905092915050565b5f819050919050565b5f61355c602084018461250b565b905092915050565b5f6135726020840184612a8b565b905092915050565b6040820161358a5f83018361354e565b6135965f85018261274e565b506135a46020830183613564565b6135b16020850182612603565b50505050565b5f6135c2838361357a565b60408301905092915050565b5f82905092915050565b5f604082019050919050565b5f6135ef8385613535565b93506135fa82613545565b805f5b858110156136325761360f82846135ce565b61361988826135b7565b9750613624836135d8565b9250506001810190506135fd565b5085925050509392505050565b5f604083016136505f8401846134d3565b8583035f8701526136628382846135e4565b92505050613673602084018461354e565b613680602086018261274e565b508091505092915050565b5f60608201905061369e5f830186612df8565b81810360208301526136b0818561363f565b90506136bf6040830184612c0e565b949350505050565b5f82825260208201905092915050565b828183375f83830152505050565b5f6136f083856136c7565b93506136fd8385846136d7565b6137068361263a565b840190509392505050565b5f6060820190506137245f830187612e07565b81810360208301526137378185876136e5565b90506137466040830184612c0e565b95945050505050565b7f656d707479206f70657261746f722064617461000000000000000000000000005f82015250565b5f613783601383612aca565b915061378e8261374f565b602082019050919050565b5f6020820190508181035f8301526137b081613777565b9050919050565b7f6f70657261746f72206461746120746f6f206c617267650000000000000000005f82015250565b5f6137eb601783612aca565b91506137f6826137b7565b602082019050919050565b5f6020820190508181035f830152613818816137df565b905091905056fea2646970667358221220fa04dead425e6aa2ee51652b77cd8bec344f89d5a5d18b42f4889b7abad1732264736f6c634300081c0033 - /// ``` - #[rustfmt::skip] - #[allow(clippy::all)] - pub static BYTECODE: alloy_sol_types::private::Bytes = alloy_sol_types::private::Bytes::from_static( - b"`\x80`@R4\x80\x15a\0\x0FW__\xFD[P`@Qa=\x0F8\x03\x80a=\x0F\x839\x81\x81\x01`@R\x81\x01\x90a\x001\x91\x90a\x03\xBDV[3__a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UP\x81a\x02\x07_\x82\x01Q\x81_\x01_a\x01\0\n\x81T\x81a\xFF\xFF\x02\x19\x16\x90\x83a\xFF\xFF\x16\x02\x17\x90UP\x90PP__\x90P[\x81Q\x81\x10\x15a\x019W\x81\x81\x81Q\x81\x10a\0\xB8Wa\0\xB7a\x04\x17V[[` \x02` \x01\x01Q`\x02_`\x02\x81\x10a\0\xD4Wa\0\xD3a\x04\x17V[[a\x01\x02\x02\x01_\x01\x82a\x01\0\x81\x10a\0\xEEWa\0\xEDa\x04\x17V[[\x01_a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UP\x80\x80`\x01\x01\x91PPa\0\x9CV[Pa\x01J\x81Qa\x01r` \x1B` \x1CV[`\x02_`\x02\x81\x10a\x01^Wa\x01]a\x04\x17V[[a\x01\x02\x02\x01a\x01\0\x01\x81\x90UPPPa\x04\xADV[_`\x01\x82`\xFF\x16`\x01\x90\x1Ba\x01\x87\x91\x90a\x04zV[\x90P\x91\x90PV[_`@Q\x90P\x90V[__\xFD[__\xFD[__\xFD[_`\x1F\x19`\x1F\x83\x01\x16\x90P\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`A`\x04R`$_\xFD[a\x01\xE9\x82a\x01\xA3V[\x81\x01\x81\x81\x10g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x17\x15a\x02\x08Wa\x02\x07a\x01\xB3V[[\x80`@RPPPV[_a\x02\x1Aa\x01\x8EV[\x90Pa\x02&\x82\x82a\x01\xE0V[\x91\x90PV[_a\xFF\xFF\x82\x16\x90P\x91\x90PV[a\x02A\x81a\x02+V[\x81\x14a\x02KW__\xFD[PV[_\x81Q\x90Pa\x02\\\x81a\x028V[\x92\x91PPV[_` \x82\x84\x03\x12\x15a\x02wWa\x02va\x01\x9FV[[a\x02\x81` a\x02\x11V[\x90P_a\x02\x90\x84\x82\x85\x01a\x02NV[_\x83\x01RP\x92\x91PPV[__\xFD[_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15a\x02\xB9Wa\x02\xB8a\x01\xB3V[[` \x82\x02\x90P` \x81\x01\x90P\x91\x90PV[__\xFD[_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[_a\x02\xF7\x82a\x02\xCEV[\x90P\x91\x90PV[a\x03\x07\x81a\x02\xEDV[\x81\x14a\x03\x11W__\xFD[PV[_\x81Q\x90Pa\x03\"\x81a\x02\xFEV[\x92\x91PPV[_a\x03:a\x035\x84a\x02\x9FV[a\x02\x11V[\x90P\x80\x83\x82R` \x82\x01\x90P` \x84\x02\x83\x01\x85\x81\x11\x15a\x03]Wa\x03\\a\x02\xCAV[[\x83[\x81\x81\x10\x15a\x03\x86W\x80a\x03r\x88\x82a\x03\x14V[\x84R` \x84\x01\x93PP` \x81\x01\x90Pa\x03_V[PPP\x93\x92PPPV[_\x82`\x1F\x83\x01\x12a\x03\xA4Wa\x03\xA3a\x02\x9BV[[\x81Qa\x03\xB4\x84\x82` \x86\x01a\x03(V[\x91PP\x92\x91PPV[__`@\x83\x85\x03\x12\x15a\x03\xD3Wa\x03\xD2a\x01\x97V[[_a\x03\xE0\x85\x82\x86\x01a\x02bV[\x92PP` \x83\x01Qg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x04\x01Wa\x04\0a\x01\x9BV[[a\x04\r\x85\x82\x86\x01a\x03\x90V[\x91PP\x92P\x92\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`2`\x04R`$_\xFD[_\x81\x90P\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`\x11`\x04R`$_\xFD[_a\x04\x84\x82a\x04DV[\x91Pa\x04\x8F\x83a\x04DV[\x92P\x82\x82\x03\x90P\x81\x81\x11\x15a\x04\xA7Wa\x04\xA6a\x04MV[[\x92\x91PPV[a8U\x80a\x04\xBA_9_\xF3\xFE`\x80`@R4\x80\x15a\0\x0FW__\xFD[P`\x046\x10a\0\xA7W_5`\xE0\x1C\x80c\xAD6\xE6\xD0\x11a\0oW\x80c\xAD6\xE6\xD0\x14a\x01'W\x80c\xC10\x80\x9A\x14a\x011W\x80c\xCD\xBF\xC6-\x14a\x01;W\x80c\xDD?\xD2i\x14a\x01WW\x80c\xF0\x19\xB1T\x14a\x01sW\x80c\xF2\xFD\xE3\x8B\x14a\x01\x8FWa\0\xA7V[\x80c0H\xBF\xBA\x14a\0\xABW\x80cU\xA4}\n\x14a\0\xB5W\x80cepo\x9C\x14a\0\xD1W\x80cuA\x8B\x9D\x14a\0\xEDW\x80c\x8BRR\xD6\x14a\x01\x0BW[__\xFD[a\0\xB3a\x01\xABV[\0[a\0\xCF`\x04\x806\x03\x81\x01\x90a\0\xCA\x91\x90a%\x1FV[a\x03\x7FV[\0[a\0\xEB`\x04\x806\x03\x81\x01\x90a\0\xE6\x91\x90a%\x7FV[a\x06\xBDV[\0[a\0\xF5a\x07aV[`@Qa\x01\x02\x91\x90a(\xBCV[`@Q\x80\x91\x03\x90\xF3[a\x01%`\x04\x806\x03\x81\x01\x90a\x01 \x91\x90a)=V[a\x0F\x8FV[\0[a\x01/a\x0F\xECV[\0[a\x019a\x11\xC6V[\0[a\x01U`\x04\x806\x03\x81\x01\x90a\x01P\x91\x90a)\xA6V[a\x13\xC9V[\0[a\x01q`\x04\x806\x03\x81\x01\x90a\x01l\x91\x90a)\xEDV[a\x1A\x99V[\0[a\x01\x8D`\x04\x806\x03\x81\x01\x90a\x01\x88\x91\x90a*\x18V[a\x1D\x15V[\0[a\x01\xA9`\x04\x806\x03\x81\x01\x90a\x01\xA4\x91\x90a*\x9FV[a \xABV[\0[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x029W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x020\x90a+$V[`@Q\x80\x91\x03\x90\xFD[a\x02Aa!{V[a\x02\x80W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x02w\x90a+\x8CV[`@Q\x80\x91\x03\x90\xFD[_a\x02\n_\x01_a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x02\xF1\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\x8F\xB9\xCD\x05M\n\x02!\x10\xCC\xED#\x9E\x90\x8B\x83NL\xD2\x19Q\x18V\xD4\xEA\xAE0Q\xD92\xD6\x04a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x03u\x91\x90a,\x1DV[`@Q\x80\x91\x03\x90\xA1V[a\x03\x87a!\xD5V[a\x03\xC6W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x03\xBD\x90a,\x80V[`@Q\x80\x91\x03\x90\xFD[a\x02\x08_\x01_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x82g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x044W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x04+\x90a,\xE8V[`@Q\x80\x91\x03\x90\xFD[3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x80a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x04o\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x81\x10a\x04\x8AWa\x04\x89a-cV[[a\x01\x02\x02\x01_\x01\x82`\xFF\x16a\x01\0\x81\x10a\x04\xA7Wa\x04\xA6a-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x05\x1EW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x05\x15\x90a-\xDAV[`@Q\x80\x91\x03\x90\xFD[a\x057\x81a\x02\x08`\x01\x01Ta!\xE5\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x06\xB9Wa\x05T\x81a\x02\x08`\x01\x01Ta!\xFA\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x02\x08`\x01\x01\x81\x90UPa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x05\x8C\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP_a\x02\x08`\x01\x01T\x03a\x06FW\x7F\x01&\x98yS_@\xEE\x89W\xE1^\x16\x0B\xF1\x86l^'(\xFF\x0C\xBCX=\x84\x88!\xE2c\x9BNa\x02\x08_\x01_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x069\x93\x92\x91\x90a.\x16V[`@Q\x80\x91\x03\x90\xA1a\x06\xB8V[\x7F\xAF^\x90\xE7 \x15\xF418\xF6kL\xD0\x8B\xD1\xDF\xA2\x83\x900\x10O\"\xA0\n\xF8C\xFE\x84|m\x19a\x02\x08_\x01_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x06\xAF\x93\x92\x91\x90a.\x16V[`@Q\x80\x91\x03\x90\xA1[[PPV[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x07KW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x07B\x90a+$V[`@Q\x80\x91\x03\x90\xFD[\x80a\x02\x07\x81\x81a\x07[\x91\x90a/*V[\x90PPPV[a\x07ia#\xA7V[a\x07qa#\xA7V[___a\x07|a!\xD5V[\x15a\x0B\xB9Wa\x02\x08_\x01_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x84` \x01Q_\x01\x90g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RPPa\x02\x08`\x01\x01T\x84` \x01Q` \x01\x81\x81RPP`\x02`\x01a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x07\xF5\x91\x90a/8V[a\x07\xFF\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x92P_`\x02a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x08/\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90Pa\x08a`\x02\x82`\x02\x81\x10a\x08RWa\x08Qa-cV[[a\x01\x02\x02\x01a\x01\0\x01Ta\"\x0EV[\x91P`\x01\x82a\x08p\x91\x90a/sV[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x08\x89Wa\x08\x88a/\xA6V[[`@Q\x90\x80\x82R\x80` \x02` \x01\x82\x01`@R\x80\x15a\x08\xC2W\x81` \x01[a\x08\xAFa$\x0FV[\x81R` \x01\x90`\x01\x90\x03\x90\x81a\x08\xA7W\x90P[P\x85`@\x01Q_\x01\x81\x90RP`\x02\x81`\x02\x81\x10a\x08\xE2Wa\x08\xE1a-cV[[a\x01\x02\x02\x01a\x01\x01\x01_\x90T\x90a\x01\0\n\x90\x04`\xFF\x16\x85`@\x01Q` \x01\x90`\xFF\x16\x90\x81`\xFF\x16\x81RPP__\x90P[\x82\x81\x11a\x0B\xB2Wa\tI\x81`\x02\x84`\x02\x81\x10a\t1Wa\t0a-cV[[a\x01\x02\x02\x01a\x01\0\x01Ta!\xE5\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x0B\x9FW`\x02\x82`\x02\x81\x10a\taWa\t`a-cV[[a\x01\x02\x02\x01_\x01\x81a\x01\0\x81\x10a\t{Wa\tza-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x93P\x83\x86`@\x01Q_\x01Q\x82\x81Q\x81\x10a\t\xB9Wa\t\xB8a-cV[[` \x02` \x01\x01Q_\x01\x90s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RPPa\n&\x81`\x02\x87`\x02\x81\x10a\n\x0EWa\n\ra-cV[[a\x01\x02\x02\x01a\x01\0\x01Ta!\xE5\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x80a\n\xABWP\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x86`\x02\x81\x10a\nWWa\nVa-cV[[a\x01\x02\x02\x01_\x01\x82a\x01\0\x81\x10a\nqWa\npa-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14\x15[\x15a\x0B\x9EW`\x01_\x85s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ \x80Ta\n\xF8\x90a0\0V[\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01\x82\x80Ta\x0B$\x90a0\0V[\x80\x15a\x0BoW\x80`\x1F\x10a\x0BFWa\x01\0\x80\x83T\x04\x02\x83R\x91` \x01\x91a\x0BoV[\x82\x01\x91\x90_R` _ \x90[\x81T\x81R\x90`\x01\x01\x90` \x01\x80\x83\x11a\x0BRW\x82\x90\x03`\x1F\x16\x82\x01\x91[PPPPP\x86`@\x01Q_\x01Q\x82\x81Q\x81\x10a\x0B\x8EWa\x0B\x8Da-cV[[` \x02` \x01\x01Q` \x01\x81\x90RP[[\x80\x80a\x0B\xAA\x90a00V[\x91PPa\t\x12V[PPa\x0B\xE9V[`\x02a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x0B\xDC\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x92P[a\x0C\x0F`\x02\x84`\x02\x81\x10a\x0C\0Wa\x0B\xFFa-cV[[a\x01\x02\x02\x01a\x01\0\x01Ta\"\x0EV[\x90P`\x01\x81a\x0C\x1E\x91\x90a/sV[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x0C7Wa\x0C6a/\xA6V[[`@Q\x90\x80\x82R\x80` \x02` \x01\x82\x01`@R\x80\x15a\x0CpW\x81` \x01[a\x0C]a$\x0FV[\x81R` \x01\x90`\x01\x90\x03\x90\x81a\x0CUW\x90P[P\x84_\x01Q_\x01\x81\x90RP`\x02\x83`\x02\x81\x10a\x0C\x8FWa\x0C\x8Ea-cV[[a\x01\x02\x02\x01a\x01\x01\x01_\x90T\x90a\x01\0\n\x90\x04`\xFF\x16\x84_\x01Q` \x01\x90`\xFF\x16\x90\x81`\xFF\x16\x81RPP__\x90P[\x81\x81\x11a\x0E\xA1Wa\x0C\xF5\x81`\x02\x86`\x02\x81\x10a\x0C\xDDWa\x0C\xDCa-cV[[a\x01\x02\x02\x01a\x01\0\x01Ta!\xE5\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x0E\x8EW`\x02\x84`\x02\x81\x10a\r\rWa\r\x0Ca-cV[[a\x01\x02\x02\x01_\x01\x81a\x01\0\x81\x10a\r'Wa\r&a-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x92P\x82\x85_\x01Q_\x01Q\x82\x81Q\x81\x10a\rdWa\rca-cV[[` \x02` \x01\x01Q_\x01\x90s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RPP`\x01_\x84s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ \x80Ta\r\xE9\x90a0\0V[\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01\x82\x80Ta\x0E\x15\x90a0\0V[\x80\x15a\x0E`W\x80`\x1F\x10a\x0E7Wa\x01\0\x80\x83T\x04\x02\x83R\x91` \x01\x91a\x0E`V[\x82\x01\x91\x90_R` _ \x90[\x81T\x81R\x90`\x01\x01\x90` \x01\x80\x83\x11a\x0ECW\x82\x90\x03`\x1F\x16\x82\x01\x91[PPPPP\x85_\x01Q_\x01Q\x82\x81Q\x81\x10a\x0E~Wa\x0E}a-cV[[` \x02` \x01\x01Q` \x01\x81\x90RP[\x80\x80a\x0E\x99\x90a00V[\x91PPa\x0C\xBEV[Pa\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x84`\x80\x01\x90g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RPPa\x02\n_\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x84``\x01Q_\x01\x90s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RPPa\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x84`\xA0\x01\x90o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RPP\x83\x94PPPPP\x90V[a\x0F\x9B\x82\x82\x90Pa\"\x1FV[\x81\x81`\x01_3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ \x91\x82a\x0F\xE7\x92\x91\x90a2\x18V[PPPV[a\x0F\xF4a!{V[a\x103W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x10*\x90a+\x8CV[`@Q\x80\x91\x03\x90\xFD[3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x02\n_\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x10\xC5W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x10\xBC\x90a-\xDAV[`@Q\x80\x91\x03\x90\xFD[_a\x02\n_\x01_a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x116\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\xF9\x10g\xEBB\x0C(\xD3\x12He\xFC\x99nj\xA9\xD5A\xB9\xB4\xFE\xF9\x18\x8C\xB9e\xA6\xCCd\x91c\x8E3a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x11\xBC\x92\x91\x90a2\xE5V[`@Q\x80\x91\x03\x90\xA1V[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x12TW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x12K\x90a+$V[`@Q\x80\x91\x03\x90\xFD[a\x12\\a!\xD5V[a\x12\x9BW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x12\x92\x90a,\x80V[`@Q\x80\x91\x03\x90\xFD[a\x02\x06_\x81\x81\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x12\xC1\x90a3\x0CV[\x91\x90a\x01\0\n\x81T\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP_a\x02\x08`\x01\x01\x81\x90UPa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x13!\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\xF72@B\"F\xF6>\xD63\xEF<\xE0rk\x8A\xB8\xFBi\xD4l\x8AN^\xCB\x0B)\"f\x86t\xA1a\x02\x08_\x01_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x13\xBF\x92\x91\x90a33V[`@Q\x80\x91\x03\x90\xA1V[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x14WW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x14N\x90a+$V[`@Q\x80\x91\x03\x90\xFD[a\x14_a!\xD5V[\x15a\x14\x9FW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x14\x96\x90a3\xA4V[`@Q\x80\x91\x03\x90\xFD[a\x14\xA7a!{V[\x15a\x14\xE7W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x14\xDE\x90a4\x0CV[`@Q\x80\x91\x03\x90\xFD[a\x02\x08_\x01_\x81\x81\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x15\x0F\x90a4*V[\x91\x90a\x01\0\n\x81T\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP_`\x02a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x15Z\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90Pa\x02\x06_\x81\x81\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x15\x8C\x90a4*V[\x91\x90a\x01\0\n\x81T\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP_`\x02a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x15\xD7\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90P__\x90P[a\x16\x0E`\x02\x84`\x02\x81\x10a\x15\xFFWa\x15\xFEa-cV[[a\x01\x02\x02\x01a\x01\0\x01Ta\"\x0EV[\x81\x11a\x17\xB2W`\x02\x83`\x02\x81\x10a\x16(Wa\x16'a-cV[[a\x01\x02\x02\x01_\x01\x81a\x01\0\x81\x10a\x16BWa\x16Aa-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x83`\x02\x81\x10a\x16\x8DWa\x16\x8Ca-cV[[a\x01\x02\x02\x01_\x01\x82a\x01\0\x81\x10a\x16\xA7Wa\x16\xA6a-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x17\x9FW`\x02\x83`\x02\x81\x10a\x16\xF7Wa\x16\xF6a-cV[[a\x01\x02\x02\x01_\x01\x81a\x01\0\x81\x10a\x17\x11Wa\x17\x10a-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x83`\x02\x81\x10a\x17FWa\x17Ea-cV[[a\x01\x02\x02\x01_\x01\x82a\x01\0\x81\x10a\x17`Wa\x17_a-cV[[\x01_a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UP[\x80\x80a\x17\xAA\x90a00V[\x91PPa\x15\xE8V[P_`\x02\x83`\x02\x81\x10a\x17\xC8Wa\x17\xC7a-cV[[a\x01\x02\x02\x01a\x01\0\x01T\x90P____\x90P[\x86\x80_\x01\x90a\x17\xEA\x91\x90a4eV[\x90P\x81\x10\x15a\x19FW\x86\x80_\x01\x90a\x18\x02\x91\x90a4eV[\x82\x81\x81\x10a\x18\x13Wa\x18\x12a-cV[[\x90P`@\x02\x01_\x01` \x81\x01\x90a\x18*\x91\x90a)\xEDV[\x92P\x86\x80_\x01\x90a\x18;\x91\x90a4eV[\x82\x81\x81\x10a\x18LWa\x18Ka-cV[[\x90P`@\x02\x01` \x01` \x81\x01\x90a\x18d\x91\x90a*\x9FV[\x91P_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x82s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x03a\x18\xB3Wa\x18\xAC\x83\x85a!\xFA\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x93Pa\x18\xC9V[a\x18\xC6\x83\x85a\"\xBD\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x93P[\x81`\x02\x86`\x02\x81\x10a\x18\xDEWa\x18\xDDa-cV[[a\x01\x02\x02\x01_\x01\x84`\xFF\x16a\x01\0\x81\x10a\x18\xFBWa\x18\xFAa-cV[[\x01_a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UP\x80\x80`\x01\x01\x91PPa\x17\xDBV[P\x82`\x02\x85`\x02\x81\x10a\x19\\Wa\x19[a-cV[[a\x01\x02\x02\x01a\x01\0\x01\x81\x90UP\x85` \x01` \x81\x01\x90a\x19|\x91\x90a)\xEDV[`\x02\x85`\x02\x81\x10a\x19\x90Wa\x19\x8Fa-cV[[a\x01\x02\x02\x01a\x01\x01\x01_a\x01\0\n\x81T\x81`\xFF\x02\x19\x16\x90\x83`\xFF\x16\x02\x17\x90UP\x82a\x02\x08`\x01\x01\x81\x90UPa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x19\xE9\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7Fx\xDA\xD2\xBC\x0BG\xC6\x88\xED\x84\xF3\xFE\xE7\x9A\xBC\x18\xE6\xC9\x82-\xB0Zy\xCA\x19\xDF\xF5E3\xC7G\ra\x02\x08_\x01_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x87a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x1A\x89\x93\x92\x91\x90a6\x8BV[`@Q\x80\x91\x03\x90\xA1PPPPPPV[a\x1A\xA1a!\xD5V[\x15a\x1A\xE1W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x1A\xD8\x90a3\xA4V[`@Q\x80\x91\x03\x90\xFD[a\x1A\xE9a!{V[\x15a\x1B)W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x1B \x90a4\x0CV[`@Q\x80\x91\x03\x90\xFD[3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x80a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x1Bd\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x81\x10a\x1B\x7FWa\x1B~a-cV[[a\x01\x02\x02\x01_\x01\x82`\xFF\x16a\x01\0\x81\x10a\x1B\x9CWa\x1B\x9Ba-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x1C\x13W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x1C\n\x90a-\xDAV[`@Q\x80\x91\x03\x90\xFD[3a\x02\n_\x01_a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x1C\x84\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\xBC'H\xCF\x02\xF7\xA1)\x15%\xE8f\xEF\xC7j\xB3\xB9m2\xD7\xAF\xCB\xB2lS\xDA\xECa{8\xB4y3a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x1D\n\x92\x91\x90a2\xE5V[`@Q\x80\x91\x03\x90\xA1PV[a\x1D!\x82\x82\x90Pa\"\x1FV[__a\x1D+a!\xD5V[\x15a\x1E\xA1W3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x80`\x01a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x1Dm\x91\x90a/8V[a\x1Dw\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x81\x10a\x1D\x92Wa\x1D\x91a-cV[[a\x01\x02\x02\x01_\x01\x86`\xFF\x16a\x01\0\x81\x10a\x1D\xAFWa\x1D\xAEa-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14\x91P\x81a\x1E\x9CW3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x80a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x1E)\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x81\x10a\x1EDWa\x1ECa-cV[[a\x01\x02\x02\x01_\x01\x86`\xFF\x16a\x01\0\x81\x10a\x1EaWa\x1E`a-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14\x90P[a\x1FOV[3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x80a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x1E\xDC\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x81\x10a\x1E\xF7Wa\x1E\xF6a-cV[[a\x01\x02\x02\x01_\x01\x86`\xFF\x16a\x01\0\x81\x10a\x1F\x14Wa\x1F\x13a-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14\x91P[\x81\x80a\x1FXWP\x80[a\x1F\x97W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x1F\x8E\x90a-\xDAV[`@Q\x80\x91\x03\x90\xFD[\x83\x83`\x01_3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ \x91\x82a\x1F\xE3\x92\x91\x90a2\x18V[Pa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a \x12\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\x12Q\x81\xEC!\x88-\xECQ\xA29)\x05\xDF\xF3\xA8,\xBD\x02b\xF1\x8B\\\x0C\x03T\x88g\x1B@\xAF\xB23\x85\x85a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa \x9C\x94\x93\x92\x91\x90a7\x11V[`@Q\x80\x91\x03\x90\xA1PPPPPV[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a!9W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a!0\x90a+$V[`@Q\x80\x91\x03\x90\xFD[\x80__a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPPV[__s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x02\n_\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14\x15\x90P\x90V[__a\x02\x08`\x01\x01T\x14\x15\x90P\x90V[__\x82`\xFF\x16`\x01\x90\x1B\x84\x16\x14\x90P\x92\x91PPV[_\x81`\xFF\x16`\x01\x90\x1B\x19\x83\x16\x90P\x92\x91PPV[_a\"\x18\x82a\"\xD0V[\x90P\x91\x90PV[_\x81\x11a\"aW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\"X\x90a7\x99V[`@Q\x80\x91\x03\x90\xFD[a\x02\x07_\x01_\x90T\x90a\x01\0\n\x90\x04a\xFF\xFF\x16a\xFF\xFF\x16\x81\x11\x15a\"\xBAW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\"\xB1\x90a8\x01V[`@Q\x80\x91\x03\x90\xFD[PV[_\x81`\xFF\x16`\x01\x90\x1B\x83\x17\x90P\x92\x91PPV[_`\x07a\"\xEEo\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x84\x11a#\x9CV[\x90\x1B\x90P`\x06a#\ng\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x83\x85\x90\x1C\x11a#\x9CV[\x90\x1B\x81\x17\x90P`\x05a#$c\xFF\xFF\xFF\xFF\x83\x85\x90\x1C\x11a#\x9CV[\x90\x1B\x81\x17\x90P`\x04a#V[\x81R` \x01a#\xC7a$ZV[\x81R` \x01a#\xD4a$>V[\x81R` \x01a#\xE1a$|V[\x81R` \x01_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01_o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RP\x90V[`@Q\x80`@\x01`@R\x80_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01``\x81RP\x90V[`@Q\x80`@\x01`@R\x80``\x81R` \x01_`\xFF\x16\x81RP\x90V[`@Q\x80`@\x01`@R\x80_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01_\x81RP\x90V[`@Q\x80` \x01`@R\x80_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RP\x90V[__\xFD[__\xFD[_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[a$\xC8\x81a$\xACV[\x81\x14a$\xD2W__\xFD[PV[_\x815\x90Pa$\xE3\x81a$\xBFV[\x92\x91PPV[_`\xFF\x82\x16\x90P\x91\x90PV[a$\xFE\x81a$\xE9V[\x81\x14a%\x08W__\xFD[PV[_\x815\x90Pa%\x19\x81a$\xF5V[\x92\x91PPV[__`@\x83\x85\x03\x12\x15a%5Wa%4a$\xA4V[[_a%B\x85\x82\x86\x01a$\xD5V[\x92PP` a%S\x85\x82\x86\x01a%\x0BV[\x91PP\x92P\x92\x90PV[__\xFD[_` \x82\x84\x03\x12\x15a%vWa%ua%]V[[\x81\x90P\x92\x91PPV[_` \x82\x84\x03\x12\x15a%\x94Wa%\x93a$\xA4V[[_a%\xA1\x84\x82\x85\x01a%aV[\x91PP\x92\x91PPV[_\x81Q\x90P\x91\x90PV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[_\x81\x90P` \x82\x01\x90P\x91\x90PV[_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[_a%\xFC\x82a%\xD3V[\x90P\x91\x90PV[a&\x0C\x81a%\xF2V[\x82RPPV[_\x81Q\x90P\x91\x90PV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[\x82\x81\x83^_\x83\x83\x01RPPPV[_`\x1F\x19`\x1F\x83\x01\x16\x90P\x91\x90PV[_a&T\x82a&\x12V[a&^\x81\x85a&\x1CV[\x93Pa&n\x81\x85` \x86\x01a&,V[a&w\x81a&:V[\x84\x01\x91PP\x92\x91PPV[_`@\x83\x01_\x83\x01Qa&\x97_\x86\x01\x82a&\x03V[P` \x83\x01Q\x84\x82\x03` \x86\x01Ra&\xAF\x82\x82a&JV[\x91PP\x80\x91PP\x92\x91PPV[_a&\xC7\x83\x83a&\x82V[\x90P\x92\x91PPV[_` \x82\x01\x90P\x91\x90PV[_a&\xE5\x82a%\xAAV[a&\xEF\x81\x85a%\xB4V[\x93P\x83` \x82\x02\x85\x01a'\x01\x85a%\xC4V[\x80_[\x85\x81\x10\x15a'\x82a1 V[\x84\x84Ta0\xAEV[\x82UPPPPV[__\x90P\x90V[a1]a1NV[a1h\x81\x84\x84a1)V[PPPV[[\x81\x81\x10\x15a1\x8BWa1\x80_\x82a1UV[`\x01\x81\x01\x90Pa1nV[PPV[`\x1F\x82\x11\x15a1\xD0Wa1\xA1\x81a0\x81V[a1\xAA\x84a0\x93V[\x81\x01` \x85\x10\x15a1\xB9W\x81\x90P[a1\xCDa1\xC5\x85a0\x93V[\x83\x01\x82a1mV[PP[PPPV[_\x82\x82\x1C\x90P\x92\x91PPV[_a1\xF0_\x19\x84`\x08\x02a1\xD5V[\x19\x80\x83\x16\x91PP\x92\x91PPV[_a2\x08\x83\x83a1\xE1V[\x91P\x82`\x02\x02\x82\x17\x90P\x92\x91PPV[a2\"\x83\x83a0wV[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a2;Wa2:a/\xA6V[[a2E\x82Ta0\0V[a2P\x82\x82\x85a1\x8FV[_`\x1F\x83\x11`\x01\x81\x14a2}W_\x84\x15a2kW\x82\x87\x015\x90P[a2u\x85\x82a1\xFDV[\x86UPa2\xDCV[`\x1F\x19\x84\x16a2\x8B\x86a0\x81V[_[\x82\x81\x10\x15a2\xB2W\x84\x89\x015\x82U`\x01\x82\x01\x91P` \x85\x01\x94P` \x81\x01\x90Pa2\x8DV[\x86\x83\x10\x15a2\xCFW\x84\x89\x015a2\xCB`\x1F\x89\x16\x82a1\xE1V[\x83UP[`\x01`\x02\x88\x02\x01\x88UPPP[PPPPPPPV[_`@\x82\x01\x90Pa2\xF8_\x83\x01\x85a.\x07V[a3\x05` \x83\x01\x84a,\x0EV[\x93\x92PPPV[_a3\x16\x82a$\xACV[\x91P_\x82\x03a3(Wa3'a+\xAAV[[`\x01\x82\x03\x90P\x91\x90PV[_`@\x82\x01\x90Pa3F_\x83\x01\x85a-\xF8V[a3S` \x83\x01\x84a,\x0EV[\x93\x92PPPV[\x7Fmigration in progress\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a3\x8E`\x15\x83a*\xCAV[\x91Pa3\x99\x82a3ZV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra3\xBB\x81a3\x82V[\x90P\x91\x90PV[\x7Fmaintenance in progress\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a3\xF6`\x17\x83a*\xCAV[\x91Pa4\x01\x82a3\xC2V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra4#\x81a3\xEAV[\x90P\x91\x90PV[_a44\x82a$\xACV[\x91Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x03a4NWa4Ma+\xAAV[[`\x01\x82\x01\x90P\x91\x90PV[__\xFD[__\xFD[__\xFD[__\x835`\x01` \x03\x846\x03\x03\x81\x12a4\x81Wa4\x80a4YV[[\x80\x84\x01\x92P\x825\x91Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15a4\xA3Wa4\xA2a4]V[[` \x83\x01\x92P`@\x82\x026\x03\x83\x13\x15a4\xBFWa4\xBEa4aV[[P\x92P\x92\x90PV[__\xFD[__\xFD[__\xFD[__\x835`\x01` \x03\x846\x03\x03\x81\x12a4\xEFWa4\xEEa4\xCFV[[\x83\x81\x01\x92P\x825\x91P` \x83\x01\x92Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15a5\x17Wa5\x16a4\xC7V[[`@\x82\x026\x03\x83\x13\x15a5-Wa5,a4\xCBV[[P\x92P\x92\x90PV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[_\x81\x90P\x91\x90PV[_a5\\` \x84\x01\x84a%\x0BV[\x90P\x92\x91PPV[_a5r` \x84\x01\x84a*\x8BV[\x90P\x92\x91PPV[`@\x82\x01a5\x8A_\x83\x01\x83a5NV[a5\x96_\x85\x01\x82a'NV[Pa5\xA4` \x83\x01\x83a5dV[a5\xB1` \x85\x01\x82a&\x03V[PPPPV[_a5\xC2\x83\x83a5zV[`@\x83\x01\x90P\x92\x91PPV[_\x82\x90P\x92\x91PPV[_`@\x82\x01\x90P\x91\x90PV[_a5\xEF\x83\x85a55V[\x93Pa5\xFA\x82a5EV[\x80_[\x85\x81\x10\x15a62Wa6\x0F\x82\x84a5\xCEV[a6\x19\x88\x82a5\xB7V[\x97Pa6$\x83a5\xD8V[\x92PP`\x01\x81\x01\x90Pa5\xFDV[P\x85\x92PPP\x93\x92PPPV[_`@\x83\x01a6P_\x84\x01\x84a4\xD3V[\x85\x83\x03_\x87\x01Ra6b\x83\x82\x84a5\xE4V[\x92PPPa6s` \x84\x01\x84a5NV[a6\x80` \x86\x01\x82a'NV[P\x80\x91PP\x92\x91PPV[_``\x82\x01\x90Pa6\x9E_\x83\x01\x86a-\xF8V[\x81\x81\x03` \x83\x01Ra6\xB0\x81\x85a6?V[\x90Pa6\xBF`@\x83\x01\x84a,\x0EV[\x94\x93PPPPV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[\x82\x81\x837_\x83\x83\x01RPPPV[_a6\xF0\x83\x85a6\xC7V[\x93Pa6\xFD\x83\x85\x84a6\xD7V[a7\x06\x83a&:V[\x84\x01\x90P\x93\x92PPPV[_``\x82\x01\x90Pa7$_\x83\x01\x87a.\x07V[\x81\x81\x03` \x83\x01Ra77\x81\x85\x87a6\xE5V[\x90Pa7F`@\x83\x01\x84a,\x0EV[\x95\x94PPPPPV[\x7Fempty operator data\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a7\x83`\x13\x83a*\xCAV[\x91Pa7\x8E\x82a7OV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra7\xB0\x81a7wV[\x90P\x91\x90PV[\x7Foperator data too large\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a7\xEB`\x17\x83a*\xCAV[\x91Pa7\xF6\x82a7\xB7V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra8\x18\x81a7\xDFV[\x90P\x91\x90PV\xFE\xA2dipfsX\"\x12 \xFA\x04\xDE\xADB^j\xA2\xEEQe+w\xCD\x8B\xEC4O\x89\xD5\xA5\xD1\x8BB\xF4\x88\x9Bz\xBA\xD1s\"dsolcC\0\x08\x1C\x003", - ); - /// The runtime bytecode of the contract, as deployed on the network. - /// - /// ```text - ///0x608060405234801561000f575f5ffd5b50600436106100a7575f3560e01c8063ad36e6d01161006f578063ad36e6d014610127578063c130809a14610131578063cdbfc62d1461013b578063dd3fd26914610157578063f019b15414610173578063f2fde38b1461018f576100a7565b80633048bfba146100ab57806355a47d0a146100b557806365706f9c146100d157806375418b9d146100ed5780638b5252d61461010b575b5f5ffd5b6100b36101ab565b005b6100cf60048036038101906100ca919061251f565b61037f565b005b6100eb60048036038101906100e6919061257f565b6106bd565b005b6100f5610761565b60405161010291906128bc565b60405180910390f35b6101256004803603810190610120919061293d565b610f8f565b005b61012f610fec565b005b6101396111c6565b005b610155600480360381019061015091906129a6565b6113c9565b005b610171600480360381019061016c91906129ed565b611a99565b005b61018d60048036038101906101889190612a18565b611d15565b005b6101a960048036038101906101a49190612a9f565b6120ab565b005b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610239576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161023090612b24565b60405180910390fd5b61024161217b565b610280576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161027790612b8c565b60405180910390fd5b5f61020a5f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff16809291906102f190612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507f8fb9cd054d0a022110cced239e908b834e4cd219511856d4eaae3051d932d60461020b5f9054906101000a90046fffffffffffffffffffffffffffffffff166040516103759190612c1d565b60405180910390a1565b6103876121d5565b6103c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103bd90612c80565b60405180910390fd5b6102085f015f9054906101000a900467ffffffffffffffff1667ffffffffffffffff168267ffffffffffffffff1614610434576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042b90612ce8565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff166002806102065f9054906101000a900467ffffffffffffffff1661046f9190612d33565b67ffffffffffffffff166002811061048a57610489612d63565b5b61010202015f018260ff1661010081106104a7576104a6612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461051e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161051590612dda565b60405180910390fd5b61053781610208600101546121e590919063ffffffff16565b6106b95761055481610208600101546121fa90919063ffffffff16565b6102086001018190555061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff168092919061058c90612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550505f6102086001015403610646577f01269879535f40ee8957e15e160bf1866c5e2728ff0cbc583d848821e2639b4e6102085f015f9054906101000a900467ffffffffffffffff163361020b5f9054906101000a90046fffffffffffffffffffffffffffffffff1660405161063993929190612e16565b60405180910390a16106b8565b7faf5e90e72015f43138f66b4cd08bd1dfa2839030104f22a00af843fe847c6d196102085f015f9054906101000a900467ffffffffffffffff163361020b5f9054906101000a90046fffffffffffffffffffffffffffffffff166040516106af93929190612e16565b60405180910390a15b5b5050565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461074b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161074290612b24565b60405180910390fd5b80610207818161075b9190612f2a565b90505050565b6107696123a7565b6107716123a7565b5f5f5f61077c6121d5565b15610bb9576102085f015f9054906101000a900467ffffffffffffffff1684602001515f019067ffffffffffffffff16908167ffffffffffffffff16815250506102086001015484602001516020018181525050600260016102065f9054906101000a900467ffffffffffffffff166107f59190612f38565b6107ff9190612d33565b67ffffffffffffffff1692505f60026102065f9054906101000a900467ffffffffffffffff1661082f9190612d33565b67ffffffffffffffff1690506108616002826002811061085257610851612d63565b5b6101020201610100015461220e565b91506001826108709190612f73565b67ffffffffffffffff81111561088957610888612fa6565b5b6040519080825280602002602001820160405280156108c257816020015b6108af61240f565b8152602001906001900390816108a75790505b5085604001515f0181905250600281600281106108e2576108e1612d63565b5b6101020201610101015f9054906101000a900460ff1685604001516020019060ff16908160ff16815250505f5f90505b828111610bb257610949816002846002811061093157610930612d63565b5b610102020161010001546121e590919063ffffffff16565b610b9f576002826002811061096157610960612d63565b5b61010202015f0181610100811061097b5761097a612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1693508386604001515f015182815181106109b9576109b8612d63565b5b60200260200101515f019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050610a268160028760028110610a0e57610a0d612d63565b5b610102020161010001546121e590919063ffffffff16565b80610aab57508373ffffffffffffffffffffffffffffffffffffffff1660028660028110610a5757610a56612d63565b5b61010202015f01826101008110610a7157610a70612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b15610b9e5760015f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f208054610af890613000565b80601f0160208091040260200160405190810160405280929190818152602001828054610b2490613000565b8015610b6f5780601f10610b4657610100808354040283529160200191610b6f565b820191905f5260205f20905b815481529060010190602001808311610b5257829003601f168201915b505050505086604001515f01518281518110610b8e57610b8d612d63565b5b6020026020010151602001819052505b5b8080610baa90613030565b915050610912565b5050610be9565b60026102065f9054906101000a900467ffffffffffffffff16610bdc9190612d33565b67ffffffffffffffff1692505b610c0f60028460028110610c0057610bff612d63565b5b6101020201610100015461220e565b9050600181610c1e9190612f73565b67ffffffffffffffff811115610c3757610c36612fa6565b5b604051908082528060200260200182016040528015610c7057816020015b610c5d61240f565b815260200190600190039081610c555790505b50845f01515f018190525060028360028110610c8f57610c8e612d63565b5b6101020201610101015f9054906101000a900460ff16845f01516020019060ff16908160ff16815250505f5f90505b818111610ea157610cf58160028660028110610cdd57610cdc612d63565b5b610102020161010001546121e590919063ffffffff16565b610e8e5760028460028110610d0d57610d0c612d63565b5b61010202015f01816101008110610d2757610d26612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16925082855f01515f01518281518110610d6457610d63612d63565b5b60200260200101515f019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f208054610de990613000565b80601f0160208091040260200160405190810160405280929190818152602001828054610e1590613000565b8015610e605780601f10610e3757610100808354040283529160200191610e60565b820191905f5260205f20905b815481529060010190602001808311610e4357829003601f168201915b5050505050855f01515f01518281518110610e7e57610e7d612d63565b5b6020026020010151602001819052505b8080610e9990613030565b915050610cbe565b506102065f9054906101000a900467ffffffffffffffff16846080019067ffffffffffffffff16908167ffffffffffffffff168152505061020a5f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684606001515f019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505061020b5f9054906101000a90046fffffffffffffffffffffffffffffffff168460a001906fffffffffffffffffffffffffffffffff1690816fffffffffffffffffffffffffffffffff16815250508394505050505090565b610f9b8282905061221f565b818160015f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f209182610fe7929190613218565b505050565b610ff461217b565b611033576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161102a90612b8c565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff1661020a5f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146110c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110bc90612dda565b60405180910390fd5b5f61020a5f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff168092919061113690612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507ff91067eb420c28d3124865fc996e6aa9d541b9b4fef9188cb965a6cc6491638e3361020b5f9054906101000a90046fffffffffffffffffffffffffffffffff166040516111bc9291906132e5565b60405180910390a1565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611254576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161124b90612b24565b60405180910390fd5b61125c6121d5565b61129b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161129290612c80565b60405180910390fd5b6102065f81819054906101000a900467ffffffffffffffff16809291906112c19061330c565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550505f6102086001018190555061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff168092919061132190612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507ff73240422246f63ed633ef3ce0726b8ab8fb69d46c8a4e5ecb0b2922668674a16102085f015f9054906101000a900467ffffffffffffffff1661020b5f9054906101000a90046fffffffffffffffffffffffffffffffff166040516113bf929190613333565b60405180910390a1565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611457576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161144e90612b24565b60405180910390fd5b61145f6121d5565b1561149f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611496906133a4565b60405180910390fd5b6114a761217b565b156114e7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114de9061340c565b60405180910390fd5b6102085f015f81819054906101000a900467ffffffffffffffff168092919061150f9061342a565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550505f60026102065f9054906101000a900467ffffffffffffffff1661155a9190612d33565b67ffffffffffffffff1690506102065f81819054906101000a900467ffffffffffffffff168092919061158c9061342a565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550505f60026102065f9054906101000a900467ffffffffffffffff166115d79190612d33565b67ffffffffffffffff1690505f5f90505b61160e600284600281106115ff576115fe612d63565b5b6101020201610100015461220e565b81116117b2576002836002811061162857611627612d63565b5b61010202015f0181610100811061164257611641612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166002836002811061168d5761168c612d63565b5b61010202015f018261010081106116a7576116a6612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461179f57600283600281106116f7576116f6612d63565b5b61010202015f0181610100811061171157611710612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff166002836002811061174657611745612d63565b5b61010202015f018261010081106117605761175f612d63565b5b015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b80806117aa90613030565b9150506115e8565b505f600283600281106117c8576117c7612d63565b5b6101020201610100015490505f5f5f5f90505b86805f01906117ea9190613465565b90508110156119465786805f01906118029190613465565b8281811061181357611812612d63565b5b9050604002015f01602081019061182a91906129ed565b925086805f019061183b9190613465565b8281811061184c5761184b612d63565b5b90506040020160200160208101906118649190612a9f565b91505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036118b3576118ac83856121fa90919063ffffffff16565b93506118c9565b6118c683856122bd90919063ffffffff16565b93505b81600286600281106118de576118dd612d63565b5b61010202015f018460ff1661010081106118fb576118fa612d63565b5b015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080806001019150506117db565b50826002856002811061195c5761195b612d63565b5b6101020201610100018190555085602001602081019061197c91906129ed565b600285600281106119905761198f612d63565b5b6101020201610101015f6101000a81548160ff021916908360ff160217905550826102086001018190555061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff16809291906119e990612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507f78dad2bc0b47c688ed84f3fee79abc18e6c9822db05a79ca19dff54533c7470d6102085f015f9054906101000a900467ffffffffffffffff168761020b5f9054906101000a90046fffffffffffffffffffffffffffffffff16604051611a899392919061368b565b60405180910390a1505050505050565b611aa16121d5565b15611ae1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ad8906133a4565b60405180910390fd5b611ae961217b565b15611b29576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b209061340c565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff166002806102065f9054906101000a900467ffffffffffffffff16611b649190612d33565b67ffffffffffffffff1660028110611b7f57611b7e612d63565b5b61010202015f018260ff166101008110611b9c57611b9b612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611c13576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c0a90612dda565b60405180910390fd5b3361020a5f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff1680929190611c8490612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507fbc2748cf02f7a1291525e866efc76ab3b96d32d7afcbb26c53daec617b38b4793361020b5f9054906101000a90046fffffffffffffffffffffffffffffffff16604051611d0a9291906132e5565b60405180910390a150565b611d218282905061221f565b5f5f611d2b6121d5565b15611ea1573373ffffffffffffffffffffffffffffffffffffffff1660028060016102065f9054906101000a900467ffffffffffffffff16611d6d9190612f38565b611d779190612d33565b67ffffffffffffffff1660028110611d9257611d91612d63565b5b61010202015f018660ff166101008110611daf57611dae612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614915081611e9c573373ffffffffffffffffffffffffffffffffffffffff166002806102065f9054906101000a900467ffffffffffffffff16611e299190612d33565b67ffffffffffffffff1660028110611e4457611e43612d63565b5b61010202015f018660ff166101008110611e6157611e60612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161490505b611f4f565b3373ffffffffffffffffffffffffffffffffffffffff166002806102065f9054906101000a900467ffffffffffffffff16611edc9190612d33565b67ffffffffffffffff1660028110611ef757611ef6612d63565b5b61010202015f018660ff166101008110611f1457611f13612d63565b5b015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161491505b8180611f585750805b611f97576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f8e90612dda565b60405180910390fd5b838360015f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f209182611fe3929190613218565b5061020b5f81819054906101000a90046fffffffffffffffffffffffffffffffff168092919061201290612bd7565b91906101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550507f125181ec21882dec51a2392905dff3a82cbd0262f18b5c0c035488671b40afb233858561020b5f9054906101000a90046fffffffffffffffffffffffffffffffff1660405161209c9493929190613711565b60405180910390a15050505050565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612139576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161213090612b24565b60405180910390fd5b805f5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b5f5f73ffffffffffffffffffffffffffffffffffffffff1661020a5f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415905090565b5f5f610208600101541415905090565b5f5f8260ff166001901b841614905092915050565b5f8160ff166001901b198316905092915050565b5f612218826122d0565b9050919050565b5f8111612261576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161225890613799565b60405180910390fd5b6102075f015f9054906101000a900461ffff1661ffff168111156122ba576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122b190613801565b60405180910390fd5b50565b5f8160ff166001901b8317905092915050565b5f60076122ee6fffffffffffffffffffffffffffffffff841161239c565b901b9050600661230a67ffffffffffffffff8385901c1161239c565b901b81179050600561232463ffffffff8385901c1161239c565b901b81179050600461233c61ffff8385901c1161239c565b901b81179050600361235360ff8385901c1161239c565b901b81179050600261236a600f8385901c1161239c565b901b811790507d01010202020203030303030303030000000000000000000000000000000082821c1a81179050919050565b5f8115159050919050565b6040518060c001604052806123ba61243e565b81526020016123c761245a565b81526020016123d461243e565b81526020016123e161247c565b81526020015f67ffffffffffffffff1681526020015f6fffffffffffffffffffffffffffffffff1681525090565b60405180604001604052805f73ffffffffffffffffffffffffffffffffffffffff168152602001606081525090565b6040518060400160405280606081526020015f60ff1681525090565b60405180604001604052805f67ffffffffffffffff1681526020015f81525090565b60405180602001604052805f73ffffffffffffffffffffffffffffffffffffffff1681525090565b5f5ffd5b5f5ffd5b5f67ffffffffffffffff82169050919050565b6124c8816124ac565b81146124d2575f5ffd5b50565b5f813590506124e3816124bf565b92915050565b5f60ff82169050919050565b6124fe816124e9565b8114612508575f5ffd5b50565b5f81359050612519816124f5565b92915050565b5f5f60408385031215612535576125346124a4565b5b5f612542858286016124d5565b92505060206125538582860161250b565b9150509250929050565b5f5ffd5b5f602082840312156125765761257561255d565b5b81905092915050565b5f60208284031215612594576125936124a4565b5b5f6125a184828501612561565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6125fc826125d3565b9050919050565b61260c816125f2565b82525050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61265482612612565b61265e818561261c565b935061266e81856020860161262c565b6126778161263a565b840191505092915050565b5f604083015f8301516126975f860182612603565b50602083015184820360208601526126af828261264a565b9150508091505092915050565b5f6126c78383612682565b905092915050565b5f602082019050919050565b5f6126e5826125aa565b6126ef81856125b4565b935083602082028501612701856125c4565b805f5b8581101561273c578484038952815161271d85826126bc565b9450612728836126cf565b925060208a01995050600181019050612704565b50829750879550505050505092915050565b612757816124e9565b82525050565b5f604083015f8301518482035f86015261277782826126db565b915050602083015161278c602086018261274e565b508091505092915050565b6127a0816124ac565b82525050565b5f819050919050565b6127b8816127a6565b82525050565b604082015f8201516127d25f850182612797565b5060208201516127e560208501826127af565b50505050565b602082015f8201516127ff5f850182612603565b50505050565b5f6fffffffffffffffffffffffffffffffff82169050919050565b61282981612805565b82525050565b5f60e083015f8301518482035f860152612849828261275d565b915050602083015161285e60208601826127be565b5060408301518482036060860152612876828261275d565b915050606083015161288b60808601826127eb565b50608083015161289e60a0860182612797565b5060a08301516128b160c0860182612820565b508091505092915050565b5f6020820190508181035f8301526128d4818461282f565b905092915050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f83601f8401126128fd576128fc6128dc565b5b8235905067ffffffffffffffff81111561291a576129196128e0565b5b602083019150836001820283011115612936576129356128e4565b5b9250929050565b5f5f60208385031215612953576129526124a4565b5b5f83013567ffffffffffffffff8111156129705761296f6124a8565b5b61297c858286016128e8565b92509250509250929050565b5f6040828403121561299d5761299c61255d565b5b81905092915050565b5f602082840312156129bb576129ba6124a4565b5b5f82013567ffffffffffffffff8111156129d8576129d76124a8565b5b6129e484828501612988565b91505092915050565b5f60208284031215612a0257612a016124a4565b5b5f612a0f8482850161250b565b91505092915050565b5f5f5f60408486031215612a2f57612a2e6124a4565b5b5f612a3c8682870161250b565b935050602084013567ffffffffffffffff811115612a5d57612a5c6124a8565b5b612a69868287016128e8565b92509250509250925092565b612a7e816125f2565b8114612a88575f5ffd5b50565b5f81359050612a9981612a75565b92915050565b5f60208284031215612ab457612ab36124a4565b5b5f612ac184828501612a8b565b91505092915050565b5f82825260208201905092915050565b7f6e6f7420746865206f776e6572000000000000000000000000000000000000005f82015250565b5f612b0e600d83612aca565b9150612b1982612ada565b602082019050919050565b5f6020820190508181035f830152612b3b81612b02565b9050919050565b7f6e6f206d61696e74656e616e63650000000000000000000000000000000000005f82015250565b5f612b76600e83612aca565b9150612b8182612b42565b602082019050919050565b5f6020820190508181035f830152612ba381612b6a565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f612be182612805565b91506fffffffffffffffffffffffffffffffff8203612c0357612c02612baa565b5b600182019050919050565b612c1781612805565b82525050565b5f602082019050612c305f830184612c0e565b92915050565b7f6e6f206d6967726174696f6e00000000000000000000000000000000000000005f82015250565b5f612c6a600c83612aca565b9150612c7582612c36565b602082019050919050565b5f6020820190508181035f830152612c9781612c5e565b9050919050565b7f77726f6e67206d6967726174696f6e20696400000000000000000000000000005f82015250565b5f612cd2601283612aca565b9150612cdd82612c9e565b602082019050919050565b5f6020820190508181035f830152612cff81612cc6565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f612d3d826124ac565b9150612d48836124ac565b925082612d5857612d57612d06565b5b828206905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f77726f6e67206f70657261746f720000000000000000000000000000000000005f82015250565b5f612dc4600e83612aca565b9150612dcf82612d90565b602082019050919050565b5f6020820190508181035f830152612df181612db8565b9050919050565b612e01816124ac565b82525050565b612e10816125f2565b82525050565b5f606082019050612e295f830186612df8565b612e366020830185612e07565b612e436040830184612c0e565b949350505050565b5f61ffff82169050919050565b612e6181612e4b565b8114612e6b575f5ffd5b50565b5f8135612e7a81612e58565b80915050919050565b5f815f1b9050919050565b5f61ffff612e9b84612e83565b9350801983169250808416831791505092915050565b5f819050919050565b5f612ed4612ecf612eca84612e4b565b612eb1565b612e4b565b9050919050565b5f819050919050565b612eed82612eba565b612f00612ef982612edb565b8354612e8e565b8255505050565b5f81015f830180612f1781612e6e565b9050612f238184612ee4565b5050505050565b612f348282612f07565b5050565b5f612f42826124ac565b9150612f4d836124ac565b9250828203905067ffffffffffffffff811115612f6d57612f6c612baa565b5b92915050565b5f612f7d826127a6565b9150612f88836127a6565b9250828201905080821115612fa057612f9f612baa565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061301757607f821691505b60208210810361302a57613029612fd3565b5b50919050565b5f61303a826127a6565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361306c5761306b612baa565b5b600182019050919050565b5f82905092915050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026130dd7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826130a2565b6130e786836130a2565b95508019841693508086168417925050509392505050565b5f61311961311461310f846127a6565b612eb1565b6127a6565b9050919050565b5f819050919050565b613132836130ff565b61314661313e82613120565b8484546130ae565b825550505050565b5f5f905090565b61315d61314e565b613168818484613129565b505050565b5b8181101561318b576131805f82613155565b60018101905061316e565b5050565b601f8211156131d0576131a181613081565b6131aa84613093565b810160208510156131b9578190505b6131cd6131c585613093565b83018261316d565b50505b505050565b5f82821c905092915050565b5f6131f05f19846008026131d5565b1980831691505092915050565b5f61320883836131e1565b9150826002028217905092915050565b6132228383613077565b67ffffffffffffffff81111561323b5761323a612fa6565b5b6132458254613000565b61325082828561318f565b5f601f83116001811461327d575f841561326b578287013590505b61327585826131fd565b8655506132dc565b601f19841661328b86613081565b5f5b828110156132b25784890135825560018201915060208501945060208101905061328d565b868310156132cf57848901356132cb601f8916826131e1565b8355505b6001600288020188555050505b50505050505050565b5f6040820190506132f85f830185612e07565b6133056020830184612c0e565b9392505050565b5f613316826124ac565b91505f820361332857613327612baa565b5b600182039050919050565b5f6040820190506133465f830185612df8565b6133536020830184612c0e565b9392505050565b7f6d6967726174696f6e20696e2070726f677265737300000000000000000000005f82015250565b5f61338e601583612aca565b91506133998261335a565b602082019050919050565b5f6020820190508181035f8301526133bb81613382565b9050919050565b7f6d61696e74656e616e636520696e2070726f67726573730000000000000000005f82015250565b5f6133f6601783612aca565b9150613401826133c2565b602082019050919050565b5f6020820190508181035f830152613423816133ea565b9050919050565b5f613434826124ac565b915067ffffffffffffffff820361344e5761344d612baa565b5b600182019050919050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f8335600160200384360303811261348157613480613459565b5b80840192508235915067ffffffffffffffff8211156134a3576134a261345d565b5b6020830192506040820236038313156134bf576134be613461565b5b509250929050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f833560016020038436030381126134ef576134ee6134cf565b5b83810192508235915060208301925067ffffffffffffffff821115613517576135166134c7565b5b60408202360383131561352d5761352c6134cb565b5b509250929050565b5f82825260208201905092915050565b5f819050919050565b5f61355c602084018461250b565b905092915050565b5f6135726020840184612a8b565b905092915050565b6040820161358a5f83018361354e565b6135965f85018261274e565b506135a46020830183613564565b6135b16020850182612603565b50505050565b5f6135c2838361357a565b60408301905092915050565b5f82905092915050565b5f604082019050919050565b5f6135ef8385613535565b93506135fa82613545565b805f5b858110156136325761360f82846135ce565b61361988826135b7565b9750613624836135d8565b9250506001810190506135fd565b5085925050509392505050565b5f604083016136505f8401846134d3565b8583035f8701526136628382846135e4565b92505050613673602084018461354e565b613680602086018261274e565b508091505092915050565b5f60608201905061369e5f830186612df8565b81810360208301526136b0818561363f565b90506136bf6040830184612c0e565b949350505050565b5f82825260208201905092915050565b828183375f83830152505050565b5f6136f083856136c7565b93506136fd8385846136d7565b6137068361263a565b840190509392505050565b5f6060820190506137245f830187612e07565b81810360208301526137378185876136e5565b90506137466040830184612c0e565b95945050505050565b7f656d707479206f70657261746f722064617461000000000000000000000000005f82015250565b5f613783601383612aca565b915061378e8261374f565b602082019050919050565b5f6020820190508181035f8301526137b081613777565b9050919050565b7f6f70657261746f72206461746120746f6f206c617267650000000000000000005f82015250565b5f6137eb601783612aca565b91506137f6826137b7565b602082019050919050565b5f6020820190508181035f830152613818816137df565b905091905056fea2646970667358221220fa04dead425e6aa2ee51652b77cd8bec344f89d5a5d18b42f4889b7abad1732264736f6c634300081c0033 - /// ``` - #[rustfmt::skip] - #[allow(clippy::all)] - pub static DEPLOYED_BYTECODE: alloy_sol_types::private::Bytes = alloy_sol_types::private::Bytes::from_static( - b"`\x80`@R4\x80\x15a\0\x0FW__\xFD[P`\x046\x10a\0\xA7W_5`\xE0\x1C\x80c\xAD6\xE6\xD0\x11a\0oW\x80c\xAD6\xE6\xD0\x14a\x01'W\x80c\xC10\x80\x9A\x14a\x011W\x80c\xCD\xBF\xC6-\x14a\x01;W\x80c\xDD?\xD2i\x14a\x01WW\x80c\xF0\x19\xB1T\x14a\x01sW\x80c\xF2\xFD\xE3\x8B\x14a\x01\x8FWa\0\xA7V[\x80c0H\xBF\xBA\x14a\0\xABW\x80cU\xA4}\n\x14a\0\xB5W\x80cepo\x9C\x14a\0\xD1W\x80cuA\x8B\x9D\x14a\0\xEDW\x80c\x8BRR\xD6\x14a\x01\x0BW[__\xFD[a\0\xB3a\x01\xABV[\0[a\0\xCF`\x04\x806\x03\x81\x01\x90a\0\xCA\x91\x90a%\x1FV[a\x03\x7FV[\0[a\0\xEB`\x04\x806\x03\x81\x01\x90a\0\xE6\x91\x90a%\x7FV[a\x06\xBDV[\0[a\0\xF5a\x07aV[`@Qa\x01\x02\x91\x90a(\xBCV[`@Q\x80\x91\x03\x90\xF3[a\x01%`\x04\x806\x03\x81\x01\x90a\x01 \x91\x90a)=V[a\x0F\x8FV[\0[a\x01/a\x0F\xECV[\0[a\x019a\x11\xC6V[\0[a\x01U`\x04\x806\x03\x81\x01\x90a\x01P\x91\x90a)\xA6V[a\x13\xC9V[\0[a\x01q`\x04\x806\x03\x81\x01\x90a\x01l\x91\x90a)\xEDV[a\x1A\x99V[\0[a\x01\x8D`\x04\x806\x03\x81\x01\x90a\x01\x88\x91\x90a*\x18V[a\x1D\x15V[\0[a\x01\xA9`\x04\x806\x03\x81\x01\x90a\x01\xA4\x91\x90a*\x9FV[a \xABV[\0[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x029W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x020\x90a+$V[`@Q\x80\x91\x03\x90\xFD[a\x02Aa!{V[a\x02\x80W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x02w\x90a+\x8CV[`@Q\x80\x91\x03\x90\xFD[_a\x02\n_\x01_a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x02\xF1\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\x8F\xB9\xCD\x05M\n\x02!\x10\xCC\xED#\x9E\x90\x8B\x83NL\xD2\x19Q\x18V\xD4\xEA\xAE0Q\xD92\xD6\x04a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x03u\x91\x90a,\x1DV[`@Q\x80\x91\x03\x90\xA1V[a\x03\x87a!\xD5V[a\x03\xC6W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x03\xBD\x90a,\x80V[`@Q\x80\x91\x03\x90\xFD[a\x02\x08_\x01_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x82g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x044W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x04+\x90a,\xE8V[`@Q\x80\x91\x03\x90\xFD[3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x80a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x04o\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x81\x10a\x04\x8AWa\x04\x89a-cV[[a\x01\x02\x02\x01_\x01\x82`\xFF\x16a\x01\0\x81\x10a\x04\xA7Wa\x04\xA6a-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x05\x1EW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x05\x15\x90a-\xDAV[`@Q\x80\x91\x03\x90\xFD[a\x057\x81a\x02\x08`\x01\x01Ta!\xE5\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x06\xB9Wa\x05T\x81a\x02\x08`\x01\x01Ta!\xFA\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x02\x08`\x01\x01\x81\x90UPa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x05\x8C\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP_a\x02\x08`\x01\x01T\x03a\x06FW\x7F\x01&\x98yS_@\xEE\x89W\xE1^\x16\x0B\xF1\x86l^'(\xFF\x0C\xBCX=\x84\x88!\xE2c\x9BNa\x02\x08_\x01_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x069\x93\x92\x91\x90a.\x16V[`@Q\x80\x91\x03\x90\xA1a\x06\xB8V[\x7F\xAF^\x90\xE7 \x15\xF418\xF6kL\xD0\x8B\xD1\xDF\xA2\x83\x900\x10O\"\xA0\n\xF8C\xFE\x84|m\x19a\x02\x08_\x01_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x06\xAF\x93\x92\x91\x90a.\x16V[`@Q\x80\x91\x03\x90\xA1[[PPV[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x07KW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x07B\x90a+$V[`@Q\x80\x91\x03\x90\xFD[\x80a\x02\x07\x81\x81a\x07[\x91\x90a/*V[\x90PPPV[a\x07ia#\xA7V[a\x07qa#\xA7V[___a\x07|a!\xD5V[\x15a\x0B\xB9Wa\x02\x08_\x01_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x84` \x01Q_\x01\x90g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RPPa\x02\x08`\x01\x01T\x84` \x01Q` \x01\x81\x81RPP`\x02`\x01a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x07\xF5\x91\x90a/8V[a\x07\xFF\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x92P_`\x02a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x08/\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90Pa\x08a`\x02\x82`\x02\x81\x10a\x08RWa\x08Qa-cV[[a\x01\x02\x02\x01a\x01\0\x01Ta\"\x0EV[\x91P`\x01\x82a\x08p\x91\x90a/sV[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x08\x89Wa\x08\x88a/\xA6V[[`@Q\x90\x80\x82R\x80` \x02` \x01\x82\x01`@R\x80\x15a\x08\xC2W\x81` \x01[a\x08\xAFa$\x0FV[\x81R` \x01\x90`\x01\x90\x03\x90\x81a\x08\xA7W\x90P[P\x85`@\x01Q_\x01\x81\x90RP`\x02\x81`\x02\x81\x10a\x08\xE2Wa\x08\xE1a-cV[[a\x01\x02\x02\x01a\x01\x01\x01_\x90T\x90a\x01\0\n\x90\x04`\xFF\x16\x85`@\x01Q` \x01\x90`\xFF\x16\x90\x81`\xFF\x16\x81RPP__\x90P[\x82\x81\x11a\x0B\xB2Wa\tI\x81`\x02\x84`\x02\x81\x10a\t1Wa\t0a-cV[[a\x01\x02\x02\x01a\x01\0\x01Ta!\xE5\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x0B\x9FW`\x02\x82`\x02\x81\x10a\taWa\t`a-cV[[a\x01\x02\x02\x01_\x01\x81a\x01\0\x81\x10a\t{Wa\tza-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x93P\x83\x86`@\x01Q_\x01Q\x82\x81Q\x81\x10a\t\xB9Wa\t\xB8a-cV[[` \x02` \x01\x01Q_\x01\x90s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RPPa\n&\x81`\x02\x87`\x02\x81\x10a\n\x0EWa\n\ra-cV[[a\x01\x02\x02\x01a\x01\0\x01Ta!\xE5\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x80a\n\xABWP\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x86`\x02\x81\x10a\nWWa\nVa-cV[[a\x01\x02\x02\x01_\x01\x82a\x01\0\x81\x10a\nqWa\npa-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14\x15[\x15a\x0B\x9EW`\x01_\x85s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ \x80Ta\n\xF8\x90a0\0V[\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01\x82\x80Ta\x0B$\x90a0\0V[\x80\x15a\x0BoW\x80`\x1F\x10a\x0BFWa\x01\0\x80\x83T\x04\x02\x83R\x91` \x01\x91a\x0BoV[\x82\x01\x91\x90_R` _ \x90[\x81T\x81R\x90`\x01\x01\x90` \x01\x80\x83\x11a\x0BRW\x82\x90\x03`\x1F\x16\x82\x01\x91[PPPPP\x86`@\x01Q_\x01Q\x82\x81Q\x81\x10a\x0B\x8EWa\x0B\x8Da-cV[[` \x02` \x01\x01Q` \x01\x81\x90RP[[\x80\x80a\x0B\xAA\x90a00V[\x91PPa\t\x12V[PPa\x0B\xE9V[`\x02a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x0B\xDC\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x92P[a\x0C\x0F`\x02\x84`\x02\x81\x10a\x0C\0Wa\x0B\xFFa-cV[[a\x01\x02\x02\x01a\x01\0\x01Ta\"\x0EV[\x90P`\x01\x81a\x0C\x1E\x91\x90a/sV[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x0C7Wa\x0C6a/\xA6V[[`@Q\x90\x80\x82R\x80` \x02` \x01\x82\x01`@R\x80\x15a\x0CpW\x81` \x01[a\x0C]a$\x0FV[\x81R` \x01\x90`\x01\x90\x03\x90\x81a\x0CUW\x90P[P\x84_\x01Q_\x01\x81\x90RP`\x02\x83`\x02\x81\x10a\x0C\x8FWa\x0C\x8Ea-cV[[a\x01\x02\x02\x01a\x01\x01\x01_\x90T\x90a\x01\0\n\x90\x04`\xFF\x16\x84_\x01Q` \x01\x90`\xFF\x16\x90\x81`\xFF\x16\x81RPP__\x90P[\x81\x81\x11a\x0E\xA1Wa\x0C\xF5\x81`\x02\x86`\x02\x81\x10a\x0C\xDDWa\x0C\xDCa-cV[[a\x01\x02\x02\x01a\x01\0\x01Ta!\xE5\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x0E\x8EW`\x02\x84`\x02\x81\x10a\r\rWa\r\x0Ca-cV[[a\x01\x02\x02\x01_\x01\x81a\x01\0\x81\x10a\r'Wa\r&a-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x92P\x82\x85_\x01Q_\x01Q\x82\x81Q\x81\x10a\rdWa\rca-cV[[` \x02` \x01\x01Q_\x01\x90s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RPP`\x01_\x84s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ \x80Ta\r\xE9\x90a0\0V[\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01\x82\x80Ta\x0E\x15\x90a0\0V[\x80\x15a\x0E`W\x80`\x1F\x10a\x0E7Wa\x01\0\x80\x83T\x04\x02\x83R\x91` \x01\x91a\x0E`V[\x82\x01\x91\x90_R` _ \x90[\x81T\x81R\x90`\x01\x01\x90` \x01\x80\x83\x11a\x0ECW\x82\x90\x03`\x1F\x16\x82\x01\x91[PPPPP\x85_\x01Q_\x01Q\x82\x81Q\x81\x10a\x0E~Wa\x0E}a-cV[[` \x02` \x01\x01Q` \x01\x81\x90RP[\x80\x80a\x0E\x99\x90a00V[\x91PPa\x0C\xBEV[Pa\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x84`\x80\x01\x90g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RPPa\x02\n_\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x84``\x01Q_\x01\x90s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RPPa\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x84`\xA0\x01\x90o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RPP\x83\x94PPPPP\x90V[a\x0F\x9B\x82\x82\x90Pa\"\x1FV[\x81\x81`\x01_3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ \x91\x82a\x0F\xE7\x92\x91\x90a2\x18V[PPPV[a\x0F\xF4a!{V[a\x103W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x10*\x90a+\x8CV[`@Q\x80\x91\x03\x90\xFD[3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x02\n_\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x10\xC5W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x10\xBC\x90a-\xDAV[`@Q\x80\x91\x03\x90\xFD[_a\x02\n_\x01_a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x116\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\xF9\x10g\xEBB\x0C(\xD3\x12He\xFC\x99nj\xA9\xD5A\xB9\xB4\xFE\xF9\x18\x8C\xB9e\xA6\xCCd\x91c\x8E3a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x11\xBC\x92\x91\x90a2\xE5V[`@Q\x80\x91\x03\x90\xA1V[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x12TW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x12K\x90a+$V[`@Q\x80\x91\x03\x90\xFD[a\x12\\a!\xD5V[a\x12\x9BW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x12\x92\x90a,\x80V[`@Q\x80\x91\x03\x90\xFD[a\x02\x06_\x81\x81\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x12\xC1\x90a3\x0CV[\x91\x90a\x01\0\n\x81T\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP_a\x02\x08`\x01\x01\x81\x90UPa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x13!\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\xF72@B\"F\xF6>\xD63\xEF<\xE0rk\x8A\xB8\xFBi\xD4l\x8AN^\xCB\x0B)\"f\x86t\xA1a\x02\x08_\x01_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x13\xBF\x92\x91\x90a33V[`@Q\x80\x91\x03\x90\xA1V[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x14WW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x14N\x90a+$V[`@Q\x80\x91\x03\x90\xFD[a\x14_a!\xD5V[\x15a\x14\x9FW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x14\x96\x90a3\xA4V[`@Q\x80\x91\x03\x90\xFD[a\x14\xA7a!{V[\x15a\x14\xE7W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x14\xDE\x90a4\x0CV[`@Q\x80\x91\x03\x90\xFD[a\x02\x08_\x01_\x81\x81\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x15\x0F\x90a4*V[\x91\x90a\x01\0\n\x81T\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP_`\x02a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x15Z\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90Pa\x02\x06_\x81\x81\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x15\x8C\x90a4*V[\x91\x90a\x01\0\n\x81T\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP_`\x02a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x15\xD7\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x90P__\x90P[a\x16\x0E`\x02\x84`\x02\x81\x10a\x15\xFFWa\x15\xFEa-cV[[a\x01\x02\x02\x01a\x01\0\x01Ta\"\x0EV[\x81\x11a\x17\xB2W`\x02\x83`\x02\x81\x10a\x16(Wa\x16'a-cV[[a\x01\x02\x02\x01_\x01\x81a\x01\0\x81\x10a\x16BWa\x16Aa-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x83`\x02\x81\x10a\x16\x8DWa\x16\x8Ca-cV[[a\x01\x02\x02\x01_\x01\x82a\x01\0\x81\x10a\x16\xA7Wa\x16\xA6a-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x17\x9FW`\x02\x83`\x02\x81\x10a\x16\xF7Wa\x16\xF6a-cV[[a\x01\x02\x02\x01_\x01\x81a\x01\0\x81\x10a\x17\x11Wa\x17\x10a-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x83`\x02\x81\x10a\x17FWa\x17Ea-cV[[a\x01\x02\x02\x01_\x01\x82a\x01\0\x81\x10a\x17`Wa\x17_a-cV[[\x01_a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UP[\x80\x80a\x17\xAA\x90a00V[\x91PPa\x15\xE8V[P_`\x02\x83`\x02\x81\x10a\x17\xC8Wa\x17\xC7a-cV[[a\x01\x02\x02\x01a\x01\0\x01T\x90P____\x90P[\x86\x80_\x01\x90a\x17\xEA\x91\x90a4eV[\x90P\x81\x10\x15a\x19FW\x86\x80_\x01\x90a\x18\x02\x91\x90a4eV[\x82\x81\x81\x10a\x18\x13Wa\x18\x12a-cV[[\x90P`@\x02\x01_\x01` \x81\x01\x90a\x18*\x91\x90a)\xEDV[\x92P\x86\x80_\x01\x90a\x18;\x91\x90a4eV[\x82\x81\x81\x10a\x18LWa\x18Ka-cV[[\x90P`@\x02\x01` \x01` \x81\x01\x90a\x18d\x91\x90a*\x9FV[\x91P_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x82s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x03a\x18\xB3Wa\x18\xAC\x83\x85a!\xFA\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x93Pa\x18\xC9V[a\x18\xC6\x83\x85a\"\xBD\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x93P[\x81`\x02\x86`\x02\x81\x10a\x18\xDEWa\x18\xDDa-cV[[a\x01\x02\x02\x01_\x01\x84`\xFF\x16a\x01\0\x81\x10a\x18\xFBWa\x18\xFAa-cV[[\x01_a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UP\x80\x80`\x01\x01\x91PPa\x17\xDBV[P\x82`\x02\x85`\x02\x81\x10a\x19\\Wa\x19[a-cV[[a\x01\x02\x02\x01a\x01\0\x01\x81\x90UP\x85` \x01` \x81\x01\x90a\x19|\x91\x90a)\xEDV[`\x02\x85`\x02\x81\x10a\x19\x90Wa\x19\x8Fa-cV[[a\x01\x02\x02\x01a\x01\x01\x01_a\x01\0\n\x81T\x81`\xFF\x02\x19\x16\x90\x83`\xFF\x16\x02\x17\x90UP\x82a\x02\x08`\x01\x01\x81\x90UPa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x19\xE9\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7Fx\xDA\xD2\xBC\x0BG\xC6\x88\xED\x84\xF3\xFE\xE7\x9A\xBC\x18\xE6\xC9\x82-\xB0Zy\xCA\x19\xDF\xF5E3\xC7G\ra\x02\x08_\x01_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x87a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x1A\x89\x93\x92\x91\x90a6\x8BV[`@Q\x80\x91\x03\x90\xA1PPPPPPV[a\x1A\xA1a!\xD5V[\x15a\x1A\xE1W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x1A\xD8\x90a3\xA4V[`@Q\x80\x91\x03\x90\xFD[a\x1A\xE9a!{V[\x15a\x1B)W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x1B \x90a4\x0CV[`@Q\x80\x91\x03\x90\xFD[3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x80a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x1Bd\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x81\x10a\x1B\x7FWa\x1B~a-cV[[a\x01\x02\x02\x01_\x01\x82`\xFF\x16a\x01\0\x81\x10a\x1B\x9CWa\x1B\x9Ba-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x1C\x13W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x1C\n\x90a-\xDAV[`@Q\x80\x91\x03\x90\xFD[3a\x02\n_\x01_a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a\x1C\x84\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\xBC'H\xCF\x02\xF7\xA1)\x15%\xE8f\xEF\xC7j\xB3\xB9m2\xD7\xAF\xCB\xB2lS\xDA\xECa{8\xB4y3a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x1D\n\x92\x91\x90a2\xE5V[`@Q\x80\x91\x03\x90\xA1PV[a\x1D!\x82\x82\x90Pa\"\x1FV[__a\x1D+a!\xD5V[\x15a\x1E\xA1W3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x80`\x01a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x1Dm\x91\x90a/8V[a\x1Dw\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x81\x10a\x1D\x92Wa\x1D\x91a-cV[[a\x01\x02\x02\x01_\x01\x86`\xFF\x16a\x01\0\x81\x10a\x1D\xAFWa\x1D\xAEa-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14\x91P\x81a\x1E\x9CW3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x80a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x1E)\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x81\x10a\x1EDWa\x1ECa-cV[[a\x01\x02\x02\x01_\x01\x86`\xFF\x16a\x01\0\x81\x10a\x1EaWa\x1E`a-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14\x90P[a\x1FOV[3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x80a\x02\x06_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x1E\xDC\x91\x90a-3V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x02\x81\x10a\x1E\xF7Wa\x1E\xF6a-cV[[a\x01\x02\x02\x01_\x01\x86`\xFF\x16a\x01\0\x81\x10a\x1F\x14Wa\x1F\x13a-cV[[\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14\x91P[\x81\x80a\x1FXWP\x80[a\x1F\x97W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x1F\x8E\x90a-\xDAV[`@Q\x80\x91\x03\x90\xFD[\x83\x83`\x01_3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ \x91\x82a\x1F\xE3\x92\x91\x90a2\x18V[Pa\x02\x0B_\x81\x81\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x80\x92\x91\x90a \x12\x90a+\xD7V[\x91\x90a\x01\0\n\x81T\x81o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPP\x7F\x12Q\x81\xEC!\x88-\xECQ\xA29)\x05\xDF\xF3\xA8,\xBD\x02b\xF1\x8B\\\x0C\x03T\x88g\x1B@\xAF\xB23\x85\x85a\x02\x0B_\x90T\x90a\x01\0\n\x90\x04o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa \x9C\x94\x93\x92\x91\x90a7\x11V[`@Q\x80\x91\x03\x90\xA1PPPPPV[__\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x163s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a!9W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a!0\x90a+$V[`@Q\x80\x91\x03\x90\xFD[\x80__a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UPPV[__s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x02\n_\x01_\x90T\x90a\x01\0\n\x90\x04s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14\x15\x90P\x90V[__a\x02\x08`\x01\x01T\x14\x15\x90P\x90V[__\x82`\xFF\x16`\x01\x90\x1B\x84\x16\x14\x90P\x92\x91PPV[_\x81`\xFF\x16`\x01\x90\x1B\x19\x83\x16\x90P\x92\x91PPV[_a\"\x18\x82a\"\xD0V[\x90P\x91\x90PV[_\x81\x11a\"aW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\"X\x90a7\x99V[`@Q\x80\x91\x03\x90\xFD[a\x02\x07_\x01_\x90T\x90a\x01\0\n\x90\x04a\xFF\xFF\x16a\xFF\xFF\x16\x81\x11\x15a\"\xBAW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\"\xB1\x90a8\x01V[`@Q\x80\x91\x03\x90\xFD[PV[_\x81`\xFF\x16`\x01\x90\x1B\x83\x17\x90P\x92\x91PPV[_`\x07a\"\xEEo\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x84\x11a#\x9CV[\x90\x1B\x90P`\x06a#\ng\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x83\x85\x90\x1C\x11a#\x9CV[\x90\x1B\x81\x17\x90P`\x05a#$c\xFF\xFF\xFF\xFF\x83\x85\x90\x1C\x11a#\x9CV[\x90\x1B\x81\x17\x90P`\x04a#V[\x81R` \x01a#\xC7a$ZV[\x81R` \x01a#\xD4a$>V[\x81R` \x01a#\xE1a$|V[\x81R` \x01_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01_o\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RP\x90V[`@Q\x80`@\x01`@R\x80_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01``\x81RP\x90V[`@Q\x80`@\x01`@R\x80``\x81R` \x01_`\xFF\x16\x81RP\x90V[`@Q\x80`@\x01`@R\x80_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01_\x81RP\x90V[`@Q\x80` \x01`@R\x80_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RP\x90V[__\xFD[__\xFD[_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[a$\xC8\x81a$\xACV[\x81\x14a$\xD2W__\xFD[PV[_\x815\x90Pa$\xE3\x81a$\xBFV[\x92\x91PPV[_`\xFF\x82\x16\x90P\x91\x90PV[a$\xFE\x81a$\xE9V[\x81\x14a%\x08W__\xFD[PV[_\x815\x90Pa%\x19\x81a$\xF5V[\x92\x91PPV[__`@\x83\x85\x03\x12\x15a%5Wa%4a$\xA4V[[_a%B\x85\x82\x86\x01a$\xD5V[\x92PP` a%S\x85\x82\x86\x01a%\x0BV[\x91PP\x92P\x92\x90PV[__\xFD[_` \x82\x84\x03\x12\x15a%vWa%ua%]V[[\x81\x90P\x92\x91PPV[_` \x82\x84\x03\x12\x15a%\x94Wa%\x93a$\xA4V[[_a%\xA1\x84\x82\x85\x01a%aV[\x91PP\x92\x91PPV[_\x81Q\x90P\x91\x90PV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[_\x81\x90P` \x82\x01\x90P\x91\x90PV[_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[_a%\xFC\x82a%\xD3V[\x90P\x91\x90PV[a&\x0C\x81a%\xF2V[\x82RPPV[_\x81Q\x90P\x91\x90PV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[\x82\x81\x83^_\x83\x83\x01RPPPV[_`\x1F\x19`\x1F\x83\x01\x16\x90P\x91\x90PV[_a&T\x82a&\x12V[a&^\x81\x85a&\x1CV[\x93Pa&n\x81\x85` \x86\x01a&,V[a&w\x81a&:V[\x84\x01\x91PP\x92\x91PPV[_`@\x83\x01_\x83\x01Qa&\x97_\x86\x01\x82a&\x03V[P` \x83\x01Q\x84\x82\x03` \x86\x01Ra&\xAF\x82\x82a&JV[\x91PP\x80\x91PP\x92\x91PPV[_a&\xC7\x83\x83a&\x82V[\x90P\x92\x91PPV[_` \x82\x01\x90P\x91\x90PV[_a&\xE5\x82a%\xAAV[a&\xEF\x81\x85a%\xB4V[\x93P\x83` \x82\x02\x85\x01a'\x01\x85a%\xC4V[\x80_[\x85\x81\x10\x15a'\x82a1 V[\x84\x84Ta0\xAEV[\x82UPPPPV[__\x90P\x90V[a1]a1NV[a1h\x81\x84\x84a1)V[PPPV[[\x81\x81\x10\x15a1\x8BWa1\x80_\x82a1UV[`\x01\x81\x01\x90Pa1nV[PPV[`\x1F\x82\x11\x15a1\xD0Wa1\xA1\x81a0\x81V[a1\xAA\x84a0\x93V[\x81\x01` \x85\x10\x15a1\xB9W\x81\x90P[a1\xCDa1\xC5\x85a0\x93V[\x83\x01\x82a1mV[PP[PPPV[_\x82\x82\x1C\x90P\x92\x91PPV[_a1\xF0_\x19\x84`\x08\x02a1\xD5V[\x19\x80\x83\x16\x91PP\x92\x91PPV[_a2\x08\x83\x83a1\xE1V[\x91P\x82`\x02\x02\x82\x17\x90P\x92\x91PPV[a2\"\x83\x83a0wV[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a2;Wa2:a/\xA6V[[a2E\x82Ta0\0V[a2P\x82\x82\x85a1\x8FV[_`\x1F\x83\x11`\x01\x81\x14a2}W_\x84\x15a2kW\x82\x87\x015\x90P[a2u\x85\x82a1\xFDV[\x86UPa2\xDCV[`\x1F\x19\x84\x16a2\x8B\x86a0\x81V[_[\x82\x81\x10\x15a2\xB2W\x84\x89\x015\x82U`\x01\x82\x01\x91P` \x85\x01\x94P` \x81\x01\x90Pa2\x8DV[\x86\x83\x10\x15a2\xCFW\x84\x89\x015a2\xCB`\x1F\x89\x16\x82a1\xE1V[\x83UP[`\x01`\x02\x88\x02\x01\x88UPPP[PPPPPPPV[_`@\x82\x01\x90Pa2\xF8_\x83\x01\x85a.\x07V[a3\x05` \x83\x01\x84a,\x0EV[\x93\x92PPPV[_a3\x16\x82a$\xACV[\x91P_\x82\x03a3(Wa3'a+\xAAV[[`\x01\x82\x03\x90P\x91\x90PV[_`@\x82\x01\x90Pa3F_\x83\x01\x85a-\xF8V[a3S` \x83\x01\x84a,\x0EV[\x93\x92PPPV[\x7Fmigration in progress\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a3\x8E`\x15\x83a*\xCAV[\x91Pa3\x99\x82a3ZV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra3\xBB\x81a3\x82V[\x90P\x91\x90PV[\x7Fmaintenance in progress\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a3\xF6`\x17\x83a*\xCAV[\x91Pa4\x01\x82a3\xC2V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra4#\x81a3\xEAV[\x90P\x91\x90PV[_a44\x82a$\xACV[\x91Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x03a4NWa4Ma+\xAAV[[`\x01\x82\x01\x90P\x91\x90PV[__\xFD[__\xFD[__\xFD[__\x835`\x01` \x03\x846\x03\x03\x81\x12a4\x81Wa4\x80a4YV[[\x80\x84\x01\x92P\x825\x91Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15a4\xA3Wa4\xA2a4]V[[` \x83\x01\x92P`@\x82\x026\x03\x83\x13\x15a4\xBFWa4\xBEa4aV[[P\x92P\x92\x90PV[__\xFD[__\xFD[__\xFD[__\x835`\x01` \x03\x846\x03\x03\x81\x12a4\xEFWa4\xEEa4\xCFV[[\x83\x81\x01\x92P\x825\x91P` \x83\x01\x92Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15a5\x17Wa5\x16a4\xC7V[[`@\x82\x026\x03\x83\x13\x15a5-Wa5,a4\xCBV[[P\x92P\x92\x90PV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[_\x81\x90P\x91\x90PV[_a5\\` \x84\x01\x84a%\x0BV[\x90P\x92\x91PPV[_a5r` \x84\x01\x84a*\x8BV[\x90P\x92\x91PPV[`@\x82\x01a5\x8A_\x83\x01\x83a5NV[a5\x96_\x85\x01\x82a'NV[Pa5\xA4` \x83\x01\x83a5dV[a5\xB1` \x85\x01\x82a&\x03V[PPPPV[_a5\xC2\x83\x83a5zV[`@\x83\x01\x90P\x92\x91PPV[_\x82\x90P\x92\x91PPV[_`@\x82\x01\x90P\x91\x90PV[_a5\xEF\x83\x85a55V[\x93Pa5\xFA\x82a5EV[\x80_[\x85\x81\x10\x15a62Wa6\x0F\x82\x84a5\xCEV[a6\x19\x88\x82a5\xB7V[\x97Pa6$\x83a5\xD8V[\x92PP`\x01\x81\x01\x90Pa5\xFDV[P\x85\x92PPP\x93\x92PPPV[_`@\x83\x01a6P_\x84\x01\x84a4\xD3V[\x85\x83\x03_\x87\x01Ra6b\x83\x82\x84a5\xE4V[\x92PPPa6s` \x84\x01\x84a5NV[a6\x80` \x86\x01\x82a'NV[P\x80\x91PP\x92\x91PPV[_``\x82\x01\x90Pa6\x9E_\x83\x01\x86a-\xF8V[\x81\x81\x03` \x83\x01Ra6\xB0\x81\x85a6?V[\x90Pa6\xBF`@\x83\x01\x84a,\x0EV[\x94\x93PPPPV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[\x82\x81\x837_\x83\x83\x01RPPPV[_a6\xF0\x83\x85a6\xC7V[\x93Pa6\xFD\x83\x85\x84a6\xD7V[a7\x06\x83a&:V[\x84\x01\x90P\x93\x92PPPV[_``\x82\x01\x90Pa7$_\x83\x01\x87a.\x07V[\x81\x81\x03` \x83\x01Ra77\x81\x85\x87a6\xE5V[\x90Pa7F`@\x83\x01\x84a,\x0EV[\x95\x94PPPPPV[\x7Fempty operator data\0\0\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a7\x83`\x13\x83a*\xCAV[\x91Pa7\x8E\x82a7OV[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra7\xB0\x81a7wV[\x90P\x91\x90PV[\x7Foperator data too large\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a7\xEB`\x17\x83a*\xCAV[\x91Pa7\xF6\x82a7\xB7V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra8\x18\x81a7\xDFV[\x90P\x91\x90PV\xFE\xA2dipfsX\"\x12 \xFA\x04\xDE\xADB^j\xA2\xEEQe+w\xCD\x8B\xEC4O\x89\xD5\xA5\xD1\x8BB\xF4\x88\x9Bz\xBA\xD1s\"dsolcC\0\x08\x1C\x003", - ); - /// ```solidity - /// struct ClusterView { KeyspaceView keyspace; Migration migration; KeyspaceView migrationKeyspace; Maintenance maintenance; uint64 keyspaceVersion; uint128 version; } - /// ``` - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct ClusterView { - #[allow(missing_docs)] - pub keyspace: ::RustType, - #[allow(missing_docs)] - pub migration: ::RustType, - #[allow(missing_docs)] - pub migrationKeyspace: ::RustType, - #[allow(missing_docs)] - pub maintenance: ::RustType, - #[allow(missing_docs)] - pub keyspaceVersion: u64, - #[allow(missing_docs)] - pub version: u128, - } - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - #[doc(hidden)] - type UnderlyingSolTuple<'a> = ( - KeyspaceView, - Migration, - KeyspaceView, - Maintenance, - alloy::sol_types::sol_data::Uint<64>, - alloy::sol_types::sol_data::Uint<128>, - ); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = ( - ::RustType, - ::RustType, - ::RustType, - ::RustType, - u64, - u128, - ); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: ClusterView) -> Self { - ( - value.keyspace, - value.migration, - value.migrationKeyspace, - value.maintenance, - value.keyspaceVersion, - value.version, - ) - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for ClusterView { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self { - keyspace: tuple.0, - migration: tuple.1, - migrationKeyspace: tuple.2, - maintenance: tuple.3, - keyspaceVersion: tuple.4, - version: tuple.5, - } - } - } - #[automatically_derived] - impl alloy_sol_types::SolValue for ClusterView { - type SolType = Self; - } - #[automatically_derived] - impl alloy_sol_types::private::SolTypeValue for ClusterView { - #[inline] - fn stv_to_tokens(&self) -> ::Token<'_> { - ( - ::tokenize(&self.keyspace), - ::tokenize(&self.migration), - ::tokenize(&self.migrationKeyspace), - ::tokenize(&self.maintenance), - as alloy_sol_types::SolType>::tokenize( - &self.keyspaceVersion, - ), - as alloy_sol_types::SolType>::tokenize( - &self.version, - ), - ) - } - #[inline] - fn stv_abi_encoded_size(&self) -> usize { - if let Some(size) = ::ENCODED_SIZE { - return size; - } - let tuple = - as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_encoded_size(&tuple) - } - #[inline] - fn stv_eip712_data_word(&self) -> alloy_sol_types::Word { - ::eip712_hash_struct(self) - } - #[inline] - fn stv_abi_encode_packed_to(&self, out: &mut alloy_sol_types::private::Vec) { - let tuple = - as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_encode_packed_to( - &tuple, out, - ) - } - #[inline] - fn stv_abi_packed_encoded_size(&self) -> usize { - if let Some(size) = ::PACKED_ENCODED_SIZE { - return size; - } - let tuple = - as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_packed_encoded_size( - &tuple, - ) - } - } - #[automatically_derived] - impl alloy_sol_types::SolType for ClusterView { - type RustType = Self; - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SOL_NAME: &'static str = ::NAME; - const ENCODED_SIZE: Option = - as alloy_sol_types::SolType>::ENCODED_SIZE; - const PACKED_ENCODED_SIZE: Option = - as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; - #[inline] - fn valid_token(token: &Self::Token<'_>) -> bool { - as alloy_sol_types::SolType>::valid_token(token) - } - #[inline] - fn detokenize(token: Self::Token<'_>) -> Self::RustType { - let tuple = as alloy_sol_types::SolType>::detokenize(token); - >>::from(tuple) - } - } - #[automatically_derived] - impl alloy_sol_types::SolStruct for ClusterView { - const NAME: &'static str = "ClusterView"; - #[inline] - fn eip712_root_type() -> alloy_sol_types::private::Cow<'static, str> { - alloy_sol_types::private::Cow::Borrowed( - "ClusterView(KeyspaceView keyspace,Migration migration,KeyspaceView \ - migrationKeyspace,Maintenance maintenance,uint64 keyspaceVersion,uint128 \ - version)", - ) - } - #[inline] - fn eip712_components( - ) -> alloy_sol_types::private::Vec> - { - let mut components = alloy_sol_types::private::Vec::with_capacity(4); - components.push(::eip712_root_type()); - components - .extend(::eip712_components()); - components.push(::eip712_root_type()); - components.extend(::eip712_components()); - components.push(::eip712_root_type()); - components - .extend(::eip712_components()); - components.push(::eip712_root_type()); - components.extend(::eip712_components()); - components - } - #[inline] - fn eip712_encode_data(&self) -> alloy_sol_types::private::Vec { - [ - ::eip712_data_word( - &self.keyspace, - ) - .0, - ::eip712_data_word( - &self.migration, - ) - .0, - ::eip712_data_word( - &self.migrationKeyspace, - ) - .0, - ::eip712_data_word( - &self.maintenance, - ) - .0, - as alloy_sol_types::SolType>::eip712_data_word( - &self.keyspaceVersion, - ) - .0, - as alloy_sol_types::SolType>::eip712_data_word(&self.version) - .0, - ] - .concat() - } - } - #[automatically_derived] - impl alloy_sol_types::EventTopic for ClusterView { - #[inline] - fn topic_preimage_length(rust: &Self::RustType) -> usize { - 0usize - + ::topic_preimage_length( - &rust.keyspace, - ) - + ::topic_preimage_length( - &rust.migration, - ) - + ::topic_preimage_length( - &rust.migrationKeyspace, - ) - + ::topic_preimage_length( - &rust.maintenance, - ) - + as alloy_sol_types::EventTopic>::topic_preimage_length( - &rust.keyspaceVersion, - ) - + as alloy_sol_types::EventTopic>::topic_preimage_length( - &rust.version, - ) - } - #[inline] - fn encode_topic_preimage( - rust: &Self::RustType, - out: &mut alloy_sol_types::private::Vec, - ) { - out.reserve(::topic_preimage_length(rust)); - ::encode_topic_preimage( - &rust.keyspace, - out, - ); - ::encode_topic_preimage( - &rust.migration, - out, - ); - ::encode_topic_preimage( - &rust.migrationKeyspace, - out, - ); - ::encode_topic_preimage( - &rust.maintenance, - out, - ); - as alloy_sol_types::EventTopic>::encode_topic_preimage( - &rust.keyspaceVersion, - out, - ); - as alloy_sol_types::EventTopic>::encode_topic_preimage( - &rust.version, - out, - ); - } - #[inline] - fn encode_topic(rust: &Self::RustType) -> alloy_sol_types::abi::token::WordToken { - let mut out = alloy_sol_types::private::Vec::new(); - ::encode_topic_preimage(rust, &mut out); - alloy_sol_types::abi::token::WordToken(alloy_sol_types::private::keccak256(out)) - } - } - }; - /// ```solidity - /// struct KeyspaceSlot { uint8 idx; address operator; } - /// ``` - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct KeyspaceSlot { - #[allow(missing_docs)] - pub idx: u8, - #[allow(missing_docs)] - pub operator: alloy::sol_types::private::Address, - } - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - #[doc(hidden)] - type UnderlyingSolTuple<'a> = ( - alloy::sol_types::sol_data::Uint<8>, - alloy::sol_types::sol_data::Address, - ); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = (u8, alloy::sol_types::private::Address); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: KeyspaceSlot) -> Self { - (value.idx, value.operator) - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for KeyspaceSlot { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self { - idx: tuple.0, - operator: tuple.1, - } - } - } - #[automatically_derived] - impl alloy_sol_types::SolValue for KeyspaceSlot { - type SolType = Self; - } - #[automatically_derived] - impl alloy_sol_types::private::SolTypeValue for KeyspaceSlot { - #[inline] - fn stv_to_tokens(&self) -> ::Token<'_> { - ( - as alloy_sol_types::SolType>::tokenize( - &self.idx, - ), - ::tokenize( - &self.operator, - ), - ) - } - #[inline] - fn stv_abi_encoded_size(&self) -> usize { - if let Some(size) = ::ENCODED_SIZE { - return size; - } - let tuple = - as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_encoded_size(&tuple) - } - #[inline] - fn stv_eip712_data_word(&self) -> alloy_sol_types::Word { - ::eip712_hash_struct(self) - } - #[inline] - fn stv_abi_encode_packed_to(&self, out: &mut alloy_sol_types::private::Vec) { - let tuple = - as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_encode_packed_to( - &tuple, out, - ) - } - #[inline] - fn stv_abi_packed_encoded_size(&self) -> usize { - if let Some(size) = ::PACKED_ENCODED_SIZE { - return size; - } - let tuple = - as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_packed_encoded_size( - &tuple, - ) - } - } - #[automatically_derived] - impl alloy_sol_types::SolType for KeyspaceSlot { - type RustType = Self; - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SOL_NAME: &'static str = ::NAME; - const ENCODED_SIZE: Option = - as alloy_sol_types::SolType>::ENCODED_SIZE; - const PACKED_ENCODED_SIZE: Option = - as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; - #[inline] - fn valid_token(token: &Self::Token<'_>) -> bool { - as alloy_sol_types::SolType>::valid_token(token) - } - #[inline] - fn detokenize(token: Self::Token<'_>) -> Self::RustType { - let tuple = as alloy_sol_types::SolType>::detokenize(token); - >>::from(tuple) - } - } - #[automatically_derived] - impl alloy_sol_types::SolStruct for KeyspaceSlot { - const NAME: &'static str = "KeyspaceSlot"; - #[inline] - fn eip712_root_type() -> alloy_sol_types::private::Cow<'static, str> { - alloy_sol_types::private::Cow::Borrowed("KeyspaceSlot(uint8 idx,address operator)") - } - #[inline] - fn eip712_components( - ) -> alloy_sol_types::private::Vec> - { - alloy_sol_types::private::Vec::new() - } - #[inline] - fn eip712_encode_type() -> alloy_sol_types::private::Cow<'static, str> { - ::eip712_root_type() - } - #[inline] - fn eip712_encode_data(&self) -> alloy_sol_types::private::Vec { - [ - as alloy_sol_types::SolType>::eip712_data_word(&self.idx) - .0, - ::eip712_data_word( - &self.operator, - ) - .0, - ] - .concat() - } - } - #[automatically_derived] - impl alloy_sol_types::EventTopic for KeyspaceSlot { - #[inline] - fn topic_preimage_length(rust: &Self::RustType) -> usize { - 0usize - + as alloy_sol_types::EventTopic>::topic_preimage_length(&rust.idx) - + ::topic_preimage_length( - &rust.operator, - ) - } - #[inline] - fn encode_topic_preimage( - rust: &Self::RustType, - out: &mut alloy_sol_types::private::Vec, - ) { - out.reserve(::topic_preimage_length(rust)); - as alloy_sol_types::EventTopic>::encode_topic_preimage(&rust.idx, out); - ::encode_topic_preimage( - &rust.operator, - out, - ); - } - #[inline] - fn encode_topic(rust: &Self::RustType) -> alloy_sol_types::abi::token::WordToken { - let mut out = alloy_sol_types::private::Vec::new(); - ::encode_topic_preimage(rust, &mut out); - alloy_sol_types::abi::token::WordToken(alloy_sol_types::private::keccak256(out)) - } - } - }; - /// ```solidity - /// struct KeyspaceView { NodeOperator[] operators; uint8 replicationStrategy; } - /// ``` - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct KeyspaceView { - #[allow(missing_docs)] - pub operators: - alloy::sol_types::private::Vec<::RustType>, - #[allow(missing_docs)] - pub replicationStrategy: u8, - } - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - #[doc(hidden)] - type UnderlyingSolTuple<'a> = ( - alloy::sol_types::sol_data::Array, - alloy::sol_types::sol_data::Uint<8>, - ); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = ( - alloy::sol_types::private::Vec<::RustType>, - u8, - ); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: KeyspaceView) -> Self { - (value.operators, value.replicationStrategy) - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for KeyspaceView { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self { - operators: tuple.0, - replicationStrategy: tuple.1, - } - } - } - #[automatically_derived] - impl alloy_sol_types::SolValue for KeyspaceView { - type SolType = Self; - } - #[automatically_derived] - impl alloy_sol_types::private::SolTypeValue for KeyspaceView { - #[inline] - fn stv_to_tokens(&self) -> ::Token<'_> { - ( - as alloy_sol_types::SolType>::tokenize(&self.operators), - as alloy_sol_types::SolType>::tokenize(&self.replicationStrategy), - ) - } - #[inline] - fn stv_abi_encoded_size(&self) -> usize { - if let Some(size) = ::ENCODED_SIZE { - return size; - } - let tuple = - as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_encoded_size(&tuple) - } - #[inline] - fn stv_eip712_data_word(&self) -> alloy_sol_types::Word { - ::eip712_hash_struct(self) - } - #[inline] - fn stv_abi_encode_packed_to(&self, out: &mut alloy_sol_types::private::Vec) { - let tuple = - as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_encode_packed_to( - &tuple, out, - ) - } - #[inline] - fn stv_abi_packed_encoded_size(&self) -> usize { - if let Some(size) = ::PACKED_ENCODED_SIZE { - return size; - } - let tuple = - as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_packed_encoded_size( - &tuple, - ) - } - } - #[automatically_derived] - impl alloy_sol_types::SolType for KeyspaceView { - type RustType = Self; - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SOL_NAME: &'static str = ::NAME; - const ENCODED_SIZE: Option = - as alloy_sol_types::SolType>::ENCODED_SIZE; - const PACKED_ENCODED_SIZE: Option = - as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; - #[inline] - fn valid_token(token: &Self::Token<'_>) -> bool { - as alloy_sol_types::SolType>::valid_token(token) - } - #[inline] - fn detokenize(token: Self::Token<'_>) -> Self::RustType { - let tuple = as alloy_sol_types::SolType>::detokenize(token); - >>::from(tuple) - } - } - #[automatically_derived] - impl alloy_sol_types::SolStruct for KeyspaceView { - const NAME: &'static str = "KeyspaceView"; - #[inline] - fn eip712_root_type() -> alloy_sol_types::private::Cow<'static, str> { - alloy_sol_types::private::Cow::Borrowed( - "KeyspaceView(NodeOperator[] operators,uint8 replicationStrategy)", - ) - } - #[inline] - fn eip712_components( - ) -> alloy_sol_types::private::Vec> - { - let mut components = alloy_sol_types::private::Vec::with_capacity(1); - components.push(::eip712_root_type()); - components - .extend(::eip712_components()); - components - } - #[inline] - fn eip712_encode_data(&self) -> alloy_sol_types::private::Vec { - [ - as alloy_sol_types::SolType>::eip712_data_word(&self.operators) - .0, - as alloy_sol_types::SolType>::eip712_data_word( - &self.replicationStrategy, - ) - .0, - ] - .concat() - } - } - #[automatically_derived] - impl alloy_sol_types::EventTopic for KeyspaceView { - #[inline] - fn topic_preimage_length(rust: &Self::RustType) -> usize { - 0usize - + as alloy_sol_types::EventTopic>::topic_preimage_length( - &rust.operators, - ) - + as alloy_sol_types::EventTopic>::topic_preimage_length( - &rust.replicationStrategy, - ) - } - #[inline] - fn encode_topic_preimage( - rust: &Self::RustType, - out: &mut alloy_sol_types::private::Vec, - ) { - out.reserve(::topic_preimage_length(rust)); - as alloy_sol_types::EventTopic>::encode_topic_preimage( - &rust.operators, - out, - ); - as alloy_sol_types::EventTopic>::encode_topic_preimage( - &rust.replicationStrategy, - out, - ); - } - #[inline] - fn encode_topic(rust: &Self::RustType) -> alloy_sol_types::abi::token::WordToken { - let mut out = alloy_sol_types::private::Vec::new(); - ::encode_topic_preimage(rust, &mut out); - alloy_sol_types::abi::token::WordToken(alloy_sol_types::private::keccak256(out)) - } - } - }; - /// ```solidity - /// struct Maintenance { address slot; } - /// ``` - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct Maintenance { - #[allow(missing_docs)] - pub slot: alloy::sol_types::private::Address, - } - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - #[doc(hidden)] - type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Address,); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = (alloy::sol_types::private::Address,); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: Maintenance) -> Self { - (value.slot,) - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for Maintenance { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self { slot: tuple.0 } - } - } - #[automatically_derived] - impl alloy_sol_types::SolValue for Maintenance { - type SolType = Self; - } - #[automatically_derived] - impl alloy_sol_types::private::SolTypeValue for Maintenance { - #[inline] - fn stv_to_tokens(&self) -> ::Token<'_> { - ( - ::tokenize( - &self.slot, - ), - ) - } - #[inline] - fn stv_abi_encoded_size(&self) -> usize { - if let Some(size) = ::ENCODED_SIZE { - return size; - } - let tuple = - as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_encoded_size(&tuple) - } - #[inline] - fn stv_eip712_data_word(&self) -> alloy_sol_types::Word { - ::eip712_hash_struct(self) - } - #[inline] - fn stv_abi_encode_packed_to(&self, out: &mut alloy_sol_types::private::Vec) { - let tuple = - as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_encode_packed_to( - &tuple, out, - ) - } - #[inline] - fn stv_abi_packed_encoded_size(&self) -> usize { - if let Some(size) = ::PACKED_ENCODED_SIZE { - return size; - } - let tuple = - as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_packed_encoded_size( - &tuple, - ) - } - } - #[automatically_derived] - impl alloy_sol_types::SolType for Maintenance { - type RustType = Self; - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SOL_NAME: &'static str = ::NAME; - const ENCODED_SIZE: Option = - as alloy_sol_types::SolType>::ENCODED_SIZE; - const PACKED_ENCODED_SIZE: Option = - as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; - #[inline] - fn valid_token(token: &Self::Token<'_>) -> bool { - as alloy_sol_types::SolType>::valid_token(token) - } - #[inline] - fn detokenize(token: Self::Token<'_>) -> Self::RustType { - let tuple = as alloy_sol_types::SolType>::detokenize(token); - >>::from(tuple) - } - } - #[automatically_derived] - impl alloy_sol_types::SolStruct for Maintenance { - const NAME: &'static str = "Maintenance"; - #[inline] - fn eip712_root_type() -> alloy_sol_types::private::Cow<'static, str> { - alloy_sol_types::private::Cow::Borrowed("Maintenance(address slot)") - } - #[inline] - fn eip712_components( - ) -> alloy_sol_types::private::Vec> - { - alloy_sol_types::private::Vec::new() - } - #[inline] - fn eip712_encode_type() -> alloy_sol_types::private::Cow<'static, str> { - ::eip712_root_type() - } - #[inline] - fn eip712_encode_data(&self) -> alloy_sol_types::private::Vec { - ::eip712_data_word( - &self.slot, - ) - .0 - .to_vec() - } - } - #[automatically_derived] - impl alloy_sol_types::EventTopic for Maintenance { - #[inline] - fn topic_preimage_length(rust: &Self::RustType) -> usize { - 0usize - + ::topic_preimage_length( - &rust.slot, - ) - } - #[inline] - fn encode_topic_preimage( - rust: &Self::RustType, - out: &mut alloy_sol_types::private::Vec, - ) { - out.reserve(::topic_preimage_length(rust)); - ::encode_topic_preimage( - &rust.slot, - out, - ); - } - #[inline] - fn encode_topic(rust: &Self::RustType) -> alloy_sol_types::abi::token::WordToken { - let mut out = alloy_sol_types::private::Vec::new(); - ::encode_topic_preimage(rust, &mut out); - alloy_sol_types::abi::token::WordToken(alloy_sol_types::private::keccak256(out)) - } - } - }; - /// ```solidity - /// struct Migration { uint64 id; uint256 pullingOperatorsBitmask; } - /// ``` - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct Migration { - #[allow(missing_docs)] - pub id: u64, - #[allow(missing_docs)] - pub pullingOperatorsBitmask: alloy::sol_types::private::primitives::aliases::U256, - } - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - #[doc(hidden)] - type UnderlyingSolTuple<'a> = ( - alloy::sol_types::sol_data::Uint<64>, - alloy::sol_types::sol_data::Uint<256>, - ); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = (u64, alloy::sol_types::private::primitives::aliases::U256); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: Migration) -> Self { - (value.id, value.pullingOperatorsBitmask) - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for Migration { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self { - id: tuple.0, - pullingOperatorsBitmask: tuple.1, - } - } - } - #[automatically_derived] - impl alloy_sol_types::SolValue for Migration { - type SolType = Self; - } - #[automatically_derived] - impl alloy_sol_types::private::SolTypeValue for Migration { - #[inline] - fn stv_to_tokens(&self) -> ::Token<'_> { - ( - as alloy_sol_types::SolType>::tokenize( - &self.id, - ), - as alloy_sol_types::SolType>::tokenize( - &self.pullingOperatorsBitmask, - ), - ) - } - #[inline] - fn stv_abi_encoded_size(&self) -> usize { - if let Some(size) = ::ENCODED_SIZE { - return size; - } - let tuple = - as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_encoded_size(&tuple) - } - #[inline] - fn stv_eip712_data_word(&self) -> alloy_sol_types::Word { - ::eip712_hash_struct(self) - } - #[inline] - fn stv_abi_encode_packed_to(&self, out: &mut alloy_sol_types::private::Vec) { - let tuple = - as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_encode_packed_to( - &tuple, out, - ) - } - #[inline] - fn stv_abi_packed_encoded_size(&self) -> usize { - if let Some(size) = ::PACKED_ENCODED_SIZE { - return size; - } - let tuple = - as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_packed_encoded_size( - &tuple, - ) - } - } - #[automatically_derived] - impl alloy_sol_types::SolType for Migration { - type RustType = Self; - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SOL_NAME: &'static str = ::NAME; - const ENCODED_SIZE: Option = - as alloy_sol_types::SolType>::ENCODED_SIZE; - const PACKED_ENCODED_SIZE: Option = - as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; - #[inline] - fn valid_token(token: &Self::Token<'_>) -> bool { - as alloy_sol_types::SolType>::valid_token(token) - } - #[inline] - fn detokenize(token: Self::Token<'_>) -> Self::RustType { - let tuple = as alloy_sol_types::SolType>::detokenize(token); - >>::from(tuple) - } - } - #[automatically_derived] - impl alloy_sol_types::SolStruct for Migration { - const NAME: &'static str = "Migration"; - #[inline] - fn eip712_root_type() -> alloy_sol_types::private::Cow<'static, str> { - alloy_sol_types::private::Cow::Borrowed( - "Migration(uint64 id,uint256 pullingOperatorsBitmask)", - ) - } - #[inline] - fn eip712_components( - ) -> alloy_sol_types::private::Vec> - { - alloy_sol_types::private::Vec::new() - } - #[inline] - fn eip712_encode_type() -> alloy_sol_types::private::Cow<'static, str> { - ::eip712_root_type() - } - #[inline] - fn eip712_encode_data(&self) -> alloy_sol_types::private::Vec { - [ - as alloy_sol_types::SolType>::eip712_data_word(&self.id) - .0, - as alloy_sol_types::SolType>::eip712_data_word( - &self.pullingOperatorsBitmask, - ) - .0, - ] - .concat() - } - } - #[automatically_derived] - impl alloy_sol_types::EventTopic for Migration { - #[inline] - fn topic_preimage_length(rust: &Self::RustType) -> usize { - 0usize - + as alloy_sol_types::EventTopic>::topic_preimage_length(&rust.id) - + as alloy_sol_types::EventTopic>::topic_preimage_length( - &rust.pullingOperatorsBitmask, - ) - } - #[inline] - fn encode_topic_preimage( - rust: &Self::RustType, - out: &mut alloy_sol_types::private::Vec, - ) { - out.reserve(::topic_preimage_length(rust)); - as alloy_sol_types::EventTopic>::encode_topic_preimage(&rust.id, out); - as alloy_sol_types::EventTopic>::encode_topic_preimage( - &rust.pullingOperatorsBitmask, - out, - ); - } - #[inline] - fn encode_topic(rust: &Self::RustType) -> alloy_sol_types::abi::token::WordToken { - let mut out = alloy_sol_types::private::Vec::new(); - ::encode_topic_preimage(rust, &mut out); - alloy_sol_types::abi::token::WordToken(alloy_sol_types::private::keccak256(out)) - } - } - }; - /// ```solidity - /// struct MigrationPlan { KeyspaceSlot[] slots; uint8 replicationStrategy; } - /// ``` - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct MigrationPlan { - #[allow(missing_docs)] - pub slots: - alloy::sol_types::private::Vec<::RustType>, - #[allow(missing_docs)] - pub replicationStrategy: u8, - } - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - #[doc(hidden)] - type UnderlyingSolTuple<'a> = ( - alloy::sol_types::sol_data::Array, - alloy::sol_types::sol_data::Uint<8>, - ); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = ( - alloy::sol_types::private::Vec<::RustType>, - u8, - ); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: MigrationPlan) -> Self { - (value.slots, value.replicationStrategy) - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for MigrationPlan { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self { - slots: tuple.0, - replicationStrategy: tuple.1, - } - } - } - #[automatically_derived] - impl alloy_sol_types::SolValue for MigrationPlan { - type SolType = Self; - } - #[automatically_derived] - impl alloy_sol_types::private::SolTypeValue for MigrationPlan { - #[inline] - fn stv_to_tokens(&self) -> ::Token<'_> { - ( - as alloy_sol_types::SolType>::tokenize(&self.slots), - as alloy_sol_types::SolType>::tokenize(&self.replicationStrategy), - ) - } - #[inline] - fn stv_abi_encoded_size(&self) -> usize { - if let Some(size) = ::ENCODED_SIZE { - return size; - } - let tuple = - as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_encoded_size(&tuple) - } - #[inline] - fn stv_eip712_data_word(&self) -> alloy_sol_types::Word { - ::eip712_hash_struct(self) - } - #[inline] - fn stv_abi_encode_packed_to(&self, out: &mut alloy_sol_types::private::Vec) { - let tuple = - as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_encode_packed_to( - &tuple, out, - ) - } - #[inline] - fn stv_abi_packed_encoded_size(&self) -> usize { - if let Some(size) = ::PACKED_ENCODED_SIZE { - return size; - } - let tuple = - as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_packed_encoded_size( - &tuple, - ) - } - } - #[automatically_derived] - impl alloy_sol_types::SolType for MigrationPlan { - type RustType = Self; - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SOL_NAME: &'static str = ::NAME; - const ENCODED_SIZE: Option = - as alloy_sol_types::SolType>::ENCODED_SIZE; - const PACKED_ENCODED_SIZE: Option = - as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; - #[inline] - fn valid_token(token: &Self::Token<'_>) -> bool { - as alloy_sol_types::SolType>::valid_token(token) - } - #[inline] - fn detokenize(token: Self::Token<'_>) -> Self::RustType { - let tuple = as alloy_sol_types::SolType>::detokenize(token); - >>::from(tuple) - } - } - #[automatically_derived] - impl alloy_sol_types::SolStruct for MigrationPlan { - const NAME: &'static str = "MigrationPlan"; - #[inline] - fn eip712_root_type() -> alloy_sol_types::private::Cow<'static, str> { - alloy_sol_types::private::Cow::Borrowed( - "MigrationPlan(KeyspaceSlot[] slots,uint8 replicationStrategy)", - ) - } - #[inline] - fn eip712_components( - ) -> alloy_sol_types::private::Vec> - { - let mut components = alloy_sol_types::private::Vec::with_capacity(1); - components.push(::eip712_root_type()); - components - .extend(::eip712_components()); - components - } - #[inline] - fn eip712_encode_data(&self) -> alloy_sol_types::private::Vec { - [ - as alloy_sol_types::SolType>::eip712_data_word(&self.slots) - .0, - as alloy_sol_types::SolType>::eip712_data_word( - &self.replicationStrategy, - ) - .0, - ] - .concat() - } - } - #[automatically_derived] - impl alloy_sol_types::EventTopic for MigrationPlan { - #[inline] - fn topic_preimage_length(rust: &Self::RustType) -> usize { - 0usize - + as alloy_sol_types::EventTopic>::topic_preimage_length(&rust.slots) - + as alloy_sol_types::EventTopic>::topic_preimage_length( - &rust.replicationStrategy, - ) - } - #[inline] - fn encode_topic_preimage( - rust: &Self::RustType, - out: &mut alloy_sol_types::private::Vec, - ) { - out.reserve(::topic_preimage_length(rust)); - as alloy_sol_types::EventTopic>::encode_topic_preimage( - &rust.slots, - out, - ); - as alloy_sol_types::EventTopic>::encode_topic_preimage( - &rust.replicationStrategy, - out, - ); - } - #[inline] - fn encode_topic(rust: &Self::RustType) -> alloy_sol_types::abi::token::WordToken { - let mut out = alloy_sol_types::private::Vec::new(); - ::encode_topic_preimage(rust, &mut out); - alloy_sol_types::abi::token::WordToken(alloy_sol_types::private::keccak256(out)) - } - } - }; - /// ```solidity - /// struct NodeOperator { address addr; bytes data; } - /// ``` - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct NodeOperator { - #[allow(missing_docs)] - pub addr: alloy::sol_types::private::Address, - #[allow(missing_docs)] - pub data: alloy::sol_types::private::Bytes, - } - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - #[doc(hidden)] - type UnderlyingSolTuple<'a> = ( - alloy::sol_types::sol_data::Address, - alloy::sol_types::sol_data::Bytes, - ); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = ( - alloy::sol_types::private::Address, - alloy::sol_types::private::Bytes, - ); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: NodeOperator) -> Self { - (value.addr, value.data) - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for NodeOperator { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self { - addr: tuple.0, - data: tuple.1, - } - } - } - #[automatically_derived] - impl alloy_sol_types::SolValue for NodeOperator { - type SolType = Self; - } - #[automatically_derived] - impl alloy_sol_types::private::SolTypeValue for NodeOperator { - #[inline] - fn stv_to_tokens(&self) -> ::Token<'_> { - ( - ::tokenize( - &self.addr, - ), - ::tokenize( - &self.data, - ), - ) - } - #[inline] - fn stv_abi_encoded_size(&self) -> usize { - if let Some(size) = ::ENCODED_SIZE { - return size; - } - let tuple = - as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_encoded_size(&tuple) - } - #[inline] - fn stv_eip712_data_word(&self) -> alloy_sol_types::Word { - ::eip712_hash_struct(self) - } - #[inline] - fn stv_abi_encode_packed_to(&self, out: &mut alloy_sol_types::private::Vec) { - let tuple = - as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_encode_packed_to( - &tuple, out, - ) - } - #[inline] - fn stv_abi_packed_encoded_size(&self) -> usize { - if let Some(size) = ::PACKED_ENCODED_SIZE { - return size; - } - let tuple = - as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_packed_encoded_size( - &tuple, - ) - } - } - #[automatically_derived] - impl alloy_sol_types::SolType for NodeOperator { - type RustType = Self; - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SOL_NAME: &'static str = ::NAME; - const ENCODED_SIZE: Option = - as alloy_sol_types::SolType>::ENCODED_SIZE; - const PACKED_ENCODED_SIZE: Option = - as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; - #[inline] - fn valid_token(token: &Self::Token<'_>) -> bool { - as alloy_sol_types::SolType>::valid_token(token) - } - #[inline] - fn detokenize(token: Self::Token<'_>) -> Self::RustType { - let tuple = as alloy_sol_types::SolType>::detokenize(token); - >>::from(tuple) - } - } - #[automatically_derived] - impl alloy_sol_types::SolStruct for NodeOperator { - const NAME: &'static str = "NodeOperator"; - #[inline] - fn eip712_root_type() -> alloy_sol_types::private::Cow<'static, str> { - alloy_sol_types::private::Cow::Borrowed("NodeOperator(address addr,bytes data)") - } - #[inline] - fn eip712_components( - ) -> alloy_sol_types::private::Vec> - { - alloy_sol_types::private::Vec::new() - } - #[inline] - fn eip712_encode_type() -> alloy_sol_types::private::Cow<'static, str> { - ::eip712_root_type() - } - #[inline] - fn eip712_encode_data(&self) -> alloy_sol_types::private::Vec { - [ - ::eip712_data_word( - &self.addr, - ) - .0, - ::eip712_data_word( - &self.data, - ) - .0, - ] - .concat() - } - } - #[automatically_derived] - impl alloy_sol_types::EventTopic for NodeOperator { - #[inline] - fn topic_preimage_length(rust: &Self::RustType) -> usize { - 0usize - + ::topic_preimage_length( - &rust.addr, - ) - + ::topic_preimage_length( - &rust.data, - ) - } - #[inline] - fn encode_topic_preimage( - rust: &Self::RustType, - out: &mut alloy_sol_types::private::Vec, - ) { - out.reserve(::topic_preimage_length(rust)); - ::encode_topic_preimage( - &rust.addr, - out, - ); - ::encode_topic_preimage( - &rust.data, - out, - ); - } - #[inline] - fn encode_topic(rust: &Self::RustType) -> alloy_sol_types::abi::token::WordToken { - let mut out = alloy_sol_types::private::Vec::new(); - ::encode_topic_preimage(rust, &mut out); - alloy_sol_types::abi::token::WordToken(alloy_sol_types::private::keccak256(out)) - } - } - }; - /// ```solidity - /// struct Settings { uint16 maxOperatorDataBytes; } - /// ``` - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct Settings { - #[allow(missing_docs)] - pub maxOperatorDataBytes: u16, - } - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - #[doc(hidden)] - type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Uint<16>,); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = (u16,); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: Settings) -> Self { - (value.maxOperatorDataBytes,) - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for Settings { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self { - maxOperatorDataBytes: tuple.0, - } - } - } - #[automatically_derived] - impl alloy_sol_types::SolValue for Settings { - type SolType = Self; - } - #[automatically_derived] - impl alloy_sol_types::private::SolTypeValue for Settings { - #[inline] - fn stv_to_tokens(&self) -> ::Token<'_> { - ( - as alloy_sol_types::SolType>::tokenize( - &self.maxOperatorDataBytes, - ), - ) - } - #[inline] - fn stv_abi_encoded_size(&self) -> usize { - if let Some(size) = ::ENCODED_SIZE { - return size; - } - let tuple = - as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_encoded_size(&tuple) - } - #[inline] - fn stv_eip712_data_word(&self) -> alloy_sol_types::Word { - ::eip712_hash_struct(self) - } - #[inline] - fn stv_abi_encode_packed_to(&self, out: &mut alloy_sol_types::private::Vec) { - let tuple = - as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_encode_packed_to( - &tuple, out, - ) - } - #[inline] - fn stv_abi_packed_encoded_size(&self) -> usize { - if let Some(size) = ::PACKED_ENCODED_SIZE { - return size; - } - let tuple = - as ::core::convert::From>::from(self.clone()); - as alloy_sol_types::SolType>::abi_packed_encoded_size( - &tuple, - ) - } - } - #[automatically_derived] - impl alloy_sol_types::SolType for Settings { - type RustType = Self; - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SOL_NAME: &'static str = ::NAME; - const ENCODED_SIZE: Option = - as alloy_sol_types::SolType>::ENCODED_SIZE; - const PACKED_ENCODED_SIZE: Option = - as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; - #[inline] - fn valid_token(token: &Self::Token<'_>) -> bool { - as alloy_sol_types::SolType>::valid_token(token) - } - #[inline] - fn detokenize(token: Self::Token<'_>) -> Self::RustType { - let tuple = as alloy_sol_types::SolType>::detokenize(token); - >>::from(tuple) - } - } - #[automatically_derived] - impl alloy_sol_types::SolStruct for Settings { - const NAME: &'static str = "Settings"; - #[inline] - fn eip712_root_type() -> alloy_sol_types::private::Cow<'static, str> { - alloy_sol_types::private::Cow::Borrowed("Settings(uint16 maxOperatorDataBytes)") - } - #[inline] - fn eip712_components( - ) -> alloy_sol_types::private::Vec> - { - alloy_sol_types::private::Vec::new() - } - #[inline] - fn eip712_encode_type() -> alloy_sol_types::private::Cow<'static, str> { - ::eip712_root_type() - } - #[inline] - fn eip712_encode_data(&self) -> alloy_sol_types::private::Vec { - as alloy_sol_types::SolType>::eip712_data_word( - &self.maxOperatorDataBytes, - ) - .0 - .to_vec() - } - } - #[automatically_derived] - impl alloy_sol_types::EventTopic for Settings { - #[inline] - fn topic_preimage_length(rust: &Self::RustType) -> usize { - 0usize - + as alloy_sol_types::EventTopic>::topic_preimage_length( - &rust.maxOperatorDataBytes, - ) - } - #[inline] - fn encode_topic_preimage( - rust: &Self::RustType, - out: &mut alloy_sol_types::private::Vec, - ) { - out.reserve(::topic_preimage_length(rust)); - as alloy_sol_types::EventTopic>::encode_topic_preimage( - &rust.maxOperatorDataBytes, - out, - ); - } - #[inline] - fn encode_topic(rust: &Self::RustType) -> alloy_sol_types::abi::token::WordToken { - let mut out = alloy_sol_types::private::Vec::new(); - ::encode_topic_preimage(rust, &mut out); - alloy_sol_types::abi::token::WordToken(alloy_sol_types::private::keccak256(out)) - } - } - }; - /// Event with signature `MaintenanceAborted(uint128)` and selector - /// `0x8fb9cd054d0a022110cced239e908b834e4cd219511856d4eaae3051d932d604`. - /// ```solidity - /// event MaintenanceAborted(uint128 clusterVersion); - /// ``` - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - #[derive(Clone)] - pub struct MaintenanceAborted { - #[allow(missing_docs)] - pub clusterVersion: u128, - } - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - #[automatically_derived] - impl alloy_sol_types::SolEvent for MaintenanceAborted { - type DataTuple<'a> = (alloy::sol_types::sol_data::Uint<128>,); - type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); - const SIGNATURE: &'static str = "MaintenanceAborted(uint128)"; - const SIGNATURE_HASH: alloy_sol_types::private::B256 = - alloy_sol_types::private::B256::new([ - 143u8, 185u8, 205u8, 5u8, 77u8, 10u8, 2u8, 33u8, 16u8, 204u8, 237u8, 35u8, - 158u8, 144u8, 139u8, 131u8, 78u8, 76u8, 210u8, 25u8, 81u8, 24u8, 86u8, 212u8, - 234u8, 174u8, 48u8, 81u8, 217u8, 50u8, 214u8, 4u8, - ]); - const ANONYMOUS: bool = false; - #[allow(unused_variables)] - #[inline] - fn new( - topics: ::RustType, - data: as alloy_sol_types::SolType>::RustType, - ) -> Self { - Self { - clusterVersion: data.0, - } - } - #[inline] - fn check_signature( - topics: &::RustType, - ) -> alloy_sol_types::Result<()> { - if topics.0 != Self::SIGNATURE_HASH { - return Err(alloy_sol_types::Error::invalid_event_signature_hash( - Self::SIGNATURE, - topics.0, - Self::SIGNATURE_HASH, - )); - } - Ok(()) - } - #[inline] - fn tokenize_body(&self) -> Self::DataToken<'_> { - ( - as alloy_sol_types::SolType>::tokenize( - &self.clusterVersion, - ), - ) - } - #[inline] - fn topics(&self) -> ::RustType { - (Self::SIGNATURE_HASH.into(),) - } - #[inline] - fn encode_topics_raw( - &self, - out: &mut [alloy_sol_types::abi::token::WordToken], - ) -> alloy_sol_types::Result<()> { - if out.len() < ::COUNT { - return Err(alloy_sol_types::Error::Overrun); - } - out[0usize] = alloy_sol_types::abi::token::WordToken(Self::SIGNATURE_HASH); - Ok(()) - } - } - #[automatically_derived] - impl alloy_sol_types::private::IntoLogData for MaintenanceAborted { - fn to_log_data(&self) -> alloy_sol_types::private::LogData { - From::from(self) - } - fn into_log_data(self) -> alloy_sol_types::private::LogData { - From::from(&self) - } - } - #[automatically_derived] - impl From<&MaintenanceAborted> for alloy_sol_types::private::LogData { - #[inline] - fn from(this: &MaintenanceAborted) -> alloy_sol_types::private::LogData { - alloy_sol_types::SolEvent::encode_log_data(this) - } - } - }; - /// Event with signature `MaintenanceCompleted(address,uint128)` and - /// selector `0xf91067eb420c28d3124865fc996e6aa9d541b9b4fef9188cb965a6cc6491638e`. - /// ```solidity - /// event MaintenanceCompleted(address operatorAddress, uint128 clusterVersion); - /// ``` - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - #[derive(Clone)] - pub struct MaintenanceCompleted { - #[allow(missing_docs)] - pub operatorAddress: alloy::sol_types::private::Address, - #[allow(missing_docs)] - pub clusterVersion: u128, - } - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - #[automatically_derived] - impl alloy_sol_types::SolEvent for MaintenanceCompleted { - type DataTuple<'a> = ( - alloy::sol_types::sol_data::Address, - alloy::sol_types::sol_data::Uint<128>, - ); - type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); - const SIGNATURE: &'static str = "MaintenanceCompleted(address,uint128)"; - const SIGNATURE_HASH: alloy_sol_types::private::B256 = - alloy_sol_types::private::B256::new([ - 249u8, 16u8, 103u8, 235u8, 66u8, 12u8, 40u8, 211u8, 18u8, 72u8, 101u8, 252u8, - 153u8, 110u8, 106u8, 169u8, 213u8, 65u8, 185u8, 180u8, 254u8, 249u8, 24u8, - 140u8, 185u8, 101u8, 166u8, 204u8, 100u8, 145u8, 99u8, 142u8, - ]); - const ANONYMOUS: bool = false; - #[allow(unused_variables)] - #[inline] - fn new( - topics: ::RustType, - data: as alloy_sol_types::SolType>::RustType, - ) -> Self { - Self { - operatorAddress: data.0, - clusterVersion: data.1, - } - } - #[inline] - fn check_signature( - topics: &::RustType, - ) -> alloy_sol_types::Result<()> { - if topics.0 != Self::SIGNATURE_HASH { - return Err(alloy_sol_types::Error::invalid_event_signature_hash( - Self::SIGNATURE, - topics.0, - Self::SIGNATURE_HASH, - )); - } - Ok(()) - } - #[inline] - fn tokenize_body(&self) -> Self::DataToken<'_> { - ( - ::tokenize( - &self.operatorAddress, - ), - as alloy_sol_types::SolType>::tokenize( - &self.clusterVersion, - ), - ) - } - #[inline] - fn topics(&self) -> ::RustType { - (Self::SIGNATURE_HASH.into(),) - } - #[inline] - fn encode_topics_raw( - &self, - out: &mut [alloy_sol_types::abi::token::WordToken], - ) -> alloy_sol_types::Result<()> { - if out.len() < ::COUNT { - return Err(alloy_sol_types::Error::Overrun); - } - out[0usize] = alloy_sol_types::abi::token::WordToken(Self::SIGNATURE_HASH); - Ok(()) - } - } - #[automatically_derived] - impl alloy_sol_types::private::IntoLogData for MaintenanceCompleted { - fn to_log_data(&self) -> alloy_sol_types::private::LogData { - From::from(self) - } - fn into_log_data(self) -> alloy_sol_types::private::LogData { - From::from(&self) - } - } - #[automatically_derived] - impl From<&MaintenanceCompleted> for alloy_sol_types::private::LogData { - #[inline] - fn from(this: &MaintenanceCompleted) -> alloy_sol_types::private::LogData { - alloy_sol_types::SolEvent::encode_log_data(this) - } - } - }; - /// Event with signature `MaintenanceStarted(address,uint128)` and selector - /// `0xbc2748cf02f7a1291525e866efc76ab3b96d32d7afcbb26c53daec617b38b479`. - /// ```solidity - /// event MaintenanceStarted(address operatorAddress, uint128 clusterVersion); - /// ``` - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - #[derive(Clone)] - pub struct MaintenanceStarted { - #[allow(missing_docs)] - pub operatorAddress: alloy::sol_types::private::Address, - #[allow(missing_docs)] - pub clusterVersion: u128, - } - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - #[automatically_derived] - impl alloy_sol_types::SolEvent for MaintenanceStarted { - type DataTuple<'a> = ( - alloy::sol_types::sol_data::Address, - alloy::sol_types::sol_data::Uint<128>, - ); - type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); - const SIGNATURE: &'static str = "MaintenanceStarted(address,uint128)"; - const SIGNATURE_HASH: alloy_sol_types::private::B256 = - alloy_sol_types::private::B256::new([ - 188u8, 39u8, 72u8, 207u8, 2u8, 247u8, 161u8, 41u8, 21u8, 37u8, 232u8, 102u8, - 239u8, 199u8, 106u8, 179u8, 185u8, 109u8, 50u8, 215u8, 175u8, 203u8, 178u8, - 108u8, 83u8, 218u8, 236u8, 97u8, 123u8, 56u8, 180u8, 121u8, - ]); - const ANONYMOUS: bool = false; - #[allow(unused_variables)] - #[inline] - fn new( - topics: ::RustType, - data: as alloy_sol_types::SolType>::RustType, - ) -> Self { - Self { - operatorAddress: data.0, - clusterVersion: data.1, - } - } - #[inline] - fn check_signature( - topics: &::RustType, - ) -> alloy_sol_types::Result<()> { - if topics.0 != Self::SIGNATURE_HASH { - return Err(alloy_sol_types::Error::invalid_event_signature_hash( - Self::SIGNATURE, - topics.0, - Self::SIGNATURE_HASH, - )); - } - Ok(()) - } - #[inline] - fn tokenize_body(&self) -> Self::DataToken<'_> { - ( - ::tokenize( - &self.operatorAddress, - ), - as alloy_sol_types::SolType>::tokenize( - &self.clusterVersion, - ), - ) - } - #[inline] - fn topics(&self) -> ::RustType { - (Self::SIGNATURE_HASH.into(),) - } - #[inline] - fn encode_topics_raw( - &self, - out: &mut [alloy_sol_types::abi::token::WordToken], - ) -> alloy_sol_types::Result<()> { - if out.len() < ::COUNT { - return Err(alloy_sol_types::Error::Overrun); - } - out[0usize] = alloy_sol_types::abi::token::WordToken(Self::SIGNATURE_HASH); - Ok(()) - } - } - #[automatically_derived] - impl alloy_sol_types::private::IntoLogData for MaintenanceStarted { - fn to_log_data(&self) -> alloy_sol_types::private::LogData { - From::from(self) - } - fn into_log_data(self) -> alloy_sol_types::private::LogData { - From::from(&self) - } - } - #[automatically_derived] - impl From<&MaintenanceStarted> for alloy_sol_types::private::LogData { - #[inline] - fn from(this: &MaintenanceStarted) -> alloy_sol_types::private::LogData { - alloy_sol_types::SolEvent::encode_log_data(this) - } - } - }; - /// Event with signature `MigrationAborted(uint64,uint128)` and selector - /// `0xf73240422246f63ed633ef3ce0726b8ab8fb69d46c8a4e5ecb0b2922668674a1`. - /// ```solidity - /// event MigrationAborted(uint64 id, uint128 clusterVersion); - /// ``` - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - #[derive(Clone)] - pub struct MigrationAborted { - #[allow(missing_docs)] - pub id: u64, - #[allow(missing_docs)] - pub clusterVersion: u128, - } - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - #[automatically_derived] - impl alloy_sol_types::SolEvent for MigrationAborted { - type DataTuple<'a> = ( - alloy::sol_types::sol_data::Uint<64>, - alloy::sol_types::sol_data::Uint<128>, - ); - type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); - const SIGNATURE: &'static str = "MigrationAborted(uint64,uint128)"; - const SIGNATURE_HASH: alloy_sol_types::private::B256 = - alloy_sol_types::private::B256::new([ - 247u8, 50u8, 64u8, 66u8, 34u8, 70u8, 246u8, 62u8, 214u8, 51u8, 239u8, 60u8, - 224u8, 114u8, 107u8, 138u8, 184u8, 251u8, 105u8, 212u8, 108u8, 138u8, 78u8, - 94u8, 203u8, 11u8, 41u8, 34u8, 102u8, 134u8, 116u8, 161u8, - ]); - const ANONYMOUS: bool = false; - #[allow(unused_variables)] - #[inline] - fn new( - topics: ::RustType, - data: as alloy_sol_types::SolType>::RustType, - ) -> Self { - Self { - id: data.0, - clusterVersion: data.1, - } - } - #[inline] - fn check_signature( - topics: &::RustType, - ) -> alloy_sol_types::Result<()> { - if topics.0 != Self::SIGNATURE_HASH { - return Err(alloy_sol_types::Error::invalid_event_signature_hash( - Self::SIGNATURE, - topics.0, - Self::SIGNATURE_HASH, - )); - } - Ok(()) - } - #[inline] - fn tokenize_body(&self) -> Self::DataToken<'_> { - ( - as alloy_sol_types::SolType>::tokenize( - &self.id, - ), - as alloy_sol_types::SolType>::tokenize( - &self.clusterVersion, - ), - ) - } - #[inline] - fn topics(&self) -> ::RustType { - (Self::SIGNATURE_HASH.into(),) - } - #[inline] - fn encode_topics_raw( - &self, - out: &mut [alloy_sol_types::abi::token::WordToken], - ) -> alloy_sol_types::Result<()> { - if out.len() < ::COUNT { - return Err(alloy_sol_types::Error::Overrun); - } - out[0usize] = alloy_sol_types::abi::token::WordToken(Self::SIGNATURE_HASH); - Ok(()) - } - } - #[automatically_derived] - impl alloy_sol_types::private::IntoLogData for MigrationAborted { - fn to_log_data(&self) -> alloy_sol_types::private::LogData { - From::from(self) - } - fn into_log_data(self) -> alloy_sol_types::private::LogData { - From::from(&self) - } - } - #[automatically_derived] - impl From<&MigrationAborted> for alloy_sol_types::private::LogData { - #[inline] - fn from(this: &MigrationAborted) -> alloy_sol_types::private::LogData { - alloy_sol_types::SolEvent::encode_log_data(this) - } - } - }; - /// Event with signature `MigrationCompleted(uint64,address,uint128)` and - /// selector `0x01269879535f40ee8957e15e160bf1866c5e2728ff0cbc583d848821e2639b4e`. - /// ```solidity - /// event MigrationCompleted(uint64 id, address operatorAddress, uint128 clusterVersion); - /// ``` - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - #[derive(Clone)] - pub struct MigrationCompleted { - #[allow(missing_docs)] - pub id: u64, - #[allow(missing_docs)] - pub operatorAddress: alloy::sol_types::private::Address, - #[allow(missing_docs)] - pub clusterVersion: u128, - } - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - #[automatically_derived] - impl alloy_sol_types::SolEvent for MigrationCompleted { - type DataTuple<'a> = ( - alloy::sol_types::sol_data::Uint<64>, - alloy::sol_types::sol_data::Address, - alloy::sol_types::sol_data::Uint<128>, - ); - type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); - const SIGNATURE: &'static str = "MigrationCompleted(uint64,address,uint128)"; - const SIGNATURE_HASH: alloy_sol_types::private::B256 = - alloy_sol_types::private::B256::new([ - 1u8, 38u8, 152u8, 121u8, 83u8, 95u8, 64u8, 238u8, 137u8, 87u8, 225u8, 94u8, - 22u8, 11u8, 241u8, 134u8, 108u8, 94u8, 39u8, 40u8, 255u8, 12u8, 188u8, 88u8, - 61u8, 132u8, 136u8, 33u8, 226u8, 99u8, 155u8, 78u8, - ]); - const ANONYMOUS: bool = false; - #[allow(unused_variables)] - #[inline] - fn new( - topics: ::RustType, - data: as alloy_sol_types::SolType>::RustType, - ) -> Self { - Self { - id: data.0, - operatorAddress: data.1, - clusterVersion: data.2, - } - } - #[inline] - fn check_signature( - topics: &::RustType, - ) -> alloy_sol_types::Result<()> { - if topics.0 != Self::SIGNATURE_HASH { - return Err(alloy_sol_types::Error::invalid_event_signature_hash( - Self::SIGNATURE, - topics.0, - Self::SIGNATURE_HASH, - )); - } - Ok(()) - } - #[inline] - fn tokenize_body(&self) -> Self::DataToken<'_> { - ( - as alloy_sol_types::SolType>::tokenize( - &self.id, - ), - ::tokenize( - &self.operatorAddress, - ), - as alloy_sol_types::SolType>::tokenize( - &self.clusterVersion, - ), - ) - } - #[inline] - fn topics(&self) -> ::RustType { - (Self::SIGNATURE_HASH.into(),) - } - #[inline] - fn encode_topics_raw( - &self, - out: &mut [alloy_sol_types::abi::token::WordToken], - ) -> alloy_sol_types::Result<()> { - if out.len() < ::COUNT { - return Err(alloy_sol_types::Error::Overrun); - } - out[0usize] = alloy_sol_types::abi::token::WordToken(Self::SIGNATURE_HASH); - Ok(()) - } - } - #[automatically_derived] - impl alloy_sol_types::private::IntoLogData for MigrationCompleted { - fn to_log_data(&self) -> alloy_sol_types::private::LogData { - From::from(self) - } - fn into_log_data(self) -> alloy_sol_types::private::LogData { - From::from(&self) - } - } - #[automatically_derived] - impl From<&MigrationCompleted> for alloy_sol_types::private::LogData { - #[inline] - fn from(this: &MigrationCompleted) -> alloy_sol_types::private::LogData { - alloy_sol_types::SolEvent::encode_log_data(this) - } - } - }; - /// Event with signature - /// `MigrationDataPullCompleted(uint64,address,uint128)` and selector - /// `0xaf5e90e72015f43138f66b4cd08bd1dfa2839030104f22a00af843fe847c6d19`. - /// ```solidity - /// event MigrationDataPullCompleted(uint64 id, address operatorAddress, uint128 clusterVersion); - /// ``` - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - #[derive(Clone)] - pub struct MigrationDataPullCompleted { - #[allow(missing_docs)] - pub id: u64, - #[allow(missing_docs)] - pub operatorAddress: alloy::sol_types::private::Address, - #[allow(missing_docs)] - pub clusterVersion: u128, - } - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - #[automatically_derived] - impl alloy_sol_types::SolEvent for MigrationDataPullCompleted { - type DataTuple<'a> = ( - alloy::sol_types::sol_data::Uint<64>, - alloy::sol_types::sol_data::Address, - alloy::sol_types::sol_data::Uint<128>, - ); - type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); - const SIGNATURE: &'static str = "MigrationDataPullCompleted(uint64,address,uint128)"; - const SIGNATURE_HASH: alloy_sol_types::private::B256 = - alloy_sol_types::private::B256::new([ - 175u8, 94u8, 144u8, 231u8, 32u8, 21u8, 244u8, 49u8, 56u8, 246u8, 107u8, 76u8, - 208u8, 139u8, 209u8, 223u8, 162u8, 131u8, 144u8, 48u8, 16u8, 79u8, 34u8, 160u8, - 10u8, 248u8, 67u8, 254u8, 132u8, 124u8, 109u8, 25u8, - ]); - const ANONYMOUS: bool = false; - #[allow(unused_variables)] - #[inline] - fn new( - topics: ::RustType, - data: as alloy_sol_types::SolType>::RustType, - ) -> Self { - Self { - id: data.0, - operatorAddress: data.1, - clusterVersion: data.2, - } - } - #[inline] - fn check_signature( - topics: &::RustType, - ) -> alloy_sol_types::Result<()> { - if topics.0 != Self::SIGNATURE_HASH { - return Err(alloy_sol_types::Error::invalid_event_signature_hash( - Self::SIGNATURE, - topics.0, - Self::SIGNATURE_HASH, - )); - } - Ok(()) - } - #[inline] - fn tokenize_body(&self) -> Self::DataToken<'_> { - ( - as alloy_sol_types::SolType>::tokenize( - &self.id, - ), - ::tokenize( - &self.operatorAddress, - ), - as alloy_sol_types::SolType>::tokenize( - &self.clusterVersion, - ), - ) - } - #[inline] - fn topics(&self) -> ::RustType { - (Self::SIGNATURE_HASH.into(),) - } - #[inline] - fn encode_topics_raw( - &self, - out: &mut [alloy_sol_types::abi::token::WordToken], - ) -> alloy_sol_types::Result<()> { - if out.len() < ::COUNT { - return Err(alloy_sol_types::Error::Overrun); - } - out[0usize] = alloy_sol_types::abi::token::WordToken(Self::SIGNATURE_HASH); - Ok(()) - } - } - #[automatically_derived] - impl alloy_sol_types::private::IntoLogData for MigrationDataPullCompleted { - fn to_log_data(&self) -> alloy_sol_types::private::LogData { - From::from(self) - } - fn into_log_data(self) -> alloy_sol_types::private::LogData { - From::from(&self) - } - } - #[automatically_derived] - impl From<&MigrationDataPullCompleted> for alloy_sol_types::private::LogData { - #[inline] - fn from(this: &MigrationDataPullCompleted) -> alloy_sol_types::private::LogData { - alloy_sol_types::SolEvent::encode_log_data(this) - } - } - }; - /// Event with signature - /// `MigrationStarted(uint64,((uint8,address)[],uint8),uint128)` and - /// selector `0x78dad2bc0b47c688ed84f3fee79abc18e6c9822db05a79ca19dff54533c7470d`. - /// ```solidity - /// event MigrationStarted(uint64 id, MigrationPlan plan, uint128 clusterVersion); - /// ``` - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - #[derive(Clone)] - pub struct MigrationStarted { - #[allow(missing_docs)] - pub id: u64, - #[allow(missing_docs)] - pub plan: ::RustType, - #[allow(missing_docs)] - pub clusterVersion: u128, - } - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - #[automatically_derived] - impl alloy_sol_types::SolEvent for MigrationStarted { - type DataTuple<'a> = ( - alloy::sol_types::sol_data::Uint<64>, - MigrationPlan, - alloy::sol_types::sol_data::Uint<128>, - ); - type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); - const SIGNATURE: &'static str = - "MigrationStarted(uint64,((uint8,address)[],uint8),uint128)"; - const SIGNATURE_HASH: alloy_sol_types::private::B256 = - alloy_sol_types::private::B256::new([ - 120u8, 218u8, 210u8, 188u8, 11u8, 71u8, 198u8, 136u8, 237u8, 132u8, 243u8, - 254u8, 231u8, 154u8, 188u8, 24u8, 230u8, 201u8, 130u8, 45u8, 176u8, 90u8, - 121u8, 202u8, 25u8, 223u8, 245u8, 69u8, 51u8, 199u8, 71u8, 13u8, - ]); - const ANONYMOUS: bool = false; - #[allow(unused_variables)] - #[inline] - fn new( - topics: ::RustType, - data: as alloy_sol_types::SolType>::RustType, - ) -> Self { - Self { - id: data.0, - plan: data.1, - clusterVersion: data.2, - } - } - #[inline] - fn check_signature( - topics: &::RustType, - ) -> alloy_sol_types::Result<()> { - if topics.0 != Self::SIGNATURE_HASH { - return Err(alloy_sol_types::Error::invalid_event_signature_hash( - Self::SIGNATURE, - topics.0, - Self::SIGNATURE_HASH, - )); - } - Ok(()) - } - #[inline] - fn tokenize_body(&self) -> Self::DataToken<'_> { - ( - as alloy_sol_types::SolType>::tokenize( - &self.id, - ), - ::tokenize(&self.plan), - as alloy_sol_types::SolType>::tokenize( - &self.clusterVersion, - ), - ) - } - #[inline] - fn topics(&self) -> ::RustType { - (Self::SIGNATURE_HASH.into(),) - } - #[inline] - fn encode_topics_raw( - &self, - out: &mut [alloy_sol_types::abi::token::WordToken], - ) -> alloy_sol_types::Result<()> { - if out.len() < ::COUNT { - return Err(alloy_sol_types::Error::Overrun); - } - out[0usize] = alloy_sol_types::abi::token::WordToken(Self::SIGNATURE_HASH); - Ok(()) - } - } - #[automatically_derived] - impl alloy_sol_types::private::IntoLogData for MigrationStarted { - fn to_log_data(&self) -> alloy_sol_types::private::LogData { - From::from(self) - } - fn into_log_data(self) -> alloy_sol_types::private::LogData { - From::from(&self) - } - } - #[automatically_derived] - impl From<&MigrationStarted> for alloy_sol_types::private::LogData { - #[inline] - fn from(this: &MigrationStarted) -> alloy_sol_types::private::LogData { - alloy_sol_types::SolEvent::encode_log_data(this) - } - } - }; - /// Event with signature `NodeOperatorDataUpdated(address,bytes,uint128)` - /// and selector - /// `0x125181ec21882dec51a2392905dff3a82cbd0262f18b5c0c035488671b40afb2`. - /// ```solidity - /// event NodeOperatorDataUpdated(address operatorAddress, bytes data, uint128 clusterVersion); - /// ``` - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - #[derive(Clone)] - pub struct NodeOperatorDataUpdated { - #[allow(missing_docs)] - pub operatorAddress: alloy::sol_types::private::Address, - #[allow(missing_docs)] - pub data: alloy::sol_types::private::Bytes, - #[allow(missing_docs)] - pub clusterVersion: u128, - } - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - #[automatically_derived] - impl alloy_sol_types::SolEvent for NodeOperatorDataUpdated { - type DataTuple<'a> = ( - alloy::sol_types::sol_data::Address, - alloy::sol_types::sol_data::Bytes, - alloy::sol_types::sol_data::Uint<128>, - ); - type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); - const SIGNATURE: &'static str = "NodeOperatorDataUpdated(address,bytes,uint128)"; - const SIGNATURE_HASH: alloy_sol_types::private::B256 = - alloy_sol_types::private::B256::new([ - 18u8, 81u8, 129u8, 236u8, 33u8, 136u8, 45u8, 236u8, 81u8, 162u8, 57u8, 41u8, - 5u8, 223u8, 243u8, 168u8, 44u8, 189u8, 2u8, 98u8, 241u8, 139u8, 92u8, 12u8, - 3u8, 84u8, 136u8, 103u8, 27u8, 64u8, 175u8, 178u8, - ]); - const ANONYMOUS: bool = false; - #[allow(unused_variables)] - #[inline] - fn new( - topics: ::RustType, - data: as alloy_sol_types::SolType>::RustType, - ) -> Self { - Self { - operatorAddress: data.0, - data: data.1, - clusterVersion: data.2, - } - } - #[inline] - fn check_signature( - topics: &::RustType, - ) -> alloy_sol_types::Result<()> { - if topics.0 != Self::SIGNATURE_HASH { - return Err(alloy_sol_types::Error::invalid_event_signature_hash( - Self::SIGNATURE, - topics.0, - Self::SIGNATURE_HASH, - )); - } - Ok(()) - } - #[inline] - fn tokenize_body(&self) -> Self::DataToken<'_> { - ( - ::tokenize( - &self.operatorAddress, - ), - ::tokenize( - &self.data, - ), - as alloy_sol_types::SolType>::tokenize( - &self.clusterVersion, - ), - ) - } - #[inline] - fn topics(&self) -> ::RustType { - (Self::SIGNATURE_HASH.into(),) - } - #[inline] - fn encode_topics_raw( - &self, - out: &mut [alloy_sol_types::abi::token::WordToken], - ) -> alloy_sol_types::Result<()> { - if out.len() < ::COUNT { - return Err(alloy_sol_types::Error::Overrun); - } - out[0usize] = alloy_sol_types::abi::token::WordToken(Self::SIGNATURE_HASH); - Ok(()) - } - } - #[automatically_derived] - impl alloy_sol_types::private::IntoLogData for NodeOperatorDataUpdated { - fn to_log_data(&self) -> alloy_sol_types::private::LogData { - From::from(self) - } - fn into_log_data(self) -> alloy_sol_types::private::LogData { - From::from(&self) - } - } - #[automatically_derived] - impl From<&NodeOperatorDataUpdated> for alloy_sol_types::private::LogData { - #[inline] - fn from(this: &NodeOperatorDataUpdated) -> alloy_sol_types::private::LogData { - alloy_sol_types::SolEvent::encode_log_data(this) - } - } - }; - /// Constructor`. - /// ```solidity - /// constructor(Settings initialSettings, address[] initialOperators); - /// ``` - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct constructorCall { - #[allow(missing_docs)] - pub initialSettings: ::RustType, - #[allow(missing_docs)] - pub initialOperators: alloy::sol_types::private::Vec, - } - const _: () = { - use alloy::sol_types as alloy_sol_types; - { - #[doc(hidden)] - type UnderlyingSolTuple<'a> = ( - Settings, - alloy::sol_types::sol_data::Array, - ); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = ( - ::RustType, - alloy::sol_types::private::Vec, - ); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: constructorCall) -> Self { - (value.initialSettings, value.initialOperators) - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for constructorCall { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self { - initialSettings: tuple.0, - initialOperators: tuple.1, - } - } - } - } - #[automatically_derived] - impl alloy_sol_types::SolConstructor for constructorCall { - type Parameters<'a> = ( - Settings, - alloy::sol_types::sol_data::Array, - ); - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - #[inline] - fn new<'a>( - tuple: as alloy_sol_types::SolType>::RustType, - ) -> Self { - tuple.into() - } - #[inline] - fn tokenize(&self) -> Self::Token<'_> { - ( - ::tokenize( - &self.initialSettings, - ), - as alloy_sol_types::SolType>::tokenize(&self.initialOperators), - ) - } - } - }; - /// Function with signature `abortMaintenance()` and selector `0x3048bfba`. - /// ```solidity - /// function abortMaintenance() external; - /// ``` - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct abortMaintenanceCall {} - /// Container type for the return parameters of the - /// [`abortMaintenance()`](abortMaintenanceCall) function. - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct abortMaintenanceReturn {} - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - { - #[doc(hidden)] - type UnderlyingSolTuple<'a> = (); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = (); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: abortMaintenanceCall) -> Self { - () - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for abortMaintenanceCall { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self {} - } - } - } - { - #[doc(hidden)] - type UnderlyingSolTuple<'a> = (); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = (); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: abortMaintenanceReturn) -> Self { - () - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for abortMaintenanceReturn { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self {} - } - } - } - #[automatically_derived] - impl alloy_sol_types::SolCall for abortMaintenanceCall { - type Parameters<'a> = (); - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - type Return = abortMaintenanceReturn; - type ReturnTuple<'a> = (); - type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SIGNATURE: &'static str = "abortMaintenance()"; - const SELECTOR: [u8; 4] = [48u8, 72u8, 191u8, 186u8]; - #[inline] - fn new<'a>( - tuple: as alloy_sol_types::SolType>::RustType, - ) -> Self { - tuple.into() - } - #[inline] - fn tokenize(&self) -> Self::Token<'_> { - () - } - #[inline] - fn abi_decode_returns( - data: &[u8], - validate: bool, - ) -> alloy_sol_types::Result { - as alloy_sol_types::SolType>::abi_decode_sequence( - data, validate, - ) - .map(Into::into) - } - } - }; - /// Function with signature `abortMigration()` and selector `0xc130809a`. - /// ```solidity - /// function abortMigration() external; - /// ``` - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct abortMigrationCall {} - /// Container type for the return parameters of the - /// [`abortMigration()`](abortMigrationCall) function. - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct abortMigrationReturn {} - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - { - #[doc(hidden)] - type UnderlyingSolTuple<'a> = (); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = (); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: abortMigrationCall) -> Self { - () - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for abortMigrationCall { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self {} - } - } - } - { - #[doc(hidden)] - type UnderlyingSolTuple<'a> = (); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = (); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: abortMigrationReturn) -> Self { - () - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for abortMigrationReturn { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self {} - } - } - } - #[automatically_derived] - impl alloy_sol_types::SolCall for abortMigrationCall { - type Parameters<'a> = (); - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - type Return = abortMigrationReturn; - type ReturnTuple<'a> = (); - type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SIGNATURE: &'static str = "abortMigration()"; - const SELECTOR: [u8; 4] = [193u8, 48u8, 128u8, 154u8]; - #[inline] - fn new<'a>( - tuple: as alloy_sol_types::SolType>::RustType, - ) -> Self { - tuple.into() - } - #[inline] - fn tokenize(&self) -> Self::Token<'_> { - () - } - #[inline] - fn abi_decode_returns( - data: &[u8], - validate: bool, - ) -> alloy_sol_types::Result { - as alloy_sol_types::SolType>::abi_decode_sequence( - data, validate, - ) - .map(Into::into) - } - } - }; - /// Function with signature `completeMaintenance()` and selector - /// `0xad36e6d0`. ```solidity - /// function completeMaintenance() external; - /// ``` - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct completeMaintenanceCall {} - /// Container type for the return parameters of the - /// [`completeMaintenance()`](completeMaintenanceCall) function. - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct completeMaintenanceReturn {} - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - { - #[doc(hidden)] - type UnderlyingSolTuple<'a> = (); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = (); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: completeMaintenanceCall) -> Self { - () - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for completeMaintenanceCall { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self {} - } - } - } - { - #[doc(hidden)] - type UnderlyingSolTuple<'a> = (); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = (); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: completeMaintenanceReturn) -> Self { - () - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for completeMaintenanceReturn { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self {} - } - } - } - #[automatically_derived] - impl alloy_sol_types::SolCall for completeMaintenanceCall { - type Parameters<'a> = (); - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - type Return = completeMaintenanceReturn; - type ReturnTuple<'a> = (); - type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SIGNATURE: &'static str = "completeMaintenance()"; - const SELECTOR: [u8; 4] = [173u8, 54u8, 230u8, 208u8]; - #[inline] - fn new<'a>( - tuple: as alloy_sol_types::SolType>::RustType, - ) -> Self { - tuple.into() - } - #[inline] - fn tokenize(&self) -> Self::Token<'_> { - () - } - #[inline] - fn abi_decode_returns( - data: &[u8], - validate: bool, - ) -> alloy_sol_types::Result { - as alloy_sol_types::SolType>::abi_decode_sequence( - data, validate, - ) - .map(Into::into) - } - } - }; - /// Function with signature `completeMigration(uint64,uint8)` and selector - /// `0x55a47d0a`. ```solidity - /// function completeMigration(uint64 id, uint8 operatorIdx) external; - /// ``` - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct completeMigrationCall { - #[allow(missing_docs)] - pub id: u64, - #[allow(missing_docs)] - pub operatorIdx: u8, - } - /// Container type for the return parameters of the - /// [`completeMigration(uint64,uint8)`](completeMigrationCall) function. - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct completeMigrationReturn {} - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - { - #[doc(hidden)] - type UnderlyingSolTuple<'a> = ( - alloy::sol_types::sol_data::Uint<64>, - alloy::sol_types::sol_data::Uint<8>, - ); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = (u64, u8); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: completeMigrationCall) -> Self { - (value.id, value.operatorIdx) - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for completeMigrationCall { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self { - id: tuple.0, - operatorIdx: tuple.1, - } - } - } - } - { - #[doc(hidden)] - type UnderlyingSolTuple<'a> = (); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = (); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: completeMigrationReturn) -> Self { - () - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for completeMigrationReturn { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self {} - } - } - } - #[automatically_derived] - impl alloy_sol_types::SolCall for completeMigrationCall { - type Parameters<'a> = ( - alloy::sol_types::sol_data::Uint<64>, - alloy::sol_types::sol_data::Uint<8>, - ); - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - type Return = completeMigrationReturn; - type ReturnTuple<'a> = (); - type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SIGNATURE: &'static str = "completeMigration(uint64,uint8)"; - const SELECTOR: [u8; 4] = [85u8, 164u8, 125u8, 10u8]; - #[inline] - fn new<'a>( - tuple: as alloy_sol_types::SolType>::RustType, - ) -> Self { - tuple.into() - } - #[inline] - fn tokenize(&self) -> Self::Token<'_> { - ( - as alloy_sol_types::SolType>::tokenize( - &self.id, - ), - as alloy_sol_types::SolType>::tokenize( - &self.operatorIdx, - ), - ) - } - #[inline] - fn abi_decode_returns( - data: &[u8], - validate: bool, - ) -> alloy_sol_types::Result { - as alloy_sol_types::SolType>::abi_decode_sequence( - data, validate, - ) - .map(Into::into) - } - } - }; - /// Function with signature `getView()` and selector `0x75418b9d`. - /// ```solidity - /// function getView() external view returns (ClusterView memory); - /// ``` - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct getViewCall {} - /// Container type for the return parameters of the - /// [`getView()`](getViewCall) function. - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct getViewReturn { - #[allow(missing_docs)] - pub _0: ::RustType, - } - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - { - #[doc(hidden)] - type UnderlyingSolTuple<'a> = (); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = (); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: getViewCall) -> Self { - () - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for getViewCall { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self {} - } - } - } - { - #[doc(hidden)] - type UnderlyingSolTuple<'a> = (ClusterView,); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = (::RustType,); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: getViewReturn) -> Self { - (value._0,) - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for getViewReturn { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self { _0: tuple.0 } - } - } - } - #[automatically_derived] - impl alloy_sol_types::SolCall for getViewCall { - type Parameters<'a> = (); - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - type Return = getViewReturn; - type ReturnTuple<'a> = (ClusterView,); - type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SIGNATURE: &'static str = "getView()"; - const SELECTOR: [u8; 4] = [117u8, 65u8, 139u8, 157u8]; - #[inline] - fn new<'a>( - tuple: as alloy_sol_types::SolType>::RustType, - ) -> Self { - tuple.into() - } - #[inline] - fn tokenize(&self) -> Self::Token<'_> { - () - } - #[inline] - fn abi_decode_returns( - data: &[u8], - validate: bool, - ) -> alloy_sol_types::Result { - as alloy_sol_types::SolType>::abi_decode_sequence( - data, validate, - ) - .map(Into::into) - } - } - }; - /// Function with signature `registerNodeOperator(bytes)` and selector - /// `0x8b5252d6`. ```solidity - /// function registerNodeOperator(bytes memory data) external; - /// ``` - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct registerNodeOperatorCall { - #[allow(missing_docs)] - pub data: alloy::sol_types::private::Bytes, - } - /// Container type for the return parameters of the - /// [`registerNodeOperator(bytes)`](registerNodeOperatorCall) function. - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct registerNodeOperatorReturn {} - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - { - #[doc(hidden)] - type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Bytes,); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = (alloy::sol_types::private::Bytes,); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: registerNodeOperatorCall) -> Self { - (value.data,) - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for registerNodeOperatorCall { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self { data: tuple.0 } - } - } - } - { - #[doc(hidden)] - type UnderlyingSolTuple<'a> = (); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = (); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: registerNodeOperatorReturn) -> Self { - () - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for registerNodeOperatorReturn { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self {} - } - } - } - #[automatically_derived] - impl alloy_sol_types::SolCall for registerNodeOperatorCall { - type Parameters<'a> = (alloy::sol_types::sol_data::Bytes,); - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - type Return = registerNodeOperatorReturn; - type ReturnTuple<'a> = (); - type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SIGNATURE: &'static str = "registerNodeOperator(bytes)"; - const SELECTOR: [u8; 4] = [139u8, 82u8, 82u8, 214u8]; - #[inline] - fn new<'a>( - tuple: as alloy_sol_types::SolType>::RustType, - ) -> Self { - tuple.into() - } - #[inline] - fn tokenize(&self) -> Self::Token<'_> { - ( - ::tokenize( - &self.data, - ), - ) - } - #[inline] - fn abi_decode_returns( - data: &[u8], - validate: bool, - ) -> alloy_sol_types::Result { - as alloy_sol_types::SolType>::abi_decode_sequence( - data, validate, - ) - .map(Into::into) - } - } - }; - /// Function with signature `startMaintenance(uint8)` and selector - /// `0xdd3fd269`. ```solidity - /// function startMaintenance(uint8 operatorIdx) external; - /// ``` - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct startMaintenanceCall { - #[allow(missing_docs)] - pub operatorIdx: u8, - } - /// Container type for the return parameters of the - /// [`startMaintenance(uint8)`](startMaintenanceCall) function. - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct startMaintenanceReturn {} - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - { - #[doc(hidden)] - type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Uint<8>,); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = (u8,); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: startMaintenanceCall) -> Self { - (value.operatorIdx,) - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for startMaintenanceCall { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self { - operatorIdx: tuple.0, - } - } - } - } - { - #[doc(hidden)] - type UnderlyingSolTuple<'a> = (); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = (); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: startMaintenanceReturn) -> Self { - () - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for startMaintenanceReturn { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self {} - } - } - } - #[automatically_derived] - impl alloy_sol_types::SolCall for startMaintenanceCall { - type Parameters<'a> = (alloy::sol_types::sol_data::Uint<8>,); - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - type Return = startMaintenanceReturn; - type ReturnTuple<'a> = (); - type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SIGNATURE: &'static str = "startMaintenance(uint8)"; - const SELECTOR: [u8; 4] = [221u8, 63u8, 210u8, 105u8]; - #[inline] - fn new<'a>( - tuple: as alloy_sol_types::SolType>::RustType, - ) -> Self { - tuple.into() - } - #[inline] - fn tokenize(&self) -> Self::Token<'_> { - ( - as alloy_sol_types::SolType>::tokenize( - &self.operatorIdx, - ), - ) - } - #[inline] - fn abi_decode_returns( - data: &[u8], - validate: bool, - ) -> alloy_sol_types::Result { - as alloy_sol_types::SolType>::abi_decode_sequence( - data, validate, - ) - .map(Into::into) - } - } - }; - /// Function with signature `startMigration(((uint8,address)[],uint8))` and - /// selector `0xcdbfc62d`. ```solidity - /// function startMigration(MigrationPlan memory plan) external; - /// ``` - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct startMigrationCall { - #[allow(missing_docs)] - pub plan: ::RustType, - } - /// Container type for the return parameters of the - /// [`startMigration(((uint8,address)[],uint8))`](startMigrationCall) - /// function. - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct startMigrationReturn {} - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - { - #[doc(hidden)] - type UnderlyingSolTuple<'a> = (MigrationPlan,); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = - (::RustType,); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: startMigrationCall) -> Self { - (value.plan,) - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for startMigrationCall { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self { plan: tuple.0 } - } - } - } - { - #[doc(hidden)] - type UnderlyingSolTuple<'a> = (); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = (); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: startMigrationReturn) -> Self { - () - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for startMigrationReturn { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self {} - } - } - } - #[automatically_derived] - impl alloy_sol_types::SolCall for startMigrationCall { - type Parameters<'a> = (MigrationPlan,); - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - type Return = startMigrationReturn; - type ReturnTuple<'a> = (); - type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SIGNATURE: &'static str = "startMigration(((uint8,address)[],uint8))"; - const SELECTOR: [u8; 4] = [205u8, 191u8, 198u8, 45u8]; - #[inline] - fn new<'a>( - tuple: as alloy_sol_types::SolType>::RustType, - ) -> Self { - tuple.into() - } - #[inline] - fn tokenize(&self) -> Self::Token<'_> { - (::tokenize( - &self.plan, - ),) - } - #[inline] - fn abi_decode_returns( - data: &[u8], - validate: bool, - ) -> alloy_sol_types::Result { - as alloy_sol_types::SolType>::abi_decode_sequence( - data, validate, - ) - .map(Into::into) - } - } - }; - /// Function with signature `transferOwnership(address)` and selector - /// `0xf2fde38b`. ```solidity - /// function transferOwnership(address newOwner) external; - /// ``` - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct transferOwnershipCall { - #[allow(missing_docs)] - pub newOwner: alloy::sol_types::private::Address, - } - /// Container type for the return parameters of the - /// [`transferOwnership(address)`](transferOwnershipCall) function. - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct transferOwnershipReturn {} - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - { - #[doc(hidden)] - type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Address,); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = (alloy::sol_types::private::Address,); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: transferOwnershipCall) -> Self { - (value.newOwner,) - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for transferOwnershipCall { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self { newOwner: tuple.0 } - } - } - } - { - #[doc(hidden)] - type UnderlyingSolTuple<'a> = (); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = (); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: transferOwnershipReturn) -> Self { - () - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for transferOwnershipReturn { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self {} - } - } - } - #[automatically_derived] - impl alloy_sol_types::SolCall for transferOwnershipCall { - type Parameters<'a> = (alloy::sol_types::sol_data::Address,); - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - type Return = transferOwnershipReturn; - type ReturnTuple<'a> = (); - type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SIGNATURE: &'static str = "transferOwnership(address)"; - const SELECTOR: [u8; 4] = [242u8, 253u8, 227u8, 139u8]; - #[inline] - fn new<'a>( - tuple: as alloy_sol_types::SolType>::RustType, - ) -> Self { - tuple.into() - } - #[inline] - fn tokenize(&self) -> Self::Token<'_> { - ( - ::tokenize( - &self.newOwner, - ), - ) - } - #[inline] - fn abi_decode_returns( - data: &[u8], - validate: bool, - ) -> alloy_sol_types::Result { - as alloy_sol_types::SolType>::abi_decode_sequence( - data, validate, - ) - .map(Into::into) - } - } - }; - /// Function with signature `updateNodeOperatorData(uint8,bytes)` and - /// selector `0xf019b154`. ```solidity - /// function updateNodeOperatorData(uint8 operatorIdx, bytes memory data) - /// external; ``` - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct updateNodeOperatorDataCall { - #[allow(missing_docs)] - pub operatorIdx: u8, - #[allow(missing_docs)] - pub data: alloy::sol_types::private::Bytes, - } - /// Container type for the return parameters of the - /// [`updateNodeOperatorData(uint8,bytes)`](updateNodeOperatorDataCall) - /// function. - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct updateNodeOperatorDataReturn {} - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - { - #[doc(hidden)] - type UnderlyingSolTuple<'a> = ( - alloy::sol_types::sol_data::Uint<8>, - alloy::sol_types::sol_data::Bytes, - ); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = (u8, alloy::sol_types::private::Bytes); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: updateNodeOperatorDataCall) -> Self { - (value.operatorIdx, value.data) - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for updateNodeOperatorDataCall { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self { - operatorIdx: tuple.0, - data: tuple.1, - } - } - } - } - { - #[doc(hidden)] - type UnderlyingSolTuple<'a> = (); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = (); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: updateNodeOperatorDataReturn) -> Self { - () - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for updateNodeOperatorDataReturn { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self {} - } - } - } - #[automatically_derived] - impl alloy_sol_types::SolCall for updateNodeOperatorDataCall { - type Parameters<'a> = ( - alloy::sol_types::sol_data::Uint<8>, - alloy::sol_types::sol_data::Bytes, - ); - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - type Return = updateNodeOperatorDataReturn; - type ReturnTuple<'a> = (); - type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SIGNATURE: &'static str = "updateNodeOperatorData(uint8,bytes)"; - const SELECTOR: [u8; 4] = [240u8, 25u8, 177u8, 84u8]; - #[inline] - fn new<'a>( - tuple: as alloy_sol_types::SolType>::RustType, - ) -> Self { - tuple.into() - } - #[inline] - fn tokenize(&self) -> Self::Token<'_> { - ( - as alloy_sol_types::SolType>::tokenize( - &self.operatorIdx, - ), - ::tokenize( - &self.data, - ), - ) - } - #[inline] - fn abi_decode_returns( - data: &[u8], - validate: bool, - ) -> alloy_sol_types::Result { - as alloy_sol_types::SolType>::abi_decode_sequence( - data, validate, - ) - .map(Into::into) - } - } - }; - /// Function with signature `updateSettings((uint16))` and selector - /// `0x65706f9c`. ```solidity - /// function updateSettings(Settings memory newSettings) external; - /// ``` - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct updateSettingsCall { - #[allow(missing_docs)] - pub newSettings: ::RustType, - } - /// Container type for the return parameters of the - /// [`updateSettings((uint16))`](updateSettingsCall) function. - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct updateSettingsReturn {} - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - { - #[doc(hidden)] - type UnderlyingSolTuple<'a> = (Settings,); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = (::RustType,); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: updateSettingsCall) -> Self { - (value.newSettings,) - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for updateSettingsCall { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self { - newSettings: tuple.0, - } - } - } - } - { - #[doc(hidden)] - type UnderlyingSolTuple<'a> = (); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = (); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: updateSettingsReturn) -> Self { - () - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for updateSettingsReturn { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self {} - } - } - } - #[automatically_derived] - impl alloy_sol_types::SolCall for updateSettingsCall { - type Parameters<'a> = (Settings,); - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - type Return = updateSettingsReturn; - type ReturnTuple<'a> = (); - type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SIGNATURE: &'static str = "updateSettings((uint16))"; - const SELECTOR: [u8; 4] = [101u8, 112u8, 111u8, 156u8]; - #[inline] - fn new<'a>( - tuple: as alloy_sol_types::SolType>::RustType, - ) -> Self { - tuple.into() - } - #[inline] - fn tokenize(&self) -> Self::Token<'_> { - (::tokenize( - &self.newSettings, - ),) - } - #[inline] - fn abi_decode_returns( - data: &[u8], - validate: bool, - ) -> alloy_sol_types::Result { - as alloy_sol_types::SolType>::abi_decode_sequence( - data, validate, - ) - .map(Into::into) - } - } - }; - /// Container for all the [`Cluster`](self) function calls. - pub enum ClusterCalls { - #[allow(missing_docs)] - abortMaintenance(abortMaintenanceCall), - #[allow(missing_docs)] - abortMigration(abortMigrationCall), - #[allow(missing_docs)] - completeMaintenance(completeMaintenanceCall), - #[allow(missing_docs)] - completeMigration(completeMigrationCall), - #[allow(missing_docs)] - getView(getViewCall), - #[allow(missing_docs)] - registerNodeOperator(registerNodeOperatorCall), - #[allow(missing_docs)] - startMaintenance(startMaintenanceCall), - #[allow(missing_docs)] - startMigration(startMigrationCall), - #[allow(missing_docs)] - transferOwnership(transferOwnershipCall), - #[allow(missing_docs)] - updateNodeOperatorData(updateNodeOperatorDataCall), - #[allow(missing_docs)] - updateSettings(updateSettingsCall), - } - #[automatically_derived] - impl ClusterCalls { - /// All the selectors of this enum. - /// - /// Note that the selectors might not be in the same order as the - /// variants. No guarantees are made about the order of the - /// selectors. - /// - /// Prefer using `SolInterface` methods instead. - pub const SELECTORS: &'static [[u8; 4usize]] = &[ - [48u8, 72u8, 191u8, 186u8], - [85u8, 164u8, 125u8, 10u8], - [101u8, 112u8, 111u8, 156u8], - [117u8, 65u8, 139u8, 157u8], - [139u8, 82u8, 82u8, 214u8], - [173u8, 54u8, 230u8, 208u8], - [193u8, 48u8, 128u8, 154u8], - [205u8, 191u8, 198u8, 45u8], - [221u8, 63u8, 210u8, 105u8], - [240u8, 25u8, 177u8, 84u8], - [242u8, 253u8, 227u8, 139u8], - ]; - } - #[automatically_derived] - impl alloy_sol_types::SolInterface for ClusterCalls { - const NAME: &'static str = "ClusterCalls"; - const MIN_DATA_LENGTH: usize = 0usize; - const COUNT: usize = 11usize; - #[inline] - fn selector(&self) -> [u8; 4] { - match self { - Self::abortMaintenance(_) => { - ::SELECTOR - } - Self::abortMigration(_) => { - ::SELECTOR - } - Self::completeMaintenance(_) => { - ::SELECTOR - } - Self::completeMigration(_) => { - ::SELECTOR - } - Self::getView(_) => ::SELECTOR, - Self::registerNodeOperator(_) => { - ::SELECTOR - } - Self::startMaintenance(_) => { - ::SELECTOR - } - Self::startMigration(_) => { - ::SELECTOR - } - Self::transferOwnership(_) => { - ::SELECTOR - } - Self::updateNodeOperatorData(_) => { - ::SELECTOR - } - Self::updateSettings(_) => { - ::SELECTOR - } - } - } - #[inline] - fn selector_at(i: usize) -> ::core::option::Option<[u8; 4]> { - Self::SELECTORS.get(i).copied() - } - #[inline] - fn valid_selector(selector: [u8; 4]) -> bool { - Self::SELECTORS.binary_search(&selector).is_ok() - } - #[inline] - #[allow(non_snake_case)] - fn abi_decode_raw( - selector: [u8; 4], - data: &[u8], - validate: bool, - ) -> alloy_sol_types::Result { - static DECODE_SHIMS: &[fn(&[u8], bool) -> alloy_sol_types::Result] = &[ - { - fn abortMaintenance( - data: &[u8], - validate: bool, - ) -> alloy_sol_types::Result { - ::abi_decode_raw( - data, validate, - ) - .map(ClusterCalls::abortMaintenance) - } - abortMaintenance - }, - { - fn completeMigration( - data: &[u8], - validate: bool, - ) -> alloy_sol_types::Result { - ::abi_decode_raw( - data, validate, - ) - .map(ClusterCalls::completeMigration) - } - completeMigration - }, - { - fn updateSettings( - data: &[u8], - validate: bool, - ) -> alloy_sol_types::Result { - ::abi_decode_raw( - data, validate, - ) - .map(ClusterCalls::updateSettings) - } - updateSettings - }, - { - fn getView( - data: &[u8], - validate: bool, - ) -> alloy_sol_types::Result { - ::abi_decode_raw(data, validate) - .map(ClusterCalls::getView) - } - getView - }, - { - fn registerNodeOperator( - data: &[u8], - validate: bool, - ) -> alloy_sol_types::Result { - ::abi_decode_raw( - data, validate, - ) - .map(ClusterCalls::registerNodeOperator) - } - registerNodeOperator - }, - { - fn completeMaintenance( - data: &[u8], - validate: bool, - ) -> alloy_sol_types::Result { - ::abi_decode_raw( - data, validate, - ) - .map(ClusterCalls::completeMaintenance) - } - completeMaintenance - }, - { - fn abortMigration( - data: &[u8], - validate: bool, - ) -> alloy_sol_types::Result { - ::abi_decode_raw( - data, validate, - ) - .map(ClusterCalls::abortMigration) - } - abortMigration - }, - { - fn startMigration( - data: &[u8], - validate: bool, - ) -> alloy_sol_types::Result { - ::abi_decode_raw( - data, validate, - ) - .map(ClusterCalls::startMigration) - } - startMigration - }, - { - fn startMaintenance( - data: &[u8], - validate: bool, - ) -> alloy_sol_types::Result { - ::abi_decode_raw( - data, validate, - ) - .map(ClusterCalls::startMaintenance) - } - startMaintenance - }, - { - fn updateNodeOperatorData( - data: &[u8], - validate: bool, - ) -> alloy_sol_types::Result { - ::abi_decode_raw( - data, validate, - ) - .map(ClusterCalls::updateNodeOperatorData) - } - updateNodeOperatorData - }, - { - fn transferOwnership( - data: &[u8], - validate: bool, - ) -> alloy_sol_types::Result { - ::abi_decode_raw( - data, validate, - ) - .map(ClusterCalls::transferOwnership) - } - transferOwnership - }, - ]; - let Ok(idx) = Self::SELECTORS.binary_search(&selector) else { - return Err(alloy_sol_types::Error::unknown_selector( - ::NAME, - selector, - )); - }; - DECODE_SHIMS[idx](data, validate) - } - #[inline] - fn abi_encoded_size(&self) -> usize { - match self { - Self::abortMaintenance(inner) => { - ::abi_encoded_size(inner) - } - Self::abortMigration(inner) => { - ::abi_encoded_size(inner) - } - Self::completeMaintenance(inner) => { - ::abi_encoded_size(inner) - } - Self::completeMigration(inner) => { - ::abi_encoded_size(inner) - } - Self::getView(inner) => { - ::abi_encoded_size(inner) - } - Self::registerNodeOperator(inner) => { - ::abi_encoded_size(inner) - } - Self::startMaintenance(inner) => { - ::abi_encoded_size(inner) - } - Self::startMigration(inner) => { - ::abi_encoded_size(inner) - } - Self::transferOwnership(inner) => { - ::abi_encoded_size(inner) - } - Self::updateNodeOperatorData(inner) => { - ::abi_encoded_size( - inner, - ) - } - Self::updateSettings(inner) => { - ::abi_encoded_size(inner) - } - } - } - #[inline] - fn abi_encode_raw(&self, out: &mut alloy_sol_types::private::Vec) { - match self { - Self::abortMaintenance(inner) => { - ::abi_encode_raw(inner, out) - } - Self::abortMigration(inner) => { - ::abi_encode_raw(inner, out) - } - Self::completeMaintenance(inner) => { - ::abi_encode_raw( - inner, out, - ) - } - Self::completeMigration(inner) => { - ::abi_encode_raw(inner, out) - } - Self::getView(inner) => { - ::abi_encode_raw(inner, out) - } - Self::registerNodeOperator(inner) => { - ::abi_encode_raw( - inner, out, - ) - } - Self::startMaintenance(inner) => { - ::abi_encode_raw(inner, out) - } - Self::startMigration(inner) => { - ::abi_encode_raw(inner, out) - } - Self::transferOwnership(inner) => { - ::abi_encode_raw(inner, out) - } - Self::updateNodeOperatorData(inner) => { - ::abi_encode_raw( - inner, out, - ) - } - Self::updateSettings(inner) => { - ::abi_encode_raw(inner, out) - } - } - } - } - /// Container for all the [`Cluster`](self) events. - pub enum ClusterEvents { - #[allow(missing_docs)] - MaintenanceAborted(MaintenanceAborted), - #[allow(missing_docs)] - MaintenanceCompleted(MaintenanceCompleted), - #[allow(missing_docs)] - MaintenanceStarted(MaintenanceStarted), - #[allow(missing_docs)] - MigrationAborted(MigrationAborted), - #[allow(missing_docs)] - MigrationCompleted(MigrationCompleted), - #[allow(missing_docs)] - MigrationDataPullCompleted(MigrationDataPullCompleted), - #[allow(missing_docs)] - MigrationStarted(MigrationStarted), - #[allow(missing_docs)] - NodeOperatorDataUpdated(NodeOperatorDataUpdated), - } - #[automatically_derived] - impl ClusterEvents { - /// All the selectors of this enum. - /// - /// Note that the selectors might not be in the same order as the - /// variants. No guarantees are made about the order of the - /// selectors. - /// - /// Prefer using `SolInterface` methods instead. - pub const SELECTORS: &'static [[u8; 32usize]] = &[ - [ - 1u8, 38u8, 152u8, 121u8, 83u8, 95u8, 64u8, 238u8, 137u8, 87u8, 225u8, 94u8, 22u8, - 11u8, 241u8, 134u8, 108u8, 94u8, 39u8, 40u8, 255u8, 12u8, 188u8, 88u8, 61u8, 132u8, - 136u8, 33u8, 226u8, 99u8, 155u8, 78u8, - ], - [ - 18u8, 81u8, 129u8, 236u8, 33u8, 136u8, 45u8, 236u8, 81u8, 162u8, 57u8, 41u8, 5u8, - 223u8, 243u8, 168u8, 44u8, 189u8, 2u8, 98u8, 241u8, 139u8, 92u8, 12u8, 3u8, 84u8, - 136u8, 103u8, 27u8, 64u8, 175u8, 178u8, - ], - [ - 120u8, 218u8, 210u8, 188u8, 11u8, 71u8, 198u8, 136u8, 237u8, 132u8, 243u8, 254u8, - 231u8, 154u8, 188u8, 24u8, 230u8, 201u8, 130u8, 45u8, 176u8, 90u8, 121u8, 202u8, - 25u8, 223u8, 245u8, 69u8, 51u8, 199u8, 71u8, 13u8, - ], - [ - 143u8, 185u8, 205u8, 5u8, 77u8, 10u8, 2u8, 33u8, 16u8, 204u8, 237u8, 35u8, 158u8, - 144u8, 139u8, 131u8, 78u8, 76u8, 210u8, 25u8, 81u8, 24u8, 86u8, 212u8, 234u8, - 174u8, 48u8, 81u8, 217u8, 50u8, 214u8, 4u8, - ], - [ - 175u8, 94u8, 144u8, 231u8, 32u8, 21u8, 244u8, 49u8, 56u8, 246u8, 107u8, 76u8, - 208u8, 139u8, 209u8, 223u8, 162u8, 131u8, 144u8, 48u8, 16u8, 79u8, 34u8, 160u8, - 10u8, 248u8, 67u8, 254u8, 132u8, 124u8, 109u8, 25u8, - ], - [ - 188u8, 39u8, 72u8, 207u8, 2u8, 247u8, 161u8, 41u8, 21u8, 37u8, 232u8, 102u8, 239u8, - 199u8, 106u8, 179u8, 185u8, 109u8, 50u8, 215u8, 175u8, 203u8, 178u8, 108u8, 83u8, - 218u8, 236u8, 97u8, 123u8, 56u8, 180u8, 121u8, - ], - [ - 247u8, 50u8, 64u8, 66u8, 34u8, 70u8, 246u8, 62u8, 214u8, 51u8, 239u8, 60u8, 224u8, - 114u8, 107u8, 138u8, 184u8, 251u8, 105u8, 212u8, 108u8, 138u8, 78u8, 94u8, 203u8, - 11u8, 41u8, 34u8, 102u8, 134u8, 116u8, 161u8, - ], - [ - 249u8, 16u8, 103u8, 235u8, 66u8, 12u8, 40u8, 211u8, 18u8, 72u8, 101u8, 252u8, - 153u8, 110u8, 106u8, 169u8, 213u8, 65u8, 185u8, 180u8, 254u8, 249u8, 24u8, 140u8, - 185u8, 101u8, 166u8, 204u8, 100u8, 145u8, 99u8, 142u8, - ], - ]; - } - #[automatically_derived] - impl alloy_sol_types::SolEventInterface for ClusterEvents { - const NAME: &'static str = "ClusterEvents"; - const COUNT: usize = 8usize; - fn decode_raw_log( - topics: &[alloy_sol_types::Word], - data: &[u8], - validate: bool, - ) -> alloy_sol_types::Result { - match topics.first().copied() { - Some(::SIGNATURE_HASH) => { - ::decode_raw_log( - topics, data, validate, - ) - .map(Self::MaintenanceAborted) - } - Some(::SIGNATURE_HASH) => { - ::decode_raw_log( - topics, data, validate, - ) - .map(Self::MaintenanceCompleted) - } - Some(::SIGNATURE_HASH) => { - ::decode_raw_log( - topics, data, validate, - ) - .map(Self::MaintenanceStarted) - } - Some(::SIGNATURE_HASH) => { - ::decode_raw_log( - topics, data, validate, - ) - .map(Self::MigrationAborted) - } - Some(::SIGNATURE_HASH) => { - ::decode_raw_log( - topics, data, validate, - ) - .map(Self::MigrationCompleted) - } - Some(::SIGNATURE_HASH) => { - ::decode_raw_log( - topics, data, validate, - ) - .map(Self::MigrationDataPullCompleted) - } - Some(::SIGNATURE_HASH) => { - ::decode_raw_log( - topics, data, validate, - ) - .map(Self::MigrationStarted) - } - Some(::SIGNATURE_HASH) => { - ::decode_raw_log( - topics, data, validate, - ) - .map(Self::NodeOperatorDataUpdated) - } - _ => alloy_sol_types::private::Err(alloy_sol_types::Error::InvalidLog { - name: ::NAME, - log: alloy_sol_types::private::Box::new( - alloy_sol_types::private::LogData::new_unchecked( - topics.to_vec(), - data.to_vec().into(), - ), - ), - }), - } - } - } - #[automatically_derived] - impl alloy_sol_types::private::IntoLogData for ClusterEvents { - fn to_log_data(&self) -> alloy_sol_types::private::LogData { - match self { - Self::MaintenanceAborted(inner) => { - alloy_sol_types::private::IntoLogData::to_log_data(inner) - } - Self::MaintenanceCompleted(inner) => { - alloy_sol_types::private::IntoLogData::to_log_data(inner) - } - Self::MaintenanceStarted(inner) => { - alloy_sol_types::private::IntoLogData::to_log_data(inner) - } - Self::MigrationAborted(inner) => { - alloy_sol_types::private::IntoLogData::to_log_data(inner) - } - Self::MigrationCompleted(inner) => { - alloy_sol_types::private::IntoLogData::to_log_data(inner) - } - Self::MigrationDataPullCompleted(inner) => { - alloy_sol_types::private::IntoLogData::to_log_data(inner) - } - Self::MigrationStarted(inner) => { - alloy_sol_types::private::IntoLogData::to_log_data(inner) - } - Self::NodeOperatorDataUpdated(inner) => { - alloy_sol_types::private::IntoLogData::to_log_data(inner) - } - } - } - fn into_log_data(self) -> alloy_sol_types::private::LogData { - match self { - Self::MaintenanceAborted(inner) => { - alloy_sol_types::private::IntoLogData::into_log_data(inner) - } - Self::MaintenanceCompleted(inner) => { - alloy_sol_types::private::IntoLogData::into_log_data(inner) - } - Self::MaintenanceStarted(inner) => { - alloy_sol_types::private::IntoLogData::into_log_data(inner) - } - Self::MigrationAborted(inner) => { - alloy_sol_types::private::IntoLogData::into_log_data(inner) - } - Self::MigrationCompleted(inner) => { - alloy_sol_types::private::IntoLogData::into_log_data(inner) - } - Self::MigrationDataPullCompleted(inner) => { - alloy_sol_types::private::IntoLogData::into_log_data(inner) - } - Self::MigrationStarted(inner) => { - alloy_sol_types::private::IntoLogData::into_log_data(inner) - } - Self::NodeOperatorDataUpdated(inner) => { - alloy_sol_types::private::IntoLogData::into_log_data(inner) - } - } - } - } - use alloy::contract as alloy_contract; - /// Creates a new wrapper around an on-chain [`Cluster`](self) contract - /// instance. - /// - /// See the [wrapper's documentation](`ClusterInstance`) for more details. - #[inline] - pub const fn new< - T: alloy_contract::private::Transport + ::core::clone::Clone, - P: alloy_contract::private::Provider, - N: alloy_contract::private::Network, - >( - address: alloy_sol_types::private::Address, - provider: P, - ) -> ClusterInstance { - ClusterInstance::::new(address, provider) - } - /// Deploys this contract using the given `provider` and constructor - /// arguments, if any. - /// - /// Returns a new instance of the contract, if the deployment was - /// successful. - /// - /// For more fine-grained control over the deployment process, use - /// [`deploy_builder`] instead. - #[inline] - pub fn deploy< - T: alloy_contract::private::Transport + ::core::clone::Clone, - P: alloy_contract::private::Provider, - N: alloy_contract::private::Network, - >( - provider: P, - initialSettings: ::RustType, - initialOperators: alloy::sol_types::private::Vec, - ) -> impl ::core::future::Future>> - { - ClusterInstance::::deploy(provider, initialSettings, initialOperators) - } - /// Creates a `RawCallBuilder` for deploying this contract using the given - /// `provider` and constructor arguments, if any. - /// - /// This is a simple wrapper around creating a `RawCallBuilder` with the - /// data set to the bytecode concatenated with the constructor's - /// ABI-encoded arguments. - #[inline] - pub fn deploy_builder< - T: alloy_contract::private::Transport + ::core::clone::Clone, - P: alloy_contract::private::Provider, - N: alloy_contract::private::Network, - >( - provider: P, - initialSettings: ::RustType, - initialOperators: alloy::sol_types::private::Vec, - ) -> alloy_contract::RawCallBuilder { - ClusterInstance::::deploy_builder(provider, initialSettings, initialOperators) - } - /// A [`Cluster`](self) instance. - /// - /// Contains type-safe methods for interacting with an on-chain instance of - /// the [`Cluster`](self) contract located at a given `address`, using a - /// given provider `P`. - /// - /// If the contract bytecode is available (see the - /// [`sol!`](alloy_sol_types::sol!) documentation on how to provide it), - /// the `deploy` and `deploy_builder` methods can be used to deploy a - /// new instance of the contract. - /// - /// See the [module-level documentation](self) for all the available - /// methods. - #[derive(Clone)] - pub struct ClusterInstance { - address: alloy_sol_types::private::Address, - provider: P, - _network_transport: ::core::marker::PhantomData<(N, T)>, - } - #[automatically_derived] - impl ::core::fmt::Debug for ClusterInstance { - #[inline] - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { - f.debug_tuple("ClusterInstance") - .field(&self.address) - .finish() - } - } - /// Instantiation and getters/setters. - #[automatically_derived] - impl< - T: alloy_contract::private::Transport + ::core::clone::Clone, - P: alloy_contract::private::Provider, - N: alloy_contract::private::Network, - > ClusterInstance - { - /// Creates a new wrapper around an on-chain [`Cluster`](self) contract - /// instance. - /// - /// See the [wrapper's documentation](`ClusterInstance`) for more - /// details. - #[inline] - pub const fn new(address: alloy_sol_types::private::Address, provider: P) -> Self { - Self { - address, - provider, - _network_transport: ::core::marker::PhantomData, - } - } - /// Deploys this contract using the given `provider` and constructor - /// arguments, if any. - /// - /// Returns a new instance of the contract, if the deployment was - /// successful. - /// - /// For more fine-grained control over the deployment process, use - /// [`deploy_builder`] instead. - #[inline] - pub async fn deploy( - provider: P, - initialSettings: ::RustType, - initialOperators: alloy::sol_types::private::Vec, - ) -> alloy_contract::Result> { - let call_builder = Self::deploy_builder(provider, initialSettings, initialOperators); - let contract_address = call_builder.deploy().await?; - Ok(Self::new(contract_address, call_builder.provider)) - } - /// Creates a `RawCallBuilder` for deploying this contract using the - /// given `provider` and constructor arguments, if any. - /// - /// This is a simple wrapper around creating a `RawCallBuilder` with the - /// data set to the bytecode concatenated with the constructor's - /// ABI-encoded arguments. - #[inline] - pub fn deploy_builder( - provider: P, - initialSettings: ::RustType, - initialOperators: alloy::sol_types::private::Vec, - ) -> alloy_contract::RawCallBuilder { - alloy_contract::RawCallBuilder::new_raw_deploy( - provider, - [ - &BYTECODE[..], - &alloy_sol_types::SolConstructor::abi_encode(&constructorCall { - initialSettings, - initialOperators, - })[..], - ] - .concat() - .into(), - ) - } - /// Returns a reference to the address. - #[inline] - pub const fn address(&self) -> &alloy_sol_types::private::Address { - &self.address - } - /// Sets the address. - #[inline] - pub fn set_address(&mut self, address: alloy_sol_types::private::Address) { - self.address = address; - } - /// Sets the address and returns `self`. - pub fn at(mut self, address: alloy_sol_types::private::Address) -> Self { - self.set_address(address); - self - } - /// Returns a reference to the provider. - #[inline] - pub const fn provider(&self) -> &P { - &self.provider - } - } - impl ClusterInstance { - /// Clones the provider and returns a new instance with the cloned - /// provider. - #[inline] - pub fn with_cloned_provider(self) -> ClusterInstance { - ClusterInstance { - address: self.address, - provider: ::core::clone::Clone::clone(&self.provider), - _network_transport: ::core::marker::PhantomData, - } - } - } - /// Function calls. - #[automatically_derived] - impl< - T: alloy_contract::private::Transport + ::core::clone::Clone, - P: alloy_contract::private::Provider, - N: alloy_contract::private::Network, - > ClusterInstance - { - /// Creates a new call builder using this contract instance's provider - /// and address. - /// - /// Note that the call can be any function call, not just those defined - /// in this contract. Prefer using the other methods for - /// building type-safe contract calls. - pub fn call_builder( - &self, - call: &C, - ) -> alloy_contract::SolCallBuilder { - alloy_contract::SolCallBuilder::new_sol(&self.provider, &self.address, call) - } - /// Creates a new call builder for the [`abortMaintenance`] function. - pub fn abortMaintenance( - &self, - ) -> alloy_contract::SolCallBuilder { - self.call_builder(&abortMaintenanceCall {}) - } - /// Creates a new call builder for the [`abortMigration`] function. - pub fn abortMigration( - &self, - ) -> alloy_contract::SolCallBuilder { - self.call_builder(&abortMigrationCall {}) - } - /// Creates a new call builder for the [`completeMaintenance`] function. - pub fn completeMaintenance( - &self, - ) -> alloy_contract::SolCallBuilder { - self.call_builder(&completeMaintenanceCall {}) - } - /// Creates a new call builder for the [`completeMigration`] function. - pub fn completeMigration( - &self, - id: u64, - operatorIdx: u8, - ) -> alloy_contract::SolCallBuilder { - self.call_builder(&completeMigrationCall { id, operatorIdx }) - } - /// Creates a new call builder for the [`getView`] function. - pub fn getView(&self) -> alloy_contract::SolCallBuilder { - self.call_builder(&getViewCall {}) - } - /// Creates a new call builder for the [`registerNodeOperator`] - /// function. - pub fn registerNodeOperator( - &self, - data: alloy::sol_types::private::Bytes, - ) -> alloy_contract::SolCallBuilder { - self.call_builder(®isterNodeOperatorCall { data }) - } - /// Creates a new call builder for the [`startMaintenance`] function. - pub fn startMaintenance( - &self, - operatorIdx: u8, - ) -> alloy_contract::SolCallBuilder { - self.call_builder(&startMaintenanceCall { operatorIdx }) - } - /// Creates a new call builder for the [`startMigration`] function. - pub fn startMigration( - &self, - plan: ::RustType, - ) -> alloy_contract::SolCallBuilder { - self.call_builder(&startMigrationCall { plan }) - } - /// Creates a new call builder for the [`transferOwnership`] function. - pub fn transferOwnership( - &self, - newOwner: alloy::sol_types::private::Address, - ) -> alloy_contract::SolCallBuilder { - self.call_builder(&transferOwnershipCall { newOwner }) - } - /// Creates a new call builder for the [`updateNodeOperatorData`] - /// function. - pub fn updateNodeOperatorData( - &self, - operatorIdx: u8, - data: alloy::sol_types::private::Bytes, - ) -> alloy_contract::SolCallBuilder { - self.call_builder(&updateNodeOperatorDataCall { operatorIdx, data }) - } - /// Creates a new call builder for the [`updateSettings`] function. - pub fn updateSettings( - &self, - newSettings: ::RustType, - ) -> alloy_contract::SolCallBuilder { - self.call_builder(&updateSettingsCall { newSettings }) - } - } - /// Event filters. - #[automatically_derived] - impl< - T: alloy_contract::private::Transport + ::core::clone::Clone, - P: alloy_contract::private::Provider, - N: alloy_contract::private::Network, - > ClusterInstance - { - /// Creates a new event filter using this contract instance's provider - /// and address. - /// - /// Note that the type can be any event, not just those defined in this - /// contract. Prefer using the other methods for building - /// type-safe event filters. - pub fn event_filter( - &self, - ) -> alloy_contract::Event { - alloy_contract::Event::new_sol(&self.provider, &self.address) - } - /// Creates a new event filter for the [`MaintenanceAborted`] event. - pub fn MaintenanceAborted_filter( - &self, - ) -> alloy_contract::Event { - self.event_filter::() - } - /// Creates a new event filter for the [`MaintenanceCompleted`] event. - pub fn MaintenanceCompleted_filter( - &self, - ) -> alloy_contract::Event { - self.event_filter::() - } - /// Creates a new event filter for the [`MaintenanceStarted`] event. - pub fn MaintenanceStarted_filter( - &self, - ) -> alloy_contract::Event { - self.event_filter::() - } - /// Creates a new event filter for the [`MigrationAborted`] event. - pub fn MigrationAborted_filter(&self) -> alloy_contract::Event { - self.event_filter::() - } - /// Creates a new event filter for the [`MigrationCompleted`] event. - pub fn MigrationCompleted_filter( - &self, - ) -> alloy_contract::Event { - self.event_filter::() - } - /// Creates a new event filter for the [`MigrationDataPullCompleted`] - /// event. - pub fn MigrationDataPullCompleted_filter( - &self, - ) -> alloy_contract::Event { - self.event_filter::() - } - /// Creates a new event filter for the [`MigrationStarted`] event. - pub fn MigrationStarted_filter(&self) -> alloy_contract::Event { - self.event_filter::() - } - /// Creates a new event filter for the [`NodeOperatorDataUpdated`] - /// event. - pub fn NodeOperatorDataUpdated_filter( - &self, - ) -> alloy_contract::Event { - self.event_filter::() - } - } -} diff --git a/crates/cluster/src/smart_contract/mod.rs b/crates/cluster/src/smart_contract/mod.rs index 7a920a2d..e2beb288 100644 --- a/crates/cluster/src/smart_contract/mod.rs +++ b/crates/cluster/src/smart_contract/mod.rs @@ -1,7 +1,5 @@ pub mod evm; -mod operator_data; - use { crate::{migration, node_operator, NewNodeOperator, Settings, View as ClusterView}, alloy::{signers::local::PrivateKeySigner, transports::http::reqwest}, diff --git a/crates/cluster/src/smart_contract/operator_data.rs b/crates/cluster/src/smart_contract/operator_data.rs deleted file mode 100644 index 8b137891..00000000 --- a/crates/cluster/src/smart_contract/operator_data.rs +++ /dev/null @@ -1 +0,0 @@ - From 147f239d0204ecad4525256e374a59072ea09b3c Mon Sep 17 00:00:00 2001 From: Github Bot Date: Tue, 27 May 2025 21:27:25 +0000 Subject: [PATCH 23/79] Bump VERSION to 250527.0 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 3cb3ed85..93a5d3e2 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -250526.0 +250527.0 From 414a3cffa78d77de6909a4175f21de5bcd2019be Mon Sep 17 00:00:00 2001 From: Darksome Date: Wed, 28 May 2025 22:38:42 +0000 Subject: [PATCH 24/79] impl event sourcing --- crates/cluster/src/keyspace.rs | 25 ++- crates/cluster/src/lib.rs | 224 +++++++++++++++++++---- crates/cluster/src/maintenance.rs | 58 +++++- crates/cluster/src/migration.rs | 144 ++++++++++++--- crates/cluster/src/node_operator.rs | 170 ++++++++++++++--- crates/cluster/src/ownership.rs | 55 ++++++ crates/cluster/src/settings.rs | 30 +++ crates/cluster/src/smart_contract/mod.rs | 4 +- 8 files changed, 617 insertions(+), 93 deletions(-) create mode 100644 crates/cluster/src/ownership.rs create mode 100644 crates/cluster/src/settings.rs diff --git a/crates/cluster/src/keyspace.rs b/crates/cluster/src/keyspace.rs index 77f0ef34..413c6528 100644 --- a/crates/cluster/src/keyspace.rs +++ b/crates/cluster/src/keyspace.rs @@ -10,6 +10,9 @@ use { const REPLICATION_FACTOR: usize = 5; +/// [`Keyspace`] version. +pub type Version = u64; + /// Strategy of replicating data within a [`Keyspace`] across a set of /// [`node::Operator`]s. #[repr(u8)] @@ -41,7 +44,14 @@ pub struct Keyspace { } impl Keyspace { - pub(super) fn new( + /// Creates a new [`Keyspace`]. + /// + /// It's highly CPU intensive to contruct a new [`Keyspace`] (order of + /// seconds), so the task is being [spawned](tokio::task::spawn_blocking) + /// to the [`tokio`] threadpool. + /// + /// May return `None` if the [`tokio`] task gets canceled for some reason. + pub(super) async fn new( operators: NodeOperators, replication_strategy: ReplicationStrategy, version: u64, @@ -67,10 +77,23 @@ impl Keyspace { }) } + /// Returns [`Version`] of this [`Keyspace`]. + pub fn version(&self) -> Version { + self.version + } + /// Get [`NodeOperators`] of this [`Keyspace`]. pub(super) fn operators(&self) -> &NodeOperators { &self.operators } + + /// Returns a mutable reference to [`NodeOperator`] data. + pub(super) fn operator_data_mut( + &mut self, + id: &node_operator::Id, + ) -> Option<&mut node_operator::VersionedData> { + self.operators.get_data_mut(id) + } } struct Snapshot {} diff --git a/crates/cluster/src/lib.rs b/crates/cluster/src/lib.rs index 868c45ca..5a4e6d8b 100644 --- a/crates/cluster/src/lib.rs +++ b/crates/cluster/src/lib.rs @@ -8,6 +8,12 @@ use { pub mod smart_contract; pub use smart_contract::SmartContract; +pub mod settings; +pub use settings::Settings; + +pub mod ownership; +pub use ownership::Ownership; + pub mod client; pub use client::{Client, ClientRef}; @@ -15,7 +21,7 @@ pub mod node; pub use node::{Node, NodeRef}; pub mod node_operator; -pub use node_operator::{NewNodeOperator, NodeOperator}; +pub use node_operator::{NewNodeOperator, NodeOperator, SerializedNodeOperator}; pub mod keyspace; pub use keyspace::Keyspace; @@ -40,12 +46,6 @@ pub struct Cluster { view: ArcSwap>, } -/// WCN [`Cluster`] settings. -pub struct Settings { - /// Maximum number of on-chain bytes stored for a single [`NodeOperator`]. - pub max_node_operator_data_bytes: u16, -} - /// Version of a WCN [`Cluster`]. /// /// Should only monotonically increase. If you observe a jump backwards it means @@ -79,6 +79,12 @@ pub enum Event { /// On-chain state of an [`NodeOperator`] has been updated. NodeOperatorUpdated(node_operator::Updated), + + /// [`Settings`] have been updated. + SettingsUpdated(settings::Updated), + + /// [`Ownership`] has been transferred. + OwnershipTransferred(ownership::Transferred), } impl Cluster { @@ -89,7 +95,13 @@ impl Cluster { initial_settings: Settings, initial_operators: Vec, ) -> Result { - if initial_operators.iter().map(|op| &op.id).dedup().count() != initial_operators.len() { + if initial_operators + .iter() + .map(NodeOperator::id) + .dedup() + .count() + != initial_operators.len() + { return Err(DeploymentError::OperatorIdDuplicate); } @@ -115,9 +127,7 @@ impl Cluster { add: Vec, ) -> Result<(), StartMigrationError> { let plan = self.using_view(move |view| { - if self.smart_contract.signer() != view.owner { - return Err(StartMigrationError::NotOwner); - } + view.ownership.validate_signer(&self.smart_contract)?; if view.migration().is_some() { return Err(StartMigrationError::MigrationInProgress); @@ -127,6 +137,19 @@ impl Cluster { return Err(StartMigrationError::MaintenanceInProgress); } + let add = add + .into_iter() + .map(|operator| { + let operator = operator.serialize()?; + + operator + .data() + .validate_size(view.settings.max_node_operator_data_bytes)?; + + Ok::<_, StartMigrationError>(operator) + }) + .try_collect()?; + migration::Plan::new(view, remove, add).map_err(Into::into) })?; @@ -173,9 +196,7 @@ impl Cluster { /// Calls [`SmartContract::abort_migration`]. pub async fn abort_migration(&self, id: migration::Id) -> Result<(), AbortMigrationError> { self.using_view(|view| { - if self.smart_contract.signer() != view.owner { - return Err(AbortMigrationError::NotOwner); - } + view.ownership.validate_signer(&self.smart_contract)?; let migration = view.migration().ok_or(AbortMigrationError::NoMigration)?; @@ -236,14 +257,12 @@ impl Cluster { /// Calls [`SmartContract::abort_maintenance`]. pub async fn abort_maintenance(&self) -> Result<(), AbortMaintenanceError> { self.using_view(|view| { - if self.smart_contract.signer() != view.owner { - return Err(AbortMaintenanceError::NotOwner); - } + view.ownership.validate_signer(&self.smart_contract)?; view.maintenance() .ok_or(AbortMaintenanceError::NoMaintenance)?; - Ok(()) + Ok::<_, AbortMaintenanceError>(()) })?; self.smart_contract @@ -260,17 +279,16 @@ impl Cluster { id: node_operator::Id, data: node_operator::Data, ) -> Result<(), UpdateNodeOperatorError> { - let idx = self - .view - .load() - .operator_idx(&id) - .ok_or(UpdateNodeOperatorError::UnknownOperator)?; + let (idx, data) = self.using_view(|view| { + let idx = view + .operator_idx(&id) + .ok_or(UpdateNodeOperatorError::UnknownOperator)?; - let data = data.serialize()?; + let data = data.serialize()?; - if data.len() > self.view.load().settings.max_node_operator_data_bytes as usize { - return Err(UpdateNodeOperatorError::DataTooLarge); - } + data.validate_size(view.settings.max_node_operator_data_bytes)?; + Ok::<_, UpdateNodeOperatorError>((idx, data)) + })?; self.smart_contract .update_node_operator(id, idx, data) @@ -299,8 +317,8 @@ pub enum DeploymentError { /// [`Cluster::start_migration`] error. #[derive(Debug, thiserror::Error)] pub enum StartMigrationError { - #[error("Signer is not the owner of the smart-contract")] - NotOwner, + #[error(transparent)] + NotOwner(#[from] ownership::NotOwnerError), #[error("Another migration in progress")] MigrationInProgress, @@ -308,6 +326,12 @@ pub enum StartMigrationError { #[error("Maintenance in progress")] MaintenanceInProgress, + #[error("Data serialization: {0}")] + DataSerialization(#[from] node_operator::DataSerializationError), + + #[error(transparent)] + NodeOperatorDataTooLarge(#[from] node_operator::DataTooLargeError), + #[error("Plan: {0}")] Plan(#[from] migration::PlanError), @@ -337,8 +361,8 @@ pub enum CompleteMigrationError { /// [`Cluster::abort_migration`] error. #[derive(Debug, thiserror::Error)] pub enum AbortMigrationError { - #[error("Signer is not the owner of the smart-contract")] - NotOwner, + #[error(transparent)] + NotOwner(#[from] ownership::NotOwnerError), #[error("No migration is currently in progress")] NoMigration, @@ -382,8 +406,8 @@ pub enum CompleteMaintenanceError { /// [`Cluster::abort_maintenance`] error. #[derive(Debug, thiserror::Error)] pub enum AbortMaintenanceError { - #[error("Signer is not the owner of the smart-contract")] - NotOwner, + #[error(transparent)] + NotOwner(#[from] ownership::NotOwnerError), #[error("No maintenance is currently in progress")] NoMaintenance, @@ -401,26 +425,96 @@ pub enum UpdateNodeOperatorError { #[error("Data serialization: {0}")] DataSerialization(#[from] node_operator::DataSerializationError), - #[error("Size of the provided operator data exceeds the configured setting")] - DataTooLarge, + #[error(transparent)] + DataTooLarge(#[from] node_operator::DataTooLargeError), #[error("Smart-contract: {0}")] SmartContract(#[from] smart_contract::Error), } +impl Event { + fn cluster_version(&self) -> Version { + match self { + Event::MigrationStarted(evt) => evt.cluster_version, + Event::MigrationDataPullCompleted(evt) => evt.cluster_version, + Event::MigrationCompleted(evt) => evt.cluster_version, + Event::MigrationAborted(evt) => evt.cluster_version, + Event::MaintenanceStarted(evt) => evt.cluster_version, + Event::MaintenanceCompleted(evt) => evt.cluster_version, + Event::MaintenanceAborted(evt) => evt.cluster_version, + Event::NodeOperatorUpdated(evt) => evt.cluster_version, + Event::SettingsUpdated(evt) => evt.cluster_version, + Event::OwnershipTransferred(evt) => evt.cluster_version, + } + } +} + /// Read-only view of a WCN cluster. pub struct View { - owner: smart_contract::PublicKey, + ownership: Ownership, settings: Settings, keyspace: Keyspace, migration: Option, maintenance: Option, - version: u128, + cluster_version: Version, } impl View { + fn no_migration(&self) -> Result<(), LogicalError> { + if let Some(migration) = self.migration() { + return Err(LogicalError::MigrationInProgress(migration.id())); + } + + Ok(()) + } + + fn no_maintenance(&self) -> Result<(), LogicalError> { + if self.maintenance().is_some() { + return Err(LogicalError::MaintenanceInProgress); + } + + Ok(()) + } + + fn has_migration(&mut self) -> Result<&mut Migration, LogicalError> { + self.migration.as_mut().ok_or(LogicalError::NoMigration) + } + + fn has_maintenance(&mut self) -> Result<&mut Maintenance, LogicalError> { + self.maintenance.as_mut().ok_or(LogicalError::NoMaintenance) + } + + /// Applies the provided [`Event`] to this [`View`]. + pub async fn apply_event(mut self, event: Event) -> Result { + let new_version = event.cluster_version(); + + if new_version != self.cluster_version + 1 { + return Err(ApplyEventError::ClusterVersionMismatch { + current: self.cluster_version, + event: new_version, + }); + } + + match event { + Event::MigrationStarted(evt) => evt.apply(&mut self).await, + Event::MigrationDataPullCompleted(evt) => evt.apply(&mut self), + Event::MigrationCompleted(evt) => evt.apply(&mut self), + Event::MigrationAborted(evt) => evt.apply(&mut self), + Event::MaintenanceStarted(evt) => evt.apply(&mut self), + Event::MaintenanceCompleted(evt) => evt.apply(&mut self), + Event::MaintenanceAborted(evt) => evt.apply(&mut self), + Event::NodeOperatorUpdated(evt) => evt.apply(&mut self), + Event::SettingsUpdated(evt) => evt.apply(&mut self), + Event::OwnershipTransferred(evt) => evt.apply(&mut self), + }?; + + self.cluster_version = new_version; + + Ok(self) + } + /// Returns the primary [`Keyspace`] of this WCN cluster. pub fn keyspace(&self) -> &Keyspace { &self.keyspace @@ -449,3 +543,59 @@ impl View { }) } } + +/// Error of [`View::apply_event`] +#[derive(Debug, thiserror::Error)] +pub enum ApplyEventError { + /// [`Version`] inside the [`Event`] wasn't monotonic. + #[error("Cluster version mismatch (current: {current}, event: {event})")] + ClusterVersionMismatch { current: Version, event: Version }, + + /// [`LogicalError`] observed while applying an [`Event`]. + #[error("Logic: {0}")] + Logic(#[from] LogicalError), +} + +/// Logical error caused by a race condition or by an incorrect implementation +/// of the [`SmartContract`] +#[derive(Debug, thiserror::Error)] +pub enum LogicalError { + #[error("Migration(id: {0}) is in progress, but it shouldn't be")] + MigrationInProgress(migration::Id), + + #[error("Maintenance is in progress, but it shouldn't be")] + MaintenanceInProgress, + + #[error("No migration, but there should be")] + NoMigration, + + #[error("No maintenance, but there should be")] + NoMaintenance, + + #[error("Migration ID mismatch (event: {event}, local: {event})")] + MigrationIdMismatch { + event: migration::Id, + local: migration::Id, + }, + + #[error("Node operator (id: {0}) is not currently pulling the data")] + NodeOperatorNotPulling(node_operator::Id), + + #[error("There are still pulling operators remaining, but ther shouldn't be")] + PullingOperatorsRemaining, + + #[error("Maintenance: node operator ID mismatch (event: {event}, local: {event})")] + MaintenanceNodeOperatorIdMismatch { + event: node_operator::Id, + local: node_operator::Id, + }, + + #[error("Node operator (id: {0}) is not within the cluster, but should be")] + UnknownOperator(node_operator::Id), + + #[error("Settings unchanged, but they should have changed")] + SettingsUnchanged, + + #[error("Owner unchanged, but it should have changed")] + OwnerUnchanged, +} diff --git a/crates/cluster/src/maintenance.rs b/crates/cluster/src/maintenance.rs index f4dac84a..bd5c472a 100644 --- a/crates/cluster/src/maintenance.rs +++ b/crates/cluster/src/maintenance.rs @@ -1,18 +1,18 @@ -use crate::{node, node_operator, Version}; +use crate::{node, node_operator, LogicalError, Version as ClusterVersion, View as ClusterView}; /// Maintenance process within a WCN cluster. /// /// Only a single [`node_operator`] at a time is allowed to be under /// maintenance. pub struct Maintenance { - operator: node_operator::Id, + operator_id: node_operator::Id, } impl Maintenance { /// Returns [`node_operator::Id`] of the node operator currently under /// [`Maintenance`]. pub fn operator(&self) -> &node_operator::Id { - &self.operator + &self.operator_id } } @@ -21,8 +21,21 @@ pub struct Started { /// ID of the [`node_operator`] that started the [`Maintenance`]. pub operator_id: node_operator::Id, - /// Updated cluster [`Version`]. - pub version: Version, + /// Updated [`ClusterVersion`]. + pub cluster_version: ClusterVersion, +} + +impl Started { + pub(super) fn apply(self, view: &mut ClusterView) -> Result<(), LogicalError> { + view.no_migration()?; + view.no_maintenance()?; + + view.maintenance = Some(Maintenance { + operator_id: self.operator_id, + }); + + Ok(()) + } } /// [`Maintenance`] has been completed. @@ -30,12 +43,39 @@ pub struct Completed { /// ID of the [`node_operator`] that completed the [`Maintenance`]. pub operator_id: node_operator::Id, - /// Updated cluster [`Version`]. - pub version: Version, + /// Updated [`ClusterVersion`]. + pub cluster_version: ClusterVersion, +} + +impl Completed { + pub(super) fn apply(self, view: &mut ClusterView) -> Result<(), LogicalError> { + let maintenance = view.has_maintenance()?; + + if maintenance.operator_id != self.operator_id { + return Err(LogicalError::MaintenanceNodeOperatorIdMismatch { + event: self.operator_id, + local: maintenance.operator_id, + }); + } + + drop(maintenance); + view.maintenance = None; + + Ok(()) + } } /// [`Maintenance`] has been aborted. pub struct Aborted { - /// Updated cluster [`Version`]. - pub version: Version, + /// Updated [`ClusterVersion`]. + pub cluster_version: ClusterVersion, +} + +impl Aborted { + pub(super) fn apply(self, view: &mut ClusterView) -> Result<(), LogicalError> { + view.has_maintenance()?; + view.maintenance = None; + + Ok(()) + } } diff --git a/crates/cluster/src/migration.rs b/crates/cluster/src/migration.rs index b8e7c1b3..dfcf900e 100644 --- a/crates/cluster/src/migration.rs +++ b/crates/cluster/src/migration.rs @@ -3,8 +3,10 @@ use { keyspace::{self, ReplicationStrategy}, node_operator, Keyspace, - NewNodeOperator, - Version, + LogicalError, + NodeOperator, + SerializedNodeOperator, + Version as ClusterVersion, View as ClusterView, }, itertools::Itertools, @@ -22,6 +24,34 @@ pub struct Migration { } impl Migration { + /// Creates a new [`Migration`]. + pub(super) async fn new(id: Id, old_keyspace: &Keyspace, plan: Plan) -> Self { + let mut operators = old_keyspace.operators().clone(); + for (idx, slot) in plan.slots { + operators.set(idx, slot); + } + + let new_keyspace = Keyspace::new( + operators, + plan.replication_strategy, + old_keyspace.version() + 1, + ) + .await; + + let pulling_operators = new_keyspace + .operators() + .slots() + .iter() + .filter_map(|slot| slot.as_ref().map(|operator| *operator.id())) + .collect(); + + Self { + id, + keyspace: new_keyspace, + pulling_operators, + } + } + /// Returns [`Id`] of this [`Migration`]. pub fn id(&self) -> Id { self.id @@ -32,6 +62,11 @@ impl Migration { &self.keyspace } + /// Mutable version of [`Migration::keyspace`]. + pub fn keyspace_mut(&mut self) -> &mut Keyspace { + &mut self.keyspace + } + /// Indicates whether the specified [`node_operator`] is still in process of /// pulling the data. pub fn is_pulling(&self, id: &node_operator::Id) -> bool { @@ -39,9 +74,12 @@ impl Migration { } } +/// [`Plan`] that is not yet published on-chain. +pub type NewPlan = Plan; + /// [`Migration`] plan. -pub struct Plan { - slots: Vec<(node_operator::Idx, Option)>, +pub struct Plan { + slots: Vec<(node_operator::Idx, Option)>, replication_strategy: ReplicationStrategy, } @@ -50,11 +88,11 @@ impl Plan { pub(super) fn new( cluster_view: &ClusterView, remove: Vec, - add: Vec, - ) -> Result { + add: Vec, + ) -> Result { let slot_count = remove .iter() - .chain(add.iter().map(|op| &op.id)) + .chain(add.iter().map(NodeOperator::id)) .dedup() .count(); @@ -87,14 +125,14 @@ impl Plan { match item.left_and_right() { (Some(_), None) => return Err(PlanError::TooManyOperators), (None, _) => break, - (Some(operator), _) if operators.contains(&operator.id) => { - return Err(PlanError::OperatorAlreadyExists(operator.id)) + (Some(operator), _) if operators.contains(operator.id()) => { + return Err(PlanError::OperatorAlreadyExists(*operator.id())) } (Some(id), Some(idx)) => slots.push((idx, Some(id))), }; } - Ok(Self { + Ok(NewPlan { slots, replication_strategy: keyspace::ReplicationStrategy::default(), }) @@ -122,44 +160,106 @@ pub enum PlanError { /// [`Migration`] has started. pub struct Started { /// [`Id`] of the [`Migration`] being started. - pub id: Id, + pub migration_id: Id, /// Migration [`Plan`] being used. pub plan: Plan, - /// Updated cluster [`Version`]. - pub version: Version, + /// Updated [`ClusterVersion`]. + pub cluster_version: ClusterVersion, +} + +impl Started { + pub(super) async fn apply(self, view: &mut ClusterView) -> Result<(), LogicalError> { + view.no_migration()?; + view.no_maintenance()?; + + view.migration = Some(Migration::new(self.migration_id, &view.keyspace, self.plan).await); + + Ok(()) + } } /// [`NodeOperator`](crate::NodeOperator) has completed the data pull. pub struct DataPullCompleted { /// [`Id`] of the [`Migration`]. - pub id: Id, + pub migration_id: Id, /// ID of the [`node_operator`] that completed the pull. pub operator_id: node_operator::Id, - /// Updated cluster [`Version`]. - pub version: u128, + /// Updated [`ClusterVersion`]. + pub cluster_version: ClusterVersion, +} + +impl DataPullCompleted { + pub(super) fn apply(self, view: &mut ClusterView) -> Result<(), LogicalError> { + let migration = view.has_migration()?.with_correct_id(self.migration_id)?; + + if !migration.pulling_operators.remove(&self.operator_id) { + return Err(LogicalError::NodeOperatorNotPulling(self.operator_id)); + } + + Ok(()) + } } /// [`Migration`] has been completed. pub struct Completed { /// [`Id`] of the completed [`Migration`]. - pub id: Id, + pub migration_id: Id, /// ID of the [`node_operator`] that completed the last data pull. pub operator_id: node_operator::Id, - /// Updated cluster [`Version`]. - pub version: u128, + /// Updated [`ClusterVersion`]. + pub cluster_version: ClusterVersion, +} + +impl Completed { + pub(super) fn apply(self, view: &mut ClusterView) -> Result<(), LogicalError> { + let migration = view.has_migration()?.with_correct_id(self.migration_id)?; + + if !migration.pulling_operators.remove(&self.operator_id) { + return Err(LogicalError::NodeOperatorNotPulling(self.operator_id)); + } + + if !migration.pulling_operators.is_empty() { + return Err(LogicalError::PullingOperatorsRemaining); + } + + view.keyspace = view.migration.take().unwrap().keyspace; + + Ok(()) + } } /// [`Migration`] has been aborted. pub struct Aborted { /// [`Id`] of the [`Migration`]. - pub id: Id, + pub migration_id: Id, + + /// Updated [`ClusterVersion`]. + pub cluster_version: ClusterVersion, +} + +impl Aborted { + pub(super) fn apply(self, view: &mut ClusterView) -> Result<(), LogicalError> { + view.has_migration()?.with_correct_id(self.migration_id)?; + view.migration = None; + + Ok(()) + } +} - /// Updated cluster [`Version`]. - pub version: u128, +impl Migration { + fn with_correct_id(&mut self, id: Id) -> Result<&mut Self, LogicalError> { + if id != self.id { + return Err(LogicalError::MigrationIdMismatch { + event: id, + local: self.id, + }); + } + Ok(self) + } } diff --git a/crates/cluster/src/node_operator.rs b/crates/cluster/src/node_operator.rs index 77bafb54..be64f477 100644 --- a/crates/cluster/src/node_operator.rs +++ b/crates/cluster/src/node_operator.rs @@ -1,9 +1,18 @@ //! Entity operating a set of nodes within a WCN cluster. use { - crate::{client, node, smart_contract, Node}, + crate::{ + client, + node, + smart_contract, + LogicalError, + Node, + Version as ClusterVersion, + View as ClusterView, + }, + derive_more::From, serde::{Deserialize, Serialize}, - std::collections::HashMap, + std::{collections::HashMap, ops::Sub}, }; /// Globally unique identifier of a [`NodeOperator`]; @@ -18,7 +27,7 @@ pub type Idx = u8; /// /// Used for informational purposes only. /// Expected to be unique within the cluster, but not enforced to. -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct Name(String); impl Name { @@ -57,32 +66,79 @@ pub struct Data { #[derive(Debug)] pub struct SerializedData(Vec); -impl SerializedData { - pub(super) fn len(&self) -> usize { - self.0.len() - } -} - /// New [`NodeOperator`] that is not a member of WCN cluster yet. -pub struct NewNodeOperator { - /// [`Id`] of this [`NewNodeOperator`]. - pub id: Id, +pub type NewNodeOperator = NodeOperator; - /// [`Data`] of this [`NewNodeOperator`]. - pub data: Data, -} +/// [`NodeOperator`] with [`SerializedData`]. +pub type SerializedNodeOperator = NodeOperator; /// Entity operating a set of [`Node`]s within a WCN cluster. -#[derive(Debug)] -pub struct NodeOperator { +#[derive(Clone, Debug)] +pub struct NodeOperator { id: Id, - data: VersionedData, + data: D, +} + +impl NodeOperator { + /// Creates a [`NewNodeOperator`]. + pub fn new(id: Id, data: Data) -> NewNodeOperator { + NewNodeOperator { id, data } + } + + /// Returns [`Id`] of this [`NodeOperator`]. + pub fn id(&self) -> &Id { + &self.id + } + + /// Returns data of this [`NodeOperator`]. + pub fn data(&self) -> &D { + &self.data + } } /// On-chain state of an [`NodeOperator`] has been updated. pub struct Updated { /// Updated [`NodeOperator`]. pub operator: NodeOperator, + + /// Updated [`ClusterVersion`]. + pub cluster_version: ClusterVersion, +} + +impl Updated { + pub(super) fn apply(self, view: &mut ClusterView) -> Result<(), LogicalError> { + let mut applied = false; + + if let Some(migration) = &mut view.migration { + if let Some(data) = migration + .keyspace_mut() + .operator_data_mut(self.operator.id()) + { + *data = self.operator.data.clone(); + applied = true; + } + } + + if let Some(data) = view.keyspace.operator_data_mut(self.operator.id()) { + *data = self.operator.data; + applied = true; + } + + if !applied { + return Err(LogicalError::UnknownOperator(self.operator.id)); + } + + Ok(()) + } +} + +impl NewNodeOperator { + pub(super) fn serialize(self) -> Result { + Ok(NodeOperator { + id: self.id, + data: self.data.serialize()?, + }) + } } impl Data { @@ -107,8 +163,18 @@ impl Data { } } -#[derive(Debug)] -enum VersionedData { +/// Backwards-compatible [`NodeOperator`] [`Data`] supporting multiple versions. +#[derive(Debug, Clone, From)] +pub struct VersionedData(VersionedDataInner); + +impl VersionedData { + fn v0(data: DataV0) -> Self { + Self(VersionedDataInner::V0(data)) + } +} + +#[derive(Debug, Clone)] +enum VersionedDataInner { V0(DataV0), } @@ -124,7 +190,7 @@ impl NodeOperator { let bytes = &data_bytes[1..]; let data = match schema_version { - 0 => postcard::from_bytes(bytes).map(VersionedData::V0), + 0 => postcard::from_bytes(bytes).map(VersionedData::v0), ver => return Err(Error::UnknownSchemaVersion(ver)), } .map_err(Error::from_postcard)?; @@ -135,7 +201,7 @@ impl NodeOperator { // NOTE: The on-chain serialization is non self-describing! Every change to // the schema should be handled by creating a new version. -#[derive(Debug, Deserialize, Serialize)] +#[derive(Debug, Clone, Deserialize, Serialize)] struct DataV0 { name: Name, nodes: Vec, @@ -172,7 +238,31 @@ impl DataDeserializationError { } } +impl SerializedData { + /// Validates that [`SerializedData`] size doesn't exceed the provided + /// `limit`. + pub(super) fn validate_size(&self, limit: u16) -> Result<(), DataTooLargeError> { + let value = self.0.len(); + let limit = limit as usize; + + if value > limit { + return Err(DataTooLargeError { value, limit }); + } + + Ok(()) + } +} + +/// [`SerializedData`] size is too large. +#[derive(Debug, thiserror::Error)] +#[error("Node operator data size is too large (value: {value}, limit: {limit})")] +pub struct DataTooLargeError { + value: usize, + limit: usize, +} + /// Slot map of [`NodeOperator`]s. +#[derive(Debug, Clone)] pub(super) struct NodeOperators { id_to_idx: HashMap, @@ -181,6 +271,31 @@ pub(super) struct NodeOperators { } impl NodeOperators { + pub(super) fn set(&mut self, idx: Idx, slot: Option) { + if let Some(id) = self.get_by_idx(idx).map(|op| op.id) { + self.id_to_idx.remove(&id); + } + + if self.slots.len() >= idx as usize { + self.expand(idx); + } + + if let Some(operator) = &slot { + self.id_to_idx.insert(operator.id, idx); + } + + self.slots[idx as usize] = slot; + } + + fn expand(&mut self, idx: Idx) { + let desired_len = (idx as usize) + 1; + let slots_to_add = desired_len.checked_sub(self.slots.len()); + + for _ in 0..slots_to_add.unwrap_or_default() { + self.slots.push(None); + } + } + /// Returns whether this map contains the [`NodeOperator`] with the provided /// [`Id`]. pub(super) fn contains(&self, id: &Id) -> bool { @@ -192,11 +307,22 @@ impl NodeOperators { self.get_by_idx(self.get_idx(id)?) } + /// Gets a mutable reference to a [`NodeOperator`] [`Data`]. + pub(super) fn get_data_mut(&mut self, id: &Id) -> Option<&mut VersionedData> { + self.get_by_idx_mut(self.get_idx(id)?) + .map(|operator| &mut operator.data) + } + /// Gets an [`NodeOperator`] by [`Idx`]. pub(super) fn get_by_idx(&self, idx: Idx) -> Option<&NodeOperator> { self.slots.get(idx as usize)?.as_ref() } + /// Mutable version of [`NodeOperators::get_by_idx`]. + fn get_by_idx_mut(&mut self, idx: Idx) -> Option<&mut NodeOperator> { + self.slots.get_mut(idx as usize)?.as_mut() + } + /// Gets an [`Idx`] by [`Id`]. pub(super) fn get_idx(&self, id: &Id) -> Option { self.id_to_idx.get(id).copied() diff --git a/crates/cluster/src/ownership.rs b/crates/cluster/src/ownership.rs new file mode 100644 index 00000000..a0329f47 --- /dev/null +++ b/crates/cluster/src/ownership.rs @@ -0,0 +1,55 @@ +//! Ownership of a WCN cluster. + +use crate::{ + smart_contract, + LogicalError, + SmartContract, + Version as ClusterVersion, + View as ClusterView, +}; + +/// Ownership of a WCN cluster. +/// +/// Cluster has a single owner, and some [`smart_contract`] methods are +/// resticted to be executed only by the owner. +pub struct Ownership { + owner: smart_contract::PublicKey, +} + +impl Ownership { + pub(super) fn validate_signer( + &self, + smart_contract: &impl SmartContract, + ) -> Result<(), NotOwnerError> { + if self.owner != smart_contract.signer() { + return Err(NotOwnerError); + } + + Ok(()) + } +} + +/// Event of [`Ownership`] being transferred. +pub struct Transferred { + /// New owner of the WCN cluster. + pub new_owner: smart_contract::PublicKey, + + /// Update [`ClusterVersion`]. + pub cluster_version: ClusterVersion, +} + +impl Transferred { + pub(super) fn apply(self, view: &mut ClusterView) -> Result<(), LogicalError> { + if view.ownership.owner == self.new_owner { + return Err(LogicalError::OwnerUnchanged); + } + + view.ownership.owner = self.new_owner; + + Ok(()) + } +} + +#[derive(Debug, thiserror::Error)] +#[error("Smart-contract signer is not the owner")] +pub struct NotOwnerError; diff --git a/crates/cluster/src/settings.rs b/crates/cluster/src/settings.rs new file mode 100644 index 00000000..117f6221 --- /dev/null +++ b/crates/cluster/src/settings.rs @@ -0,0 +1,30 @@ +//! WCN cluster settings. +use crate::{LogicalError, Version as ClusterVersion, View as ClusterView}; + +/// WCN cluster settings. +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct Settings { + /// Maximum number of on-chain bytes stored for a single [`NodeOperator`]. + pub max_node_operator_data_bytes: u16, +} + +/// Event of [`Settings`] being updated. +pub struct Updated { + /// Updated [`Settings`]. + pub settings: Settings, + + /// Updated [`ClusterVersion`]. + pub cluster_version: ClusterVersion, +} + +impl Updated { + pub(super) fn apply(self, view: &mut ClusterView) -> Result<(), LogicalError> { + if view.settings == self.settings { + return Err(LogicalError::SettingsUnchanged); + } + + view.settings = self.settings; + + Ok(()) + } +} diff --git a/crates/cluster/src/smart_contract/mod.rs b/crates/cluster/src/smart_contract/mod.rs index e2beb288..4ddad3c1 100644 --- a/crates/cluster/src/smart_contract/mod.rs +++ b/crates/cluster/src/smart_contract/mod.rs @@ -43,7 +43,7 @@ pub trait SmartContract: ReadOnlySmartContract { /// [`SmartContract`] /// /// The implementation MUST emit [`migration::Started`] event on success. - async fn start_migration(&self, plan: migration::Plan) -> Result<()>; + async fn start_migration(&self, plan: migration::NewPlan) -> Result<()>; /// Marks that the [`signer`](SmartContract::signer) has completed the data /// pull required for completion of the current [`migration`]. @@ -158,7 +158,7 @@ pub type Result = std::result::Result; pub type ReadResult = std::result::Result; -#[derive(Clone, Debug, Display, PartialEq, Eq, Hash, Serialize, Deserialize)] +#[derive(Clone, Copy, Debug, Display, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct PublicKey(evm::Address); impl FromStr for PublicKey { From 16ddff4f42c79fb8987b3d38292b4cdae22eff09 Mon Sep 17 00:00:00 2001 From: Github Bot Date: Wed, 28 May 2025 22:39:37 +0000 Subject: [PATCH 25/79] Bump VERSION to 250528.0 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 93a5d3e2..6fc3d08d 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -250527.0 +250528.0 From 906dee9e54fb68e789dff80797b9e4e943e79af2 Mon Sep 17 00:00:00 2001 From: Darksome Date: Thu, 29 May 2025 22:45:05 +0000 Subject: [PATCH 26/79] switch to ABI / more events / SC improvements --- .gitignore | 3 +- contracts/out/Cluster.sol/Bitmask.json | 1 + contracts/out/Cluster.sol/Cluster.json | 1 + contracts/src/Cluster.sol | 184 +++++++++---- contracts/test/Suite.sol | 337 ++++++++++------------- crates/cluster/src/lib.rs | 29 +- crates/cluster/src/maintenance.rs | 33 +-- crates/cluster/src/node_operator.rs | 32 ++- crates/cluster/src/smart_contract/evm.rs | 3 +- 9 files changed, 326 insertions(+), 297 deletions(-) create mode 100644 contracts/out/Cluster.sol/Bitmask.json create mode 100644 contracts/out/Cluster.sol/Cluster.json diff --git a/.gitignore b/.gitignore index e98574c6..dfc31c8c 100644 --- a/.gitignore +++ b/.gitignore @@ -5,7 +5,8 @@ target/ /crates/*/target/ /crates/*/Cargo.lock /contracts/dependencies/ -/contracts/out/ +/contracts/out/* +!/contracts/out/Cluster.sol /contracts/cache/ .direnv .env diff --git a/contracts/out/Cluster.sol/Bitmask.json b/contracts/out/Cluster.sol/Bitmask.json new file mode 100644 index 00000000..ecd27e45 --- /dev/null +++ b/contracts/out/Cluster.sol/Bitmask.json @@ -0,0 +1 @@ +{"abi":[],"bytecode":{"object":"0x608060405234601d57600e6021565b603e602c823930815050603e90f35b6027565b60405190565b5f80fdfe60806040525f80fdfea2646970667358221220c3467853a46be3b5ea2da8aadd52764c5be8b8225fef262a18ff8f7bbb94d55764736f6c634300081c0033","sourceMap":"12772:953:22:-:0;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;","linkReferences":{}},"deployedBytecode":{"object":"0x60806040525f80fdfea2646970667358221220c3467853a46be3b5ea2da8aadd52764c5be8b8225fef262a18ff8f7bbb94d55764736f6c634300081c0033","sourceMap":"12772:953:22:-:0;;;;;","linkReferences":{}},"methodIdentifiers":{},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.28+commit.7893614a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/Cluster.sol\":\"Bitmask\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[\":@openzeppelin/contracts/=dependencies/openzeppelin-contracts/contracts/\",\":erc4626-tests/=dependencies/openzeppelin-contracts/lib/erc4626-tests/\",\":forge-std-1.9.7/=dependencies/forge-std-1.9.7/src/\",\":forge-std/=dependencies/openzeppelin-contracts/lib/forge-std/src/\",\":halmos-cheatcodes/=dependencies/openzeppelin-contracts/lib/halmos-cheatcodes/src/\",\":openzeppelin-contracts/=dependencies/openzeppelin-contracts/\"],\"viaIR\":true},\"sources\":{\"dependencies/openzeppelin-contracts/contracts/utils/Panic.sol\":{\"keccak256\":\"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a\",\"dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG\"]},\"dependencies/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0x1225214420c83ebcca88f2ae2b50f053aaa7df7bd684c3e878d334627f2edfc6\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6c5fab4970634f9ab9a620983dc1c8a30153981a0b1a521666e269d0a11399d3\",\"dweb:/ipfs/QmVRnBC575MESGkEHndjujtR7qub2FzU9RWy9eKLp4hPZB\"]},\"dependencies/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\":{\"keccak256\":\"0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b1d578337048cad08c1c03041cca5978eff5428aa130c781b271ad9e5566e1f8\",\"dweb:/ipfs/QmPFKL2r9CBsMwmUqqdcFPfHZB2qcs9g1HDrPxzWSxomvy\"]},\"src/Cluster.sol\":{\"keccak256\":\"0xfd4a17d0b8327f8248d37ae5b16b7076095a7b4f6ed1d75f859446b33c086a88\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://91b3747c61898f3f65d064a173e6795fede772a88d3848870bf73266498dc71f\",\"dweb:/ipfs/QmStHTacgfN8y7nzkFrju9GGVV7kv5WD9ez2yeTP8YgcAe\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.28+commit.7893614a"},"language":"Solidity","output":{"abi":[],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"remappings":["@openzeppelin/contracts/=dependencies/openzeppelin-contracts/contracts/","erc4626-tests/=dependencies/openzeppelin-contracts/lib/erc4626-tests/","forge-std-1.9.7/=dependencies/forge-std-1.9.7/src/","forge-std/=dependencies/openzeppelin-contracts/lib/forge-std/src/","halmos-cheatcodes/=dependencies/openzeppelin-contracts/lib/halmos-cheatcodes/src/","openzeppelin-contracts/=dependencies/openzeppelin-contracts/"],"optimizer":{"enabled":false,"runs":200},"metadata":{"bytecodeHash":"ipfs"},"compilationTarget":{"src/Cluster.sol":"Bitmask"},"evmVersion":"cancun","libraries":{},"viaIR":true},"sources":{"dependencies/openzeppelin-contracts/contracts/utils/Panic.sol":{"keccak256":"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a","urls":["bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a","dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG"],"license":"MIT"},"dependencies/openzeppelin-contracts/contracts/utils/math/Math.sol":{"keccak256":"0x1225214420c83ebcca88f2ae2b50f053aaa7df7bd684c3e878d334627f2edfc6","urls":["bzz-raw://6c5fab4970634f9ab9a620983dc1c8a30153981a0b1a521666e269d0a11399d3","dweb:/ipfs/QmVRnBC575MESGkEHndjujtR7qub2FzU9RWy9eKLp4hPZB"],"license":"MIT"},"dependencies/openzeppelin-contracts/contracts/utils/math/SafeCast.sol":{"keccak256":"0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54","urls":["bzz-raw://b1d578337048cad08c1c03041cca5978eff5428aa130c781b271ad9e5566e1f8","dweb:/ipfs/QmPFKL2r9CBsMwmUqqdcFPfHZB2qcs9g1HDrPxzWSxomvy"],"license":"MIT"},"src/Cluster.sol":{"keccak256":"0xfd4a17d0b8327f8248d37ae5b16b7076095a7b4f6ed1d75f859446b33c086a88","urls":["bzz-raw://91b3747c61898f3f65d064a173e6795fede772a88d3848870bf73266498dc71f","dweb:/ipfs/QmStHTacgfN8y7nzkFrju9GGVV7kv5WD9ez2yeTP8YgcAe"],"license":"MIT"}},"version":1},"id":22} \ No newline at end of file diff --git a/contracts/out/Cluster.sol/Cluster.json b/contracts/out/Cluster.sol/Cluster.json new file mode 100644 index 00000000..a42de7b4 --- /dev/null +++ b/contracts/out/Cluster.sol/Cluster.json @@ -0,0 +1 @@ +{"abi":[{"type":"constructor","inputs":[{"name":"initialSettings","type":"tuple","internalType":"struct Settings","components":[{"name":"maxOperatorDataBytes","type":"uint16","internalType":"uint16"}]},{"name":"initialOperators","type":"tuple[]","internalType":"struct NodeOperator[]","components":[{"name":"addr","type":"address","internalType":"address"},{"name":"data","type":"bytes","internalType":"bytes"}]}],"stateMutability":"nonpayable"},{"type":"function","name":"abortMigration","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"completeMigration","inputs":[{"name":"id","type":"uint64","internalType":"uint64"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"createNodeOperator","inputs":[{"name":"operator","type":"tuple","internalType":"struct NodeOperator","components":[{"name":"addr","type":"address","internalType":"address"},{"name":"data","type":"bytes","internalType":"bytes"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"deleteNodeOperator","inputs":[{"name":"operatorAddress","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"finishMaintenance","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"getView","inputs":[],"outputs":[{"name":"","type":"tuple","internalType":"struct ClusterView","components":[{"name":"keyspace","type":"tuple","internalType":"struct KeyspaceView","components":[{"name":"operators","type":"tuple[]","internalType":"struct NodeOperator[]","components":[{"name":"addr","type":"address","internalType":"address"},{"name":"data","type":"bytes","internalType":"bytes"}]},{"name":"replicationStrategy","type":"uint8","internalType":"uint8"}]},{"name":"migration","type":"tuple","internalType":"struct Migration","components":[{"name":"id","type":"uint64","internalType":"uint64"},{"name":"pullingOperatorsBitmask","type":"uint256","internalType":"uint256"}]},{"name":"migrationKeyspace","type":"tuple","internalType":"struct KeyspaceView","components":[{"name":"operators","type":"tuple[]","internalType":"struct NodeOperator[]","components":[{"name":"addr","type":"address","internalType":"address"},{"name":"data","type":"bytes","internalType":"bytes"}]},{"name":"replicationStrategy","type":"uint8","internalType":"uint8"}]},{"name":"maintenance","type":"tuple","internalType":"struct Maintenance","components":[{"name":"slot","type":"address","internalType":"address"}]},{"name":"keyspaceVersion","type":"uint64","internalType":"uint64"},{"name":"version","type":"uint128","internalType":"uint128"}]}],"stateMutability":"view"},{"type":"function","name":"startMaintenance","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"startMigration","inputs":[{"name":"plan","type":"tuple","internalType":"struct MigrationPlan","components":[{"name":"slots","type":"tuple[]","internalType":"struct KeyspaceSlot[]","components":[{"name":"idx","type":"uint8","internalType":"uint8"},{"name":"operatorAddress","type":"address","internalType":"address"}]},{"name":"replicationStrategy","type":"uint8","internalType":"uint8"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"transferOwnership","inputs":[{"name":"newOwner","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateNodeOperator","inputs":[{"name":"operator","type":"tuple","internalType":"struct NodeOperator","components":[{"name":"addr","type":"address","internalType":"address"},{"name":"data","type":"bytes","internalType":"bytes"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateSettings","inputs":[{"name":"newSettings","type":"tuple","internalType":"struct Settings","components":[{"name":"maxOperatorDataBytes","type":"uint16","internalType":"uint16"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"event","name":"MaintenanceFinished","inputs":[{"name":"operatorAddress","type":"address","indexed":false,"internalType":"address"},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"MaintenanceStarted","inputs":[{"name":"operatorAddress","type":"address","indexed":false,"internalType":"address"},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"MigrationAborted","inputs":[{"name":"id","type":"uint64","indexed":false,"internalType":"uint64"},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"MigrationCompleted","inputs":[{"name":"id","type":"uint64","indexed":false,"internalType":"uint64"},{"name":"operatorAddress","type":"address","indexed":false,"internalType":"address"},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"MigrationDataPullCompleted","inputs":[{"name":"id","type":"uint64","indexed":false,"internalType":"uint64"},{"name":"operatorAddress","type":"address","indexed":false,"internalType":"address"},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"MigrationStarted","inputs":[{"name":"id","type":"uint64","indexed":false,"internalType":"uint64"},{"name":"plan","type":"tuple","indexed":false,"internalType":"struct MigrationPlan","components":[{"name":"slots","type":"tuple[]","internalType":"struct KeyspaceSlot[]","components":[{"name":"idx","type":"uint8","internalType":"uint8"},{"name":"operatorAddress","type":"address","internalType":"address"}]},{"name":"replicationStrategy","type":"uint8","internalType":"uint8"}]},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"NodeOperatorCreated","inputs":[{"name":"operator","type":"tuple","indexed":false,"internalType":"struct NodeOperator","components":[{"name":"addr","type":"address","internalType":"address"},{"name":"data","type":"bytes","internalType":"bytes"}]},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"NodeOperatorDeleted","inputs":[{"name":"operatorAddress","type":"address","indexed":false,"internalType":"address"},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"NodeOperatorUpdated","inputs":[{"name":"operator","type":"tuple","indexed":false,"internalType":"struct NodeOperator","components":[{"name":"addr","type":"address","internalType":"address"},{"name":"data","type":"bytes","internalType":"bytes"}]},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"name":"newOwner","type":"address","indexed":false,"internalType":"address"},{"name":"cluserVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"SettingsUpdated","inputs":[{"name":"newSettings","type":"tuple","indexed":false,"internalType":"struct Settings","components":[{"name":"maxOperatorDataBytes","type":"uint16","internalType":"uint16"}]},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false}],"bytecode":{"object":"0x6080604052346100305761001a61001461030f565b90610a8f565b610022610035565b613d5a610edd8239613d5a90f35b61003b565b60405190565b5f80fd5b601f801991011690565b634e487b7160e01b5f52604160045260245ffd5b906100679061003f565b810190811060018060401b0382111761007f57604052565b610049565b90610097610090610035565b928361005d565b565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b61ffff1690565b6100b9816100a9565b036100c057565b5f80fd5b905051906100d1826100b0565b565b91906020838203126100fb576100f5906100ed6020610084565b935f016100c4565b5f830152565b6100a1565b5f80fd5b60018060401b03811161011a5760208091020190565b610049565b5f80fd5b60018060a01b031690565b61013790610123565b90565b6101438161012e565b0361014a57565b5f80fd5b9050519061015b8261013a565b565b5f80fd5b60018060401b03811161017d5761017960209161003f565b0190565b610049565b90825f9392825e0152565b909291926101a261019d82610161565b610084565b938185526020850190828401116101be576101bc92610182565b565b61015d565b9080601f830112156101e1578160206101de9351910161018d565b90565b610100565b919091604081840312610236576101fd6040610084565b9261020a815f840161014e565b5f850152602082015160018060401b0381116102315761022a92016101c3565b6020830152565b6100a5565b6100a1565b92919061024f61024a82610104565b610084565b93818552602080860192028101918383116102a45781905b838210610275575050505050565b815160018060401b03811161029f5760209161029487849387016101e6565b815201910190610267565b610100565b61011f565b9080601f830112156102c7578160206102c49351910161023b565b90565b610100565b91909160408184031261030a576102e5835f83016100d3565b92602082015160018060401b0381116103055761030292016102a9565b90565b61009d565b610099565b61032d614c378038038061032281610084565b9283398101906102cc565b9091565b5190565b90565b90565b90565b61035261034d61035792610338565b61033b565b610335565b90565b60209181520190565b5f7f746f6f206d616e79206f70657261746f72730000000000000000000000000000910152565b610397601260209261035a565b6103a081610363565b0190565b6103b99060208101905f81830391015261038a565b90565b156103c357565b6103cb610035565b62461bcd60e51b8152806103e1600482016103a4565b0390fd5b5f1b90565b906103fb60018060a01b03916103e5565b9181191691161790565b61041961041461041e92610123565b61033b565b610123565b90565b61042a90610405565b90565b61043690610421565b90565b90565b9061045161044c6104589261042d565b610439565b82546103ea565b9055565b61046690516100a9565b90565b9061047661ffff916103e5565b9181191691161790565b61049461048f610499926100a9565b61033b565b6100a9565b90565b90565b906104b46104af6104bb92610480565b61049c565b8254610469565b9055565b906104d15f806104d79401920161045c565b9061049f565b565b906104e3916104bf565b565b90565b6104fc6104f7610501926104e5565b61033b565b610335565b90565b60016105109101610335565b90565b634e487b7160e01b5f52603260045260245ffd5b9061053182610331565b811015610542576020809102010190565b610513565b5190565b610555905161012e565b90565b906105629061042d565b5f5260205260405f2090565b634e487b7160e01b5f52602260045260245ffd5b90600160028304921680156105a2575b602083101461059d57565b61056e565b91607f1691610592565b6105b69054610582565b90565b5f7f6475706c6963617465206f70657261746f720000000000000000000000000000910152565b6105ed601260209261035a565b6105f6816105b9565b0190565b61060f9060208101905f8183039101526105e0565b90565b1561061957565b610621610035565b62461bcd60e51b815280610637600482016105fa565b0390fd5b50600290565b90565b61064d8161063b565b8210156106685761066061010391610641565b910201905f90565b610513565b5061010090565b90565b6106808161066d565b82101561069a57610692600191610674565b910201905f90565b610513565b1b90565b919060086106c39102916106bd60018060a01b038461069f565b9261069f565b9181191691161790565b91906106e36106de6106eb9361042d565b610439565b9083546106a3565b9055565b60ff1690565b61070961070461070e92610335565b61033b565b6106ef565b90565b61071b6040610084565b90565b151590565b9061072d9061071e565b9052565b9061073b906106ef565b9052565b906107499061042d565b5f5260205260405f2090565b61075f905161071e565b90565b9061076e60ff916103e5565b9181191691161790565b6107819061071e565b90565b90565b9061079c6107976107a392610778565b610784565b8254610762565b9055565b6107b190516106ef565b90565b60081b90565b906107c761ff00916107b4565b9181191691161790565b6107e56107e06107ea926106ef565b61033b565b6106ef565b90565b90565b9061080561080061080c926107d1565b6107ed565b82546107ba565b9055565b9061083a60205f6108409461083282820161082c848801610755565b90610787565b0192016107a7565b906107f0565b565b9061084c91610810565b565b5f5260205f2090565b601f602091010490565b9190600861087c9102916108765f198461069f565b9261069f565b9181191691161790565b61089a61089561089f92610335565b61033b565b610335565b90565b90565b91906108bb6108b66108c393610886565b6108a2565b908354610861565b9055565b5f90565b6108dd916108d76108c7565b916108a5565b565b5b8181106108eb575050565b806108f85f6001936108cb565b016108e0565b9190601f811161090e575b505050565b61091a61093f9361084e565b90602061092684610857565b83019310610947575b61093890610857565b01906108df565b5f8080610909565b91506109388192905061092f565b1c90565b90610969905f1990600802610955565b191690565b8161097891610959565b906002021790565b9061098a81610547565b9060018060401b038211610a48576109ac826109a68554610582565b856108fe565b602090601f83116001146109e0579180916109cf935f926109d4575b505061096e565b90555b565b90915001515f806109c8565b601f198316916109ef8561084e565b925f5b818110610a3057509160029391856001969410610a16575b505050020190556109d2565b610a26910151601f841690610959565b90555f8080610a0a565b919360206001819287870151815501950192016109f2565b610049565b90610a5791610980565b565b90610a655f19916103e5565b9181191691161790565b90610a84610a7f610a8b92610886565b6108a2565b8254610a59565b9055565b610acc90610aba610a9f84610331565b610ab3610aad61010061033e565b91610335565b11156103bc565b610ac4335f61043c565b6102096104d9565b610ad55f6104e8565b5b80610af1610aeb610ae685610331565b610335565b91610335565b1015610c3c57610c3790610b1b610b166020610b0e868590610527565b510151610547565b610dbe565b610b5f610b47610b426001610b3c5f610b35898890610527565b510161054b565b90610558565b6105ac565b610b59610b535f6104e8565b91610335565b14610612565b610b98610b785f610b71868590610527565b510161054b565b610b926001610b8960025f90610644565b50018490610677565b906106cd565b610bf96001610bc6610ba9846106f5565b610bbd610bb4610711565b935f8501610723565b60208301610731565b610bf45f610bd660028290610644565b5001610bee5f610be7898890610527565b510161054b565b9061073f565b610842565b610c326020610c09858490610527565b510151610c2d6001610c275f610c20898890610527565b510161054b565b90610558565b610a4d565b610504565b610ad6565b50610c59610c54610c4f610c6f93610331565b6106f5565b610ea0565b610101610c6860025f90610644565b5001610a6f565b565b5f7f656d707479206f70657261746f72206461746100000000000000000000000000910152565b610ca5601360209261035a565b610cae81610c71565b0190565b610cc79060208101905f818303910152610c98565b90565b15610cd157565b610cd9610035565b62461bcd60e51b815280610cef60048201610cb2565b0390fd5b5f1c90565b61ffff1690565b610d0b610d1091610cf3565b610cf8565b90565b610d1d9054610cff565b90565b610d34610d2f610d39926100a9565b61033b565b610335565b90565b5f7f6f70657261746f72206461746120746f6f206c61726765000000000000000000910152565b610d70601760209261035a565b610d7981610d3c565b0190565b610d929060208101905f818303910152610d63565b90565b15610d9c57565b610da4610035565b62461bcd60e51b815280610dba60048201610d7d565b0390fd5b610e0390610dde81610dd8610dd25f6104e8565b91610335565b11610cca565b610dfc610df6610df15f61020901610d13565b610d20565b91610335565b1115610d95565b565b610e19610e14610e1e926106ef565b61033b565b610335565b90565b90565b610e38610e33610e3d92610e21565b61033b565b610335565b90565b610e5f90610e59610e53610e6494610335565b91610335565b9061069f565b610335565b90565b634e487b7160e01b5f52601160045260245ffd5b610e8a610e9091939293610335565b92610335565b8203918211610e9b57565b610e67565b610ec9610ed991610eaf6108c7565b50610ec4610ebe600192610e05565b91610e24565b610e40565b610ed36001610e24565b90610e7b565b9056fe60806040526004361015610013575b6106f7565b61001d5f356100cc565b806326322217146100c757806353bfb584146100c257806365706f9c146100bd57806375418b9d146100b85780639d44e717146100b3578063b55a4142146100ae578063c130809a146100a9578063cdbfc62d146100a4578063db1b0fd71461009f578063f2fde38b1461009a5763f5f2d9f10361000e576106c4565b610691565b61065e565b6105ea565b61056f565b61053c565b610509565b610493565b6101db565b610177565b610135565b60e01c90565b60405190565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b908160409103126100f65790565b6100e4565b9060208282031261012b575f82013567ffffffffffffffff81116101265761012392016100e8565b90565b6100e0565b6100dc565b5f0190565b346101635761014d6101483660046100fb565b610d6f565b6101556100d2565b8061015f81610130565b0390f35b6100d8565b5f91031261017257565b6100dc565b346101a557610187366004610168565b61018f6110b2565b6101976100d2565b806101a181610130565b0390f35b6100d8565b908160209103126101b85790565b6100e4565b906020828203126101d6576101d3915f016101aa565b90565b6100dc565b34610209576101f36101ee3660046101bd565b6112ee565b6101fb6100d2565b8061020581610130565b0390f35b6100d8565b5190565b60209181520190565b60200190565b60018060a01b031690565b61023590610221565b90565b6102419061022c565b9052565b5190565b60209181520190565b90825f9392825e0152565b601f801991011690565b61028661028f6020936102949361027d81610245565b93848093610249565b95869101610252565b61025d565b0190565b6102c391602060408201926102b35f8201515f850190610238565b0151906020818403910152610267565b90565b906102d091610298565b90565b60200190565b906102ed6102e68361020e565b8092610212565b90816102fe6020830284019461021b565b925f915b83831061031157505050505090565b9091929394602061033361032d838560019503875289516102c6565b976102d3565b9301930191939290610302565b60ff1690565b61034f90610340565b9052565b9061037d90602080610372604084015f8701518582035f8701526102d9565b940151910190610346565b90565b67ffffffffffffffff1690565b61039690610380565b9052565b90565b6103a69061039a565b9052565b906020806103cc936103c25f8201515f86019061038d565b015191019061039d565b565b905f806103df930151910190610238565b565b6fffffffffffffffffffffffffffffffff1690565b6103ff906103e1565b9052565b906104789060c060a061044a61042660e085015f8801518682035f880152610353565b610438602088015160208701906103aa565b60408701518582036060870152610353565b9461045d606082015160808601906103ce565b61046e60808201518386019061038d565b01519101906103f6565b90565b6104909160208201915f818403910152610403565b90565b346104c3576104a3366004610168565b6104bf6104ae6118a9565b6104b66100d2565b9182918261047b565b0390f35b6100d8565b6104d181610380565b036104d857565b5f80fd5b905035906104e9826104c8565b565b9060208282031261050457610501915f016104dc565b90565b6100dc565b346105375761052161051c3660046104eb565b6121b7565b6105296100d2565b8061053381610130565b0390f35b6100d8565b3461056a5761055461054f3660046100fb565b61235c565b61055c6100d2565b8061056681610130565b0390f35b6100d8565b3461059d5761057f366004610168565b6105876124f0565b61058f6100d2565b8061059981610130565b0390f35b6100d8565b908160409103126105b05790565b6100e4565b906020828203126105e5575f82013567ffffffffffffffff81116105e0576105dd92016105a2565b90565b6100e0565b6100dc565b34610618576106026105fd3660046105b5565b61297e565b61060a6100d2565b8061061481610130565b0390f35b6100d8565b6106268161022c565b0361062d57565b5f80fd5b9050359061063e8261061d565b565b9060208282031261065957610656915f01610631565b90565b6100dc565b3461068c57610676610671366004610640565b612d62565b61067e6100d2565b8061068881610130565b0390f35b6100d8565b346106bf576106a96106a4366004610640565b612e0a565b6106b16100d2565b806106bb81610130565b0390f35b6100d8565b346106f2576106d4366004610168565b6106dc612f45565b6106e46100d2565b806106ee81610130565b0390f35b6100d8565b5f80fd5b5f1c90565b60018060a01b031690565b61071761071c916106fb565b610700565b90565b610729905461070b565b90565b356107368161061d565b90565b60209181520190565b5f7f756e617574686f72697a65640000000000000000000000000000000000000000910152565b610776600c602092610739565b61077f81610742565b0190565b6107989060208101905f818303910152610769565b90565b156107a257565b6107aa6100d2565b62461bcd60e51b8152806107c060048201610783565b0390fd5b90565b6107db6107d66107e092610221565b6107c4565b610221565b90565b6107ec906107c7565b90565b6107f8906107e3565b90565b90610805906107ef565b5f5260205260405f2090565b634e487b7160e01b5f52602260045260245ffd5b9060016002830492168015610845575b602083101461084057565b610811565b91607f1691610835565b6108599054610825565b90565b90565b61087361086e6108789261085c565b6107c4565b61039a565b90565b5f7f756e6b6e6f776e206f70657261746f7200000000000000000000000000000000910152565b6108af6010602092610739565b6108b88161087b565b0190565b6108d19060208101905f8183039101526108a2565b90565b156108db57565b6108e36100d2565b62461bcd60e51b8152806108f9600482016108bc565b0390fd5b5f80fd5b5f80fd5b5f80fd5b90359060016020038136030382121561094b570180359067ffffffffffffffff82116109465760200191600182023603831361094157565b610905565b610901565b6108fd565b5090565b634e487b7160e01b5f525f60045260245ffd5b634e487b7160e01b5f52604160045260245ffd5b5f5260205f2090565b601f602091010490565b1b90565b919060086109ad9102916109a75f198461098e565b9261098e565b9181191691161790565b6109cb6109c66109d09261039a565b6107c4565b61039a565b90565b90565b91906109ec6109e76109f4936109b7565b6109d3565b908354610992565b9055565b5f90565b610a0e91610a086109f8565b916109d6565b565b5b818110610a1c575050565b80610a295f6001936109fc565b01610a11565b9190601f8111610a3f575b505050565b610a4b610a709361097b565b906020610a5784610984565b83019310610a78575b610a6990610984565b0190610a10565b5f8080610a3a565b9150610a6981929050610a60565b1c90565b90610a9a905f1990600802610a86565b191690565b81610aa991610a8a565b906002021790565b91610abc9082610950565b9067ffffffffffffffff8211610b7b57610ae082610ada8554610825565b85610a2f565b5f90601f8311600114610b1357918091610b02935f92610b07575b5050610a9f565b90555b565b90915001355f80610afb565b601f19831691610b228561097b565b925f5b818110610b6357509160029391856001969410610b49575b50505002019055610b05565b610b59910135601f841690610a8a565b90555f8080610b3d565b91936020600181928787013581550195019201610b25565b610967565b90610b8b9291610ab1565b565b6fffffffffffffffffffffffffffffffff1690565b610bae610bb3916106fb565b610b8d565b90565b610bc09054610ba2565b90565b634e487b7160e01b5f52601160045260245ffd5b610be0906103e1565b6fffffffffffffffffffffffffffffffff8114610bfd5760010190565b610bc3565b5f1b90565b90610c226fffffffffffffffffffffffffffffffff91610c02565b9181191691161790565b610c40610c3b610c45926103e1565b6107c4565b6103e1565b90565b90565b90610c60610c5b610c6792610c2c565b610c48565b8254610c07565b9055565b50610c7a906020810190610631565b90565b5f80fd5b5f80fd5b5f80fd5b9035600160200382360303811215610cca57016020813591019167ffffffffffffffff8211610cc5576001820236038313610cc057565b610c81565b610c7d565b610c85565b90825f939282370152565b9190610cf481610ced81610cf995610249565b8095610ccf565b61025d565b0190565b610d3991610d2b6040820192610d21610d185f830183610c6b565b5f850190610238565b6020810190610c89565b916020818503910152610cda565b90565b610d45906103e1565b9052565b92916020610d65610d6d9360408701908782035f890152610cfd565b940190610d3c565b565b33610d8a610d84610d7f5f61071f565b61022c565b9161022c565b148015610e85575b610d9b9061079b565b610dd5610dbc610db76001610db15f860161072c565b906107fb565b61084f565b610dce610dc85f61085f565b9161039a565b14156108d4565b610df4610def610de9836020810190610909565b90610950565b613097565b610e21610e05826020810190610909565b90610e1c6001610e165f870161072c565b906107fb565b610b80565b610e3f610e37610e3261020d610bb6565b610bd7565b61020d610c4b565b610e4a61020d610bb6565b7f5aab2c32b1e447db4dba1d2790fe8b863d4775042b10b92e00dab9d6b671b5b591610e80610e776100d2565b92839283610d49565b0390a1565b50610d9b33610ea6610ea0610e9b5f860161072c565b61022c565b9161022c565b149050610d92565b5f7f6e6f206d61696e74656e616e6365000000000000000000000000000000000000910152565b610ee2600e602092610739565b610eeb81610eae565b0190565b610f049060208101905f818303910152610ed5565b90565b15610f0e57565b610f166100d2565b62461bcd60e51b815280610f2c60048201610eef565b0390fd5b610f40610f3b6130e2565b610f07565b610f48610fe0565b565b610f5e610f59610f639261085c565b6107c4565b610221565b90565b610f6f90610f4a565b90565b90610f8360018060a01b0391610c02565b9181191691161790565b90565b90610fa5610fa0610fac926107ef565b610f8d565b8254610f72565b9055565b610fb99061022c565b9052565b916020610fde929493610fd760408201965f830190610fb0565b0190610d3c565b565b33610ffb610ff5610ff05f61071f565b61022c565b9161022c565b148015611087575b61100c9061079b565b6110226110185f610f66565b5f61020c01610f90565b61104061103861103361020d610bb6565b610bd7565b61020d610c4b565b3361104c61020d610bb6565b7f2e1c659da2dc5f4ec69512e86bda1a7a48c5e97669b37f9bb5a3064b6353159f916110826110796100d2565b92839283610fbd565b0390a1565b5061100c6110985f61020c0161071f565b6110aa6110a43361022c565b9161022c565b149050611003565b6110ba610f30565b565b5f7f6e6f7420746865206f776e657200000000000000000000000000000000000000910152565b6110f0600d602092610739565b6110f9816110bc565b0190565b6111129060208101905f8183039101526110e3565b90565b1561111c57565b6111246100d2565b62461bcd60e51b81528061113a600482016110fd565b0390fd5b61116b906111663361116061115a6111555f61071f565b61022c565b9161022c565b14611115565b61127e565b565b61ffff1690565b61117d8161116d565b0361118457565b5f80fd5b3561119281611174565b90565b906111a261ffff91610c02565b9181191691161790565b6111c06111bb6111c59261116d565b6107c4565b61116d565b90565b90565b906111e06111db6111e7926111ac565b6111c8565b8254611195565b9055565b906111fd5f8061120394019201611188565b906111cb565b565b9061120f916111eb565b565b9050359061121e82611174565b565b5061122f906020810190611211565b90565b61123b9061116d565b9052565b905f6112516112599382810190611220565b910190611232565b565b91602061127c92949361127560408201965f83019061123f565b0190610d3c565b565b61128a81610209611205565b6112a86112a061129b61020d610bb6565b610bd7565b61020d610c4b565b6112b361020d610bb6565b7fb24d8d9dcfbb6be13176c1c7bfb0e76445a9ba2a3553b413d8671446f1030830916112e96112e06100d2565b9283928361125b565b0390a1565b6112f79061113e565b565b906113039061025d565b810190811067ffffffffffffffff82111761131d57604052565b610967565b9061133561132e6100d2565b92836112f9565b565b61134160c0611322565b90565b61134e6040611322565b90565b606090565b5f90565b611362611344565b906020808361136f611351565b81520161137a611356565b81525050565b61138861135a565b90565b6113956040611322565b90565b5f90565b5f90565b6113a861138b565b90602080836113b5611398565b8152016113c061139c565b81525050565b6113ce6113a0565b90565b6113db6020611322565b90565b5f90565b6113ea6113d1565b906020826113f66113de565b81525050565b6114046113e2565b90565b5f90565b611413611337565b906020808080808087611424611380565b81520161142f6113c6565b81520161143a611380565b8152016114456113fc565b815201611450611398565b81520161145b611407565b81525050565b61146961140b565b90565b5f90565b67ffffffffffffffff1690565b61148961148e916106fb565b611470565b90565b61149b905461147d565b90565b90565b6114b56114b06114ba9261149e565b6107c4565b610380565b90565b634e487b7160e01b5f52601260045260245ffd5b6114dd6114e391610380565b91610380565b9081156114ee570690565b6114bd565b61150761150261150c92610380565b6107c4565b61039a565b90565b9061151990610380565b9052565b90565b61152c611531916106fb565b61151d565b90565b61153e9054611520565b90565b9061154b9061039a565b9052565b90565b61156661156161156b9261154f565b6107c4565b610380565b90565b61157a61158091610380565b91610380565b90039067ffffffffffffffff821161159457565b610bc3565b634e487b7160e01b5f52603260045260245ffd5b50600290565b90565b6115bf816115ad565b8210156115da576115d2610103916115b3565b910201905f90565b611599565b6115f36115ee6115f89261154f565b6107c4565b61039a565b90565b61160a6116109193929361039a565b9261039a565b820180921161161b57565b610bc3565b67ffffffffffffffff81116116385760208091020190565b610967565b9061164f61164a83611620565b611322565b918252565b61165e6040611322565b90565b606090565b61166e611654565b906020808361167b6113de565b815201611686611661565b81525050565b611694611666565b90565b5f5b8281106116a557505050565b6020906116b061168c565b8184015201611699565b906116df6116c78361163d565b926020806116d58693611620565b9201910390611697565b565b60ff1690565b6116f36116f8916106fb565b6116e1565b90565b61170590546116e7565b90565b9061171290610340565b9052565b61171f9061039a565b5f19811461172d5760010190565b610bc3565b61174661174161174b9261039a565b6107c4565b610340565b90565b5061010090565b90565b6117618161174e565b82101561177b57611773600191611755565b910201905f90565b611599565b6117909060086117959302610a86565b610700565b90565b906117a39154611780565b90565b906117b08261020e565b8110156117c1576020809102010190565b611599565b906117d09061022c565b9052565b905f92918054906117ee6117e783610825565b8094610249565b916001811690815f146118455750600114611809575b505050565b611816919293945061097b565b915f925b81841061182d57505001905f8080611804565b6001816020929593955484860152019101929061181a565b92949550505060ff19168252151560200201905f8080611804565b9061186a916117d4565b90565b9061188d6118869261187d6100d2565b93848092611860565b03836112f9565b565b6118989061186d565b90565b906118a5906103e1565b9052565b6118b1611461565b506118ba611461565b6118c26109f8565b506118cb61146c565b506118d46109f8565b506118dd613117565b5f14611ccb576118ff6118f35f61020a01611491565b5f60208401510161150f565b61191c611910600161020a01611534565b60208084015101611541565b611955611950611940611930610208611491565b61193a6001611552565b9061156e565b61194a60026114a1565b906114d1565b6114f3565b9061197c611977611967610208611491565b61197160026114a1565b906114d1565b6114f3565b9161199e611999610101611992600287906115b6565b5001611534565b613145565b926119bb6119b6856119b060016115df565b906115fb565b6116ba565b5f604085015101526119ec6119df6101026119d8600285906115b6565b50016116fb565b6020604086015101611708565b6119f55f61085f565b5b80611a09611a038761039a565b9161039a565b11611b3957611ac090611a3d611a2e610101611a27600287906115b6565b5001611534565b611a3783611732565b9061319d565b611b3457611a64611a5e6001611a55600287906115b6565b50018390611758565b90611798565b611a82815f611a7b8160408b0151015186906117a6565b51016117c6565b611aad611a9e610101611a97600289906115b6565b5001611534565b611aa784611732565b9061319d565b8015611af7575b611ac5575b505b611716565b6119f6565b611ad09060016107fb565b611aef6020611ae75f60408a0151015185906117a6565b51019161188f565b90525f611ab9565b50611b1b611b156001611b0c600289906115b6565b50018490611758565b90611798565b611b2d611b278361022c565b9161022c565b1415611ab4565b611abb565b505091505b611b5f611b5a610101611b53600286906115b6565b5001611534565b613145565b91611b7c611b7784611b7160016115df565b906115fb565b6116ba565b5f808401510152611bab611b9f610102611b98600285906115b6565b50016116fb565b60205f85015101611708565b611bb45f61085f565b5b80611bc8611bc28661039a565b9161039a565b11611c7a57611c7090611bfc611bed610101611be6600287906115b6565b5001611534565b611bf683611732565b9061319d565b611c7557611c4a611c26611c206001611c17600288906115b6565b50018490611758565b90611798565b611c43815f611c3c81808b0151015187906117a6565b51016117c6565b60016107fb565b611c686020611c605f80890151015185906117a6565b51019161188f565b90525b611716565b611bb5565b611c6b565b50509050611c95611c8c610208611491565b6080830161150f565b611cb1611ca55f61020c0161071f565b5f6060840151016117c6565b611cc8611cbf61020d610bb6565b60a0830161189b565b90565b611cf1611cec611cdc610208611491565b611ce660026114a1565b906114d1565b6114f3565b90611b3e565b5f7f6e6f206d6967726174696f6e0000000000000000000000000000000000000000910152565b611d2b600c602092610739565b611d3481611cf7565b0190565b611d4d9060208101905f818303910152611d1e565b90565b15611d5757565b611d5f6100d2565b62461bcd60e51b815280611d7560048201611d38565b0390fd5b611d9290611d8d611d88613117565b611d50565b611fef565b565b5f7f77726f6e67206d6967726174696f6e2069640000000000000000000000000000910152565b611dc86012602092610739565b611dd181611d94565b0190565b611dea9060208101905f818303910152611dbb565b90565b15611df457565b611dfc6100d2565b62461bcd60e51b815280611e1260048201611dd5565b0390fd5b90611e20906107ef565b5f5260205260405f2090565b60ff1690565b611e3e611e43916106fb565b611e2c565b90565b611e509054611e32565b90565b151590565b90611e6290611e53565b9052565b60081c90565b611e78611e7d91611e66565b6116e1565b90565b611e8a9054611e6c565b90565b611e976040611322565b90565b90611ed0611ec75f611eaa611e8d565b94611ec1611eb9838301611e46565b838801611e58565b01611e80565b60208401611708565b565b611edb90611e9a565b90565b611ee89051611e53565b90565b611ef59051610340565b90565b5f7f6e6f742070756c6c696e67000000000000000000000000000000000000000000910152565b611f2c600b602092610739565b611f3581611ef8565b0190565b611f4e9060208101905f818303910152611f1f565b90565b15611f5857565b611f606100d2565b62461bcd60e51b815280611f7660048201611f39565b0390fd5b90611f865f1991610c02565b9181191691161790565b90611fa5611fa0611fac926109b7565b6109d3565b8254611f7a565b9055565b611fb990610380565b9052565b604090611fe6611fed9496959396611fdc60608401985f850190611fb0565b6020830190610fb0565b0190610d3c565b565b6120179061201161200b6120065f61020a01611491565b610380565b91610380565b14611ded565b6120c46120b961205b6120565f61204d6002612047612037610208611491565b61204160026114a1565b906114d1565b906115b6565b50013390611e16565b611ed2565b61206e6120695f8301611ede565b6108d4565b612099612094612082600161020a01611534565b61208e60208501611eeb565b906131db565b611f51565b6120b360206120ac600161020a01611534565b9201611eeb565b9061321a565b600161020a01611f90565b6120e26120da6120d561020d610bb6565b610bd7565b61020d610c4b565b6120f0600161020a01611534565b6121026120fc5f61085f565b9161039a565b145f1461215f576121165f61020a01611491565b3361212261020d610bb6565b916121597f01269879535f40ee8957e15e160bf1866c5e2728ff0cbc583d848821e2639b4e936121506100d2565b93849384611fbd565b0390a15b565b61216c5f61020a01611491565b3361217861020d610bb6565b916121af7faf5e90e72015f43138f66b4cd08bd1dfa2839030104f22a00af843fe847c6d19936121a66100d2565b93849384611fbd565b0390a161215d565b6121c090611d79565b565b6121ef906121ea336121e46121de6121d95f61071f565b61022c565b9161022c565b14611115565b612273565b565b5f7f6f70657261746f7220616c726561647920657869737473000000000000000000910152565b6122256017602092610739565b61222e816121f1565b0190565b6122479060208101905f818303910152612218565b90565b1561225157565b6122596100d2565b62461bcd60e51b81528061226f60048201612232565b0390fd5b6122ac61229461228f60016122895f860161072c565b906107fb565b61084f565b6122a66122a05f61085f565b9161039a565b1461224a565b6122cb6122c66122c0836020810190610909565b90610950565b613097565b6122f86122dc826020810190610909565b906122f360016122ed5f870161072c565b906107fb565b610b80565b61231661230e61230961020d610bb6565b610bd7565b61020d610c4b565b61232161020d610bb6565b7febdc606e899772e1d31d9535a98eea5ddb0d41e47128c921e64919c73f3edfa69161235761234e6100d2565b92839283610d49565b0390a1565b612365906121c2565b565b61238b3361238561237f61237a5f61071f565b61022c565b9161022c565b14611115565b612393612395565b565b6123a56123a0613117565b611d50565b6123ad61244a565b565b6123b890610380565b5f81146123c6576001900390565b610bc3565b906123de67ffffffffffffffff91610c02565b9181191691161790565b6123fc6123f761240192610380565b6107c4565b610380565b90565b90565b9061241c612417612423926123e8565b612404565b82546123cb565b9055565b91602061244892949361244160408201965f830190611fb0565b0190610d3c565b565b61246861246061245b610208611491565b6123af565b610208612407565b61247f6124745f61085f565b600161020a01611f90565b61249d61249561249061020d610bb6565b610bd7565b61020d610c4b565b6124aa5f61020a01611491565b6124b561020d610bb6565b7ff73240422246f63ed633ef3ce0726b8ab8fb69d46c8a4e5ecb0b2922668674a1916124eb6124e26100d2565b92839283612427565b0390a1565b6124f8612367565b565b612527906125223361251c6125166125115f61071f565b61022c565b9161022c565b14611115565b6125ab565b565b5f7f6d6967726174696f6e20696e2070726f67726573730000000000000000000000910152565b61255d6015602092610739565b61256681612529565b0190565b61257f9060208101905f818303910152612550565b90565b1561258957565b6125916100d2565b62461bcd60e51b8152806125a76004820161256a565b0390fd5b6125cd906125c86125c36125bd613117565b15611e53565b612582565b612651565b565b5f7f6d61696e74656e616e636520696e2070726f6772657373000000000000000000910152565b6126036017602092610739565b61260c816125cf565b0190565b6126259060208101905f8183039101526125f6565b90565b1561262f57565b6126376100d2565b62461bcd60e51b81528061264d60048201612610565b0390fd5b6126739061266e6126696126636130e2565b15611e53565b612628565b61283a565b565b61267e90610380565b67ffffffffffffffff81146126935760010190565b610bc3565b90565b90356001602003823603038112156126dc57016020813591019167ffffffffffffffff82116126d75760408202360383136126d257565b610c81565b610c7d565b610c85565b60209181520190565b90565b6126f681610340565b036126fd57565b5f80fd5b9050359061270e826126ed565b565b5061271f906020810190612701565b90565b90602061274d6127559361274461273b5f830183612710565b5f860190610346565b82810190610c6b565b910190610238565b565b9061276481604093612722565b0190565b5090565b60400190565b9161278082612786926126e1565b926126ea565b90815f905b828210612799575050505090565b909192936127bb6127b56001926127b08886612768565b612757565b9561276c565b92019092919261278b565b906128029060206127fa6127f0604084016127e35f88018861269b565b908683035f880152612772565b9482810190612710565b910190610346565b90565b9392906128306040916128389461282360608901925f8a0190611fb0565b87820360208901526127c6565b940190610d3c565b565b6128595f61020a0161285361284e82611491565b612675565b90612407565b61290b61290061010161289461288e6002612888612878610208611491565b61288260026114a1565b906114d1565b906115b6565b50612698565b6128b26128aa6128a5610208611491565b612675565b610208612407565b6128ef6128e76128e160026128db6128cb610208611491565b6128d560026114a1565b906114d1565b906115b6565b50612698565b9182906133c4565b6128fa818690613702565b01611534565b600161020a01611f90565b61292961292161291c61020d610bb6565b610bd7565b61020d610c4b565b6129365f61020a01611491565b9061294261020d610bb6565b916129797f78dad2bc0b47c688ed84f3fee79abc18e6c9822db05a79ca19dff54533c7470d936129706100d2565b93849384612805565b0390a1565b612987906124fa565b565b6129b6906129b1336129ab6129a56129a05f61071f565b61022c565b9161022c565b14611115565b612beb565b565b5f7f696e206b65797370616365000000000000000000000000000000000000000000910152565b6129ec600b602092610739565b6129f5816129b8565b0190565b612a0e9060208101905f8183039101526129df565b90565b15612a1857565b612a206100d2565b62461bcd60e51b815280612a36600482016129f9565b0390fd5b90612a4d905f1990602003600802610a86565b8154169055565b905f91612a6b612a638261097b565b928354610a9f565b905555565b919290602082105f14612ac957601f8411600114612a9957612a93929350610a9f565b90555b5b565b5090612abf612ac4936001612ab6612ab08561097b565b92610984565b82019101610a10565b612a54565b612a96565b50612b008293612ada60019461097b565b612af9612ae685610984565b820192601f861680612b0b575b50610984565b0190610a10565b600202179055612a97565b612b1790888603612a3a565b5f612af3565b929091680100000000000000008211612b7d576020115f14612b6e57602081105f14612b5257612b4c91610a9f565b90555b5b565b60019160ff1916612b628461097b565b55600202019055612b4f565b60019150600202019055612b50565b610967565b908154612b8e81610825565b90818311612bb7575b818310612ba5575b50505050565b612bae93612a70565b5f808080612b9f565b612bc383838387612b1d565b612b97565b5f612bd291612b82565b565b905f03612be657612be490612bc8565b565b610954565b612c1b612c02612bfd600184906107fb565b61084f565b612c14612c0e5f61085f565b9161039a565b14156108d4565b612c23613117565b5f14612d0c57612c5d612c58612c525f612c4c81612c43600282906115b6565b50018690611e16565b01611e46565b15611e53565b612a11565b612c92612c8d612c875f612c8181612c7860026001906115b6565b50018690611e16565b01611e46565b15611e53565b612a11565b5b612ca85f612ca3600184906107fb565b612bd4565b612cc6612cbe612cb961020d610bb6565b610bd7565b61020d610c4b565b612cd161020d610bb6565b7f9df3075e519fdff3ab71e9fc679060e9d2dd37c49ccc1c1fc1996d517752220a91612d07612cfe6100d2565b92839283610fbd565b0390a1565b612d5d612d58612d525f612d4c81612d436002612d3d612d2d610208611491565b612d3760026114a1565b906114d1565b906115b6565b50018690611e16565b01611e46565b15611e53565b612a11565b612c93565b612d6b90612989565b565b612d9a90612d9533612d8f612d89612d845f61071f565b61022c565b9161022c565b14611115565b612d9c565b565b612da6815f610f90565b612dc4612dbc612db761020d610bb6565b610bd7565b61020d610c4b565b612dcf61020d610bb6565b7f476610ebc6647c15376100955efbf22ef2a0c3b923fc00b380b660c873ef20ac91612e05612dfc6100d2565b92839283610fbd565b0390a1565b612e1390612d6d565b565b612e2e612e29612e23613117565b15611e53565b612582565b612e36612e38565b565b612e51612e4c612e466130e2565b15611e53565b612628565b612e59612e5b565b565b612e9b5f612e9581612e8c6002612e86612e76610208611491565b612e8060026114a1565b906114d1565b906115b6565b50013390611e16565b01611e46565b8015612f1e575b612eab9061079b565b612eb9335f61020c01610f90565b612ed7612ecf612eca61020d610bb6565b610bd7565b61020d610c4b565b33612ee361020d610bb6565b7fbc2748cf02f7a1291525e866efc76ab3b96d32d7afcbb26c53daec617b38b47991612f19612f106100d2565b92839283610fbd565b0390a1565b50612eab33612f3d612f37612f325f61071f565b61022c565b9161022c565b149050612ea2565b612f4d612e15565b565b5f7f656d707479206f70657261746f72206461746100000000000000000000000000910152565b612f836013602092610739565b612f8c81612f4f565b0190565b612fa59060208101905f818303910152612f76565b90565b15612faf57565b612fb76100d2565b62461bcd60e51b815280612fcd60048201612f90565b0390fd5b61ffff1690565b612fe4612fe9916106fb565b612fd1565b90565b612ff69054612fd8565b90565b61300d6130086130129261116d565b6107c4565b61039a565b90565b5f7f6f70657261746f72206461746120746f6f206c61726765000000000000000000910152565b6130496017602092610739565b61305281613015565b0190565b61306b9060208101905f81830391015261303c565b90565b1561307557565b61307d6100d2565b62461bcd60e51b81528061309360048201613056565b0390fd5b6130dc906130b7816130b16130ab5f61085f565b9161039a565b11612fa8565b6130d56130cf6130ca5f61020901612fec565b612ff9565b9161039a565b111561306e565b565b5f90565b6130ea6130de565b506130f85f61020c0161071f565b61311261310c6131075f610f66565b61022c565b9161022c565b141590565b61311f6130de565b5061312e600161020a01611534565b61314061313a5f61085f565b9161039a565b141590565b613157906131516109f8565b50613af8565b90565b61316e61316961317392610340565b6107c4565b61039a565b90565b6131959061318f61318961319a9461039a565b9161039a565b9061098e565b61039a565b90565b6131c4906131a96130de565b50916131bf6131b960019261315a565b916115df565b613176565b166131d76131d15f61085f565b9161039a565b1490565b613202906131e76130de565b50916131fd6131f760019261315a565b916115df565b613176565b1661321561320f5f61085f565b9161039a565b141590565b61324461324a916132296109f8565b509261323f61323960019261315a565b916115df565b613176565b1961039a565b1690565b5f80910155565b905f03613267576132659061324e565b565b610954565b6132766040611322565b90565b9061328560ff91610c02565b9181191691161790565b61329890611e53565b90565b90565b906132b36132ae6132ba9261328f565b61329b565b8254613279565b9055565b60081b90565b906132d161ff00916132be565b9181191691161790565b6132ef6132ea6132f492610340565b6107c4565b610340565b90565b90565b9061330f61330a613316926132db565b6132f7565b82546132c4565b9055565b9061334460205f61334a9461333c828201613336848801611ede565b9061329e565b019201611eeb565b906132fa565b565b906133569161331a565b565b9190600861337891029161337260018060a01b038461098e565b9261098e565b9181191691161790565b91906133986133936133a0936107ef565b610f8d565b908354613358565b9055565b906133b96133b46133c0926132db565b6132f7565b8254613279565b9055565b91906133f96133de6133d96101018601611534565b613145565b6133f36133ee6101018501611534565b613145565b90613c8d565b9161340261146c565b5061340b61146c565b506134155f61085f565b5b806134296134238661039a565b9161039a565b11613546576134da90613449613443600188018390611758565b90611798565b61346061345a600187018490611758565b90611798565b908061347461346e8461022c565b9161022c565b1461353f57816134d49261349861349261348d5f610f66565b61022c565b9161022c565b03613524575b50806134ba6134b46134af5f610f66565b61022c565b9161022c565b036134df575b6134ce600187018490611758565b90613382565b5b611716565b613416565b61351f600161350d6134f086611732565b6135046134fb61326c565b935f8501611e58565b60208301611708565b61351a5f89018490611e16565b61334c565b6134c0565b5f61353461353992828a01611e16565b613255565b5f61349e565b50506134d5565b509261357c9250613575610101809261356f61356561010283016116fb565b61010287016133a4565b01611534565b9101611f90565b565b5f90565b600161358e910161039a565b90565b9035906001602003813603038212156135d3570180359067ffffffffffffffff82116135ce576020019160408202360383136135c957565b610905565b610901565b6108fd565b5090565b91908110156135ec576040020190565b611599565b356135fb816126ed565b90565b5f7f756e6368616e67656420736c6f74000000000000000000000000000000000000910152565b613632600e602092610739565b61363b816135fe565b0190565b6136549060208101905f818303910152613625565b90565b1561365e57565b6136666100d2565b62461bcd60e51b81528061367c6004820161363f565b0390fd5b5f7f6f70657261746f72206475706c69636174650000000000000000000000000000910152565b6136b46012602092610739565b6136bd81613680565b0190565b6136d69060208101905f8183039101526136a7565b90565b156136e057565b6136e86100d2565b62461bcd60e51b8152806136fe600482016136c1565b0390fd5b61370f6101018201611534565b9061371861357e565b5061372161146c565b5061372a61146c565b506137345f61085f565b5b8061375d61375761375261374c885f810190613591565b906135d8565b61039a565b9161039a565b101561390e576138879061388261378b5f61378561377e8983810190613591565b86916135dc565b016135f1565b61387d6137b060206137aa6137a38b5f810190613591565b88916135dc565b0161072c565b80976137c96137c360018a018690611758565b90611798565b6137e6816137df6137d98661022c565b9161022c565b1415613657565b806138016137fb6137f65f610f66565b61022c565b9161022c565b036138f3575b50878261382461381e6138195f610f66565b61022c565b9161022c565b145f1461388c57506138389150839061321a565b965b6138528161384c60018a018690611758565b90613382565b61387560019361386c61386361326c565b955f8701611e58565b60208501611708565b5f8701611e16565b61334c565b613582565b613735565b6138e16138db5f6138d56138ed96826138e6966138cf6138b66138b1600186906107fb565b61084f565b6138c86138c28561085f565b9161039a565b14156108d4565b01611e16565b01611e46565b15611e53565b6136d9565b8390613cb9565b9661383a565b5f61390361390892828c01611e16565b613255565b5f613807565b509061393060206139379461392a610102946101018701611f90565b016135f1565b91016133a4565b565b90565b61395061394b61395592613939565b6107c4565b61039a565b90565b90565b61396f61396a61397492613958565b6107c4565b610340565b90565b6139969061399061398a61399b94610340565b9161039a565b9061098e565b61039a565b90565b6139bd906139b76139b16139c29461039a565b9161039a565b90610a86565b61039a565b90565b90565b6139dc6139d76139e1926139c5565b6107c4565b61039a565b90565b90565b6139fb6139f6613a00926139e4565b6107c4565b610340565b90565b90565b613a1a613a15613a1f92613a03565b6107c4565b61039a565b90565b90565b613a39613a34613a3e92613a22565b6107c4565b610340565b90565b90565b613a58613a53613a5d92613a41565b6107c4565b61039a565b90565b90565b613a77613a72613a7c92613a60565b6107c4565b610340565b90565b90565b613a96613a91613a9b92613a7f565b6107c4565b61039a565b90565b90565b613ab5613ab0613aba92613a9e565b6107c4565b610340565b90565b90565b613ad4613acf613ad992613abd565b6107c4565b61039a565b90565b613af0613aeb613af59261149e565b6107c4565b610340565b90565b613b006109f8565b50613b40613b3082613b2a613b246fffffffffffffffffffffffffffffffff61393c565b9161039a565b11613ce4565b613b3a600761395b565b90613977565b613b81613b71613b5184849061399e565b613b6b613b6567ffffffffffffffff6139c8565b9161039a565b11613ce4565b613b7b60066139e7565b90613977565b17613bbf613baf613b9384849061399e565b613ba9613ba363ffffffff613a06565b9161039a565b11613ce4565b613bb96005613a25565b90613977565b17613bfb613beb613bd184849061399e565b613be5613bdf61ffff613a44565b9161039a565b11613ce4565b613bf56004613a63565b90613977565b17613c36613c26613c0d84849061399e565b613c20613c1a60ff613a82565b9161039a565b11613ce4565b613c306003613aa1565b90613977565b17613c71613c61613c4884849061399e565b613c5b613c55600f613ac0565b9161039a565b11613ce4565b613c6b6002613adc565b90613977565b17906d010102020202030303030303030360801b90821c1a1790565b613cb691613c996109f8565b5081613cad613ca78361039a565b9161039a565b11919091613d00565b90565b613ce090613cc56109f8565b5091613cdb613cd560019261315a565b916115df565b613176565b1790565b613cec6109f8565b50151590565b90613cfd910261039a565b90565b613d1a613d209293613d106109f8565b5080941891613ce4565b90613cf2565b189056fea26469706673582212208b10234b08244c919ee8fc151ed15483fad0d05bc89d37a4de3b8fc6879959b364736f6c634300081c0033","sourceMap":"1030:10844:22:-:0;;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;:::i;:::-;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;:::i;:::-;;;;;;;;;;:::o;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;:::o;:::-;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;:::o;:::-;;;:::o;:::-;;:::o;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;:::o;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;:::i;:::-;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;:::o;:::-;;:::o;:::-;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;:::o;:::-;;:::i;:::-;;;;:::o;:::-;;:::o;:::-;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;:::o;:::-;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;;;:::i;:::-;;:::i;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;:::i;:::-;:::o;:::-;;;;;;;:::o;:::-;;;;;;;:::o;:::-;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;:::i;:::-;;;;;:::i;:::-;;;:::o;:::-;;;:::o;:::-;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;;;;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;:::o;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;:::i;:::-;;;;;;:::o;:::-;;;;;:::i;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;1367:833::-;1562:26;1367:833;1462:61;1470:23;:16;:23;:::i;:::-;:30;;1497:3;1470:30;:::i;:::-;;;:::i;:::-;;;1462:61;:::i;:::-;1534:18;1542:10;1534:18;;:::i;:::-;1562:26;;:::i;:::-;1620:13;1632:1;1620:13;:::i;:::-;1664:3;1635:1;:27;;1639:23;:16;:23;:::i;:::-;1635:27;:::i;:::-;;;:::i;:::-;;;;;1664:3;1708:16;:31;;:24;:19;:16;1725:1;1708:19;;:::i;:::-;;:24;;:31;:::i;:::-;;:::i;:::-;1754:81;1762:45;:38;:12;1775:24;;:19;:16;1792:1;1775:19;;:::i;:::-;;:24;;:::i;:::-;1762:38;;:::i;:::-;:45;:::i;:::-;:50;;1811:1;1762:50;:::i;:::-;;;:::i;:::-;;1754:81;:::i;:::-;1850:52;1878:24;;:19;:16;1895:1;1878:19;;:::i;:::-;;:24;;:::i;:::-;1850:25;:22;:12;:9;1860:1;1850:12;;:::i;:::-;;:22;1873:1;1850:25;;:::i;:::-;:52;;:::i;:::-;1916:101;1993:4;1973:44;2006:8;2012:1;2006:8;:::i;:::-;1973:44;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::i;:::-;1916:54;:28;:12;:9;1926:1;1916:12;;:::i;:::-;;:28;1945:24;;:19;:16;1962:1;1945:19;;:::i;:::-;;:24;;:::i;:::-;1916:54;;:::i;:::-;:101;:::i;:::-;2031:65;2072:24;:19;:16;2089:1;2072:19;;:::i;:::-;;:24;;2031:38;:12;2044:24;;:19;:16;2061:1;2044:19;;:::i;:::-;;:24;;:::i;:::-;2031:38;;:::i;:::-;:65;:::i;:::-;1664:3;:::i;:::-;1620:13;;1635:27;;2149:44;2162:30;2168:23;2117:76;1635:27;2168:23;:::i;:::-;2162:30;:::i;:::-;2149:44;:::i;:::-;2117:29;:12;:9;2127:1;2117:12;;:::i;:::-;;:29;:76;:::i;:::-;1367:833::o;1030:10844::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;:::o;:::-;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;11413:205;11537:74;11413:205;11486:41;11494:5;:9;;11502:1;11494:9;:::i;:::-;;;:::i;:::-;;11486:41;:::i;:::-;11545:38;;11554:29;;:8;:29;;:::i;:::-;11545:38;:::i;:::-;;;:::i;:::-;;;11537:74;:::i;:::-;11413:205::o;1030:10844::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;:::o;:::-;;:::i;12794:101::-;12868:15;12867:21;12794:101;12840:7;;:::i;:::-;12868:1;:15;12873:10;12868:1;12881;12873:10;:::i;:::-;12868:15;;:::i;:::-;;:::i;:::-;12867:21;12887:1;12867:21;:::i;:::-;;;:::i;:::-;12860:28;:::o","linkReferences":{}},"deployedBytecode":{"object":"0x60806040526004361015610013575b6106f7565b61001d5f356100cc565b806326322217146100c757806353bfb584146100c257806365706f9c146100bd57806375418b9d146100b85780639d44e717146100b3578063b55a4142146100ae578063c130809a146100a9578063cdbfc62d146100a4578063db1b0fd71461009f578063f2fde38b1461009a5763f5f2d9f10361000e576106c4565b610691565b61065e565b6105ea565b61056f565b61053c565b610509565b610493565b6101db565b610177565b610135565b60e01c90565b60405190565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b908160409103126100f65790565b6100e4565b9060208282031261012b575f82013567ffffffffffffffff81116101265761012392016100e8565b90565b6100e0565b6100dc565b5f0190565b346101635761014d6101483660046100fb565b610d6f565b6101556100d2565b8061015f81610130565b0390f35b6100d8565b5f91031261017257565b6100dc565b346101a557610187366004610168565b61018f6110b2565b6101976100d2565b806101a181610130565b0390f35b6100d8565b908160209103126101b85790565b6100e4565b906020828203126101d6576101d3915f016101aa565b90565b6100dc565b34610209576101f36101ee3660046101bd565b6112ee565b6101fb6100d2565b8061020581610130565b0390f35b6100d8565b5190565b60209181520190565b60200190565b60018060a01b031690565b61023590610221565b90565b6102419061022c565b9052565b5190565b60209181520190565b90825f9392825e0152565b601f801991011690565b61028661028f6020936102949361027d81610245565b93848093610249565b95869101610252565b61025d565b0190565b6102c391602060408201926102b35f8201515f850190610238565b0151906020818403910152610267565b90565b906102d091610298565b90565b60200190565b906102ed6102e68361020e565b8092610212565b90816102fe6020830284019461021b565b925f915b83831061031157505050505090565b9091929394602061033361032d838560019503875289516102c6565b976102d3565b9301930191939290610302565b60ff1690565b61034f90610340565b9052565b9061037d90602080610372604084015f8701518582035f8701526102d9565b940151910190610346565b90565b67ffffffffffffffff1690565b61039690610380565b9052565b90565b6103a69061039a565b9052565b906020806103cc936103c25f8201515f86019061038d565b015191019061039d565b565b905f806103df930151910190610238565b565b6fffffffffffffffffffffffffffffffff1690565b6103ff906103e1565b9052565b906104789060c060a061044a61042660e085015f8801518682035f880152610353565b610438602088015160208701906103aa565b60408701518582036060870152610353565b9461045d606082015160808601906103ce565b61046e60808201518386019061038d565b01519101906103f6565b90565b6104909160208201915f818403910152610403565b90565b346104c3576104a3366004610168565b6104bf6104ae6118a9565b6104b66100d2565b9182918261047b565b0390f35b6100d8565b6104d181610380565b036104d857565b5f80fd5b905035906104e9826104c8565b565b9060208282031261050457610501915f016104dc565b90565b6100dc565b346105375761052161051c3660046104eb565b6121b7565b6105296100d2565b8061053381610130565b0390f35b6100d8565b3461056a5761055461054f3660046100fb565b61235c565b61055c6100d2565b8061056681610130565b0390f35b6100d8565b3461059d5761057f366004610168565b6105876124f0565b61058f6100d2565b8061059981610130565b0390f35b6100d8565b908160409103126105b05790565b6100e4565b906020828203126105e5575f82013567ffffffffffffffff81116105e0576105dd92016105a2565b90565b6100e0565b6100dc565b34610618576106026105fd3660046105b5565b61297e565b61060a6100d2565b8061061481610130565b0390f35b6100d8565b6106268161022c565b0361062d57565b5f80fd5b9050359061063e8261061d565b565b9060208282031261065957610656915f01610631565b90565b6100dc565b3461068c57610676610671366004610640565b612d62565b61067e6100d2565b8061068881610130565b0390f35b6100d8565b346106bf576106a96106a4366004610640565b612e0a565b6106b16100d2565b806106bb81610130565b0390f35b6100d8565b346106f2576106d4366004610168565b6106dc612f45565b6106e46100d2565b806106ee81610130565b0390f35b6100d8565b5f80fd5b5f1c90565b60018060a01b031690565b61071761071c916106fb565b610700565b90565b610729905461070b565b90565b356107368161061d565b90565b60209181520190565b5f7f756e617574686f72697a65640000000000000000000000000000000000000000910152565b610776600c602092610739565b61077f81610742565b0190565b6107989060208101905f818303910152610769565b90565b156107a257565b6107aa6100d2565b62461bcd60e51b8152806107c060048201610783565b0390fd5b90565b6107db6107d66107e092610221565b6107c4565b610221565b90565b6107ec906107c7565b90565b6107f8906107e3565b90565b90610805906107ef565b5f5260205260405f2090565b634e487b7160e01b5f52602260045260245ffd5b9060016002830492168015610845575b602083101461084057565b610811565b91607f1691610835565b6108599054610825565b90565b90565b61087361086e6108789261085c565b6107c4565b61039a565b90565b5f7f756e6b6e6f776e206f70657261746f7200000000000000000000000000000000910152565b6108af6010602092610739565b6108b88161087b565b0190565b6108d19060208101905f8183039101526108a2565b90565b156108db57565b6108e36100d2565b62461bcd60e51b8152806108f9600482016108bc565b0390fd5b5f80fd5b5f80fd5b5f80fd5b90359060016020038136030382121561094b570180359067ffffffffffffffff82116109465760200191600182023603831361094157565b610905565b610901565b6108fd565b5090565b634e487b7160e01b5f525f60045260245ffd5b634e487b7160e01b5f52604160045260245ffd5b5f5260205f2090565b601f602091010490565b1b90565b919060086109ad9102916109a75f198461098e565b9261098e565b9181191691161790565b6109cb6109c66109d09261039a565b6107c4565b61039a565b90565b90565b91906109ec6109e76109f4936109b7565b6109d3565b908354610992565b9055565b5f90565b610a0e91610a086109f8565b916109d6565b565b5b818110610a1c575050565b80610a295f6001936109fc565b01610a11565b9190601f8111610a3f575b505050565b610a4b610a709361097b565b906020610a5784610984565b83019310610a78575b610a6990610984565b0190610a10565b5f8080610a3a565b9150610a6981929050610a60565b1c90565b90610a9a905f1990600802610a86565b191690565b81610aa991610a8a565b906002021790565b91610abc9082610950565b9067ffffffffffffffff8211610b7b57610ae082610ada8554610825565b85610a2f565b5f90601f8311600114610b1357918091610b02935f92610b07575b5050610a9f565b90555b565b90915001355f80610afb565b601f19831691610b228561097b565b925f5b818110610b6357509160029391856001969410610b49575b50505002019055610b05565b610b59910135601f841690610a8a565b90555f8080610b3d565b91936020600181928787013581550195019201610b25565b610967565b90610b8b9291610ab1565b565b6fffffffffffffffffffffffffffffffff1690565b610bae610bb3916106fb565b610b8d565b90565b610bc09054610ba2565b90565b634e487b7160e01b5f52601160045260245ffd5b610be0906103e1565b6fffffffffffffffffffffffffffffffff8114610bfd5760010190565b610bc3565b5f1b90565b90610c226fffffffffffffffffffffffffffffffff91610c02565b9181191691161790565b610c40610c3b610c45926103e1565b6107c4565b6103e1565b90565b90565b90610c60610c5b610c6792610c2c565b610c48565b8254610c07565b9055565b50610c7a906020810190610631565b90565b5f80fd5b5f80fd5b5f80fd5b9035600160200382360303811215610cca57016020813591019167ffffffffffffffff8211610cc5576001820236038313610cc057565b610c81565b610c7d565b610c85565b90825f939282370152565b9190610cf481610ced81610cf995610249565b8095610ccf565b61025d565b0190565b610d3991610d2b6040820192610d21610d185f830183610c6b565b5f850190610238565b6020810190610c89565b916020818503910152610cda565b90565b610d45906103e1565b9052565b92916020610d65610d6d9360408701908782035f890152610cfd565b940190610d3c565b565b33610d8a610d84610d7f5f61071f565b61022c565b9161022c565b148015610e85575b610d9b9061079b565b610dd5610dbc610db76001610db15f860161072c565b906107fb565b61084f565b610dce610dc85f61085f565b9161039a565b14156108d4565b610df4610def610de9836020810190610909565b90610950565b613097565b610e21610e05826020810190610909565b90610e1c6001610e165f870161072c565b906107fb565b610b80565b610e3f610e37610e3261020d610bb6565b610bd7565b61020d610c4b565b610e4a61020d610bb6565b7f5aab2c32b1e447db4dba1d2790fe8b863d4775042b10b92e00dab9d6b671b5b591610e80610e776100d2565b92839283610d49565b0390a1565b50610d9b33610ea6610ea0610e9b5f860161072c565b61022c565b9161022c565b149050610d92565b5f7f6e6f206d61696e74656e616e6365000000000000000000000000000000000000910152565b610ee2600e602092610739565b610eeb81610eae565b0190565b610f049060208101905f818303910152610ed5565b90565b15610f0e57565b610f166100d2565b62461bcd60e51b815280610f2c60048201610eef565b0390fd5b610f40610f3b6130e2565b610f07565b610f48610fe0565b565b610f5e610f59610f639261085c565b6107c4565b610221565b90565b610f6f90610f4a565b90565b90610f8360018060a01b0391610c02565b9181191691161790565b90565b90610fa5610fa0610fac926107ef565b610f8d565b8254610f72565b9055565b610fb99061022c565b9052565b916020610fde929493610fd760408201965f830190610fb0565b0190610d3c565b565b33610ffb610ff5610ff05f61071f565b61022c565b9161022c565b148015611087575b61100c9061079b565b6110226110185f610f66565b5f61020c01610f90565b61104061103861103361020d610bb6565b610bd7565b61020d610c4b565b3361104c61020d610bb6565b7f2e1c659da2dc5f4ec69512e86bda1a7a48c5e97669b37f9bb5a3064b6353159f916110826110796100d2565b92839283610fbd565b0390a1565b5061100c6110985f61020c0161071f565b6110aa6110a43361022c565b9161022c565b149050611003565b6110ba610f30565b565b5f7f6e6f7420746865206f776e657200000000000000000000000000000000000000910152565b6110f0600d602092610739565b6110f9816110bc565b0190565b6111129060208101905f8183039101526110e3565b90565b1561111c57565b6111246100d2565b62461bcd60e51b81528061113a600482016110fd565b0390fd5b61116b906111663361116061115a6111555f61071f565b61022c565b9161022c565b14611115565b61127e565b565b61ffff1690565b61117d8161116d565b0361118457565b5f80fd5b3561119281611174565b90565b906111a261ffff91610c02565b9181191691161790565b6111c06111bb6111c59261116d565b6107c4565b61116d565b90565b90565b906111e06111db6111e7926111ac565b6111c8565b8254611195565b9055565b906111fd5f8061120394019201611188565b906111cb565b565b9061120f916111eb565b565b9050359061121e82611174565b565b5061122f906020810190611211565b90565b61123b9061116d565b9052565b905f6112516112599382810190611220565b910190611232565b565b91602061127c92949361127560408201965f83019061123f565b0190610d3c565b565b61128a81610209611205565b6112a86112a061129b61020d610bb6565b610bd7565b61020d610c4b565b6112b361020d610bb6565b7fb24d8d9dcfbb6be13176c1c7bfb0e76445a9ba2a3553b413d8671446f1030830916112e96112e06100d2565b9283928361125b565b0390a1565b6112f79061113e565b565b906113039061025d565b810190811067ffffffffffffffff82111761131d57604052565b610967565b9061133561132e6100d2565b92836112f9565b565b61134160c0611322565b90565b61134e6040611322565b90565b606090565b5f90565b611362611344565b906020808361136f611351565b81520161137a611356565b81525050565b61138861135a565b90565b6113956040611322565b90565b5f90565b5f90565b6113a861138b565b90602080836113b5611398565b8152016113c061139c565b81525050565b6113ce6113a0565b90565b6113db6020611322565b90565b5f90565b6113ea6113d1565b906020826113f66113de565b81525050565b6114046113e2565b90565b5f90565b611413611337565b906020808080808087611424611380565b81520161142f6113c6565b81520161143a611380565b8152016114456113fc565b815201611450611398565b81520161145b611407565b81525050565b61146961140b565b90565b5f90565b67ffffffffffffffff1690565b61148961148e916106fb565b611470565b90565b61149b905461147d565b90565b90565b6114b56114b06114ba9261149e565b6107c4565b610380565b90565b634e487b7160e01b5f52601260045260245ffd5b6114dd6114e391610380565b91610380565b9081156114ee570690565b6114bd565b61150761150261150c92610380565b6107c4565b61039a565b90565b9061151990610380565b9052565b90565b61152c611531916106fb565b61151d565b90565b61153e9054611520565b90565b9061154b9061039a565b9052565b90565b61156661156161156b9261154f565b6107c4565b610380565b90565b61157a61158091610380565b91610380565b90039067ffffffffffffffff821161159457565b610bc3565b634e487b7160e01b5f52603260045260245ffd5b50600290565b90565b6115bf816115ad565b8210156115da576115d2610103916115b3565b910201905f90565b611599565b6115f36115ee6115f89261154f565b6107c4565b61039a565b90565b61160a6116109193929361039a565b9261039a565b820180921161161b57565b610bc3565b67ffffffffffffffff81116116385760208091020190565b610967565b9061164f61164a83611620565b611322565b918252565b61165e6040611322565b90565b606090565b61166e611654565b906020808361167b6113de565b815201611686611661565b81525050565b611694611666565b90565b5f5b8281106116a557505050565b6020906116b061168c565b8184015201611699565b906116df6116c78361163d565b926020806116d58693611620565b9201910390611697565b565b60ff1690565b6116f36116f8916106fb565b6116e1565b90565b61170590546116e7565b90565b9061171290610340565b9052565b61171f9061039a565b5f19811461172d5760010190565b610bc3565b61174661174161174b9261039a565b6107c4565b610340565b90565b5061010090565b90565b6117618161174e565b82101561177b57611773600191611755565b910201905f90565b611599565b6117909060086117959302610a86565b610700565b90565b906117a39154611780565b90565b906117b08261020e565b8110156117c1576020809102010190565b611599565b906117d09061022c565b9052565b905f92918054906117ee6117e783610825565b8094610249565b916001811690815f146118455750600114611809575b505050565b611816919293945061097b565b915f925b81841061182d57505001905f8080611804565b6001816020929593955484860152019101929061181a565b92949550505060ff19168252151560200201905f8080611804565b9061186a916117d4565b90565b9061188d6118869261187d6100d2565b93848092611860565b03836112f9565b565b6118989061186d565b90565b906118a5906103e1565b9052565b6118b1611461565b506118ba611461565b6118c26109f8565b506118cb61146c565b506118d46109f8565b506118dd613117565b5f14611ccb576118ff6118f35f61020a01611491565b5f60208401510161150f565b61191c611910600161020a01611534565b60208084015101611541565b611955611950611940611930610208611491565b61193a6001611552565b9061156e565b61194a60026114a1565b906114d1565b6114f3565b9061197c611977611967610208611491565b61197160026114a1565b906114d1565b6114f3565b9161199e611999610101611992600287906115b6565b5001611534565b613145565b926119bb6119b6856119b060016115df565b906115fb565b6116ba565b5f604085015101526119ec6119df6101026119d8600285906115b6565b50016116fb565b6020604086015101611708565b6119f55f61085f565b5b80611a09611a038761039a565b9161039a565b11611b3957611ac090611a3d611a2e610101611a27600287906115b6565b5001611534565b611a3783611732565b9061319d565b611b3457611a64611a5e6001611a55600287906115b6565b50018390611758565b90611798565b611a82815f611a7b8160408b0151015186906117a6565b51016117c6565b611aad611a9e610101611a97600289906115b6565b5001611534565b611aa784611732565b9061319d565b8015611af7575b611ac5575b505b611716565b6119f6565b611ad09060016107fb565b611aef6020611ae75f60408a0151015185906117a6565b51019161188f565b90525f611ab9565b50611b1b611b156001611b0c600289906115b6565b50018490611758565b90611798565b611b2d611b278361022c565b9161022c565b1415611ab4565b611abb565b505091505b611b5f611b5a610101611b53600286906115b6565b5001611534565b613145565b91611b7c611b7784611b7160016115df565b906115fb565b6116ba565b5f808401510152611bab611b9f610102611b98600285906115b6565b50016116fb565b60205f85015101611708565b611bb45f61085f565b5b80611bc8611bc28661039a565b9161039a565b11611c7a57611c7090611bfc611bed610101611be6600287906115b6565b5001611534565b611bf683611732565b9061319d565b611c7557611c4a611c26611c206001611c17600288906115b6565b50018490611758565b90611798565b611c43815f611c3c81808b0151015187906117a6565b51016117c6565b60016107fb565b611c686020611c605f80890151015185906117a6565b51019161188f565b90525b611716565b611bb5565b611c6b565b50509050611c95611c8c610208611491565b6080830161150f565b611cb1611ca55f61020c0161071f565b5f6060840151016117c6565b611cc8611cbf61020d610bb6565b60a0830161189b565b90565b611cf1611cec611cdc610208611491565b611ce660026114a1565b906114d1565b6114f3565b90611b3e565b5f7f6e6f206d6967726174696f6e0000000000000000000000000000000000000000910152565b611d2b600c602092610739565b611d3481611cf7565b0190565b611d4d9060208101905f818303910152611d1e565b90565b15611d5757565b611d5f6100d2565b62461bcd60e51b815280611d7560048201611d38565b0390fd5b611d9290611d8d611d88613117565b611d50565b611fef565b565b5f7f77726f6e67206d6967726174696f6e2069640000000000000000000000000000910152565b611dc86012602092610739565b611dd181611d94565b0190565b611dea9060208101905f818303910152611dbb565b90565b15611df457565b611dfc6100d2565b62461bcd60e51b815280611e1260048201611dd5565b0390fd5b90611e20906107ef565b5f5260205260405f2090565b60ff1690565b611e3e611e43916106fb565b611e2c565b90565b611e509054611e32565b90565b151590565b90611e6290611e53565b9052565b60081c90565b611e78611e7d91611e66565b6116e1565b90565b611e8a9054611e6c565b90565b611e976040611322565b90565b90611ed0611ec75f611eaa611e8d565b94611ec1611eb9838301611e46565b838801611e58565b01611e80565b60208401611708565b565b611edb90611e9a565b90565b611ee89051611e53565b90565b611ef59051610340565b90565b5f7f6e6f742070756c6c696e67000000000000000000000000000000000000000000910152565b611f2c600b602092610739565b611f3581611ef8565b0190565b611f4e9060208101905f818303910152611f1f565b90565b15611f5857565b611f606100d2565b62461bcd60e51b815280611f7660048201611f39565b0390fd5b90611f865f1991610c02565b9181191691161790565b90611fa5611fa0611fac926109b7565b6109d3565b8254611f7a565b9055565b611fb990610380565b9052565b604090611fe6611fed9496959396611fdc60608401985f850190611fb0565b6020830190610fb0565b0190610d3c565b565b6120179061201161200b6120065f61020a01611491565b610380565b91610380565b14611ded565b6120c46120b961205b6120565f61204d6002612047612037610208611491565b61204160026114a1565b906114d1565b906115b6565b50013390611e16565b611ed2565b61206e6120695f8301611ede565b6108d4565b612099612094612082600161020a01611534565b61208e60208501611eeb565b906131db565b611f51565b6120b360206120ac600161020a01611534565b9201611eeb565b9061321a565b600161020a01611f90565b6120e26120da6120d561020d610bb6565b610bd7565b61020d610c4b565b6120f0600161020a01611534565b6121026120fc5f61085f565b9161039a565b145f1461215f576121165f61020a01611491565b3361212261020d610bb6565b916121597f01269879535f40ee8957e15e160bf1866c5e2728ff0cbc583d848821e2639b4e936121506100d2565b93849384611fbd565b0390a15b565b61216c5f61020a01611491565b3361217861020d610bb6565b916121af7faf5e90e72015f43138f66b4cd08bd1dfa2839030104f22a00af843fe847c6d19936121a66100d2565b93849384611fbd565b0390a161215d565b6121c090611d79565b565b6121ef906121ea336121e46121de6121d95f61071f565b61022c565b9161022c565b14611115565b612273565b565b5f7f6f70657261746f7220616c726561647920657869737473000000000000000000910152565b6122256017602092610739565b61222e816121f1565b0190565b6122479060208101905f818303910152612218565b90565b1561225157565b6122596100d2565b62461bcd60e51b81528061226f60048201612232565b0390fd5b6122ac61229461228f60016122895f860161072c565b906107fb565b61084f565b6122a66122a05f61085f565b9161039a565b1461224a565b6122cb6122c66122c0836020810190610909565b90610950565b613097565b6122f86122dc826020810190610909565b906122f360016122ed5f870161072c565b906107fb565b610b80565b61231661230e61230961020d610bb6565b610bd7565b61020d610c4b565b61232161020d610bb6565b7febdc606e899772e1d31d9535a98eea5ddb0d41e47128c921e64919c73f3edfa69161235761234e6100d2565b92839283610d49565b0390a1565b612365906121c2565b565b61238b3361238561237f61237a5f61071f565b61022c565b9161022c565b14611115565b612393612395565b565b6123a56123a0613117565b611d50565b6123ad61244a565b565b6123b890610380565b5f81146123c6576001900390565b610bc3565b906123de67ffffffffffffffff91610c02565b9181191691161790565b6123fc6123f761240192610380565b6107c4565b610380565b90565b90565b9061241c612417612423926123e8565b612404565b82546123cb565b9055565b91602061244892949361244160408201965f830190611fb0565b0190610d3c565b565b61246861246061245b610208611491565b6123af565b610208612407565b61247f6124745f61085f565b600161020a01611f90565b61249d61249561249061020d610bb6565b610bd7565b61020d610c4b565b6124aa5f61020a01611491565b6124b561020d610bb6565b7ff73240422246f63ed633ef3ce0726b8ab8fb69d46c8a4e5ecb0b2922668674a1916124eb6124e26100d2565b92839283612427565b0390a1565b6124f8612367565b565b612527906125223361251c6125166125115f61071f565b61022c565b9161022c565b14611115565b6125ab565b565b5f7f6d6967726174696f6e20696e2070726f67726573730000000000000000000000910152565b61255d6015602092610739565b61256681612529565b0190565b61257f9060208101905f818303910152612550565b90565b1561258957565b6125916100d2565b62461bcd60e51b8152806125a76004820161256a565b0390fd5b6125cd906125c86125c36125bd613117565b15611e53565b612582565b612651565b565b5f7f6d61696e74656e616e636520696e2070726f6772657373000000000000000000910152565b6126036017602092610739565b61260c816125cf565b0190565b6126259060208101905f8183039101526125f6565b90565b1561262f57565b6126376100d2565b62461bcd60e51b81528061264d60048201612610565b0390fd5b6126739061266e6126696126636130e2565b15611e53565b612628565b61283a565b565b61267e90610380565b67ffffffffffffffff81146126935760010190565b610bc3565b90565b90356001602003823603038112156126dc57016020813591019167ffffffffffffffff82116126d75760408202360383136126d257565b610c81565b610c7d565b610c85565b60209181520190565b90565b6126f681610340565b036126fd57565b5f80fd5b9050359061270e826126ed565b565b5061271f906020810190612701565b90565b90602061274d6127559361274461273b5f830183612710565b5f860190610346565b82810190610c6b565b910190610238565b565b9061276481604093612722565b0190565b5090565b60400190565b9161278082612786926126e1565b926126ea565b90815f905b828210612799575050505090565b909192936127bb6127b56001926127b08886612768565b612757565b9561276c565b92019092919261278b565b906128029060206127fa6127f0604084016127e35f88018861269b565b908683035f880152612772565b9482810190612710565b910190610346565b90565b9392906128306040916128389461282360608901925f8a0190611fb0565b87820360208901526127c6565b940190610d3c565b565b6128595f61020a0161285361284e82611491565b612675565b90612407565b61290b61290061010161289461288e6002612888612878610208611491565b61288260026114a1565b906114d1565b906115b6565b50612698565b6128b26128aa6128a5610208611491565b612675565b610208612407565b6128ef6128e76128e160026128db6128cb610208611491565b6128d560026114a1565b906114d1565b906115b6565b50612698565b9182906133c4565b6128fa818690613702565b01611534565b600161020a01611f90565b61292961292161291c61020d610bb6565b610bd7565b61020d610c4b565b6129365f61020a01611491565b9061294261020d610bb6565b916129797f78dad2bc0b47c688ed84f3fee79abc18e6c9822db05a79ca19dff54533c7470d936129706100d2565b93849384612805565b0390a1565b612987906124fa565b565b6129b6906129b1336129ab6129a56129a05f61071f565b61022c565b9161022c565b14611115565b612beb565b565b5f7f696e206b65797370616365000000000000000000000000000000000000000000910152565b6129ec600b602092610739565b6129f5816129b8565b0190565b612a0e9060208101905f8183039101526129df565b90565b15612a1857565b612a206100d2565b62461bcd60e51b815280612a36600482016129f9565b0390fd5b90612a4d905f1990602003600802610a86565b8154169055565b905f91612a6b612a638261097b565b928354610a9f565b905555565b919290602082105f14612ac957601f8411600114612a9957612a93929350610a9f565b90555b5b565b5090612abf612ac4936001612ab6612ab08561097b565b92610984565b82019101610a10565b612a54565b612a96565b50612b008293612ada60019461097b565b612af9612ae685610984565b820192601f861680612b0b575b50610984565b0190610a10565b600202179055612a97565b612b1790888603612a3a565b5f612af3565b929091680100000000000000008211612b7d576020115f14612b6e57602081105f14612b5257612b4c91610a9f565b90555b5b565b60019160ff1916612b628461097b565b55600202019055612b4f565b60019150600202019055612b50565b610967565b908154612b8e81610825565b90818311612bb7575b818310612ba5575b50505050565b612bae93612a70565b5f808080612b9f565b612bc383838387612b1d565b612b97565b5f612bd291612b82565b565b905f03612be657612be490612bc8565b565b610954565b612c1b612c02612bfd600184906107fb565b61084f565b612c14612c0e5f61085f565b9161039a565b14156108d4565b612c23613117565b5f14612d0c57612c5d612c58612c525f612c4c81612c43600282906115b6565b50018690611e16565b01611e46565b15611e53565b612a11565b612c92612c8d612c875f612c8181612c7860026001906115b6565b50018690611e16565b01611e46565b15611e53565b612a11565b5b612ca85f612ca3600184906107fb565b612bd4565b612cc6612cbe612cb961020d610bb6565b610bd7565b61020d610c4b565b612cd161020d610bb6565b7f9df3075e519fdff3ab71e9fc679060e9d2dd37c49ccc1c1fc1996d517752220a91612d07612cfe6100d2565b92839283610fbd565b0390a1565b612d5d612d58612d525f612d4c81612d436002612d3d612d2d610208611491565b612d3760026114a1565b906114d1565b906115b6565b50018690611e16565b01611e46565b15611e53565b612a11565b612c93565b612d6b90612989565b565b612d9a90612d9533612d8f612d89612d845f61071f565b61022c565b9161022c565b14611115565b612d9c565b565b612da6815f610f90565b612dc4612dbc612db761020d610bb6565b610bd7565b61020d610c4b565b612dcf61020d610bb6565b7f476610ebc6647c15376100955efbf22ef2a0c3b923fc00b380b660c873ef20ac91612e05612dfc6100d2565b92839283610fbd565b0390a1565b612e1390612d6d565b565b612e2e612e29612e23613117565b15611e53565b612582565b612e36612e38565b565b612e51612e4c612e466130e2565b15611e53565b612628565b612e59612e5b565b565b612e9b5f612e9581612e8c6002612e86612e76610208611491565b612e8060026114a1565b906114d1565b906115b6565b50013390611e16565b01611e46565b8015612f1e575b612eab9061079b565b612eb9335f61020c01610f90565b612ed7612ecf612eca61020d610bb6565b610bd7565b61020d610c4b565b33612ee361020d610bb6565b7fbc2748cf02f7a1291525e866efc76ab3b96d32d7afcbb26c53daec617b38b47991612f19612f106100d2565b92839283610fbd565b0390a1565b50612eab33612f3d612f37612f325f61071f565b61022c565b9161022c565b149050612ea2565b612f4d612e15565b565b5f7f656d707479206f70657261746f72206461746100000000000000000000000000910152565b612f836013602092610739565b612f8c81612f4f565b0190565b612fa59060208101905f818303910152612f76565b90565b15612faf57565b612fb76100d2565b62461bcd60e51b815280612fcd60048201612f90565b0390fd5b61ffff1690565b612fe4612fe9916106fb565b612fd1565b90565b612ff69054612fd8565b90565b61300d6130086130129261116d565b6107c4565b61039a565b90565b5f7f6f70657261746f72206461746120746f6f206c61726765000000000000000000910152565b6130496017602092610739565b61305281613015565b0190565b61306b9060208101905f81830391015261303c565b90565b1561307557565b61307d6100d2565b62461bcd60e51b81528061309360048201613056565b0390fd5b6130dc906130b7816130b16130ab5f61085f565b9161039a565b11612fa8565b6130d56130cf6130ca5f61020901612fec565b612ff9565b9161039a565b111561306e565b565b5f90565b6130ea6130de565b506130f85f61020c0161071f565b61311261310c6131075f610f66565b61022c565b9161022c565b141590565b61311f6130de565b5061312e600161020a01611534565b61314061313a5f61085f565b9161039a565b141590565b613157906131516109f8565b50613af8565b90565b61316e61316961317392610340565b6107c4565b61039a565b90565b6131959061318f61318961319a9461039a565b9161039a565b9061098e565b61039a565b90565b6131c4906131a96130de565b50916131bf6131b960019261315a565b916115df565b613176565b166131d76131d15f61085f565b9161039a565b1490565b613202906131e76130de565b50916131fd6131f760019261315a565b916115df565b613176565b1661321561320f5f61085f565b9161039a565b141590565b61324461324a916132296109f8565b509261323f61323960019261315a565b916115df565b613176565b1961039a565b1690565b5f80910155565b905f03613267576132659061324e565b565b610954565b6132766040611322565b90565b9061328560ff91610c02565b9181191691161790565b61329890611e53565b90565b90565b906132b36132ae6132ba9261328f565b61329b565b8254613279565b9055565b60081b90565b906132d161ff00916132be565b9181191691161790565b6132ef6132ea6132f492610340565b6107c4565b610340565b90565b90565b9061330f61330a613316926132db565b6132f7565b82546132c4565b9055565b9061334460205f61334a9461333c828201613336848801611ede565b9061329e565b019201611eeb565b906132fa565b565b906133569161331a565b565b9190600861337891029161337260018060a01b038461098e565b9261098e565b9181191691161790565b91906133986133936133a0936107ef565b610f8d565b908354613358565b9055565b906133b96133b46133c0926132db565b6132f7565b8254613279565b9055565b91906133f96133de6133d96101018601611534565b613145565b6133f36133ee6101018501611534565b613145565b90613c8d565b9161340261146c565b5061340b61146c565b506134155f61085f565b5b806134296134238661039a565b9161039a565b11613546576134da90613449613443600188018390611758565b90611798565b61346061345a600187018490611758565b90611798565b908061347461346e8461022c565b9161022c565b1461353f57816134d49261349861349261348d5f610f66565b61022c565b9161022c565b03613524575b50806134ba6134b46134af5f610f66565b61022c565b9161022c565b036134df575b6134ce600187018490611758565b90613382565b5b611716565b613416565b61351f600161350d6134f086611732565b6135046134fb61326c565b935f8501611e58565b60208301611708565b61351a5f89018490611e16565b61334c565b6134c0565b5f61353461353992828a01611e16565b613255565b5f61349e565b50506134d5565b509261357c9250613575610101809261356f61356561010283016116fb565b61010287016133a4565b01611534565b9101611f90565b565b5f90565b600161358e910161039a565b90565b9035906001602003813603038212156135d3570180359067ffffffffffffffff82116135ce576020019160408202360383136135c957565b610905565b610901565b6108fd565b5090565b91908110156135ec576040020190565b611599565b356135fb816126ed565b90565b5f7f756e6368616e67656420736c6f74000000000000000000000000000000000000910152565b613632600e602092610739565b61363b816135fe565b0190565b6136549060208101905f818303910152613625565b90565b1561365e57565b6136666100d2565b62461bcd60e51b81528061367c6004820161363f565b0390fd5b5f7f6f70657261746f72206475706c69636174650000000000000000000000000000910152565b6136b46012602092610739565b6136bd81613680565b0190565b6136d69060208101905f8183039101526136a7565b90565b156136e057565b6136e86100d2565b62461bcd60e51b8152806136fe600482016136c1565b0390fd5b61370f6101018201611534565b9061371861357e565b5061372161146c565b5061372a61146c565b506137345f61085f565b5b8061375d61375761375261374c885f810190613591565b906135d8565b61039a565b9161039a565b101561390e576138879061388261378b5f61378561377e8983810190613591565b86916135dc565b016135f1565b61387d6137b060206137aa6137a38b5f810190613591565b88916135dc565b0161072c565b80976137c96137c360018a018690611758565b90611798565b6137e6816137df6137d98661022c565b9161022c565b1415613657565b806138016137fb6137f65f610f66565b61022c565b9161022c565b036138f3575b50878261382461381e6138195f610f66565b61022c565b9161022c565b145f1461388c57506138389150839061321a565b965b6138528161384c60018a018690611758565b90613382565b61387560019361386c61386361326c565b955f8701611e58565b60208501611708565b5f8701611e16565b61334c565b613582565b613735565b6138e16138db5f6138d56138ed96826138e6966138cf6138b66138b1600186906107fb565b61084f565b6138c86138c28561085f565b9161039a565b14156108d4565b01611e16565b01611e46565b15611e53565b6136d9565b8390613cb9565b9661383a565b5f61390361390892828c01611e16565b613255565b5f613807565b509061393060206139379461392a610102946101018701611f90565b016135f1565b91016133a4565b565b90565b61395061394b61395592613939565b6107c4565b61039a565b90565b90565b61396f61396a61397492613958565b6107c4565b610340565b90565b6139969061399061398a61399b94610340565b9161039a565b9061098e565b61039a565b90565b6139bd906139b76139b16139c29461039a565b9161039a565b90610a86565b61039a565b90565b90565b6139dc6139d76139e1926139c5565b6107c4565b61039a565b90565b90565b6139fb6139f6613a00926139e4565b6107c4565b610340565b90565b90565b613a1a613a15613a1f92613a03565b6107c4565b61039a565b90565b90565b613a39613a34613a3e92613a22565b6107c4565b610340565b90565b90565b613a58613a53613a5d92613a41565b6107c4565b61039a565b90565b90565b613a77613a72613a7c92613a60565b6107c4565b610340565b90565b90565b613a96613a91613a9b92613a7f565b6107c4565b61039a565b90565b90565b613ab5613ab0613aba92613a9e565b6107c4565b610340565b90565b90565b613ad4613acf613ad992613abd565b6107c4565b61039a565b90565b613af0613aeb613af59261149e565b6107c4565b610340565b90565b613b006109f8565b50613b40613b3082613b2a613b246fffffffffffffffffffffffffffffffff61393c565b9161039a565b11613ce4565b613b3a600761395b565b90613977565b613b81613b71613b5184849061399e565b613b6b613b6567ffffffffffffffff6139c8565b9161039a565b11613ce4565b613b7b60066139e7565b90613977565b17613bbf613baf613b9384849061399e565b613ba9613ba363ffffffff613a06565b9161039a565b11613ce4565b613bb96005613a25565b90613977565b17613bfb613beb613bd184849061399e565b613be5613bdf61ffff613a44565b9161039a565b11613ce4565b613bf56004613a63565b90613977565b17613c36613c26613c0d84849061399e565b613c20613c1a60ff613a82565b9161039a565b11613ce4565b613c306003613aa1565b90613977565b17613c71613c61613c4884849061399e565b613c5b613c55600f613ac0565b9161039a565b11613ce4565b613c6b6002613adc565b90613977565b17906d010102020202030303030303030360801b90821c1a1790565b613cb691613c996109f8565b5081613cad613ca78361039a565b9161039a565b11919091613d00565b90565b613ce090613cc56109f8565b5091613cdb613cd560019261315a565b916115df565b613176565b1790565b613cec6109f8565b50151590565b90613cfd910261039a565b90565b613d1a613d209293613d106109f8565b5080941891613ce4565b90613cf2565b189056fea26469706673582212208b10234b08244c919ee8fc151ed15483fad0d05bc89d37a4de3b8fc6879959b364736f6c634300081c0033","sourceMap":"1030:10844:22:-:0;;;;;;;;;-1:-1:-1;1030:10844:22;:::i;:::-;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;;;:::o;:::-;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;:::i;:::-;;;;:::o;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;:::o;:::-;;;;:::o;:::-;;;;;;;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;:::o;:::-;;;;;;;:::o;:::-;;;;;;;;;;:::o;:::-;;;;;;;;:::o;:::-;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;;;;;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;;;:::i;:::-;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;:::i;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;:::o;:::-;;;;;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;:::o;:::-;;;:::o;:::-;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;:::i;:::-;;;;;:::i;:::-;;;:::o;:::-;;;:::o;:::-;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;;;;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;:::o;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;:::i;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;:::o;:::-;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;:::i;:::-;;;;:::o;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;;;;;;;;;:::o;:::-;;;;;;;;;;:::i;:::-;;;;:::i;:::-;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;:::o;7520:421::-;7607:10;:19;;7621:5;;;:::i;:::-;7607:19;:::i;:::-;;;:::i;:::-;;:50;;;;7520:421;7599:75;;;:::i;:::-;7684:68;7692:34;:27;:12;7705:13;;:8;:13;;:::i;:::-;7692:27;;:::i;:::-;:34;:::i;:::-;:39;;7730:1;7692:39;:::i;:::-;;;:::i;:::-;;;7684:68;:::i;:::-;7787:20;;:13;:8;:13;;;;;:::i;:::-;:20;;:::i;:::-;;:::i;:::-;7819:43;7849:13;:8;:13;;;;;:::i;:::-;7819:12;:27;:12;7832:13;;:8;:13;;:::i;:::-;7819:27;;:::i;:::-;:43;:::i;:::-;7872:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;7926:7;;;:::i;:::-;7896:38;;;;;:::i;:::-;;;;;;:::i;:::-;;;;7520:421::o;7607:50::-;7630:10;7599:75;7630:10;:27;;7644:13;;:8;:13;;:::i;:::-;7630:27;:::i;:::-;;;:::i;:::-;;7607:50;;;;1030:10844;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;2527:106;2563:52;2571:25;;:::i;:::-;2563:52;:::i;:::-;2625:1;;:::i;:::-;2527:106::o;1030:10844::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;:::o;6892:263::-;6963:10;:19;;6977:5;;;:::i;:::-;6963:19;:::i;:::-;;;:::i;:::-;;:53;;;;6892:263;6955:78;;;:::i;:::-;7044:29;7063:10;7071:1;7063:10;:::i;:::-;7044:16;:11;:16;:29;:::i;:::-;7084:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;7128:10;7140:7;;;:::i;:::-;7108:40;;;;;:::i;:::-;;;;;;:::i;:::-;;;;6892:263::o;6963:53::-;6986:11;6955:78;6986:16;;:11;:16;;:::i;:::-;:30;;7006:10;6986:30;:::i;:::-;;;:::i;:::-;;6963:53;;;;6892:263;;;:::i;:::-;:::o;1030:10844::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;2206:94;2292:1;2206:94;2237:45;2245:10;:19;;2259:5;;;:::i;:::-;2245:19;:::i;:::-;;;:::i;:::-;;2237:45;:::i;:::-;2292:1;:::i;:::-;2206:94::o;1030:10844::-;;;;:::o;:::-;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;:::i;:::-;:::o;:::-;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;:::o;8600:184::-;8684:22;8695:11;8684:22;;:::i;:::-;8716:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;8769:7;;;:::i;:::-;8740:37;;;;;:::i;:::-;;;;;;:::i;:::-;;;;8600:184::o;:::-;;;;:::i;:::-;:::o;1030:10844::-;;;;;:::i;:::-;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;:::i;:::-;;;;:::i;:::-;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;:::o;:::-;;;:::o;:::-;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::o;:::-;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;:::o;:::-;;;:::o;:::-;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::o;:::-;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;:::o;:::-;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::o;:::-;;;:::i;:::-;;:::o;:::-;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::o;:::-;;;:::i;:::-;;:::o;:::-;;;:::o;:::-;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;;;:::o;:::-;;:::o;:::-;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;:::o;:::-;;:::i;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;:::i;:::-;;:::i;:::-;;;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;:::o;:::-;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::o;:::-;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;:::o;:::-;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;:::o;:::-;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;:::i;:::-;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;:::o;:::-;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;:::i;:::-;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;:::o;8966:2441::-;9006:18;;:::i;:::-;9036:30;;;:::i;:::-;9077:19;;:::i;:::-;9115:12;;;:::i;:::-;9137:22;;;:::i;:::-;9182:23;;;:::i;:::-;9178:1406;;;;9221:39;9248:12;;:9;:12;;:::i;:::-;9221:24;:21;:11;:21;;:24;:39;:::i;:::-;9274:81;9322:33;;:9;:33;;:::i;:::-;9274:45;:11;;:21;;:45;:81;:::i;:::-;9370:39;9384:25;9385:19;:15;;;:::i;:::-;:19;9403:1;9385:19;:::i;:::-;;;:::i;:::-;9384:25;9408:1;9384:25;:::i;:::-;;;:::i;:::-;9370:39;:::i;:::-;9454:15;9423:50;9454:19;:15;;;:::i;:::-;:19;9472:1;9454:19;:::i;:::-;;;:::i;:::-;9423:50;:::i;:::-;9505:9;:59;:48;;:31;:9;9515:20;9505:31;;:::i;:::-;;:48;;:::i;:::-;:59;:::i;:::-;9639:14;9620:38;9639:18;:14;:18;9656:1;9639:18;:::i;:::-;;;:::i;:::-;9620:38;:::i;:::-;9578:39;:29;:11;:29;;:39;:80;9672:103;9724:51;;:31;:9;9734:20;9724:31;;:::i;:::-;;:51;;:::i;:::-;9672:49;:29;:11;:29;;:49;:103;:::i;:::-;9807:13;9819:1;9807:13;:::i;:::-;9843:3;9822:1;:19;;9827:14;9822:19;:::i;:::-;;;:::i;:::-;;;;9843:3;9870:9;:62;:48;;:31;:9;9880:20;9870:31;;:::i;:::-;;:48;;:::i;:::-;9923:8;9929:1;9923:8;:::i;:::-;9870:62;;:::i;:::-;9866:117;;10020:44;;:41;:31;:9;10030:20;10020:31;;:::i;:::-;;:41;10062:1;10020:44;;:::i;:::-;;;:::i;:::-;10082:54;10132:4;10082:47;:42;:11;:29;:11;:29;;:39;;10122:1;10082:42;;:::i;:::-;;:47;:54;:::i;:::-;10285:53;:39;;:22;:9;10295:11;10285:22;;:::i;:::-;;:39;;:::i;:::-;10329:8;10335:1;10329:8;:::i;:::-;10285:53;;:::i;:::-;:100;;;;9843:3;10281:215;;9843:3;;9807:13;9843:3;:::i;:::-;9807:13;;10281:215;10459:18;:12;;:18;:::i;:::-;10409:68;:47;:42;:39;:29;:11;:29;;:39;;10449:1;10409:42;;:::i;:::-;;:47;:68;;:::i;:::-;;;10281:215;;;10285:100;10342:9;:35;;:32;:22;:9;10352:11;10342:22;;:::i;:::-;;:32;10375:1;10342:35;;:::i;:::-;;;:::i;:::-;:43;;10381:4;10342:43;:::i;:::-;;;:::i;:::-;;;10285:100;;9866:117;9956:8;;9822:19;;;;;9178:1406;10611:50;:39;;:22;:9;10621:11;10611:22;;:::i;:::-;;:39;;:::i;:::-;:50;:::i;:::-;10723:14;10704:38;10723:18;:14;:18;10740:1;10723:18;:::i;:::-;;;:::i;:::-;10704:38;:::i;:::-;10671:30;:11;;:20;;:30;:71;10753:85;10796:42;;:22;:9;10806:11;10796:22;;:::i;:::-;;:42;;:::i;:::-;10753:40;:20;:11;:20;;:40;:85;:::i;:::-;10854:13;10866:1;10854:13;:::i;:::-;10890:3;10869:1;:19;;10874:14;10869:19;:::i;:::-;;;:::i;:::-;;;;10890:3;10913:9;:53;:39;;:22;:9;10923:11;10913:22;;:::i;:::-;;:39;;:::i;:::-;10957:8;10963:1;10957:8;:::i;:::-;10913:53;;:::i;:::-;10909:100;;11179:18;11030:35;;:32;:22;:9;11040:11;11030:22;;:::i;:::-;;:32;11063:1;11030:35;;:::i;:::-;;;:::i;:::-;11079:45;11120:4;11079:38;:33;:11;;;:20;;:30;;11110:1;11079:33;;:::i;:::-;;:38;:45;:::i;:::-;11179:12;:18;:::i;:::-;11138:59;:38;:33;:30;:11;;:20;;:30;;11169:1;11138:33;;:::i;:::-;;:38;:59;;:::i;:::-;;;10854:13;10890:3;:::i;:::-;10854:13;;10909:100;10986:8;;10869:19;;;;;11218:45;11248:15;;;:::i;:::-;11218:27;:11;:27;:45;:::i;:::-;11273:47;11304:16;;:11;:16;;:::i;:::-;11273:28;:23;:11;:23;;:28;:47;:::i;:::-;11338:29;11360:7;;;:::i;:::-;11338:19;:11;:19;:29;:::i;:::-;11382:18;:::o;9178:1406::-;10540:33;10554:19;:15;;;:::i;:::-;:19;10572:1;10554:19;:::i;:::-;;;:::i;:::-;10540:33;:::i;:::-;9178:1406;;;1030:10844;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;2306:100;2398:1;2306:100;2340:48;2348:23;;:::i;:::-;2340:48;:::i;:::-;2398:1;:::i;:::-;2306:100::o;1030:10844::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;:::i;:::-;:::o;5603:742::-;5673:49;5603:742;5681:18;;5687:12;;:9;:12;;:::i;:::-;5681:18;:::i;:::-;;;:::i;:::-;;5673:49;:::i;:::-;5988:93;6024:57;5733:88;5763:58;:46;:30;:9;5773:19;:15;;;:::i;:::-;:19;5791:1;5773:19;:::i;:::-;;;:::i;:::-;5763:30;;:::i;:::-;;:46;5810:10;5763:58;;:::i;:::-;5733:88;:::i;:::-;5831:48;5839:19;;:11;:19;;:::i;:::-;5831:48;:::i;:::-;5897:80;5905:56;:33;;:9;:33;;:::i;:::-;5943:17;;:11;:17;;:::i;:::-;5905:56;;:::i;:::-;5897:80;:::i;:::-;6063:17;;6024:33;;:9;:33;;:::i;:::-;6063:11;:17;;:::i;:::-;6024:57;;:::i;:::-;5988:33;:9;:33;:93;:::i;:::-;6096:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;6119:33;;:9;:33;;:::i;:::-;:38;;6156:1;6119:38;:::i;:::-;;;:::i;:::-;;6115:224;;;;6197:12;;:9;:12;;:::i;:::-;6211:10;6223:7;;;:::i;:::-;6178:53;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;6115:224;5603:742::o;6115:224::-;6294:12;;:9;:12;;:::i;:::-;6308:10;6320:7;;;:::i;:::-;6267:61;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;6115:224;;5603:742;;;;:::i;:::-;:::o;2206:94::-;2292:1;2206:94;2237:45;2245:10;:19;;2259:5;;;:::i;:::-;2245:19;:::i;:::-;;;:::i;:::-;;2237:45;:::i;:::-;2292:1;:::i;:::-;2206:94::o;1030:10844::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;7161:353;7250:75;7258:34;:27;:12;7271:13;;:8;:13;;:::i;:::-;7258:27;;:::i;:::-;:34;:::i;:::-;:39;;7296:1;7258:39;:::i;:::-;;;:::i;:::-;;7250:75;:::i;:::-;7360:20;;:13;:8;:13;;;;;:::i;:::-;:20;;:::i;:::-;;:::i;:::-;7392:43;7422:13;:8;:13;;;;;:::i;:::-;7392:12;:27;:12;7405:13;;:8;:13;;:::i;:::-;7392:27;;:::i;:::-;:43;:::i;:::-;7445:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;7499:7;;;:::i;:::-;7469:38;;;;;:::i;:::-;;;;;;:::i;:::-;;;;7161:353::o;:::-;;;;:::i;:::-;:::o;2206:94::-;2237:45;2245:10;:19;;2259:5;;;:::i;:::-;2245:19;:::i;:::-;;;:::i;:::-;;2237:45;:::i;:::-;2292:1;;:::i;:::-;2206:94::o;2306:100::-;2340:48;2348:23;;:::i;:::-;2340:48;:::i;:::-;2398:1;;:::i;:::-;2306:100::o;1030:10844::-;;;;:::i;:::-;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;:::o;6351:213::-;6419:17;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;6446:37;;6482:1;6446:37;:::i;:::-;:33;:9;:33;:37;:::i;:::-;6494:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;6535:12;;:9;:12;;:::i;:::-;6549:7;;;:::i;:::-;6518:39;;;;;:::i;:::-;;;;;;:::i;:::-;;;;6351:213::o;:::-;;;:::i;:::-;:::o;2206:94::-;2292:1;2206:94;2237:45;2245:10;:19;;2259:5;;;:::i;:::-;2245:19;:::i;:::-;;;:::i;:::-;;2237:45;:::i;:::-;2292:1;:::i;:::-;2206:94::o;1030:10844::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;2412:109;2513:1;2412:109;2445:58;2453:24;2454:23;;:::i;:::-;2453:24;;:::i;:::-;2445:58;:::i;:::-;2513:1;:::i;:::-;2412:109::o;1030:10844::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;2639:115;2746:1;2639:115;2674:62;2682:26;2683:25;;:::i;:::-;2682:26;;:::i;:::-;2674:62;:::i;:::-;2746:1;:::i;:::-;2639:115::o;1030:10844::-;;;;:::i;:::-;;;;;;;;;:::o;:::-;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;;;;;;:::o;:::-;;:::o;:::-;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;;;;:::i;:::-;;;:::o;:::-;;;:::o;:::-;;;;:::o;:::-;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;:::i;:::-;:::o;2760:632::-;2868:14;:12;:9;:12;:14;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;3241:64;3277:28;;2897:58;2925:30;:9;2935:19;:15;;;:::i;:::-;:19;2953:1;2935:19;:::i;:::-;;;:::i;:::-;2925:30;;:::i;:::-;;2897:58;:::i;:::-;2965:17;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;3170:11;2992:61;3023:30;:9;3033:19;:15;;;:::i;:::-;:19;3051:1;3033:19;:::i;:::-;;;:::i;:::-;3023:30;;:::i;:::-;;2992:61;:::i;:::-;3160:8;3170:11;;;:::i;:::-;3225:4;3212:11;3225:4;;;:::i;:::-;3277:28;;:::i;:::-;3241:33;:9;:33;:64;:::i;:::-;3316:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;3357:12;;:9;:12;;:::i;:::-;3371:4;3377:7;;;:::i;:::-;3340:45;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;2760:632::o;:::-;;;;:::i;:::-;:::o;2206:94::-;2292:1;2206:94;2237:45;2245:10;:19;;2259:5;;;:::i;:::-;2245:19;:::i;:::-;;;:::i;:::-;;2237:45;:::i;:::-;2292:1;:::i;:::-;2206:94::o;1030:10844::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;:::o;:::-;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;:::o;:::-;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;-1:-1:-1;1030:10844:22;;;;;;;;;;;;;;:::i;:::-;;;;;:::o;:::-;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;:::o;:::-;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;:::i;:::-;:::o;:::-;;:::i;7947:647::-;8029:70;8037:36;:29;:12;8050:15;8037:29;;:::i;:::-;:36;:::i;:::-;:41;;8077:1;8037:41;:::i;:::-;;;:::i;:::-;;;8029:70;:::i;:::-;8114:23;;:::i;:::-;8110:351;;;;8153:78;8161:54;8162:53;;:45;:9;:12;:9;8172:1;8162:12;;:::i;:::-;;:28;8191:15;8162:45;;:::i;:::-;:53;;:::i;:::-;8161:54;;:::i;:::-;8153:78;:::i;:::-;8245;8253:54;8254:53;;:45;:9;:12;:9;8264:1;8254:12;;:::i;:::-;;:28;8283:15;8254:45;;:::i;:::-;:53;;:::i;:::-;8253:54;;:::i;:::-;8245:78;:::i;:::-;8110:351;8471:37;;8478:29;:12;8491:15;8478:29;;:::i;:::-;8471:37;:::i;:::-;8518:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;8579:7;;;:::i;:::-;8542:45;;;;;:::i;:::-;;;;;;:::i;:::-;;;;7947:647::o;8110:351::-;8354:96;8362:72;8363:71;;:63;:9;:30;:9;8373:19;:15;;;:::i;:::-;:19;8391:1;8373:19;:::i;:::-;;;:::i;:::-;8363:30;;:::i;:::-;;:46;8410:15;8363:63;;:::i;:::-;:71;;:::i;:::-;8362:72;;:::i;:::-;8354:96;:::i;:::-;8110:351;;7947:647;;;;:::i;:::-;:::o;2206:94::-;2292:1;2206:94;2237:45;2245:10;:19;;2259:5;;;:::i;:::-;2245:19;:::i;:::-;;;:::i;:::-;;2237:45;:::i;:::-;2292:1;:::i;:::-;2206:94::o;8790:170::-;8864:16;8872:8;8864:16;;:::i;:::-;8890:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;8945:7;;;:::i;:::-;8914:39;;;;;:::i;:::-;;;;;;:::i;:::-;;;;8790:170::o;:::-;;;;:::i;:::-;:::o;2412:109::-;2445:58;2453:24;2454:23;;:::i;:::-;2453:24;;:::i;:::-;2445:58;:::i;:::-;2513:1;;:::i;:::-;2412:109::o;2639:115::-;2674:62;2682:26;2683:25;;:::i;:::-;2682:26;;:::i;:::-;2674:62;:::i;:::-;2746:1;;:::i;:::-;2639:115::o;6570:316::-;6651:66;;:58;:9;:30;:9;6661:19;:15;;;:::i;:::-;:19;6679:1;6661:19;:::i;:::-;;;:::i;:::-;6651:30;;:::i;:::-;;:46;6698:10;6651:58;;:::i;:::-;:66;;:::i;:::-;:89;;;;6570:316;6643:114;;;:::i;:::-;6776:29;6795:10;6776:16;:11;:16;:29;:::i;:::-;6816:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;6859:10;6871:7;;;:::i;:::-;6840:39;;;;;:::i;:::-;;;;;;:::i;:::-;;;;6570:316::o;6651:89::-;6721:10;6643:114;6721:10;:19;;6735:5;;;:::i;:::-;6721:19;:::i;:::-;;;:::i;:::-;;6651:89;;;;6570:316;;;:::i;:::-;:::o;1030:10844::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;11413:205;11537:74;11413:205;11486:41;11494:5;:9;;11502:1;11494:9;:::i;:::-;;;:::i;:::-;;11486:41;:::i;:::-;11545:38;;11554:29;;:8;:29;;:::i;:::-;11545:38;:::i;:::-;;;:::i;:::-;;;11537:74;:::i;:::-;11413:205::o;1030:10844::-;;;:::o;11754:118::-;11812:4;;:::i;:::-;11835:11;:16;;:11;:16;;:::i;:::-;:30;;11855:10;11863:1;11855:10;:::i;:::-;11835:30;:::i;:::-;;;:::i;:::-;;;11828:37;:::o;11624:124::-;11680:4;;:::i;:::-;11703:9;:33;;:9;:33;;:::i;:::-;:38;;11740:1;11703:38;:::i;:::-;;;:::i;:::-;;;11696:45;:::o;13610:113::-;13694:18;13610:113;13668:7;;:::i;:::-;13704;13694:18;:::i;:::-;13687:25;:::o;1030:10844::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;:::i;:::-;;:::o;13293:127::-;13391:15;13293:127;13355:4;;:::i;:::-;13380:7;13391:1;:15;13396:10;13391:1;13404;13396:10;:::i;:::-;13391:15;;:::i;:::-;;:::i;:::-;13380:27;13379:34;;13412:1;13379:34;:::i;:::-;;;:::i;:::-;;13372:41;:::o;13160:127::-;13258:15;13160:127;13222:4;;:::i;:::-;13247:7;13258:1;:15;13263:10;13258:1;13271;13263:10;:::i;:::-;13258:15;;:::i;:::-;;:::i;:::-;13247:27;13246:34;;13279:1;13246:34;:::i;:::-;;;:::i;:::-;;;13239:41;:::o;13029:125::-;13131:15;13129:18;13029:125;13092:7;;:::i;:::-;13119;13131:1;:15;13136:10;13131:1;13144;13136:10;:::i;:::-;13131:15;;:::i;:::-;;:::i;:::-;13129:18;;:::i;:::-;13119:28;13112:35;:::o;1030:10844::-;;;;;;:::o;:::-;;;;;;;;;:::i;:::-;:::o;:::-;;:::i;:::-;;;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;:::o;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;;;:::i;:::-;;:::i;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;3398:965::-;;;3597:74;3606:31;:20;;:3;:20;;:::i;:::-;:31;:::i;:::-;3639;:20;;:3;:20;;:::i;:::-;:31;:::i;:::-;3597:74;;:::i;:::-;3681:15;;;:::i;:::-;3706;;;:::i;:::-;3748:1;3736:13;3748:1;3736:13;:::i;:::-;3769:3;3751:1;:16;;3756:11;3751:16;:::i;:::-;;;:::i;:::-;;;;3769:3;3798;:16;;:13;:3;:13;3812:1;3798:16;;:::i;:::-;;;:::i;:::-;3838;;:13;:3;:13;3852:1;3838:16;;:::i;:::-;;;:::i;:::-;3873:7;;:18;;3884:7;3873:18;:::i;:::-;;;:::i;:::-;;3869:65;;3952:7;4207:26;3952:7;:21;;3963:10;3971:1;3963:10;:::i;:::-;3952:21;:::i;:::-;;;:::i;:::-;;3948:96;;3769:3;4062:7;;:21;;4073:10;4081:1;4073:10;:::i;:::-;4062:21;:::i;:::-;;;:::i;:::-;;4058:135;;3769:3;4207:16;:13;:3;:13;4221:1;4207:16;;:::i;:::-;:26;;:::i;:::-;3736:13;3769:3;:::i;:::-;3736:13;;4058:135;4103:75;4154:4;4134:44;4167:8;4173:1;4167:8;:::i;:::-;4134:44;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::i;:::-;4103:28;:19;:3;:19;4123:7;4103:28;;:::i;:::-;:75;:::i;:::-;4058:135;;3948:96;3993:36;4000:28;3993:36;4000:3;;;:19;:28;:::i;:::-;3993:36;:::i;:::-;3948:96;;;3869:65;3911:8;;;;3751:16;;;4313:43;3751:16;;4336:20;;3751:16;;4254:49;4280:23;;:3;:23;;:::i;:::-;4254;:3;:23;:49;:::i;:::-;4336:20;;:::i;:::-;4313:3;:20;:43;:::i;:::-;3398:965::o;1030:10844::-;;;:::o;:::-;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;4369:1228;4499:25;;:8;:25;;:::i;:::-;4535:9;;;:::i;:::-;4554:12;;;:::i;:::-;4576:15;;;:::i;:::-;4618:1;4606:13;4618:1;4606:13;:::i;:::-;4644:3;4621:1;:21;;4625:17;:10;:4;:10;;;;;:::i;:::-;:17;;:::i;:::-;4621:21;:::i;:::-;;;:::i;:::-;;;;;4644:3;4669:4;5385:75;4669:17;;:13;:10;:4;:10;;;;;:::i;:::-;4680:1;4669:13;;:::i;:::-;:17;;:::i;:::-;5385:33;4710:29;;:13;:10;:4;:10;;;;;:::i;:::-;4721:1;4710:13;;:::i;:::-;:29;;:::i;:::-;4760:8;;:23;;:18;:8;:18;4779:3;4760:23;;:::i;:::-;;;:::i;:::-;4798:42;4806:4;:15;;4814:7;4806:15;:::i;:::-;;;:::i;:::-;;;4798:42;:::i;:::-;4859:4;:18;;4867:10;4875:1;4867:10;:::i;:::-;4859:18;:::i;:::-;;;:::i;:::-;;4855:95;;4644:3;4968:7;;;:21;;4979:10;4987:1;4979:10;:::i;:::-;4968:21;:::i;:::-;;;:::i;:::-;;4964:360;;;;5028:16;:26;:16;;5050:3;5028:26;;:::i;:::-;4964:360;;5338:33;5364:7;5338:23;:18;:8;:18;5357:3;5338:23;;:::i;:::-;:33;;:::i;:::-;5421:39;5441:4;5454:3;5421:39;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::i;:::-;5385:24;:8;:24;:33;:::i;:::-;:75;:::i;:::-;4644:3;:::i;:::-;4606:13;;4964:360;5181:42;5182:41;;:33;5283:26;5101:12;;5173:73;5101:12;5093:62;5101:28;:21;:12;5114:7;5101:21;;:::i;:::-;:28;:::i;:::-;:33;;5133:1;5101:33;:::i;:::-;;;:::i;:::-;;;5093:62;:::i;:::-;5182:24;:33;:::i;:::-;:41;;:::i;:::-;5181:42;;:::i;:::-;5173:73;:::i;:::-;5305:3;5283:26;;:::i;:::-;4964:360;;;4855:95;4897:38;4904:30;4897:38;4904:8;;;:24;:30;:::i;:::-;4897:38;:::i;:::-;4855:95;;;4621:21;;;5566:24;;5535:55;4621:21;5481:44;5535:28;4621:21;5481:25;:8;:25;:44;:::i;:::-;5566:24;;:::i;:::-;5535:8;:28;:55;:::i;:::-;4369:1228::o;1030:10844::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;26222:2393:20:-;26270:9;;:::i;:::-;26383:1;26367:60;:55;26383:1;:38;;26387:34;26383:38;:::i;:::-;;;:::i;:::-;;26367:55;:::i;:::-;:60;26426:1;26367:60;:::i;:::-;;;:::i;:::-;26508:51;:46;26525:6;:1;26530;26525:6;;:::i;:::-;26524:29;;26535:18;26524:29;:::i;:::-;;;:::i;:::-;;26508:46;:::i;:::-;:51;26558:1;26508:51;:::i;:::-;;;:::i;:::-;26503:56;26639:43;:38;26656:6;:1;26661;26656:6;;:::i;:::-;26655:21;;26666:10;26655:21;:::i;:::-;;;:::i;:::-;;26639:38;:::i;:::-;:43;26681:1;26639:43;:::i;:::-;;;:::i;:::-;26634:48;26762:39;:34;26779:6;:1;26784;26779:6;;:::i;:::-;26778:17;;26789:6;26778:17;:::i;:::-;;;:::i;:::-;;26762:34;:::i;:::-;:39;26800:1;26762:39;:::i;:::-;;;:::i;:::-;26757:44;26879:37;:32;26896:6;:1;26901;26896:6;;:::i;:::-;26895:15;;26906:4;26895:15;:::i;:::-;;;:::i;:::-;;26879:32;:::i;:::-;:37;26915:1;26879:37;:::i;:::-;;;:::i;:::-;26874:42;26993:36;:31;27010:6;:1;27015;27010:6;;:::i;:::-;27009:14;;27020:3;27009:14;:::i;:::-;;;:::i;:::-;;26993:31;:::i;:::-;:36;27028:1;26993:36;:::i;:::-;;;:::i;:::-;26988:41;28465:144;;;;;;;;;26222:2393;:::o;5435:111::-;5519:20;5435:111;5493:7;;:::i;:::-;5527:1;;:5;;5531:1;5527:5;:::i;:::-;;;:::i;:::-;;5534:1;5537;5519:20;;:::i;:::-;5512:27;:::o;12901:122:22:-;13001:15;12901:122;12964:7;;:::i;:::-;12991;13001:1;:15;13006:10;13001:1;13014;13006:10;:::i;:::-;13001:15;;:::i;:::-;;:::i;:::-;12991:25;12984:32;:::o;34795:145:21:-;34842:9;;:::i;:::-;34863:71;;;34795:145;:::o;1030:10844:22:-;;;;;;:::i;:::-;;:::o;5071:294:20:-;5321:26;5311:36;5071:294;;5149:7;;:::i;:::-;5306:1;;5312;:5;5337:9;5321:26;:::i;:::-;5311:36;;:::i;:::-;5306:42;5299:49;:::o","linkReferences":{}},"methodIdentifiers":{"abortMigration()":"c130809a","completeMigration(uint64)":"9d44e717","createNodeOperator((address,bytes))":"b55a4142","deleteNodeOperator(address)":"db1b0fd7","finishMaintenance()":"53bfb584","getView()":"75418b9d","startMaintenance()":"f5f2d9f1","startMigration(((uint8,address)[],uint8))":"cdbfc62d","transferOwnership(address)":"f2fde38b","updateNodeOperator((address,bytes))":"26322217","updateSettings((uint16))":"65706f9c"},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.28+commit.7893614a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"components\":[{\"internalType\":\"uint16\",\"name\":\"maxOperatorDataBytes\",\"type\":\"uint16\"}],\"internalType\":\"struct Settings\",\"name\":\"initialSettings\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"struct NodeOperator[]\",\"name\":\"initialOperators\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"operatorAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"MaintenanceFinished\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"operatorAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"MaintenanceStarted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"MigrationAborted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"operatorAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"MigrationCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"operatorAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"MigrationDataPullCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"uint8\",\"name\":\"idx\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"operatorAddress\",\"type\":\"address\"}],\"internalType\":\"struct KeyspaceSlot[]\",\"name\":\"slots\",\"type\":\"tuple[]\"},{\"internalType\":\"uint8\",\"name\":\"replicationStrategy\",\"type\":\"uint8\"}],\"indexed\":false,\"internalType\":\"struct MigrationPlan\",\"name\":\"plan\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"MigrationStarted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"struct NodeOperator\",\"name\":\"operator\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"NodeOperatorCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"operatorAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"NodeOperatorDeleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"struct NodeOperator\",\"name\":\"operator\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"NodeOperatorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"cluserVersion\",\"type\":\"uint128\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint16\",\"name\":\"maxOperatorDataBytes\",\"type\":\"uint16\"}],\"indexed\":false,\"internalType\":\"struct Settings\",\"name\":\"newSettings\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"SettingsUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"abortMigration\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"}],\"name\":\"completeMigration\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"struct NodeOperator\",\"name\":\"operator\",\"type\":\"tuple\"}],\"name\":\"createNodeOperator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operatorAddress\",\"type\":\"address\"}],\"name\":\"deleteNodeOperator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"finishMaintenance\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getView\",\"outputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"struct NodeOperator[]\",\"name\":\"operators\",\"type\":\"tuple[]\"},{\"internalType\":\"uint8\",\"name\":\"replicationStrategy\",\"type\":\"uint8\"}],\"internalType\":\"struct KeyspaceView\",\"name\":\"keyspace\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"pullingOperatorsBitmask\",\"type\":\"uint256\"}],\"internalType\":\"struct Migration\",\"name\":\"migration\",\"type\":\"tuple\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"struct NodeOperator[]\",\"name\":\"operators\",\"type\":\"tuple[]\"},{\"internalType\":\"uint8\",\"name\":\"replicationStrategy\",\"type\":\"uint8\"}],\"internalType\":\"struct KeyspaceView\",\"name\":\"migrationKeyspace\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"slot\",\"type\":\"address\"}],\"internalType\":\"struct Maintenance\",\"name\":\"maintenance\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"keyspaceVersion\",\"type\":\"uint64\"},{\"internalType\":\"uint128\",\"name\":\"version\",\"type\":\"uint128\"}],\"internalType\":\"struct ClusterView\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startMaintenance\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"uint8\",\"name\":\"idx\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"operatorAddress\",\"type\":\"address\"}],\"internalType\":\"struct KeyspaceSlot[]\",\"name\":\"slots\",\"type\":\"tuple[]\"},{\"internalType\":\"uint8\",\"name\":\"replicationStrategy\",\"type\":\"uint8\"}],\"internalType\":\"struct MigrationPlan\",\"name\":\"plan\",\"type\":\"tuple\"}],\"name\":\"startMigration\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"struct NodeOperator\",\"name\":\"operator\",\"type\":\"tuple\"}],\"name\":\"updateNodeOperator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint16\",\"name\":\"maxOperatorDataBytes\",\"type\":\"uint16\"}],\"internalType\":\"struct Settings\",\"name\":\"newSettings\",\"type\":\"tuple\"}],\"name\":\"updateSettings\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/Cluster.sol\":\"Cluster\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[\":@openzeppelin/contracts/=dependencies/openzeppelin-contracts/contracts/\",\":erc4626-tests/=dependencies/openzeppelin-contracts/lib/erc4626-tests/\",\":forge-std-1.9.7/=dependencies/forge-std-1.9.7/src/\",\":forge-std/=dependencies/openzeppelin-contracts/lib/forge-std/src/\",\":halmos-cheatcodes/=dependencies/openzeppelin-contracts/lib/halmos-cheatcodes/src/\",\":openzeppelin-contracts/=dependencies/openzeppelin-contracts/\"],\"viaIR\":true},\"sources\":{\"dependencies/openzeppelin-contracts/contracts/utils/Panic.sol\":{\"keccak256\":\"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a\",\"dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG\"]},\"dependencies/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0x1225214420c83ebcca88f2ae2b50f053aaa7df7bd684c3e878d334627f2edfc6\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6c5fab4970634f9ab9a620983dc1c8a30153981a0b1a521666e269d0a11399d3\",\"dweb:/ipfs/QmVRnBC575MESGkEHndjujtR7qub2FzU9RWy9eKLp4hPZB\"]},\"dependencies/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\":{\"keccak256\":\"0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b1d578337048cad08c1c03041cca5978eff5428aa130c781b271ad9e5566e1f8\",\"dweb:/ipfs/QmPFKL2r9CBsMwmUqqdcFPfHZB2qcs9g1HDrPxzWSxomvy\"]},\"src/Cluster.sol\":{\"keccak256\":\"0xfd4a17d0b8327f8248d37ae5b16b7076095a7b4f6ed1d75f859446b33c086a88\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://91b3747c61898f3f65d064a173e6795fede772a88d3848870bf73266498dc71f\",\"dweb:/ipfs/QmStHTacgfN8y7nzkFrju9GGVV7kv5WD9ez2yeTP8YgcAe\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.28+commit.7893614a"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"struct Settings","name":"initialSettings","type":"tuple","components":[{"internalType":"uint16","name":"maxOperatorDataBytes","type":"uint16"}]},{"internalType":"struct NodeOperator[]","name":"initialOperators","type":"tuple[]","components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}]}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"operatorAddress","type":"address","indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"MaintenanceFinished","anonymous":false},{"inputs":[{"internalType":"address","name":"operatorAddress","type":"address","indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"MaintenanceStarted","anonymous":false},{"inputs":[{"internalType":"uint64","name":"id","type":"uint64","indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"MigrationAborted","anonymous":false},{"inputs":[{"internalType":"uint64","name":"id","type":"uint64","indexed":false},{"internalType":"address","name":"operatorAddress","type":"address","indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"MigrationCompleted","anonymous":false},{"inputs":[{"internalType":"uint64","name":"id","type":"uint64","indexed":false},{"internalType":"address","name":"operatorAddress","type":"address","indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"MigrationDataPullCompleted","anonymous":false},{"inputs":[{"internalType":"uint64","name":"id","type":"uint64","indexed":false},{"internalType":"struct MigrationPlan","name":"plan","type":"tuple","components":[{"internalType":"struct KeyspaceSlot[]","name":"slots","type":"tuple[]","components":[{"internalType":"uint8","name":"idx","type":"uint8"},{"internalType":"address","name":"operatorAddress","type":"address"}]},{"internalType":"uint8","name":"replicationStrategy","type":"uint8"}],"indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"MigrationStarted","anonymous":false},{"inputs":[{"internalType":"struct NodeOperator","name":"operator","type":"tuple","components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"NodeOperatorCreated","anonymous":false},{"inputs":[{"internalType":"address","name":"operatorAddress","type":"address","indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"NodeOperatorDeleted","anonymous":false},{"inputs":[{"internalType":"struct NodeOperator","name":"operator","type":"tuple","components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"NodeOperatorUpdated","anonymous":false},{"inputs":[{"internalType":"address","name":"newOwner","type":"address","indexed":false},{"internalType":"uint128","name":"cluserVersion","type":"uint128","indexed":false}],"type":"event","name":"OwnershipTransferred","anonymous":false},{"inputs":[{"internalType":"struct Settings","name":"newSettings","type":"tuple","components":[{"internalType":"uint16","name":"maxOperatorDataBytes","type":"uint16"}],"indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"SettingsUpdated","anonymous":false},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"abortMigration"},{"inputs":[{"internalType":"uint64","name":"id","type":"uint64"}],"stateMutability":"nonpayable","type":"function","name":"completeMigration"},{"inputs":[{"internalType":"struct NodeOperator","name":"operator","type":"tuple","components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}]}],"stateMutability":"nonpayable","type":"function","name":"createNodeOperator"},{"inputs":[{"internalType":"address","name":"operatorAddress","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"deleteNodeOperator"},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"finishMaintenance"},{"inputs":[],"stateMutability":"view","type":"function","name":"getView","outputs":[{"internalType":"struct ClusterView","name":"","type":"tuple","components":[{"internalType":"struct KeyspaceView","name":"keyspace","type":"tuple","components":[{"internalType":"struct NodeOperator[]","name":"operators","type":"tuple[]","components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}]},{"internalType":"uint8","name":"replicationStrategy","type":"uint8"}]},{"internalType":"struct Migration","name":"migration","type":"tuple","components":[{"internalType":"uint64","name":"id","type":"uint64"},{"internalType":"uint256","name":"pullingOperatorsBitmask","type":"uint256"}]},{"internalType":"struct KeyspaceView","name":"migrationKeyspace","type":"tuple","components":[{"internalType":"struct NodeOperator[]","name":"operators","type":"tuple[]","components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}]},{"internalType":"uint8","name":"replicationStrategy","type":"uint8"}]},{"internalType":"struct Maintenance","name":"maintenance","type":"tuple","components":[{"internalType":"address","name":"slot","type":"address"}]},{"internalType":"uint64","name":"keyspaceVersion","type":"uint64"},{"internalType":"uint128","name":"version","type":"uint128"}]}]},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"startMaintenance"},{"inputs":[{"internalType":"struct MigrationPlan","name":"plan","type":"tuple","components":[{"internalType":"struct KeyspaceSlot[]","name":"slots","type":"tuple[]","components":[{"internalType":"uint8","name":"idx","type":"uint8"},{"internalType":"address","name":"operatorAddress","type":"address"}]},{"internalType":"uint8","name":"replicationStrategy","type":"uint8"}]}],"stateMutability":"nonpayable","type":"function","name":"startMigration"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"transferOwnership"},{"inputs":[{"internalType":"struct NodeOperator","name":"operator","type":"tuple","components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}]}],"stateMutability":"nonpayable","type":"function","name":"updateNodeOperator"},{"inputs":[{"internalType":"struct Settings","name":"newSettings","type":"tuple","components":[{"internalType":"uint16","name":"maxOperatorDataBytes","type":"uint16"}]}],"stateMutability":"nonpayable","type":"function","name":"updateSettings"}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"remappings":["@openzeppelin/contracts/=dependencies/openzeppelin-contracts/contracts/","erc4626-tests/=dependencies/openzeppelin-contracts/lib/erc4626-tests/","forge-std-1.9.7/=dependencies/forge-std-1.9.7/src/","forge-std/=dependencies/openzeppelin-contracts/lib/forge-std/src/","halmos-cheatcodes/=dependencies/openzeppelin-contracts/lib/halmos-cheatcodes/src/","openzeppelin-contracts/=dependencies/openzeppelin-contracts/"],"optimizer":{"enabled":false,"runs":200},"metadata":{"bytecodeHash":"ipfs"},"compilationTarget":{"src/Cluster.sol":"Cluster"},"evmVersion":"cancun","libraries":{},"viaIR":true},"sources":{"dependencies/openzeppelin-contracts/contracts/utils/Panic.sol":{"keccak256":"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a","urls":["bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a","dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG"],"license":"MIT"},"dependencies/openzeppelin-contracts/contracts/utils/math/Math.sol":{"keccak256":"0x1225214420c83ebcca88f2ae2b50f053aaa7df7bd684c3e878d334627f2edfc6","urls":["bzz-raw://6c5fab4970634f9ab9a620983dc1c8a30153981a0b1a521666e269d0a11399d3","dweb:/ipfs/QmVRnBC575MESGkEHndjujtR7qub2FzU9RWy9eKLp4hPZB"],"license":"MIT"},"dependencies/openzeppelin-contracts/contracts/utils/math/SafeCast.sol":{"keccak256":"0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54","urls":["bzz-raw://b1d578337048cad08c1c03041cca5978eff5428aa130c781b271ad9e5566e1f8","dweb:/ipfs/QmPFKL2r9CBsMwmUqqdcFPfHZB2qcs9g1HDrPxzWSxomvy"],"license":"MIT"},"src/Cluster.sol":{"keccak256":"0xfd4a17d0b8327f8248d37ae5b16b7076095a7b4f6ed1d75f859446b33c086a88","urls":["bzz-raw://91b3747c61898f3f65d064a173e6795fede772a88d3848870bf73266498dc71f","dweb:/ipfs/QmStHTacgfN8y7nzkFrju9GGVV7kv5WD9ez2yeTP8YgcAe"],"license":"MIT"}},"version":1},"id":22} \ No newline at end of file diff --git a/contracts/src/Cluster.sol b/contracts/src/Cluster.sol index 7e24f80d..9cb5046b 100644 --- a/contracts/src/Cluster.sol +++ b/contracts/src/Cluster.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; -// import '../dependencies/openzeppelin-contracts/contracts/utils/math/Math.sol'; +import './../dependencies/openzeppelin-contracts/contracts/utils/math/Math.sol'; struct Settings { uint16 maxOperatorDataBytes; @@ -13,10 +13,15 @@ event MigrationCompleted(uint64 id, address operatorAddress, uint128 clusterVers event MigrationAborted(uint64 id, uint128 clusterVersion); event MaintenanceStarted(address operatorAddress, uint128 clusterVersion); -event MaintenanceCompleted(address operatorAddress, uint128 clusterVersion); -event MaintenanceAborted(uint128 clusterVersion); +event MaintenanceFinished(address operatorAddress, uint128 clusterVersion); -event NodeOperatorDataUpdated(address operatorAddress, bytes data, uint128 clusterVersion); +event NodeOperatorCreated(NodeOperator operator, uint128 clusterVersion); +event NodeOperatorUpdated(NodeOperator operator, uint128 clusterVersion); +event NodeOperatorDeleted(address operatorAddress, uint128 clusterVersion); + +event SettingsUpdated(Settings newSettings, uint128 clusterVersion); + +event OwnershipTransferred(address newOwner, uint128 cluserVersion); contract Cluster { using Bitmask for uint256; @@ -36,13 +41,21 @@ contract Cluster { uint128 version; - constructor(Settings memory initialSettings, address[] memory initialOperators) { + constructor(Settings memory initialSettings, NodeOperator[] memory initialOperators) { + require(initialOperators.length <= 256, "too many operators"); + owner = msg.sender; settings = initialSettings; - + for (uint256 i = 0; i < initialOperators.length; i++) { - keyspaces[0].operators[i] = initialOperators[i]; + validateOperatorDataSize(initialOperators[i].data.length); + require(operatorData[initialOperators[i].addr].length == 0, "duplicate operator"); + + keyspaces[0].operators[i] = initialOperators[i].addr; + keyspaces[0].operatorIndexes[initialOperators[i].addr] = OptionU8({ is_some: true, value: uint8(i) }); + operatorData[initialOperators[i].addr] = initialOperators[i].data; } + keyspaces[0].operatorsBitmask = Bitmask.fill(uint8(initialOperators.length)); } @@ -74,52 +87,90 @@ contract Cluster { function startMigration(MigrationPlan calldata plan) external onlyOwner noMigration noMaintenance { migration.id++; - uint256 keyspaceIdx = keyspaceVersion % 2; + Keyspace storage keyspace = keyspaces[keyspaceVersion % 2]; keyspaceVersion++; - uint256 migrationKeyspaceIdx = keyspaceVersion % 2; + Keyspace storage newKeyspace = keyspaces[keyspaceVersion % 2]; - // NOTE: We are not zeroing out the rest of the buffer, so there might be some junk left. - // The source of truth on whether the value is set or not should be the bitmask! - for (uint256 i = 0; i <= keyspaces[keyspaceIdx].operatorsBitmask.highest1(); i++) { - if (keyspaces[migrationKeyspaceIdx].operators[i] != keyspaces[keyspaceIdx].operators[i]) { - keyspaces[migrationKeyspaceIdx].operators[i] = keyspaces[keyspaceIdx].operators[i]; + // Make sure that initially the new keyspace is identical to the old one. + cloneKeyspace(keyspace, newKeyspace); + + applyMigrationPlan(newKeyspace, plan); + + migration.pullingOperatorsBitmask = newKeyspace.operatorsBitmask; + + version++; + emit MigrationStarted(migration.id, plan, version); + } + + function cloneKeyspace(Keyspace storage src, Keyspace storage dst) internal { + // Pick highest out of two to ensure that all non-empty slots are being processed. + uint256 highestSlot = Math.max(src.operatorsBitmask.highest1(), dst.operatorsBitmask.highest1()); + address srcAddr; + address dstAddr; + for (uint256 i = 0; i <= highestSlot; i++) { + srcAddr = src.operators[i]; + dstAddr = dst.operators[i]; + + if (srcAddr == dstAddr) { + continue; } + + if (dstAddr != address(0)) { + delete(dst.operatorIndexes[dstAddr]); + } + + if (srcAddr != address(0)) { + dst.operatorIndexes[srcAddr] = OptionU8({ is_some: true, value: uint8(i) }); + } + + dst.operators[i] = srcAddr; } - uint256 operatorsBitmask = keyspaces[keyspaceIdx].operatorsBitmask; + dst.replicationStrategy = src.replicationStrategy; + dst.operatorsBitmask = src.operatorsBitmask; + } + + function applyMigrationPlan(Keyspace storage keyspace, MigrationPlan calldata plan) internal { + uint256 operatorsBitmask = keyspace.operatorsBitmask; uint8 idx; - address addr; + address addr; + address newAddr; for (uint256 i = 0; i < plan.slots.length; i++) { idx = plan.slots[i].idx; - addr = plan.slots[i].operator; + newAddr = plan.slots[i].operatorAddress; + addr = keyspace.operators[idx]; - if (addr == address(0)) { + require(addr != newAddr, "unchanged slot"); + + if (addr != address(0)) { + delete(keyspace.operatorIndexes[addr]); + } + + if (newAddr == address(0)) { operatorsBitmask = operatorsBitmask.set0(idx); } else { + require(operatorData[newAddr].length != 0, "unknown operator"); + require(!keyspace.operatorIndexes[newAddr].is_some, "operator duplicate"); operatorsBitmask = operatorsBitmask.set1(idx); } - keyspaces[migrationKeyspaceIdx].operators[idx] = addr; + keyspace.operators[idx] = newAddr; + keyspace.operatorIndexes[newAddr] = OptionU8({ is_some: true, value: idx }); } - keyspaces[migrationKeyspaceIdx].operatorsBitmask = operatorsBitmask; - keyspaces[migrationKeyspaceIdx].replicationStrategy = plan.replicationStrategy; - - migration.pullingOperatorsBitmask = operatorsBitmask; - - version++; - emit MigrationStarted(migration.id, plan, version); + keyspace.operatorsBitmask = operatorsBitmask; + keyspace.replicationStrategy = plan.replicationStrategy; } - function completeMigration(uint64 id, uint8 operatorIdx) external hasMigration { + function completeMigration(uint64 id) external hasMigration { require(id == migration.id, "wrong migration id"); - require(keyspaces[keyspaceVersion % 2].operators[operatorIdx] == msg.sender, "wrong operator"); - if (migration.pullingOperatorsBitmask.is0(operatorIdx)) { - return; - } - migration.pullingOperatorsBitmask = migration.pullingOperatorsBitmask.set0(operatorIdx); + OptionU8 memory operatorIdx = keyspaces[keyspaceVersion % 2].operatorIndexes[msg.sender]; + require(operatorIdx.is_some, "unknown operator"); + require(migration.pullingOperatorsBitmask.is1(operatorIdx.value), "not pulling"); + + migration.pullingOperatorsBitmask = migration.pullingOperatorsBitmask.set0(operatorIdx.value); version++; if (migration.pullingOperatorsBitmask == 0) { @@ -137,8 +188,8 @@ contract Cluster { emit MigrationAborted(migration.id, version); } - function startMaintenance(uint8 operatorIdx) external noMigration noMaintenance { - require(keyspaces[keyspaceVersion % 2].operators[operatorIdx] == msg.sender, "wrong operator"); + function startMaintenance() external noMigration noMaintenance { + require(keyspaces[keyspaceVersion % 2].operatorIndexes[msg.sender].is_some || msg.sender == owner, "unauthorized"); maintenance.slot = msg.sender; @@ -146,55 +197,59 @@ contract Cluster { emit MaintenanceStarted(msg.sender, version); } - function completeMaintenance() external hasMaintenance { - require(maintenance.slot == msg.sender, "wrong operator"); + function finishMaintenance() external hasMaintenance { + require(msg.sender == owner || maintenance.slot == msg.sender, "unauthorized"); maintenance.slot = address(0); version++; - emit MaintenanceCompleted(msg.sender, version); + emit MaintenanceFinished(msg.sender, version); } - function abortMaintenance() external onlyOwner hasMaintenance { - maintenance.slot = address(0); - + function createNodeOperator(NodeOperator calldata operator) external onlyOwner { + require(operatorData[operator.addr].length == 0, "operator already exists"); + validateOperatorDataSize(operator.data.length); + + operatorData[operator.addr] = operator.data; version++; - emit MaintenanceAborted(version); + emit NodeOperatorCreated(operator, version); } - function registerNodeOperator(bytes calldata data) external { - validateOperatorDataSize(data.length); - operatorData[msg.sender] = data; - } + function updateNodeOperator(NodeOperator calldata operator) external { + require(msg.sender == owner || msg.sender == operator.addr, "unauthorized"); + require(operatorData[operator.addr].length != 0, "unknown operator"); + validateOperatorDataSize(operator.data.length); - function updateNodeOperatorData(uint8 operatorIdx, bytes calldata data) external { - validateOperatorDataSize(data.length); + operatorData[operator.addr] = operator.data; + version++; + emit NodeOperatorUpdated(operator, version); + } - bool inKeyspace; - bool inMigrationKeyspace; + function deleteNodeOperator(address operatorAddress) external onlyOwner { + require(operatorData[operatorAddress].length != 0, "unknown operator"); if (isMigrationInProgress()) { - inKeyspace = keyspaces[(keyspaceVersion - 1) % 2].operators[operatorIdx] == msg.sender; - if (!inKeyspace) { - inMigrationKeyspace = keyspaces[keyspaceVersion % 2].operators[operatorIdx] == msg.sender; - } + require(!keyspaces[0].operatorIndexes[operatorAddress].is_some, "in keyspace"); + require(!keyspaces[1].operatorIndexes[operatorAddress].is_some, "in keyspace"); } else { - inKeyspace = keyspaces[keyspaceVersion % 2].operators[operatorIdx] == msg.sender; + require(!keyspaces[keyspaceVersion % 2].operatorIndexes[operatorAddress].is_some, "in keyspace"); } - require(inKeyspace || inMigrationKeyspace, "wrong operator"); - - operatorData[msg.sender] = data; + delete(operatorData[operatorAddress]); version++; - emit NodeOperatorDataUpdated(msg.sender, data, version); + emit NodeOperatorDeleted(operatorAddress, version); } function updateSettings(Settings calldata newSettings) external onlyOwner { settings = newSettings; + version++; + emit SettingsUpdated(newSettings, version); } function transferOwnership(address newOwner) external onlyOwner { owner = newOwner; + version++; + emit OwnershipTransferred(newOwner, version); } function getView() public view returns (ClusterView memory) { @@ -274,12 +329,23 @@ struct NodeOperator { } struct Keyspace { + mapping(address => OptionU8) operatorIndexes; address[256] operators; uint256 operatorsBitmask; uint8 replicationStrategy; } +struct OptionU8 { + bool is_some; + uint8 value; +} + +struct OptionalUInt8 { + bool exists; + uint8 value; +} + struct KeyspaceView { NodeOperator[] operators; @@ -288,7 +354,7 @@ struct KeyspaceView { struct KeyspaceSlot { uint8 idx; - address operator; + address operatorAddress; } struct MigrationPlan { diff --git a/contracts/test/Suite.sol b/contracts/test/Suite.sol index be8a0f2f..1b838e38 100644 --- a/contracts/test/Suite.sol +++ b/contracts/test/Suite.sol @@ -104,7 +104,7 @@ contract ClusterTest is Test { } function test_canNotStartMigrationWhenMaintenanceInProgress() public { - startMaintenance(1, 0); + startMaintenance(1); expectRevert("maintenance in progress"); startMigration(OWNER, newMigration().clear(0)); } @@ -127,6 +127,8 @@ contract ClusterTest is Test { } function test_startMigrationInitializesMigration() public { + createNodeOperator(OWNER, 6); + createNodeOperator(OWNER, 7); startMigration(OWNER, newMigration().set(4, 6).set(5, 7).clear(2)); assertMigration(1, 5); assertMigrationPullingOperator(0); @@ -137,8 +139,8 @@ contract ClusterTest is Test { } function test_startMigrationPopulatesMigrationKeyspace() public { - registerNodeOperator(6, "operator6"); - registerNodeOperator(7, "operator7"); + createNodeOperator(OWNER, 6, "operator6"); + createNodeOperator(OWNER, 7, "operator7"); startMigration(OWNER, newMigration().set(4, 6).set(5, 7).clear(2)); assertKeyspaceSlotsCount(clusterView.migrationKeyspace, 6); @@ -154,41 +156,43 @@ contract ClusterTest is Test { function test_anyoneCanNotCompleteMigration() public { startMigration(OWNER, newMigration().clear(0)); - expectRevert("wrong operator"); - completeMigration(ANYONE, 1, 0); + expectRevert("unknown operator"); + completeMigration(ANYONE, 1); } function test_ownerCanNotCompleteMigration() public { startMigration(OWNER, newMigration().clear(0)); - expectRevert("wrong operator"); - completeMigration(OWNER, 1, 0); + expectRevert("unknown operator"); + completeMigration(OWNER, 1); } function test_operatorCanNotCompleteNonExistentMigration() public { expectRevert("no migration"); - completeMigration(OPERATOR, 1, 0); + completeMigration(OPERATOR, 1); } function test_operatorCanCompleteMigration() public { startMigration(OWNER, newMigration().clear(1)); - completeMigration(OPERATOR, 1, 0); + completeMigration(OPERATOR, 1); } - function test_completeMigrationIsIdempotent() public { + function test_canNotCompleteMigrationTwice() public { startMigration(OWNER, newMigration().clear(1)); - completeMigration(OPERATOR, 1, 0); - completeMigration(OPERATOR, 1, 0); + completeMigration(OPERATOR, 1); + expectRevert("not pulling"); + completeMigration(OPERATOR, 1); } function test_completeMigrationBumpsVersion() public { startMigration(OWNER, newMigration().clear(1)); - completeMigration(OPERATOR, 1, 0); + completeMigration(OPERATOR, 1); assertVersion(2); } function test_completeMigrationDoesNotUpdateKeyspaceIfNotCompleted() public { + createNodeOperator(OWNER, 6); startMigration(OWNER, newMigration().set(5, 6)); - completeMigration(OPERATOR, 1, 0); + completeMigration(OPERATOR, 1); assertKeyspaceSlotsCount(clusterView.keyspace, 5); assertKeyspaceSlot(clusterView.keyspace, 0, 1); assertKeyspaceSlot(clusterView.keyspace, 1, 2); @@ -198,13 +202,13 @@ contract ClusterTest is Test { } function test_completeMigrationUpdatesOperatorsIfCompleted() public { - registerNodeOperator(6, "operator6"); + createNodeOperator(OWNER, 6, "operator6"); startMigration(OWNER, newMigration().set(4, 6)); - completeMigration(1, 1, 0); - completeMigration(2, 1, 1); - completeMigration(3, 1, 2); - completeMigration(4, 1, 3); - completeMigration(6, 1, 4); + completeMigration(1, 1); + completeMigration(2, 1); + completeMigration(3, 1); + completeMigration(4, 1); + completeMigration(6, 1); assertKeyspaceSlotsCount(clusterView.keyspace, 5); assertKeyspaceSlot(clusterView.keyspace, 0, 1); assertKeyspaceSlot(clusterView.keyspace, 1, 2); @@ -215,46 +219,49 @@ contract ClusterTest is Test { function test_completeMigrationDeletesMigrationIfCompleted() public { startMigration(OWNER, newMigration().clear(3).clear(4)); - completeMigration(1, 1, 0); - completeMigration(2, 1, 1); - completeMigration(3, 1, 2); + completeMigration(1, 1); + completeMigration(2, 1); + completeMigration(3, 1); assertNoMigration(); } function test_completeMigrationRemovesPullingOperatorBitIfNotCompleted() public { + createNodeOperator(OWNER, 10); startMigration(OWNER, newMigration().set(2, 10)); - completeMigration(1, 1, 0); + completeMigration(1, 1); assert(clusterView.migration.pullingOperatorsBitmask.is0(0)); } function test_completeMigrationDoesNotBumpKeyspaceVersionIfNotCompleted() public { + createNodeOperator(OWNER, 10); startMigration(OWNER, newMigration().set(2, 10)); - completeMigration(1, 1, 0); + completeMigration(1, 1); assertKeyspaceVersion(1); } function test_completeMigrationDoesNotBumpKeyspaceVersionIfCompleted() public { startMigration(OWNER, newMigration().clear(3).clear(4)); - completeMigration(1, 1, 0); - completeMigration(2, 1, 1); - completeMigration(3, 1, 2); + completeMigration(1, 1); + completeMigration(2, 1); + completeMigration(3, 1); assertKeyspaceVersion(1); } function test_completeMigrationEmitsMigrationDataPullCompletedEventIfNotCompleted() public { + createNodeOperator(OWNER, 10); startMigration(OWNER, newMigration().set(2, 10)); vm.expectEmit(); - emit MigrationDataPullCompleted(1, vm.addr(1), 2); - completeMigration(1, 1, 0); + emit MigrationDataPullCompleted(1, vm.addr(1), 3); + completeMigration(1, 1); } function test_completeMigrationEmitsMigrationCompletedEventIfCompleted() public { startMigration(OWNER, newMigration().clear(3).clear(4)); - completeMigration(1, 1, 0); - completeMigration(2, 1, 1); + completeMigration(1, 1); + completeMigration(2, 1); vm.expectEmit(); emit MigrationCompleted(1, vm.addr(3), 4); - completeMigration(3, 1, 2); + completeMigration(3, 1); } // abortMigration @@ -320,213 +327,172 @@ contract ClusterTest is Test { // startMaintenance function test_anyoneCanNotStartMaintenance() public { - expectRevert("wrong operator"); - startMaintenance(ANYONE, 0); + expectRevert("unauthorized"); + startMaintenance(ANYONE); } - function test_ownerCanNotStartMaintenance() public { - expectRevert("wrong operator"); - startMaintenance(OWNER, 0); + function test_ownerCanStartMaintenance() public { + startMaintenance(OWNER); } function test_operatorCanStartMaintenance() public { - startMaintenance(OPERATOR, 0); + startMaintenance(OPERATOR); } function test_canNotStartMoreThanOneMaintenance() public { - startMaintenance(1, 0); + startMaintenance(1); expectRevert("maintenance in progress"); - startMaintenance(2, 1); + startMaintenance(2); } function test_operatorCanNotStartMaintenanceWhenMigrationInProgress() public { startMigration(OWNER, newMigration().clear(1)); expectRevert("migration in progress"); - startMaintenance(1, 0); + startMaintenance(1); } function test_startMaintenanceBumpsVersion() public { - startMaintenance(1, 0); + startMaintenance(1); assertVersion(1); } function test_startMaintenanceDoesNotBumpKeyspaceVersion() public { - startMaintenance(1, 0); + startMaintenance(1); assertKeyspaceVersion(0); } function test_startMaintenanceUpdatesMaintenance() public { - startMaintenance(1, 0); + startMaintenance(1); assertMaintenance(1); } function test_startMaintenanceEmitsMaintenanceStartedEvent() public { vm.expectEmit(); emit MaintenanceStarted(vm.addr(1), 1); - startMaintenance(1, 0); + startMaintenance(1); } - // completeMaintenance + // finishMaintenance function test_anyoneCanNotCompleteMaintenance() public { - startMaintenance(1, 0); - expectRevert("wrong operator"); - completeMaintenance(ANYONE); + startMaintenance(1); + expectRevert("unauthorized"); + finishMaintenance(ANYONE); } function test_anotherOperatorCanNotCompleteMaintenance() public { - startMaintenance(2, 1); - expectRevert("wrong operator"); - completeMaintenance(OPERATOR); + startMaintenance(2); + expectRevert("unauthorized"); + finishMaintenance(OPERATOR); } - function test_ownerCanNotCompleteMaintenance() public { - startMaintenance(1, 0); - expectRevert("wrong operator"); - completeMaintenance(OWNER); + function test_ownerCanCompleteMaintenance() public { + startMaintenance(1); + finishMaintenance(OWNER); } function test_sameOperatorCanCompleteMaintenance() public { - startMaintenance(1, 0); - completeMaintenance(OPERATOR); + startMaintenance(1); + finishMaintenance(OPERATOR); } function test_canNotCompleteNonExistentMaintenance() public { expectRevert("no maintenance"); - completeMaintenance(OPERATOR); + finishMaintenance(OPERATOR); } - function test_completeMaintenanceBumpsVersion() public { - startMaintenance(1, 0); - completeMaintenance(1); + function test_finishMaintenanceBumpsVersion() public { + startMaintenance(1); + finishMaintenance(1); assertVersion(2); } - function test_completeMaintenanceDoesNotBumpKeyspaceVersion() public { - startMaintenance(1, 0); - completeMaintenance(1); + function test_finishMaintenanceDoesNotBumpKeyspaceVersion() public { + startMaintenance(1); + finishMaintenance(1); assertKeyspaceVersion(0); } - function test_completeMaintenanceDeletesMaintenance() public { - startMaintenance(1, 0); - completeMaintenance(1); + function test_finishMaintenanceDeletesMaintenance() public { + startMaintenance(1); + finishMaintenance(1); assertNoMaintenance(); } - function test_completeMaintenanceEmitsMaintenanceCompletedEvent() public { - startMaintenance(1, 0); + function test_finishMaintenanceEmitsMaintenanceFinishedEvent() public { + startMaintenance(1); vm.expectEmit(); - emit MaintenanceCompleted(vm.addr(1), 2); - completeMaintenance(1); + emit MaintenanceFinished(vm.addr(1), 2); + finishMaintenance(1); } - // abortMaintenance - - function test_anyoneCanNotAbortMaintenance() public { - startMaintenance(1, 0); + // createNodeOperator + + function test_anyoneCanNotCreateNodeOperator() public { expectRevert("not the owner"); - abortMaintenance(ANYONE); + createNodeOperator(ANYONE, 42, "data"); } - function test_operatorCanNotAbortMaintenance() public { - startMaintenance(1, 0); + function test_operatorCanNotCreateAnotherNodeOperator() public { expectRevert("not the owner"); - abortMaintenance(OPERATOR); + createNodeOperator(OPERATOR, 42, "data"); } - function test_ownerCanAbortMaintenance() public { - startMaintenance(1, 0); - abortMaintenance(OWNER); + function test_ownerCanCreateNodeOperator() public { + createNodeOperator(OWNER, 42, "data"); } - function test_canNotAbortNonExistentMaintenance() public { - expectRevert("no maintenance"); - abortMaintenance(OWNER); - } - - function test_abortMaintenanceBumpsVersion() public { - startMaintenance(1, 0); - abortMaintenance(OWNER); - assertVersion(2); + function test_createNodeOperatorBumpsVersion() public { + createNodeOperator(OWNER, 42, "data"); + assertVersion(1); } - function test_abortMaintenanceDoesNotBumpKeyspaceVersion() public { - startMaintenance(1, 0); - abortMaintenance(OWNER); + function test_createNodeOperatorDoesNotBumpKeyspaceVersion() public { + createNodeOperator(OWNER, 42, "data"); assertKeyspaceVersion(0); } - function test_abortMaintenanceDeletesMaintenance() public { - startMaintenance(1, 0); - abortMaintenance(OWNER); - assertNoMaintenance(); - } - - function test_abortMaintenanceEmitsMaintenanceAbortedEvent() public { - startMaintenance(1, 0); + function test_createNodeOperatorEmitsEventNodeOperatorCreated() public { vm.expectEmit(); - emit MaintenanceAborted(2); - abortMaintenance(OWNER); - } - - // registerNodeOperator - - function test_anyoneCanRegisterNodeOperator() public { - registerNodeOperator(ANYONE, "anyone"); - } - - function test_registerNodeOperatorDoesNotBumpVersion() public { - registerNodeOperator(ANYONE, "anyone"); - assertVersion(0); - } - - function test_registerNodeOperatorDoesNotBumpKeyspaceVersion() public { - registerNodeOperator(ANYONE, "anyone"); - assertKeyspaceVersion(0); - } - - function test_registerNodeOperatorDoesNotEmitEvents() public { - vm.recordLogs(); - registerNodeOperator(ANYONE, "anyone"); - assertEq(vm.getRecordedLogs().length, 0); + emit NodeOperatorCreated(NodeOperator({ addr: vm.addr(42), data: "data" }), 1); + createNodeOperator(OWNER, 42, "data"); } - // updateNodeOperatorData + // updateNodeOperator - function test_anyoneCanNotUpdateNodeOperatorData() public { - expectRevert("wrong operator"); - updateNodeOperatorData(ANYONE, 0, "new data"); + function test_anyoneCanNotUpdateNodeOperator() public { + expectRevert("unauthorized"); + updateNodeOperator(ANYONE, 1, "new data"); } - function test_ownerCanNotUpdateNodeOperatorData() public { - expectRevert("wrong operator"); - updateNodeOperatorData(OWNER, 0, "new data"); + function test_ownerCanNotUpdateNodeOperator() public { + // expectRevert("wrong operator"); + updateNodeOperator(OWNER, 1, "new data"); } - function test_operatorCanUpdateNodeOperatorData() public { - updateNodeOperatorData(OPERATOR, 0, "new data"); + function test_operatorCanUpdateNodeOperator() public { + updateNodeOperator(OPERATOR, 1, "new data"); } - function test_updateNodeOperatorDataDoesUpdateTheData() public { - updateNodeOperatorData(OPERATOR, 0, "new data"); + function test_updateNodeOperatorDoesUpdateTheData() public { + updateNodeOperator(OPERATOR, 1, "new data"); assertKeyspaceSlot(clusterView.keyspace, 0, OPERATOR, "new data"); } - function test_updateNodeOperatorDataBumpsVersion() public { - updateNodeOperatorData(OPERATOR, 0, "new data"); + function test_updateNodeOperatorBumpsVersion() public { + updateNodeOperator(OPERATOR, 1, "new data"); assertVersion(1); } - function test_updateNodeOperatorDataDoesNotBumpKeyspaceVersion() public { - updateNodeOperatorData(OPERATOR, 0, "new data"); + function test_updateNodeOperatorDoesNotBumpKeyspaceVersion() public { + updateNodeOperator(OPERATOR, 1, "new data"); assertKeyspaceVersion(0); } - function test_updateNodeOperatorDataEmitsEventNodeOperatorDataUpdated() public { + function test_updateNodeOperatorEmitsEventNodeOperatorUpdated() public { vm.expectEmit(); - emit NodeOperatorDataUpdated(vm.addr(OPERATOR), "new data", 1); - updateNodeOperatorData(OPERATOR, 0, "new data"); + emit NodeOperatorUpdated(NodeOperator({ addr: vm.addr(OPERATOR), data: "new data" }), 1); + updateNodeOperator(OPERATOR, 1, "new data"); } // updateSettings @@ -548,7 +514,7 @@ contract ClusterTest is Test { function test_updateSettingsUpdatesMaxOperatorDataBytes() public { updateSettings(OWNER, Settings({ maxOperatorDataBytes: 5 })); expectRevert("operator data too large"); - registerNodeOperator(10, "123456"); + createNodeOperator(OWNER, 10, "123456"); } // transferOwnership @@ -575,36 +541,36 @@ contract ClusterTest is Test { // full lifecycle function test_fullClusterLifecycle() public { - updateNodeOperatorData(1, 0, "operator1"); - startMaintenance(2, 1); - updateNodeOperatorData(3, 2, "operator3"); - completeMaintenance(2); - - registerNodeOperator(6, "operator6"); - registerNodeOperator(7, "operator7"); - registerNodeOperator(8, "operator8"); + updateNodeOperator(1, 1, "operator1"); + startMaintenance(2); + updateNodeOperator(3, 3, "operator3"); + finishMaintenance(2); + + createNodeOperator(OWNER, 6, "operator6"); + createNodeOperator(OWNER, 7, "operator7"); + createNodeOperator(OWNER, 8, "operator8"); startMigration(OWNER, newMigration().set(5, 6).set(6, 7).set(7, 8)); - updateNodeOperatorData(1, 0, "operator1'"); + updateNodeOperator(1, 1, "operator1'"); for (uint256 i = 0; i < 8; i++) { - completeMigration(i + 1, 1, uint8(i)); + completeMigration(i + 1, 1); } - updateNodeOperatorData(3, 2, "operator3'"); - startMaintenance(7, 6); - updateNodeOperatorData(7, 6, "operator8"); - abortMaintenance(OWNER); + updateNodeOperator(3, 3, "operator3'"); + startMaintenance(7); + updateNodeOperator(7, 7, "operator8"); + finishMaintenance(OWNER); startMigration(OWNER, newMigration().clear(6)); for (uint256 i = 0; i < 8; i++) { if (i != 6) { - completeMigration(i + 1, 2, uint8(i)); + completeMigration(i + 1, 2); } } - registerNodeOperator(9, "operator9"); + createNodeOperator(OWNER, 9, "operator9"); startMigration(OWNER, newMigration().set(6, 9)); for (uint256 i = 0; i < 8; i++) { if (i != 6) { - completeMigration(i + 1, 3, uint8(i)); + completeMigration(i + 1, 3); } } abortMigration(OWNER); @@ -628,9 +594,10 @@ contract ClusterTest is Test { function newCluster(Vm vm, Settings memory settings, uint256 operatorsCount) internal { setCaller(OWNER); - address[] memory operators = new address[](operatorsCount); + NodeOperator[] memory operators = new NodeOperator[](operatorsCount); for (uint256 i = 0; i < operatorsCount; i++) { - operators[i] = vm.addr(i + 1); + operators[i].addr = vm.addr(i + 1); + operators[i].data = DEFAULT_OPERATOR_DATA; } cluster = new Cluster(settings, operators); @@ -639,10 +606,6 @@ contract ClusterTest is Test { return; } - for (uint256 i = 0; i < operatorsCount; i++) { - registerNodeOperator(i + 1); - } - updateClusterView(); } @@ -722,9 +685,9 @@ contract ClusterTest is Test { updateClusterView(); } - function completeMigration(uint256 caller, uint64 id, uint8 operatorIdx) internal { + function completeMigration(uint256 caller, uint64 id) internal { setCaller(caller); - cluster.completeMigration(id, operatorIdx); + cluster.completeMigration(id); updateClusterView(); } @@ -734,37 +697,31 @@ contract ClusterTest is Test { updateClusterView(); } - function startMaintenance(uint256 caller, uint8 operatorIdx) internal { - setCaller(caller); - cluster.startMaintenance(operatorIdx); - updateClusterView(); - } - - function completeMaintenance(uint256 caller) internal { + function startMaintenance(uint256 caller) internal { setCaller(caller); - cluster.completeMaintenance(); + cluster.startMaintenance(); updateClusterView(); } - function abortMaintenance(uint256 caller) internal { + function finishMaintenance(uint256 caller) internal { setCaller(caller); - cluster.abortMaintenance(); + cluster.finishMaintenance(); updateClusterView(); } - function registerNodeOperator(uint256 caller) internal { - registerNodeOperator(caller, DEFAULT_OPERATOR_DATA); + function createNodeOperator(uint256 caller, uint256 privKey) internal { + createNodeOperator(caller, privKey, DEFAULT_OPERATOR_DATA); } - function registerNodeOperator(uint256 caller, bytes memory data) internal { + function createNodeOperator(uint256 caller, uint256 privKey, bytes memory data) internal { setCaller(caller); - cluster.registerNodeOperator(data); + cluster.createNodeOperator(NodeOperator({ addr: vm.addr(privKey), data: data })); updateClusterView(); } - function updateNodeOperatorData(uint256 caller, uint8 idx, bytes memory data) internal { + function updateNodeOperator(uint256 caller, uint256 privKey, bytes memory data) internal { setCaller(caller); - cluster.updateNodeOperatorData(idx, data); + cluster.updateNodeOperator(NodeOperator({ addr: vm.addr(privKey), data: data })); updateClusterView(); } @@ -787,12 +744,12 @@ struct TestMigration { library TestMigrationLib { function set(TestMigration memory self, uint8 idx, uint256 privateKey) internal pure returns (TestMigration memory) { - TestMigrationLib.setSlot(self, idx, KeyspaceSlot({ idx: idx, operator: self.vm.addr(privateKey) })); + TestMigrationLib.setSlot(self, idx, KeyspaceSlot({ idx: idx, operatorAddress: self.vm.addr(privateKey) })); return self; } function clear(TestMigration memory self, uint8 idx) internal pure returns (TestMigration memory) { - TestMigrationLib.setSlot(self, idx, KeyspaceSlot({ idx: idx, operator: address(0) })); + TestMigrationLib.setSlot(self, idx, KeyspaceSlot({ idx: idx, operatorAddress: address(0) })); return self; } diff --git a/crates/cluster/src/lib.rs b/crates/cluster/src/lib.rs index 5a4e6d8b..760aafeb 100644 --- a/crates/cluster/src/lib.rs +++ b/crates/cluster/src/lib.rs @@ -71,15 +71,18 @@ pub enum Event { /// [`Maintenance`] has started. MaintenanceStarted(maintenance::Started), - /// [`Maintenance`] has been completed. - MaintenanceCompleted(maintenance::Completed), + /// [`Maintenance`] has been finished. + MaintenanceFinished(maintenance::Finished), - /// [`Maintenance`] has been aborted. - MaintenanceAborted(maintenance::Aborted), + /// [`NodeOperator`] has been updated. + NodeOperatorAdded(node_operator::Added), - /// On-chain state of an [`NodeOperator`] has been updated. + /// [`NodeOperator`] has been updated. NodeOperatorUpdated(node_operator::Updated), + /// [`NodeOperator`] has been removed. + NodeOperatorRemoved(node_operator::Removed), + /// [`Settings`] have been updated. SettingsUpdated(settings::Updated), @@ -440,9 +443,10 @@ impl Event { Event::MigrationCompleted(evt) => evt.cluster_version, Event::MigrationAborted(evt) => evt.cluster_version, Event::MaintenanceStarted(evt) => evt.cluster_version, - Event::MaintenanceCompleted(evt) => evt.cluster_version, - Event::MaintenanceAborted(evt) => evt.cluster_version, + Event::MaintenanceFinished(evt) => evt.cluster_version, + Event::NodeOperatorAdded(evt) => evt.cluster_version, Event::NodeOperatorUpdated(evt) => evt.cluster_version, + Event::NodeOperatorRemoved(evt) => evt.cluster_version, Event::SettingsUpdated(evt) => evt.cluster_version, Event::OwnershipTransferred(evt) => evt.cluster_version, } @@ -503,9 +507,10 @@ impl View { Event::MigrationCompleted(evt) => evt.apply(&mut self), Event::MigrationAborted(evt) => evt.apply(&mut self), Event::MaintenanceStarted(evt) => evt.apply(&mut self), - Event::MaintenanceCompleted(evt) => evt.apply(&mut self), - Event::MaintenanceAborted(evt) => evt.apply(&mut self), + Event::MaintenanceFinished(evt) => evt.apply(&mut self), + Event::NodeOperatorAdded(evt) => evt.apply(&mut self), Event::NodeOperatorUpdated(evt) => evt.apply(&mut self), + Event::NodeOperatorRemoved(evt) => evt.apply(&mut self), Event::SettingsUpdated(evt) => evt.apply(&mut self), Event::OwnershipTransferred(evt) => evt.apply(&mut self), }?; @@ -584,12 +589,6 @@ pub enum LogicalError { #[error("There are still pulling operators remaining, but ther shouldn't be")] PullingOperatorsRemaining, - #[error("Maintenance: node operator ID mismatch (event: {event}, local: {event})")] - MaintenanceNodeOperatorIdMismatch { - event: node_operator::Id, - local: node_operator::Id, - }, - #[error("Node operator (id: {0}) is not within the cluster, but should be")] UnknownOperator(node_operator::Id), diff --git a/crates/cluster/src/maintenance.rs b/crates/cluster/src/maintenance.rs index bd5c472a..26915085 100644 --- a/crates/cluster/src/maintenance.rs +++ b/crates/cluster/src/maintenance.rs @@ -38,40 +38,13 @@ impl Started { } } -/// [`Maintenance`] has been completed. -pub struct Completed { - /// ID of the [`node_operator`] that completed the [`Maintenance`]. - pub operator_id: node_operator::Id, - - /// Updated [`ClusterVersion`]. - pub cluster_version: ClusterVersion, -} - -impl Completed { - pub(super) fn apply(self, view: &mut ClusterView) -> Result<(), LogicalError> { - let maintenance = view.has_maintenance()?; - - if maintenance.operator_id != self.operator_id { - return Err(LogicalError::MaintenanceNodeOperatorIdMismatch { - event: self.operator_id, - local: maintenance.operator_id, - }); - } - - drop(maintenance); - view.maintenance = None; - - Ok(()) - } -} - -/// [`Maintenance`] has been aborted. -pub struct Aborted { +/// [`Maintenance`] has been finished. +pub struct Finished { /// Updated [`ClusterVersion`]. pub cluster_version: ClusterVersion, } -impl Aborted { +impl Finished { pub(super) fn apply(self, view: &mut ClusterView) -> Result<(), LogicalError> { view.has_maintenance()?; view.maintenance = None; diff --git a/crates/cluster/src/node_operator.rs b/crates/cluster/src/node_operator.rs index be64f477..f529e11c 100644 --- a/crates/cluster/src/node_operator.rs +++ b/crates/cluster/src/node_operator.rs @@ -96,7 +96,22 @@ impl NodeOperator { } } -/// On-chain state of an [`NodeOperator`] has been updated. +/// Event of a new [`NodeOperator`] being added to a WCN cluster. +pub struct Added { + /// [`NodeOperator`] being added. + pub operator: NodeOperator, + + /// Updated [`ClusterVersion`]. + pub cluster_version: ClusterVersion, +} + +impl Added { + pub(super) fn apply(self, view: &mut ClusterView) -> Result<(), LogicalError> { + todo!() + } +} + +/// Event of a [`NodeOperator`] [`Data`] being updated. pub struct Updated { /// Updated [`NodeOperator`]. pub operator: NodeOperator, @@ -132,6 +147,21 @@ impl Updated { } } +/// Event of a [`NodeOperator`] being removed from a WCN cluster. +pub struct Removed { + /// [`Id`] of the [`NodeOperator`] being removed. + pub id: Id, + + /// Updated [`ClusterVersion`]. + pub cluster_version: ClusterVersion, +} + +impl Removed { + pub(super) fn apply(self, view: &mut ClusterView) -> Result<(), LogicalError> { + todo!() + } +} + impl NewNodeOperator { pub(super) fn serialize(self) -> Result { Ok(NodeOperator { diff --git a/crates/cluster/src/smart_contract/evm.rs b/crates/cluster/src/smart_contract/evm.rs index 8b4dc197..a35e46a7 100644 --- a/crates/cluster/src/smart_contract/evm.rs +++ b/crates/cluster/src/smart_contract/evm.rs @@ -7,7 +7,8 @@ use { mod bindings { alloy::sol!( #[sol(rpc)] - "../../contracts/src/Cluster.sol" + Cluster, + "../../contracts/out/Cluster.sol/Cluster.json", ); } From b6817f97c9a8560b37427cafcf4055cfebea162d Mon Sep 17 00:00:00 2001 From: Github Bot Date: Thu, 29 May 2025 22:45:52 +0000 Subject: [PATCH 27/79] Bump VERSION to 250529.0 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 6fc3d08d..019c40eb 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -250528.0 +250529.0 From 27451ed46bf5c533fdf2db44fd272f90666ad63e Mon Sep 17 00:00:00 2001 From: Darksome Date: Mon, 2 Jun 2025 15:34:57 +0000 Subject: [PATCH 28/79] another SC overhaul --- contracts/foundry.toml | 3 + contracts/out/Cluster.sol/Bitmask.json | 2 +- contracts/out/Cluster.sol/Cluster.json | 2 +- contracts/soldeer.lock | 7 + contracts/src/Cluster.sol | 266 ++++------ contracts/test/Suite.sol | 613 ++++++++++++----------- crates/cluster/src/keyspace.rs | 13 +- crates/cluster/src/lib.rs | 48 +- crates/cluster/src/migration.rs | 6 +- crates/cluster/src/node_operator.rs | 51 +- crates/cluster/src/smart_contract/evm.rs | 10 +- crates/cluster/src/smart_contract/mod.rs | 26 +- 12 files changed, 490 insertions(+), 557 deletions(-) diff --git a/contracts/foundry.toml b/contracts/foundry.toml index 9977ac1c..2d21a26d 100644 --- a/contracts/foundry.toml +++ b/contracts/foundry.toml @@ -3,7 +3,10 @@ src = "src" out = "out" libs = ["dependencies"] +remappings = ["openzeppelin-contracts/=./dependencies/@openzeppelin-contracts-5.3.0/"] + [dependencies] forge-std = "1.9.7" +"@openzeppelin-contracts" = "5.3.0" # See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options diff --git a/contracts/out/Cluster.sol/Bitmask.json b/contracts/out/Cluster.sol/Bitmask.json index ecd27e45..52be07a0 100644 --- a/contracts/out/Cluster.sol/Bitmask.json +++ b/contracts/out/Cluster.sol/Bitmask.json @@ -1 +1 @@ -{"abi":[],"bytecode":{"object":"0x608060405234601d57600e6021565b603e602c823930815050603e90f35b6027565b60405190565b5f80fdfe60806040525f80fdfea2646970667358221220c3467853a46be3b5ea2da8aadd52764c5be8b8225fef262a18ff8f7bbb94d55764736f6c634300081c0033","sourceMap":"12772:953:22:-:0;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;","linkReferences":{}},"deployedBytecode":{"object":"0x60806040525f80fdfea2646970667358221220c3467853a46be3b5ea2da8aadd52764c5be8b8225fef262a18ff8f7bbb94d55764736f6c634300081c0033","sourceMap":"12772:953:22:-:0;;;;;","linkReferences":{}},"methodIdentifiers":{},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.28+commit.7893614a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/Cluster.sol\":\"Bitmask\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[\":@openzeppelin/contracts/=dependencies/openzeppelin-contracts/contracts/\",\":erc4626-tests/=dependencies/openzeppelin-contracts/lib/erc4626-tests/\",\":forge-std-1.9.7/=dependencies/forge-std-1.9.7/src/\",\":forge-std/=dependencies/openzeppelin-contracts/lib/forge-std/src/\",\":halmos-cheatcodes/=dependencies/openzeppelin-contracts/lib/halmos-cheatcodes/src/\",\":openzeppelin-contracts/=dependencies/openzeppelin-contracts/\"],\"viaIR\":true},\"sources\":{\"dependencies/openzeppelin-contracts/contracts/utils/Panic.sol\":{\"keccak256\":\"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a\",\"dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG\"]},\"dependencies/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0x1225214420c83ebcca88f2ae2b50f053aaa7df7bd684c3e878d334627f2edfc6\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6c5fab4970634f9ab9a620983dc1c8a30153981a0b1a521666e269d0a11399d3\",\"dweb:/ipfs/QmVRnBC575MESGkEHndjujtR7qub2FzU9RWy9eKLp4hPZB\"]},\"dependencies/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\":{\"keccak256\":\"0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b1d578337048cad08c1c03041cca5978eff5428aa130c781b271ad9e5566e1f8\",\"dweb:/ipfs/QmPFKL2r9CBsMwmUqqdcFPfHZB2qcs9g1HDrPxzWSxomvy\"]},\"src/Cluster.sol\":{\"keccak256\":\"0xfd4a17d0b8327f8248d37ae5b16b7076095a7b4f6ed1d75f859446b33c086a88\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://91b3747c61898f3f65d064a173e6795fede772a88d3848870bf73266498dc71f\",\"dweb:/ipfs/QmStHTacgfN8y7nzkFrju9GGVV7kv5WD9ez2yeTP8YgcAe\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.28+commit.7893614a"},"language":"Solidity","output":{"abi":[],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"remappings":["@openzeppelin/contracts/=dependencies/openzeppelin-contracts/contracts/","erc4626-tests/=dependencies/openzeppelin-contracts/lib/erc4626-tests/","forge-std-1.9.7/=dependencies/forge-std-1.9.7/src/","forge-std/=dependencies/openzeppelin-contracts/lib/forge-std/src/","halmos-cheatcodes/=dependencies/openzeppelin-contracts/lib/halmos-cheatcodes/src/","openzeppelin-contracts/=dependencies/openzeppelin-contracts/"],"optimizer":{"enabled":false,"runs":200},"metadata":{"bytecodeHash":"ipfs"},"compilationTarget":{"src/Cluster.sol":"Bitmask"},"evmVersion":"cancun","libraries":{},"viaIR":true},"sources":{"dependencies/openzeppelin-contracts/contracts/utils/Panic.sol":{"keccak256":"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a","urls":["bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a","dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG"],"license":"MIT"},"dependencies/openzeppelin-contracts/contracts/utils/math/Math.sol":{"keccak256":"0x1225214420c83ebcca88f2ae2b50f053aaa7df7bd684c3e878d334627f2edfc6","urls":["bzz-raw://6c5fab4970634f9ab9a620983dc1c8a30153981a0b1a521666e269d0a11399d3","dweb:/ipfs/QmVRnBC575MESGkEHndjujtR7qub2FzU9RWy9eKLp4hPZB"],"license":"MIT"},"dependencies/openzeppelin-contracts/contracts/utils/math/SafeCast.sol":{"keccak256":"0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54","urls":["bzz-raw://b1d578337048cad08c1c03041cca5978eff5428aa130c781b271ad9e5566e1f8","dweb:/ipfs/QmPFKL2r9CBsMwmUqqdcFPfHZB2qcs9g1HDrPxzWSxomvy"],"license":"MIT"},"src/Cluster.sol":{"keccak256":"0xfd4a17d0b8327f8248d37ae5b16b7076095a7b4f6ed1d75f859446b33c086a88","urls":["bzz-raw://91b3747c61898f3f65d064a173e6795fede772a88d3848870bf73266498dc71f","dweb:/ipfs/QmStHTacgfN8y7nzkFrju9GGVV7kv5WD9ez2yeTP8YgcAe"],"license":"MIT"}},"version":1},"id":22} \ No newline at end of file +{"abi":[],"bytecode":{"object":"0x608060405234601d57600e6021565b603e602c823930815050603e90f35b6027565b60405190565b5f80fdfe60806040525f80fdfea26469706673582212209214e53cf637b9ecf7ac29bc4f2b6d20a74434c2aa0e3cb577b8e0dcd1b9e88564736f6c634300081c0033","sourceMap":"8863:1079:24:-:0;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;","linkReferences":{}},"deployedBytecode":{"object":"0x60806040525f80fdfea26469706673582212209214e53cf637b9ecf7ac29bc4f2b6d20a74434c2aa0e3cb577b8e0dcd1b9e88564736f6c634300081c0033","sourceMap":"8863:1079:24:-:0;;;;;","linkReferences":{}},"methodIdentifiers":{},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.28+commit.7893614a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/Cluster.sol\":\"Bitmask\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[\":@openzeppelin-contracts-5.3.0/=dependencies/@openzeppelin-contracts-5.3.0/\",\":forge-std-1.9.7/=dependencies/forge-std-1.9.7/src/\",\":forge-std/=dependencies/forge-std/src/\",\":openzeppelin-contracts/=dependencies/@openzeppelin-contracts-5.3.0/\"],\"viaIR\":true},\"sources\":{\"dependencies/openzeppelin-contracts/utils/Panic.sol\":{\"keccak256\":\"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a\",\"dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG\"]},\"dependencies/openzeppelin-contracts/utils/math/Math.sol\":{\"keccak256\":\"0x1225214420c83ebcca88f2ae2b50f053aaa7df7bd684c3e878d334627f2edfc6\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6c5fab4970634f9ab9a620983dc1c8a30153981a0b1a521666e269d0a11399d3\",\"dweb:/ipfs/QmVRnBC575MESGkEHndjujtR7qub2FzU9RWy9eKLp4hPZB\"]},\"dependencies/openzeppelin-contracts/utils/math/SafeCast.sol\":{\"keccak256\":\"0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b1d578337048cad08c1c03041cca5978eff5428aa130c781b271ad9e5566e1f8\",\"dweb:/ipfs/QmPFKL2r9CBsMwmUqqdcFPfHZB2qcs9g1HDrPxzWSxomvy\"]},\"src/Cluster.sol\":{\"keccak256\":\"0x8ade3b168437cafe86f09cb2c71514eb497e9e25b9f9b836497e05942427217b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://1a4141701f07e7ccd86e1573762adfd8dd292eb286ce6a113d7baae6bbc9f087\",\"dweb:/ipfs/QmYGCqntKqzcfeCnDx667mgQn9vVYKXFokJvt8Kp2Lycxn\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.28+commit.7893614a"},"language":"Solidity","output":{"abi":[],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"remappings":["@openzeppelin-contracts-5.3.0/=dependencies/@openzeppelin-contracts-5.3.0/","forge-std-1.9.7/=dependencies/forge-std-1.9.7/src/","forge-std/=dependencies/forge-std/src/","openzeppelin-contracts/=dependencies/@openzeppelin-contracts-5.3.0/"],"optimizer":{"enabled":false,"runs":200},"metadata":{"bytecodeHash":"ipfs"},"compilationTarget":{"src/Cluster.sol":"Bitmask"},"evmVersion":"cancun","libraries":{},"viaIR":true},"sources":{"dependencies/openzeppelin-contracts/utils/Panic.sol":{"keccak256":"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a","urls":["bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a","dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG"],"license":"MIT"},"dependencies/openzeppelin-contracts/utils/math/Math.sol":{"keccak256":"0x1225214420c83ebcca88f2ae2b50f053aaa7df7bd684c3e878d334627f2edfc6","urls":["bzz-raw://6c5fab4970634f9ab9a620983dc1c8a30153981a0b1a521666e269d0a11399d3","dweb:/ipfs/QmVRnBC575MESGkEHndjujtR7qub2FzU9RWy9eKLp4hPZB"],"license":"MIT"},"dependencies/openzeppelin-contracts/utils/math/SafeCast.sol":{"keccak256":"0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54","urls":["bzz-raw://b1d578337048cad08c1c03041cca5978eff5428aa130c781b271ad9e5566e1f8","dweb:/ipfs/QmPFKL2r9CBsMwmUqqdcFPfHZB2qcs9g1HDrPxzWSxomvy"],"license":"MIT"},"src/Cluster.sol":{"keccak256":"0x8ade3b168437cafe86f09cb2c71514eb497e9e25b9f9b836497e05942427217b","urls":["bzz-raw://1a4141701f07e7ccd86e1573762adfd8dd292eb286ce6a113d7baae6bbc9f087","dweb:/ipfs/QmYGCqntKqzcfeCnDx667mgQn9vVYKXFokJvt8Kp2Lycxn"],"license":"MIT"}},"version":1},"id":24} \ No newline at end of file diff --git a/contracts/out/Cluster.sol/Cluster.json b/contracts/out/Cluster.sol/Cluster.json index a42de7b4..24436f05 100644 --- a/contracts/out/Cluster.sol/Cluster.json +++ b/contracts/out/Cluster.sol/Cluster.json @@ -1 +1 @@ -{"abi":[{"type":"constructor","inputs":[{"name":"initialSettings","type":"tuple","internalType":"struct Settings","components":[{"name":"maxOperatorDataBytes","type":"uint16","internalType":"uint16"}]},{"name":"initialOperators","type":"tuple[]","internalType":"struct NodeOperator[]","components":[{"name":"addr","type":"address","internalType":"address"},{"name":"data","type":"bytes","internalType":"bytes"}]}],"stateMutability":"nonpayable"},{"type":"function","name":"abortMigration","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"completeMigration","inputs":[{"name":"id","type":"uint64","internalType":"uint64"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"createNodeOperator","inputs":[{"name":"operator","type":"tuple","internalType":"struct NodeOperator","components":[{"name":"addr","type":"address","internalType":"address"},{"name":"data","type":"bytes","internalType":"bytes"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"deleteNodeOperator","inputs":[{"name":"operatorAddress","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"finishMaintenance","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"getView","inputs":[],"outputs":[{"name":"","type":"tuple","internalType":"struct ClusterView","components":[{"name":"keyspace","type":"tuple","internalType":"struct KeyspaceView","components":[{"name":"operators","type":"tuple[]","internalType":"struct NodeOperator[]","components":[{"name":"addr","type":"address","internalType":"address"},{"name":"data","type":"bytes","internalType":"bytes"}]},{"name":"replicationStrategy","type":"uint8","internalType":"uint8"}]},{"name":"migration","type":"tuple","internalType":"struct Migration","components":[{"name":"id","type":"uint64","internalType":"uint64"},{"name":"pullingOperatorsBitmask","type":"uint256","internalType":"uint256"}]},{"name":"migrationKeyspace","type":"tuple","internalType":"struct KeyspaceView","components":[{"name":"operators","type":"tuple[]","internalType":"struct NodeOperator[]","components":[{"name":"addr","type":"address","internalType":"address"},{"name":"data","type":"bytes","internalType":"bytes"}]},{"name":"replicationStrategy","type":"uint8","internalType":"uint8"}]},{"name":"maintenance","type":"tuple","internalType":"struct Maintenance","components":[{"name":"slot","type":"address","internalType":"address"}]},{"name":"keyspaceVersion","type":"uint64","internalType":"uint64"},{"name":"version","type":"uint128","internalType":"uint128"}]}],"stateMutability":"view"},{"type":"function","name":"startMaintenance","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"startMigration","inputs":[{"name":"plan","type":"tuple","internalType":"struct MigrationPlan","components":[{"name":"slots","type":"tuple[]","internalType":"struct KeyspaceSlot[]","components":[{"name":"idx","type":"uint8","internalType":"uint8"},{"name":"operatorAddress","type":"address","internalType":"address"}]},{"name":"replicationStrategy","type":"uint8","internalType":"uint8"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"transferOwnership","inputs":[{"name":"newOwner","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateNodeOperator","inputs":[{"name":"operator","type":"tuple","internalType":"struct NodeOperator","components":[{"name":"addr","type":"address","internalType":"address"},{"name":"data","type":"bytes","internalType":"bytes"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateSettings","inputs":[{"name":"newSettings","type":"tuple","internalType":"struct Settings","components":[{"name":"maxOperatorDataBytes","type":"uint16","internalType":"uint16"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"event","name":"MaintenanceFinished","inputs":[{"name":"operatorAddress","type":"address","indexed":false,"internalType":"address"},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"MaintenanceStarted","inputs":[{"name":"operatorAddress","type":"address","indexed":false,"internalType":"address"},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"MigrationAborted","inputs":[{"name":"id","type":"uint64","indexed":false,"internalType":"uint64"},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"MigrationCompleted","inputs":[{"name":"id","type":"uint64","indexed":false,"internalType":"uint64"},{"name":"operatorAddress","type":"address","indexed":false,"internalType":"address"},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"MigrationDataPullCompleted","inputs":[{"name":"id","type":"uint64","indexed":false,"internalType":"uint64"},{"name":"operatorAddress","type":"address","indexed":false,"internalType":"address"},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"MigrationStarted","inputs":[{"name":"id","type":"uint64","indexed":false,"internalType":"uint64"},{"name":"plan","type":"tuple","indexed":false,"internalType":"struct MigrationPlan","components":[{"name":"slots","type":"tuple[]","internalType":"struct KeyspaceSlot[]","components":[{"name":"idx","type":"uint8","internalType":"uint8"},{"name":"operatorAddress","type":"address","internalType":"address"}]},{"name":"replicationStrategy","type":"uint8","internalType":"uint8"}]},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"NodeOperatorCreated","inputs":[{"name":"operator","type":"tuple","indexed":false,"internalType":"struct NodeOperator","components":[{"name":"addr","type":"address","internalType":"address"},{"name":"data","type":"bytes","internalType":"bytes"}]},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"NodeOperatorDeleted","inputs":[{"name":"operatorAddress","type":"address","indexed":false,"internalType":"address"},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"NodeOperatorUpdated","inputs":[{"name":"operator","type":"tuple","indexed":false,"internalType":"struct NodeOperator","components":[{"name":"addr","type":"address","internalType":"address"},{"name":"data","type":"bytes","internalType":"bytes"}]},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"name":"newOwner","type":"address","indexed":false,"internalType":"address"},{"name":"cluserVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"SettingsUpdated","inputs":[{"name":"newSettings","type":"tuple","indexed":false,"internalType":"struct Settings","components":[{"name":"maxOperatorDataBytes","type":"uint16","internalType":"uint16"}]},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false}],"bytecode":{"object":"0x6080604052346100305761001a61001461030f565b90610a8f565b610022610035565b613d5a610edd8239613d5a90f35b61003b565b60405190565b5f80fd5b601f801991011690565b634e487b7160e01b5f52604160045260245ffd5b906100679061003f565b810190811060018060401b0382111761007f57604052565b610049565b90610097610090610035565b928361005d565b565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b61ffff1690565b6100b9816100a9565b036100c057565b5f80fd5b905051906100d1826100b0565b565b91906020838203126100fb576100f5906100ed6020610084565b935f016100c4565b5f830152565b6100a1565b5f80fd5b60018060401b03811161011a5760208091020190565b610049565b5f80fd5b60018060a01b031690565b61013790610123565b90565b6101438161012e565b0361014a57565b5f80fd5b9050519061015b8261013a565b565b5f80fd5b60018060401b03811161017d5761017960209161003f565b0190565b610049565b90825f9392825e0152565b909291926101a261019d82610161565b610084565b938185526020850190828401116101be576101bc92610182565b565b61015d565b9080601f830112156101e1578160206101de9351910161018d565b90565b610100565b919091604081840312610236576101fd6040610084565b9261020a815f840161014e565b5f850152602082015160018060401b0381116102315761022a92016101c3565b6020830152565b6100a5565b6100a1565b92919061024f61024a82610104565b610084565b93818552602080860192028101918383116102a45781905b838210610275575050505050565b815160018060401b03811161029f5760209161029487849387016101e6565b815201910190610267565b610100565b61011f565b9080601f830112156102c7578160206102c49351910161023b565b90565b610100565b91909160408184031261030a576102e5835f83016100d3565b92602082015160018060401b0381116103055761030292016102a9565b90565b61009d565b610099565b61032d614c378038038061032281610084565b9283398101906102cc565b9091565b5190565b90565b90565b90565b61035261034d61035792610338565b61033b565b610335565b90565b60209181520190565b5f7f746f6f206d616e79206f70657261746f72730000000000000000000000000000910152565b610397601260209261035a565b6103a081610363565b0190565b6103b99060208101905f81830391015261038a565b90565b156103c357565b6103cb610035565b62461bcd60e51b8152806103e1600482016103a4565b0390fd5b5f1b90565b906103fb60018060a01b03916103e5565b9181191691161790565b61041961041461041e92610123565b61033b565b610123565b90565b61042a90610405565b90565b61043690610421565b90565b90565b9061045161044c6104589261042d565b610439565b82546103ea565b9055565b61046690516100a9565b90565b9061047661ffff916103e5565b9181191691161790565b61049461048f610499926100a9565b61033b565b6100a9565b90565b90565b906104b46104af6104bb92610480565b61049c565b8254610469565b9055565b906104d15f806104d79401920161045c565b9061049f565b565b906104e3916104bf565b565b90565b6104fc6104f7610501926104e5565b61033b565b610335565b90565b60016105109101610335565b90565b634e487b7160e01b5f52603260045260245ffd5b9061053182610331565b811015610542576020809102010190565b610513565b5190565b610555905161012e565b90565b906105629061042d565b5f5260205260405f2090565b634e487b7160e01b5f52602260045260245ffd5b90600160028304921680156105a2575b602083101461059d57565b61056e565b91607f1691610592565b6105b69054610582565b90565b5f7f6475706c6963617465206f70657261746f720000000000000000000000000000910152565b6105ed601260209261035a565b6105f6816105b9565b0190565b61060f9060208101905f8183039101526105e0565b90565b1561061957565b610621610035565b62461bcd60e51b815280610637600482016105fa565b0390fd5b50600290565b90565b61064d8161063b565b8210156106685761066061010391610641565b910201905f90565b610513565b5061010090565b90565b6106808161066d565b82101561069a57610692600191610674565b910201905f90565b610513565b1b90565b919060086106c39102916106bd60018060a01b038461069f565b9261069f565b9181191691161790565b91906106e36106de6106eb9361042d565b610439565b9083546106a3565b9055565b60ff1690565b61070961070461070e92610335565b61033b565b6106ef565b90565b61071b6040610084565b90565b151590565b9061072d9061071e565b9052565b9061073b906106ef565b9052565b906107499061042d565b5f5260205260405f2090565b61075f905161071e565b90565b9061076e60ff916103e5565b9181191691161790565b6107819061071e565b90565b90565b9061079c6107976107a392610778565b610784565b8254610762565b9055565b6107b190516106ef565b90565b60081b90565b906107c761ff00916107b4565b9181191691161790565b6107e56107e06107ea926106ef565b61033b565b6106ef565b90565b90565b9061080561080061080c926107d1565b6107ed565b82546107ba565b9055565b9061083a60205f6108409461083282820161082c848801610755565b90610787565b0192016107a7565b906107f0565b565b9061084c91610810565b565b5f5260205f2090565b601f602091010490565b9190600861087c9102916108765f198461069f565b9261069f565b9181191691161790565b61089a61089561089f92610335565b61033b565b610335565b90565b90565b91906108bb6108b66108c393610886565b6108a2565b908354610861565b9055565b5f90565b6108dd916108d76108c7565b916108a5565b565b5b8181106108eb575050565b806108f85f6001936108cb565b016108e0565b9190601f811161090e575b505050565b61091a61093f9361084e565b90602061092684610857565b83019310610947575b61093890610857565b01906108df565b5f8080610909565b91506109388192905061092f565b1c90565b90610969905f1990600802610955565b191690565b8161097891610959565b906002021790565b9061098a81610547565b9060018060401b038211610a48576109ac826109a68554610582565b856108fe565b602090601f83116001146109e0579180916109cf935f926109d4575b505061096e565b90555b565b90915001515f806109c8565b601f198316916109ef8561084e565b925f5b818110610a3057509160029391856001969410610a16575b505050020190556109d2565b610a26910151601f841690610959565b90555f8080610a0a565b919360206001819287870151815501950192016109f2565b610049565b90610a5791610980565b565b90610a655f19916103e5565b9181191691161790565b90610a84610a7f610a8b92610886565b6108a2565b8254610a59565b9055565b610acc90610aba610a9f84610331565b610ab3610aad61010061033e565b91610335565b11156103bc565b610ac4335f61043c565b6102096104d9565b610ad55f6104e8565b5b80610af1610aeb610ae685610331565b610335565b91610335565b1015610c3c57610c3790610b1b610b166020610b0e868590610527565b510151610547565b610dbe565b610b5f610b47610b426001610b3c5f610b35898890610527565b510161054b565b90610558565b6105ac565b610b59610b535f6104e8565b91610335565b14610612565b610b98610b785f610b71868590610527565b510161054b565b610b926001610b8960025f90610644565b50018490610677565b906106cd565b610bf96001610bc6610ba9846106f5565b610bbd610bb4610711565b935f8501610723565b60208301610731565b610bf45f610bd660028290610644565b5001610bee5f610be7898890610527565b510161054b565b9061073f565b610842565b610c326020610c09858490610527565b510151610c2d6001610c275f610c20898890610527565b510161054b565b90610558565b610a4d565b610504565b610ad6565b50610c59610c54610c4f610c6f93610331565b6106f5565b610ea0565b610101610c6860025f90610644565b5001610a6f565b565b5f7f656d707479206f70657261746f72206461746100000000000000000000000000910152565b610ca5601360209261035a565b610cae81610c71565b0190565b610cc79060208101905f818303910152610c98565b90565b15610cd157565b610cd9610035565b62461bcd60e51b815280610cef60048201610cb2565b0390fd5b5f1c90565b61ffff1690565b610d0b610d1091610cf3565b610cf8565b90565b610d1d9054610cff565b90565b610d34610d2f610d39926100a9565b61033b565b610335565b90565b5f7f6f70657261746f72206461746120746f6f206c61726765000000000000000000910152565b610d70601760209261035a565b610d7981610d3c565b0190565b610d929060208101905f818303910152610d63565b90565b15610d9c57565b610da4610035565b62461bcd60e51b815280610dba60048201610d7d565b0390fd5b610e0390610dde81610dd8610dd25f6104e8565b91610335565b11610cca565b610dfc610df6610df15f61020901610d13565b610d20565b91610335565b1115610d95565b565b610e19610e14610e1e926106ef565b61033b565b610335565b90565b90565b610e38610e33610e3d92610e21565b61033b565b610335565b90565b610e5f90610e59610e53610e6494610335565b91610335565b9061069f565b610335565b90565b634e487b7160e01b5f52601160045260245ffd5b610e8a610e9091939293610335565b92610335565b8203918211610e9b57565b610e67565b610ec9610ed991610eaf6108c7565b50610ec4610ebe600192610e05565b91610e24565b610e40565b610ed36001610e24565b90610e7b565b9056fe60806040526004361015610013575b6106f7565b61001d5f356100cc565b806326322217146100c757806353bfb584146100c257806365706f9c146100bd57806375418b9d146100b85780639d44e717146100b3578063b55a4142146100ae578063c130809a146100a9578063cdbfc62d146100a4578063db1b0fd71461009f578063f2fde38b1461009a5763f5f2d9f10361000e576106c4565b610691565b61065e565b6105ea565b61056f565b61053c565b610509565b610493565b6101db565b610177565b610135565b60e01c90565b60405190565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b908160409103126100f65790565b6100e4565b9060208282031261012b575f82013567ffffffffffffffff81116101265761012392016100e8565b90565b6100e0565b6100dc565b5f0190565b346101635761014d6101483660046100fb565b610d6f565b6101556100d2565b8061015f81610130565b0390f35b6100d8565b5f91031261017257565b6100dc565b346101a557610187366004610168565b61018f6110b2565b6101976100d2565b806101a181610130565b0390f35b6100d8565b908160209103126101b85790565b6100e4565b906020828203126101d6576101d3915f016101aa565b90565b6100dc565b34610209576101f36101ee3660046101bd565b6112ee565b6101fb6100d2565b8061020581610130565b0390f35b6100d8565b5190565b60209181520190565b60200190565b60018060a01b031690565b61023590610221565b90565b6102419061022c565b9052565b5190565b60209181520190565b90825f9392825e0152565b601f801991011690565b61028661028f6020936102949361027d81610245565b93848093610249565b95869101610252565b61025d565b0190565b6102c391602060408201926102b35f8201515f850190610238565b0151906020818403910152610267565b90565b906102d091610298565b90565b60200190565b906102ed6102e68361020e565b8092610212565b90816102fe6020830284019461021b565b925f915b83831061031157505050505090565b9091929394602061033361032d838560019503875289516102c6565b976102d3565b9301930191939290610302565b60ff1690565b61034f90610340565b9052565b9061037d90602080610372604084015f8701518582035f8701526102d9565b940151910190610346565b90565b67ffffffffffffffff1690565b61039690610380565b9052565b90565b6103a69061039a565b9052565b906020806103cc936103c25f8201515f86019061038d565b015191019061039d565b565b905f806103df930151910190610238565b565b6fffffffffffffffffffffffffffffffff1690565b6103ff906103e1565b9052565b906104789060c060a061044a61042660e085015f8801518682035f880152610353565b610438602088015160208701906103aa565b60408701518582036060870152610353565b9461045d606082015160808601906103ce565b61046e60808201518386019061038d565b01519101906103f6565b90565b6104909160208201915f818403910152610403565b90565b346104c3576104a3366004610168565b6104bf6104ae6118a9565b6104b66100d2565b9182918261047b565b0390f35b6100d8565b6104d181610380565b036104d857565b5f80fd5b905035906104e9826104c8565b565b9060208282031261050457610501915f016104dc565b90565b6100dc565b346105375761052161051c3660046104eb565b6121b7565b6105296100d2565b8061053381610130565b0390f35b6100d8565b3461056a5761055461054f3660046100fb565b61235c565b61055c6100d2565b8061056681610130565b0390f35b6100d8565b3461059d5761057f366004610168565b6105876124f0565b61058f6100d2565b8061059981610130565b0390f35b6100d8565b908160409103126105b05790565b6100e4565b906020828203126105e5575f82013567ffffffffffffffff81116105e0576105dd92016105a2565b90565b6100e0565b6100dc565b34610618576106026105fd3660046105b5565b61297e565b61060a6100d2565b8061061481610130565b0390f35b6100d8565b6106268161022c565b0361062d57565b5f80fd5b9050359061063e8261061d565b565b9060208282031261065957610656915f01610631565b90565b6100dc565b3461068c57610676610671366004610640565b612d62565b61067e6100d2565b8061068881610130565b0390f35b6100d8565b346106bf576106a96106a4366004610640565b612e0a565b6106b16100d2565b806106bb81610130565b0390f35b6100d8565b346106f2576106d4366004610168565b6106dc612f45565b6106e46100d2565b806106ee81610130565b0390f35b6100d8565b5f80fd5b5f1c90565b60018060a01b031690565b61071761071c916106fb565b610700565b90565b610729905461070b565b90565b356107368161061d565b90565b60209181520190565b5f7f756e617574686f72697a65640000000000000000000000000000000000000000910152565b610776600c602092610739565b61077f81610742565b0190565b6107989060208101905f818303910152610769565b90565b156107a257565b6107aa6100d2565b62461bcd60e51b8152806107c060048201610783565b0390fd5b90565b6107db6107d66107e092610221565b6107c4565b610221565b90565b6107ec906107c7565b90565b6107f8906107e3565b90565b90610805906107ef565b5f5260205260405f2090565b634e487b7160e01b5f52602260045260245ffd5b9060016002830492168015610845575b602083101461084057565b610811565b91607f1691610835565b6108599054610825565b90565b90565b61087361086e6108789261085c565b6107c4565b61039a565b90565b5f7f756e6b6e6f776e206f70657261746f7200000000000000000000000000000000910152565b6108af6010602092610739565b6108b88161087b565b0190565b6108d19060208101905f8183039101526108a2565b90565b156108db57565b6108e36100d2565b62461bcd60e51b8152806108f9600482016108bc565b0390fd5b5f80fd5b5f80fd5b5f80fd5b90359060016020038136030382121561094b570180359067ffffffffffffffff82116109465760200191600182023603831361094157565b610905565b610901565b6108fd565b5090565b634e487b7160e01b5f525f60045260245ffd5b634e487b7160e01b5f52604160045260245ffd5b5f5260205f2090565b601f602091010490565b1b90565b919060086109ad9102916109a75f198461098e565b9261098e565b9181191691161790565b6109cb6109c66109d09261039a565b6107c4565b61039a565b90565b90565b91906109ec6109e76109f4936109b7565b6109d3565b908354610992565b9055565b5f90565b610a0e91610a086109f8565b916109d6565b565b5b818110610a1c575050565b80610a295f6001936109fc565b01610a11565b9190601f8111610a3f575b505050565b610a4b610a709361097b565b906020610a5784610984565b83019310610a78575b610a6990610984565b0190610a10565b5f8080610a3a565b9150610a6981929050610a60565b1c90565b90610a9a905f1990600802610a86565b191690565b81610aa991610a8a565b906002021790565b91610abc9082610950565b9067ffffffffffffffff8211610b7b57610ae082610ada8554610825565b85610a2f565b5f90601f8311600114610b1357918091610b02935f92610b07575b5050610a9f565b90555b565b90915001355f80610afb565b601f19831691610b228561097b565b925f5b818110610b6357509160029391856001969410610b49575b50505002019055610b05565b610b59910135601f841690610a8a565b90555f8080610b3d565b91936020600181928787013581550195019201610b25565b610967565b90610b8b9291610ab1565b565b6fffffffffffffffffffffffffffffffff1690565b610bae610bb3916106fb565b610b8d565b90565b610bc09054610ba2565b90565b634e487b7160e01b5f52601160045260245ffd5b610be0906103e1565b6fffffffffffffffffffffffffffffffff8114610bfd5760010190565b610bc3565b5f1b90565b90610c226fffffffffffffffffffffffffffffffff91610c02565b9181191691161790565b610c40610c3b610c45926103e1565b6107c4565b6103e1565b90565b90565b90610c60610c5b610c6792610c2c565b610c48565b8254610c07565b9055565b50610c7a906020810190610631565b90565b5f80fd5b5f80fd5b5f80fd5b9035600160200382360303811215610cca57016020813591019167ffffffffffffffff8211610cc5576001820236038313610cc057565b610c81565b610c7d565b610c85565b90825f939282370152565b9190610cf481610ced81610cf995610249565b8095610ccf565b61025d565b0190565b610d3991610d2b6040820192610d21610d185f830183610c6b565b5f850190610238565b6020810190610c89565b916020818503910152610cda565b90565b610d45906103e1565b9052565b92916020610d65610d6d9360408701908782035f890152610cfd565b940190610d3c565b565b33610d8a610d84610d7f5f61071f565b61022c565b9161022c565b148015610e85575b610d9b9061079b565b610dd5610dbc610db76001610db15f860161072c565b906107fb565b61084f565b610dce610dc85f61085f565b9161039a565b14156108d4565b610df4610def610de9836020810190610909565b90610950565b613097565b610e21610e05826020810190610909565b90610e1c6001610e165f870161072c565b906107fb565b610b80565b610e3f610e37610e3261020d610bb6565b610bd7565b61020d610c4b565b610e4a61020d610bb6565b7f5aab2c32b1e447db4dba1d2790fe8b863d4775042b10b92e00dab9d6b671b5b591610e80610e776100d2565b92839283610d49565b0390a1565b50610d9b33610ea6610ea0610e9b5f860161072c565b61022c565b9161022c565b149050610d92565b5f7f6e6f206d61696e74656e616e6365000000000000000000000000000000000000910152565b610ee2600e602092610739565b610eeb81610eae565b0190565b610f049060208101905f818303910152610ed5565b90565b15610f0e57565b610f166100d2565b62461bcd60e51b815280610f2c60048201610eef565b0390fd5b610f40610f3b6130e2565b610f07565b610f48610fe0565b565b610f5e610f59610f639261085c565b6107c4565b610221565b90565b610f6f90610f4a565b90565b90610f8360018060a01b0391610c02565b9181191691161790565b90565b90610fa5610fa0610fac926107ef565b610f8d565b8254610f72565b9055565b610fb99061022c565b9052565b916020610fde929493610fd760408201965f830190610fb0565b0190610d3c565b565b33610ffb610ff5610ff05f61071f565b61022c565b9161022c565b148015611087575b61100c9061079b565b6110226110185f610f66565b5f61020c01610f90565b61104061103861103361020d610bb6565b610bd7565b61020d610c4b565b3361104c61020d610bb6565b7f2e1c659da2dc5f4ec69512e86bda1a7a48c5e97669b37f9bb5a3064b6353159f916110826110796100d2565b92839283610fbd565b0390a1565b5061100c6110985f61020c0161071f565b6110aa6110a43361022c565b9161022c565b149050611003565b6110ba610f30565b565b5f7f6e6f7420746865206f776e657200000000000000000000000000000000000000910152565b6110f0600d602092610739565b6110f9816110bc565b0190565b6111129060208101905f8183039101526110e3565b90565b1561111c57565b6111246100d2565b62461bcd60e51b81528061113a600482016110fd565b0390fd5b61116b906111663361116061115a6111555f61071f565b61022c565b9161022c565b14611115565b61127e565b565b61ffff1690565b61117d8161116d565b0361118457565b5f80fd5b3561119281611174565b90565b906111a261ffff91610c02565b9181191691161790565b6111c06111bb6111c59261116d565b6107c4565b61116d565b90565b90565b906111e06111db6111e7926111ac565b6111c8565b8254611195565b9055565b906111fd5f8061120394019201611188565b906111cb565b565b9061120f916111eb565b565b9050359061121e82611174565b565b5061122f906020810190611211565b90565b61123b9061116d565b9052565b905f6112516112599382810190611220565b910190611232565b565b91602061127c92949361127560408201965f83019061123f565b0190610d3c565b565b61128a81610209611205565b6112a86112a061129b61020d610bb6565b610bd7565b61020d610c4b565b6112b361020d610bb6565b7fb24d8d9dcfbb6be13176c1c7bfb0e76445a9ba2a3553b413d8671446f1030830916112e96112e06100d2565b9283928361125b565b0390a1565b6112f79061113e565b565b906113039061025d565b810190811067ffffffffffffffff82111761131d57604052565b610967565b9061133561132e6100d2565b92836112f9565b565b61134160c0611322565b90565b61134e6040611322565b90565b606090565b5f90565b611362611344565b906020808361136f611351565b81520161137a611356565b81525050565b61138861135a565b90565b6113956040611322565b90565b5f90565b5f90565b6113a861138b565b90602080836113b5611398565b8152016113c061139c565b81525050565b6113ce6113a0565b90565b6113db6020611322565b90565b5f90565b6113ea6113d1565b906020826113f66113de565b81525050565b6114046113e2565b90565b5f90565b611413611337565b906020808080808087611424611380565b81520161142f6113c6565b81520161143a611380565b8152016114456113fc565b815201611450611398565b81520161145b611407565b81525050565b61146961140b565b90565b5f90565b67ffffffffffffffff1690565b61148961148e916106fb565b611470565b90565b61149b905461147d565b90565b90565b6114b56114b06114ba9261149e565b6107c4565b610380565b90565b634e487b7160e01b5f52601260045260245ffd5b6114dd6114e391610380565b91610380565b9081156114ee570690565b6114bd565b61150761150261150c92610380565b6107c4565b61039a565b90565b9061151990610380565b9052565b90565b61152c611531916106fb565b61151d565b90565b61153e9054611520565b90565b9061154b9061039a565b9052565b90565b61156661156161156b9261154f565b6107c4565b610380565b90565b61157a61158091610380565b91610380565b90039067ffffffffffffffff821161159457565b610bc3565b634e487b7160e01b5f52603260045260245ffd5b50600290565b90565b6115bf816115ad565b8210156115da576115d2610103916115b3565b910201905f90565b611599565b6115f36115ee6115f89261154f565b6107c4565b61039a565b90565b61160a6116109193929361039a565b9261039a565b820180921161161b57565b610bc3565b67ffffffffffffffff81116116385760208091020190565b610967565b9061164f61164a83611620565b611322565b918252565b61165e6040611322565b90565b606090565b61166e611654565b906020808361167b6113de565b815201611686611661565b81525050565b611694611666565b90565b5f5b8281106116a557505050565b6020906116b061168c565b8184015201611699565b906116df6116c78361163d565b926020806116d58693611620565b9201910390611697565b565b60ff1690565b6116f36116f8916106fb565b6116e1565b90565b61170590546116e7565b90565b9061171290610340565b9052565b61171f9061039a565b5f19811461172d5760010190565b610bc3565b61174661174161174b9261039a565b6107c4565b610340565b90565b5061010090565b90565b6117618161174e565b82101561177b57611773600191611755565b910201905f90565b611599565b6117909060086117959302610a86565b610700565b90565b906117a39154611780565b90565b906117b08261020e565b8110156117c1576020809102010190565b611599565b906117d09061022c565b9052565b905f92918054906117ee6117e783610825565b8094610249565b916001811690815f146118455750600114611809575b505050565b611816919293945061097b565b915f925b81841061182d57505001905f8080611804565b6001816020929593955484860152019101929061181a565b92949550505060ff19168252151560200201905f8080611804565b9061186a916117d4565b90565b9061188d6118869261187d6100d2565b93848092611860565b03836112f9565b565b6118989061186d565b90565b906118a5906103e1565b9052565b6118b1611461565b506118ba611461565b6118c26109f8565b506118cb61146c565b506118d46109f8565b506118dd613117565b5f14611ccb576118ff6118f35f61020a01611491565b5f60208401510161150f565b61191c611910600161020a01611534565b60208084015101611541565b611955611950611940611930610208611491565b61193a6001611552565b9061156e565b61194a60026114a1565b906114d1565b6114f3565b9061197c611977611967610208611491565b61197160026114a1565b906114d1565b6114f3565b9161199e611999610101611992600287906115b6565b5001611534565b613145565b926119bb6119b6856119b060016115df565b906115fb565b6116ba565b5f604085015101526119ec6119df6101026119d8600285906115b6565b50016116fb565b6020604086015101611708565b6119f55f61085f565b5b80611a09611a038761039a565b9161039a565b11611b3957611ac090611a3d611a2e610101611a27600287906115b6565b5001611534565b611a3783611732565b9061319d565b611b3457611a64611a5e6001611a55600287906115b6565b50018390611758565b90611798565b611a82815f611a7b8160408b0151015186906117a6565b51016117c6565b611aad611a9e610101611a97600289906115b6565b5001611534565b611aa784611732565b9061319d565b8015611af7575b611ac5575b505b611716565b6119f6565b611ad09060016107fb565b611aef6020611ae75f60408a0151015185906117a6565b51019161188f565b90525f611ab9565b50611b1b611b156001611b0c600289906115b6565b50018490611758565b90611798565b611b2d611b278361022c565b9161022c565b1415611ab4565b611abb565b505091505b611b5f611b5a610101611b53600286906115b6565b5001611534565b613145565b91611b7c611b7784611b7160016115df565b906115fb565b6116ba565b5f808401510152611bab611b9f610102611b98600285906115b6565b50016116fb565b60205f85015101611708565b611bb45f61085f565b5b80611bc8611bc28661039a565b9161039a565b11611c7a57611c7090611bfc611bed610101611be6600287906115b6565b5001611534565b611bf683611732565b9061319d565b611c7557611c4a611c26611c206001611c17600288906115b6565b50018490611758565b90611798565b611c43815f611c3c81808b0151015187906117a6565b51016117c6565b60016107fb565b611c686020611c605f80890151015185906117a6565b51019161188f565b90525b611716565b611bb5565b611c6b565b50509050611c95611c8c610208611491565b6080830161150f565b611cb1611ca55f61020c0161071f565b5f6060840151016117c6565b611cc8611cbf61020d610bb6565b60a0830161189b565b90565b611cf1611cec611cdc610208611491565b611ce660026114a1565b906114d1565b6114f3565b90611b3e565b5f7f6e6f206d6967726174696f6e0000000000000000000000000000000000000000910152565b611d2b600c602092610739565b611d3481611cf7565b0190565b611d4d9060208101905f818303910152611d1e565b90565b15611d5757565b611d5f6100d2565b62461bcd60e51b815280611d7560048201611d38565b0390fd5b611d9290611d8d611d88613117565b611d50565b611fef565b565b5f7f77726f6e67206d6967726174696f6e2069640000000000000000000000000000910152565b611dc86012602092610739565b611dd181611d94565b0190565b611dea9060208101905f818303910152611dbb565b90565b15611df457565b611dfc6100d2565b62461bcd60e51b815280611e1260048201611dd5565b0390fd5b90611e20906107ef565b5f5260205260405f2090565b60ff1690565b611e3e611e43916106fb565b611e2c565b90565b611e509054611e32565b90565b151590565b90611e6290611e53565b9052565b60081c90565b611e78611e7d91611e66565b6116e1565b90565b611e8a9054611e6c565b90565b611e976040611322565b90565b90611ed0611ec75f611eaa611e8d565b94611ec1611eb9838301611e46565b838801611e58565b01611e80565b60208401611708565b565b611edb90611e9a565b90565b611ee89051611e53565b90565b611ef59051610340565b90565b5f7f6e6f742070756c6c696e67000000000000000000000000000000000000000000910152565b611f2c600b602092610739565b611f3581611ef8565b0190565b611f4e9060208101905f818303910152611f1f565b90565b15611f5857565b611f606100d2565b62461bcd60e51b815280611f7660048201611f39565b0390fd5b90611f865f1991610c02565b9181191691161790565b90611fa5611fa0611fac926109b7565b6109d3565b8254611f7a565b9055565b611fb990610380565b9052565b604090611fe6611fed9496959396611fdc60608401985f850190611fb0565b6020830190610fb0565b0190610d3c565b565b6120179061201161200b6120065f61020a01611491565b610380565b91610380565b14611ded565b6120c46120b961205b6120565f61204d6002612047612037610208611491565b61204160026114a1565b906114d1565b906115b6565b50013390611e16565b611ed2565b61206e6120695f8301611ede565b6108d4565b612099612094612082600161020a01611534565b61208e60208501611eeb565b906131db565b611f51565b6120b360206120ac600161020a01611534565b9201611eeb565b9061321a565b600161020a01611f90565b6120e26120da6120d561020d610bb6565b610bd7565b61020d610c4b565b6120f0600161020a01611534565b6121026120fc5f61085f565b9161039a565b145f1461215f576121165f61020a01611491565b3361212261020d610bb6565b916121597f01269879535f40ee8957e15e160bf1866c5e2728ff0cbc583d848821e2639b4e936121506100d2565b93849384611fbd565b0390a15b565b61216c5f61020a01611491565b3361217861020d610bb6565b916121af7faf5e90e72015f43138f66b4cd08bd1dfa2839030104f22a00af843fe847c6d19936121a66100d2565b93849384611fbd565b0390a161215d565b6121c090611d79565b565b6121ef906121ea336121e46121de6121d95f61071f565b61022c565b9161022c565b14611115565b612273565b565b5f7f6f70657261746f7220616c726561647920657869737473000000000000000000910152565b6122256017602092610739565b61222e816121f1565b0190565b6122479060208101905f818303910152612218565b90565b1561225157565b6122596100d2565b62461bcd60e51b81528061226f60048201612232565b0390fd5b6122ac61229461228f60016122895f860161072c565b906107fb565b61084f565b6122a66122a05f61085f565b9161039a565b1461224a565b6122cb6122c66122c0836020810190610909565b90610950565b613097565b6122f86122dc826020810190610909565b906122f360016122ed5f870161072c565b906107fb565b610b80565b61231661230e61230961020d610bb6565b610bd7565b61020d610c4b565b61232161020d610bb6565b7febdc606e899772e1d31d9535a98eea5ddb0d41e47128c921e64919c73f3edfa69161235761234e6100d2565b92839283610d49565b0390a1565b612365906121c2565b565b61238b3361238561237f61237a5f61071f565b61022c565b9161022c565b14611115565b612393612395565b565b6123a56123a0613117565b611d50565b6123ad61244a565b565b6123b890610380565b5f81146123c6576001900390565b610bc3565b906123de67ffffffffffffffff91610c02565b9181191691161790565b6123fc6123f761240192610380565b6107c4565b610380565b90565b90565b9061241c612417612423926123e8565b612404565b82546123cb565b9055565b91602061244892949361244160408201965f830190611fb0565b0190610d3c565b565b61246861246061245b610208611491565b6123af565b610208612407565b61247f6124745f61085f565b600161020a01611f90565b61249d61249561249061020d610bb6565b610bd7565b61020d610c4b565b6124aa5f61020a01611491565b6124b561020d610bb6565b7ff73240422246f63ed633ef3ce0726b8ab8fb69d46c8a4e5ecb0b2922668674a1916124eb6124e26100d2565b92839283612427565b0390a1565b6124f8612367565b565b612527906125223361251c6125166125115f61071f565b61022c565b9161022c565b14611115565b6125ab565b565b5f7f6d6967726174696f6e20696e2070726f67726573730000000000000000000000910152565b61255d6015602092610739565b61256681612529565b0190565b61257f9060208101905f818303910152612550565b90565b1561258957565b6125916100d2565b62461bcd60e51b8152806125a76004820161256a565b0390fd5b6125cd906125c86125c36125bd613117565b15611e53565b612582565b612651565b565b5f7f6d61696e74656e616e636520696e2070726f6772657373000000000000000000910152565b6126036017602092610739565b61260c816125cf565b0190565b6126259060208101905f8183039101526125f6565b90565b1561262f57565b6126376100d2565b62461bcd60e51b81528061264d60048201612610565b0390fd5b6126739061266e6126696126636130e2565b15611e53565b612628565b61283a565b565b61267e90610380565b67ffffffffffffffff81146126935760010190565b610bc3565b90565b90356001602003823603038112156126dc57016020813591019167ffffffffffffffff82116126d75760408202360383136126d257565b610c81565b610c7d565b610c85565b60209181520190565b90565b6126f681610340565b036126fd57565b5f80fd5b9050359061270e826126ed565b565b5061271f906020810190612701565b90565b90602061274d6127559361274461273b5f830183612710565b5f860190610346565b82810190610c6b565b910190610238565b565b9061276481604093612722565b0190565b5090565b60400190565b9161278082612786926126e1565b926126ea565b90815f905b828210612799575050505090565b909192936127bb6127b56001926127b08886612768565b612757565b9561276c565b92019092919261278b565b906128029060206127fa6127f0604084016127e35f88018861269b565b908683035f880152612772565b9482810190612710565b910190610346565b90565b9392906128306040916128389461282360608901925f8a0190611fb0565b87820360208901526127c6565b940190610d3c565b565b6128595f61020a0161285361284e82611491565b612675565b90612407565b61290b61290061010161289461288e6002612888612878610208611491565b61288260026114a1565b906114d1565b906115b6565b50612698565b6128b26128aa6128a5610208611491565b612675565b610208612407565b6128ef6128e76128e160026128db6128cb610208611491565b6128d560026114a1565b906114d1565b906115b6565b50612698565b9182906133c4565b6128fa818690613702565b01611534565b600161020a01611f90565b61292961292161291c61020d610bb6565b610bd7565b61020d610c4b565b6129365f61020a01611491565b9061294261020d610bb6565b916129797f78dad2bc0b47c688ed84f3fee79abc18e6c9822db05a79ca19dff54533c7470d936129706100d2565b93849384612805565b0390a1565b612987906124fa565b565b6129b6906129b1336129ab6129a56129a05f61071f565b61022c565b9161022c565b14611115565b612beb565b565b5f7f696e206b65797370616365000000000000000000000000000000000000000000910152565b6129ec600b602092610739565b6129f5816129b8565b0190565b612a0e9060208101905f8183039101526129df565b90565b15612a1857565b612a206100d2565b62461bcd60e51b815280612a36600482016129f9565b0390fd5b90612a4d905f1990602003600802610a86565b8154169055565b905f91612a6b612a638261097b565b928354610a9f565b905555565b919290602082105f14612ac957601f8411600114612a9957612a93929350610a9f565b90555b5b565b5090612abf612ac4936001612ab6612ab08561097b565b92610984565b82019101610a10565b612a54565b612a96565b50612b008293612ada60019461097b565b612af9612ae685610984565b820192601f861680612b0b575b50610984565b0190610a10565b600202179055612a97565b612b1790888603612a3a565b5f612af3565b929091680100000000000000008211612b7d576020115f14612b6e57602081105f14612b5257612b4c91610a9f565b90555b5b565b60019160ff1916612b628461097b565b55600202019055612b4f565b60019150600202019055612b50565b610967565b908154612b8e81610825565b90818311612bb7575b818310612ba5575b50505050565b612bae93612a70565b5f808080612b9f565b612bc383838387612b1d565b612b97565b5f612bd291612b82565b565b905f03612be657612be490612bc8565b565b610954565b612c1b612c02612bfd600184906107fb565b61084f565b612c14612c0e5f61085f565b9161039a565b14156108d4565b612c23613117565b5f14612d0c57612c5d612c58612c525f612c4c81612c43600282906115b6565b50018690611e16565b01611e46565b15611e53565b612a11565b612c92612c8d612c875f612c8181612c7860026001906115b6565b50018690611e16565b01611e46565b15611e53565b612a11565b5b612ca85f612ca3600184906107fb565b612bd4565b612cc6612cbe612cb961020d610bb6565b610bd7565b61020d610c4b565b612cd161020d610bb6565b7f9df3075e519fdff3ab71e9fc679060e9d2dd37c49ccc1c1fc1996d517752220a91612d07612cfe6100d2565b92839283610fbd565b0390a1565b612d5d612d58612d525f612d4c81612d436002612d3d612d2d610208611491565b612d3760026114a1565b906114d1565b906115b6565b50018690611e16565b01611e46565b15611e53565b612a11565b612c93565b612d6b90612989565b565b612d9a90612d9533612d8f612d89612d845f61071f565b61022c565b9161022c565b14611115565b612d9c565b565b612da6815f610f90565b612dc4612dbc612db761020d610bb6565b610bd7565b61020d610c4b565b612dcf61020d610bb6565b7f476610ebc6647c15376100955efbf22ef2a0c3b923fc00b380b660c873ef20ac91612e05612dfc6100d2565b92839283610fbd565b0390a1565b612e1390612d6d565b565b612e2e612e29612e23613117565b15611e53565b612582565b612e36612e38565b565b612e51612e4c612e466130e2565b15611e53565b612628565b612e59612e5b565b565b612e9b5f612e9581612e8c6002612e86612e76610208611491565b612e8060026114a1565b906114d1565b906115b6565b50013390611e16565b01611e46565b8015612f1e575b612eab9061079b565b612eb9335f61020c01610f90565b612ed7612ecf612eca61020d610bb6565b610bd7565b61020d610c4b565b33612ee361020d610bb6565b7fbc2748cf02f7a1291525e866efc76ab3b96d32d7afcbb26c53daec617b38b47991612f19612f106100d2565b92839283610fbd565b0390a1565b50612eab33612f3d612f37612f325f61071f565b61022c565b9161022c565b149050612ea2565b612f4d612e15565b565b5f7f656d707479206f70657261746f72206461746100000000000000000000000000910152565b612f836013602092610739565b612f8c81612f4f565b0190565b612fa59060208101905f818303910152612f76565b90565b15612faf57565b612fb76100d2565b62461bcd60e51b815280612fcd60048201612f90565b0390fd5b61ffff1690565b612fe4612fe9916106fb565b612fd1565b90565b612ff69054612fd8565b90565b61300d6130086130129261116d565b6107c4565b61039a565b90565b5f7f6f70657261746f72206461746120746f6f206c61726765000000000000000000910152565b6130496017602092610739565b61305281613015565b0190565b61306b9060208101905f81830391015261303c565b90565b1561307557565b61307d6100d2565b62461bcd60e51b81528061309360048201613056565b0390fd5b6130dc906130b7816130b16130ab5f61085f565b9161039a565b11612fa8565b6130d56130cf6130ca5f61020901612fec565b612ff9565b9161039a565b111561306e565b565b5f90565b6130ea6130de565b506130f85f61020c0161071f565b61311261310c6131075f610f66565b61022c565b9161022c565b141590565b61311f6130de565b5061312e600161020a01611534565b61314061313a5f61085f565b9161039a565b141590565b613157906131516109f8565b50613af8565b90565b61316e61316961317392610340565b6107c4565b61039a565b90565b6131959061318f61318961319a9461039a565b9161039a565b9061098e565b61039a565b90565b6131c4906131a96130de565b50916131bf6131b960019261315a565b916115df565b613176565b166131d76131d15f61085f565b9161039a565b1490565b613202906131e76130de565b50916131fd6131f760019261315a565b916115df565b613176565b1661321561320f5f61085f565b9161039a565b141590565b61324461324a916132296109f8565b509261323f61323960019261315a565b916115df565b613176565b1961039a565b1690565b5f80910155565b905f03613267576132659061324e565b565b610954565b6132766040611322565b90565b9061328560ff91610c02565b9181191691161790565b61329890611e53565b90565b90565b906132b36132ae6132ba9261328f565b61329b565b8254613279565b9055565b60081b90565b906132d161ff00916132be565b9181191691161790565b6132ef6132ea6132f492610340565b6107c4565b610340565b90565b90565b9061330f61330a613316926132db565b6132f7565b82546132c4565b9055565b9061334460205f61334a9461333c828201613336848801611ede565b9061329e565b019201611eeb565b906132fa565b565b906133569161331a565b565b9190600861337891029161337260018060a01b038461098e565b9261098e565b9181191691161790565b91906133986133936133a0936107ef565b610f8d565b908354613358565b9055565b906133b96133b46133c0926132db565b6132f7565b8254613279565b9055565b91906133f96133de6133d96101018601611534565b613145565b6133f36133ee6101018501611534565b613145565b90613c8d565b9161340261146c565b5061340b61146c565b506134155f61085f565b5b806134296134238661039a565b9161039a565b11613546576134da90613449613443600188018390611758565b90611798565b61346061345a600187018490611758565b90611798565b908061347461346e8461022c565b9161022c565b1461353f57816134d49261349861349261348d5f610f66565b61022c565b9161022c565b03613524575b50806134ba6134b46134af5f610f66565b61022c565b9161022c565b036134df575b6134ce600187018490611758565b90613382565b5b611716565b613416565b61351f600161350d6134f086611732565b6135046134fb61326c565b935f8501611e58565b60208301611708565b61351a5f89018490611e16565b61334c565b6134c0565b5f61353461353992828a01611e16565b613255565b5f61349e565b50506134d5565b509261357c9250613575610101809261356f61356561010283016116fb565b61010287016133a4565b01611534565b9101611f90565b565b5f90565b600161358e910161039a565b90565b9035906001602003813603038212156135d3570180359067ffffffffffffffff82116135ce576020019160408202360383136135c957565b610905565b610901565b6108fd565b5090565b91908110156135ec576040020190565b611599565b356135fb816126ed565b90565b5f7f756e6368616e67656420736c6f74000000000000000000000000000000000000910152565b613632600e602092610739565b61363b816135fe565b0190565b6136549060208101905f818303910152613625565b90565b1561365e57565b6136666100d2565b62461bcd60e51b81528061367c6004820161363f565b0390fd5b5f7f6f70657261746f72206475706c69636174650000000000000000000000000000910152565b6136b46012602092610739565b6136bd81613680565b0190565b6136d69060208101905f8183039101526136a7565b90565b156136e057565b6136e86100d2565b62461bcd60e51b8152806136fe600482016136c1565b0390fd5b61370f6101018201611534565b9061371861357e565b5061372161146c565b5061372a61146c565b506137345f61085f565b5b8061375d61375761375261374c885f810190613591565b906135d8565b61039a565b9161039a565b101561390e576138879061388261378b5f61378561377e8983810190613591565b86916135dc565b016135f1565b61387d6137b060206137aa6137a38b5f810190613591565b88916135dc565b0161072c565b80976137c96137c360018a018690611758565b90611798565b6137e6816137df6137d98661022c565b9161022c565b1415613657565b806138016137fb6137f65f610f66565b61022c565b9161022c565b036138f3575b50878261382461381e6138195f610f66565b61022c565b9161022c565b145f1461388c57506138389150839061321a565b965b6138528161384c60018a018690611758565b90613382565b61387560019361386c61386361326c565b955f8701611e58565b60208501611708565b5f8701611e16565b61334c565b613582565b613735565b6138e16138db5f6138d56138ed96826138e6966138cf6138b66138b1600186906107fb565b61084f565b6138c86138c28561085f565b9161039a565b14156108d4565b01611e16565b01611e46565b15611e53565b6136d9565b8390613cb9565b9661383a565b5f61390361390892828c01611e16565b613255565b5f613807565b509061393060206139379461392a610102946101018701611f90565b016135f1565b91016133a4565b565b90565b61395061394b61395592613939565b6107c4565b61039a565b90565b90565b61396f61396a61397492613958565b6107c4565b610340565b90565b6139969061399061398a61399b94610340565b9161039a565b9061098e565b61039a565b90565b6139bd906139b76139b16139c29461039a565b9161039a565b90610a86565b61039a565b90565b90565b6139dc6139d76139e1926139c5565b6107c4565b61039a565b90565b90565b6139fb6139f6613a00926139e4565b6107c4565b610340565b90565b90565b613a1a613a15613a1f92613a03565b6107c4565b61039a565b90565b90565b613a39613a34613a3e92613a22565b6107c4565b610340565b90565b90565b613a58613a53613a5d92613a41565b6107c4565b61039a565b90565b90565b613a77613a72613a7c92613a60565b6107c4565b610340565b90565b90565b613a96613a91613a9b92613a7f565b6107c4565b61039a565b90565b90565b613ab5613ab0613aba92613a9e565b6107c4565b610340565b90565b90565b613ad4613acf613ad992613abd565b6107c4565b61039a565b90565b613af0613aeb613af59261149e565b6107c4565b610340565b90565b613b006109f8565b50613b40613b3082613b2a613b246fffffffffffffffffffffffffffffffff61393c565b9161039a565b11613ce4565b613b3a600761395b565b90613977565b613b81613b71613b5184849061399e565b613b6b613b6567ffffffffffffffff6139c8565b9161039a565b11613ce4565b613b7b60066139e7565b90613977565b17613bbf613baf613b9384849061399e565b613ba9613ba363ffffffff613a06565b9161039a565b11613ce4565b613bb96005613a25565b90613977565b17613bfb613beb613bd184849061399e565b613be5613bdf61ffff613a44565b9161039a565b11613ce4565b613bf56004613a63565b90613977565b17613c36613c26613c0d84849061399e565b613c20613c1a60ff613a82565b9161039a565b11613ce4565b613c306003613aa1565b90613977565b17613c71613c61613c4884849061399e565b613c5b613c55600f613ac0565b9161039a565b11613ce4565b613c6b6002613adc565b90613977565b17906d010102020202030303030303030360801b90821c1a1790565b613cb691613c996109f8565b5081613cad613ca78361039a565b9161039a565b11919091613d00565b90565b613ce090613cc56109f8565b5091613cdb613cd560019261315a565b916115df565b613176565b1790565b613cec6109f8565b50151590565b90613cfd910261039a565b90565b613d1a613d209293613d106109f8565b5080941891613ce4565b90613cf2565b189056fea26469706673582212208b10234b08244c919ee8fc151ed15483fad0d05bc89d37a4de3b8fc6879959b364736f6c634300081c0033","sourceMap":"1030:10844:22:-:0;;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;:::i;:::-;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;:::i;:::-;;;;;;;;;;:::o;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;:::o;:::-;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;:::o;:::-;;;:::o;:::-;;:::o;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;:::o;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;:::i;:::-;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;:::o;:::-;;:::o;:::-;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;:::o;:::-;;:::i;:::-;;;;:::o;:::-;;:::o;:::-;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;:::o;:::-;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;;;:::i;:::-;;:::i;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;:::i;:::-;:::o;:::-;;;;;;;:::o;:::-;;;;;;;:::o;:::-;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;:::i;:::-;;;;;:::i;:::-;;;:::o;:::-;;;:::o;:::-;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;;;;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;:::o;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;:::i;:::-;;;;;;:::o;:::-;;;;;:::i;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;1367:833::-;1562:26;1367:833;1462:61;1470:23;:16;:23;:::i;:::-;:30;;1497:3;1470:30;:::i;:::-;;;:::i;:::-;;;1462:61;:::i;:::-;1534:18;1542:10;1534:18;;:::i;:::-;1562:26;;:::i;:::-;1620:13;1632:1;1620:13;:::i;:::-;1664:3;1635:1;:27;;1639:23;:16;:23;:::i;:::-;1635:27;:::i;:::-;;;:::i;:::-;;;;;1664:3;1708:16;:31;;:24;:19;:16;1725:1;1708:19;;:::i;:::-;;:24;;:31;:::i;:::-;;:::i;:::-;1754:81;1762:45;:38;:12;1775:24;;:19;:16;1792:1;1775:19;;:::i;:::-;;:24;;:::i;:::-;1762:38;;:::i;:::-;:45;:::i;:::-;:50;;1811:1;1762:50;:::i;:::-;;;:::i;:::-;;1754:81;:::i;:::-;1850:52;1878:24;;:19;:16;1895:1;1878:19;;:::i;:::-;;:24;;:::i;:::-;1850:25;:22;:12;:9;1860:1;1850:12;;:::i;:::-;;:22;1873:1;1850:25;;:::i;:::-;:52;;:::i;:::-;1916:101;1993:4;1973:44;2006:8;2012:1;2006:8;:::i;:::-;1973:44;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::i;:::-;1916:54;:28;:12;:9;1926:1;1916:12;;:::i;:::-;;:28;1945:24;;:19;:16;1962:1;1945:19;;:::i;:::-;;:24;;:::i;:::-;1916:54;;:::i;:::-;:101;:::i;:::-;2031:65;2072:24;:19;:16;2089:1;2072:19;;:::i;:::-;;:24;;2031:38;:12;2044:24;;:19;:16;2061:1;2044:19;;:::i;:::-;;:24;;:::i;:::-;2031:38;;:::i;:::-;:65;:::i;:::-;1664:3;:::i;:::-;1620:13;;1635:27;;2149:44;2162:30;2168:23;2117:76;1635:27;2168:23;:::i;:::-;2162:30;:::i;:::-;2149:44;:::i;:::-;2117:29;:12;:9;2127:1;2117:12;;:::i;:::-;;:29;:76;:::i;:::-;1367:833::o;1030:10844::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;:::o;:::-;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;11413:205;11537:74;11413:205;11486:41;11494:5;:9;;11502:1;11494:9;:::i;:::-;;;:::i;:::-;;11486:41;:::i;:::-;11545:38;;11554:29;;:8;:29;;:::i;:::-;11545:38;:::i;:::-;;;:::i;:::-;;;11537:74;:::i;:::-;11413:205::o;1030:10844::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;:::o;:::-;;:::i;12794:101::-;12868:15;12867:21;12794:101;12840:7;;:::i;:::-;12868:1;:15;12873:10;12868:1;12881;12873:10;:::i;:::-;12868:15;;:::i;:::-;;:::i;:::-;12867:21;12887:1;12867:21;:::i;:::-;;;:::i;:::-;12860:28;:::o","linkReferences":{}},"deployedBytecode":{"object":"0x60806040526004361015610013575b6106f7565b61001d5f356100cc565b806326322217146100c757806353bfb584146100c257806365706f9c146100bd57806375418b9d146100b85780639d44e717146100b3578063b55a4142146100ae578063c130809a146100a9578063cdbfc62d146100a4578063db1b0fd71461009f578063f2fde38b1461009a5763f5f2d9f10361000e576106c4565b610691565b61065e565b6105ea565b61056f565b61053c565b610509565b610493565b6101db565b610177565b610135565b60e01c90565b60405190565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b908160409103126100f65790565b6100e4565b9060208282031261012b575f82013567ffffffffffffffff81116101265761012392016100e8565b90565b6100e0565b6100dc565b5f0190565b346101635761014d6101483660046100fb565b610d6f565b6101556100d2565b8061015f81610130565b0390f35b6100d8565b5f91031261017257565b6100dc565b346101a557610187366004610168565b61018f6110b2565b6101976100d2565b806101a181610130565b0390f35b6100d8565b908160209103126101b85790565b6100e4565b906020828203126101d6576101d3915f016101aa565b90565b6100dc565b34610209576101f36101ee3660046101bd565b6112ee565b6101fb6100d2565b8061020581610130565b0390f35b6100d8565b5190565b60209181520190565b60200190565b60018060a01b031690565b61023590610221565b90565b6102419061022c565b9052565b5190565b60209181520190565b90825f9392825e0152565b601f801991011690565b61028661028f6020936102949361027d81610245565b93848093610249565b95869101610252565b61025d565b0190565b6102c391602060408201926102b35f8201515f850190610238565b0151906020818403910152610267565b90565b906102d091610298565b90565b60200190565b906102ed6102e68361020e565b8092610212565b90816102fe6020830284019461021b565b925f915b83831061031157505050505090565b9091929394602061033361032d838560019503875289516102c6565b976102d3565b9301930191939290610302565b60ff1690565b61034f90610340565b9052565b9061037d90602080610372604084015f8701518582035f8701526102d9565b940151910190610346565b90565b67ffffffffffffffff1690565b61039690610380565b9052565b90565b6103a69061039a565b9052565b906020806103cc936103c25f8201515f86019061038d565b015191019061039d565b565b905f806103df930151910190610238565b565b6fffffffffffffffffffffffffffffffff1690565b6103ff906103e1565b9052565b906104789060c060a061044a61042660e085015f8801518682035f880152610353565b610438602088015160208701906103aa565b60408701518582036060870152610353565b9461045d606082015160808601906103ce565b61046e60808201518386019061038d565b01519101906103f6565b90565b6104909160208201915f818403910152610403565b90565b346104c3576104a3366004610168565b6104bf6104ae6118a9565b6104b66100d2565b9182918261047b565b0390f35b6100d8565b6104d181610380565b036104d857565b5f80fd5b905035906104e9826104c8565b565b9060208282031261050457610501915f016104dc565b90565b6100dc565b346105375761052161051c3660046104eb565b6121b7565b6105296100d2565b8061053381610130565b0390f35b6100d8565b3461056a5761055461054f3660046100fb565b61235c565b61055c6100d2565b8061056681610130565b0390f35b6100d8565b3461059d5761057f366004610168565b6105876124f0565b61058f6100d2565b8061059981610130565b0390f35b6100d8565b908160409103126105b05790565b6100e4565b906020828203126105e5575f82013567ffffffffffffffff81116105e0576105dd92016105a2565b90565b6100e0565b6100dc565b34610618576106026105fd3660046105b5565b61297e565b61060a6100d2565b8061061481610130565b0390f35b6100d8565b6106268161022c565b0361062d57565b5f80fd5b9050359061063e8261061d565b565b9060208282031261065957610656915f01610631565b90565b6100dc565b3461068c57610676610671366004610640565b612d62565b61067e6100d2565b8061068881610130565b0390f35b6100d8565b346106bf576106a96106a4366004610640565b612e0a565b6106b16100d2565b806106bb81610130565b0390f35b6100d8565b346106f2576106d4366004610168565b6106dc612f45565b6106e46100d2565b806106ee81610130565b0390f35b6100d8565b5f80fd5b5f1c90565b60018060a01b031690565b61071761071c916106fb565b610700565b90565b610729905461070b565b90565b356107368161061d565b90565b60209181520190565b5f7f756e617574686f72697a65640000000000000000000000000000000000000000910152565b610776600c602092610739565b61077f81610742565b0190565b6107989060208101905f818303910152610769565b90565b156107a257565b6107aa6100d2565b62461bcd60e51b8152806107c060048201610783565b0390fd5b90565b6107db6107d66107e092610221565b6107c4565b610221565b90565b6107ec906107c7565b90565b6107f8906107e3565b90565b90610805906107ef565b5f5260205260405f2090565b634e487b7160e01b5f52602260045260245ffd5b9060016002830492168015610845575b602083101461084057565b610811565b91607f1691610835565b6108599054610825565b90565b90565b61087361086e6108789261085c565b6107c4565b61039a565b90565b5f7f756e6b6e6f776e206f70657261746f7200000000000000000000000000000000910152565b6108af6010602092610739565b6108b88161087b565b0190565b6108d19060208101905f8183039101526108a2565b90565b156108db57565b6108e36100d2565b62461bcd60e51b8152806108f9600482016108bc565b0390fd5b5f80fd5b5f80fd5b5f80fd5b90359060016020038136030382121561094b570180359067ffffffffffffffff82116109465760200191600182023603831361094157565b610905565b610901565b6108fd565b5090565b634e487b7160e01b5f525f60045260245ffd5b634e487b7160e01b5f52604160045260245ffd5b5f5260205f2090565b601f602091010490565b1b90565b919060086109ad9102916109a75f198461098e565b9261098e565b9181191691161790565b6109cb6109c66109d09261039a565b6107c4565b61039a565b90565b90565b91906109ec6109e76109f4936109b7565b6109d3565b908354610992565b9055565b5f90565b610a0e91610a086109f8565b916109d6565b565b5b818110610a1c575050565b80610a295f6001936109fc565b01610a11565b9190601f8111610a3f575b505050565b610a4b610a709361097b565b906020610a5784610984565b83019310610a78575b610a6990610984565b0190610a10565b5f8080610a3a565b9150610a6981929050610a60565b1c90565b90610a9a905f1990600802610a86565b191690565b81610aa991610a8a565b906002021790565b91610abc9082610950565b9067ffffffffffffffff8211610b7b57610ae082610ada8554610825565b85610a2f565b5f90601f8311600114610b1357918091610b02935f92610b07575b5050610a9f565b90555b565b90915001355f80610afb565b601f19831691610b228561097b565b925f5b818110610b6357509160029391856001969410610b49575b50505002019055610b05565b610b59910135601f841690610a8a565b90555f8080610b3d565b91936020600181928787013581550195019201610b25565b610967565b90610b8b9291610ab1565b565b6fffffffffffffffffffffffffffffffff1690565b610bae610bb3916106fb565b610b8d565b90565b610bc09054610ba2565b90565b634e487b7160e01b5f52601160045260245ffd5b610be0906103e1565b6fffffffffffffffffffffffffffffffff8114610bfd5760010190565b610bc3565b5f1b90565b90610c226fffffffffffffffffffffffffffffffff91610c02565b9181191691161790565b610c40610c3b610c45926103e1565b6107c4565b6103e1565b90565b90565b90610c60610c5b610c6792610c2c565b610c48565b8254610c07565b9055565b50610c7a906020810190610631565b90565b5f80fd5b5f80fd5b5f80fd5b9035600160200382360303811215610cca57016020813591019167ffffffffffffffff8211610cc5576001820236038313610cc057565b610c81565b610c7d565b610c85565b90825f939282370152565b9190610cf481610ced81610cf995610249565b8095610ccf565b61025d565b0190565b610d3991610d2b6040820192610d21610d185f830183610c6b565b5f850190610238565b6020810190610c89565b916020818503910152610cda565b90565b610d45906103e1565b9052565b92916020610d65610d6d9360408701908782035f890152610cfd565b940190610d3c565b565b33610d8a610d84610d7f5f61071f565b61022c565b9161022c565b148015610e85575b610d9b9061079b565b610dd5610dbc610db76001610db15f860161072c565b906107fb565b61084f565b610dce610dc85f61085f565b9161039a565b14156108d4565b610df4610def610de9836020810190610909565b90610950565b613097565b610e21610e05826020810190610909565b90610e1c6001610e165f870161072c565b906107fb565b610b80565b610e3f610e37610e3261020d610bb6565b610bd7565b61020d610c4b565b610e4a61020d610bb6565b7f5aab2c32b1e447db4dba1d2790fe8b863d4775042b10b92e00dab9d6b671b5b591610e80610e776100d2565b92839283610d49565b0390a1565b50610d9b33610ea6610ea0610e9b5f860161072c565b61022c565b9161022c565b149050610d92565b5f7f6e6f206d61696e74656e616e6365000000000000000000000000000000000000910152565b610ee2600e602092610739565b610eeb81610eae565b0190565b610f049060208101905f818303910152610ed5565b90565b15610f0e57565b610f166100d2565b62461bcd60e51b815280610f2c60048201610eef565b0390fd5b610f40610f3b6130e2565b610f07565b610f48610fe0565b565b610f5e610f59610f639261085c565b6107c4565b610221565b90565b610f6f90610f4a565b90565b90610f8360018060a01b0391610c02565b9181191691161790565b90565b90610fa5610fa0610fac926107ef565b610f8d565b8254610f72565b9055565b610fb99061022c565b9052565b916020610fde929493610fd760408201965f830190610fb0565b0190610d3c565b565b33610ffb610ff5610ff05f61071f565b61022c565b9161022c565b148015611087575b61100c9061079b565b6110226110185f610f66565b5f61020c01610f90565b61104061103861103361020d610bb6565b610bd7565b61020d610c4b565b3361104c61020d610bb6565b7f2e1c659da2dc5f4ec69512e86bda1a7a48c5e97669b37f9bb5a3064b6353159f916110826110796100d2565b92839283610fbd565b0390a1565b5061100c6110985f61020c0161071f565b6110aa6110a43361022c565b9161022c565b149050611003565b6110ba610f30565b565b5f7f6e6f7420746865206f776e657200000000000000000000000000000000000000910152565b6110f0600d602092610739565b6110f9816110bc565b0190565b6111129060208101905f8183039101526110e3565b90565b1561111c57565b6111246100d2565b62461bcd60e51b81528061113a600482016110fd565b0390fd5b61116b906111663361116061115a6111555f61071f565b61022c565b9161022c565b14611115565b61127e565b565b61ffff1690565b61117d8161116d565b0361118457565b5f80fd5b3561119281611174565b90565b906111a261ffff91610c02565b9181191691161790565b6111c06111bb6111c59261116d565b6107c4565b61116d565b90565b90565b906111e06111db6111e7926111ac565b6111c8565b8254611195565b9055565b906111fd5f8061120394019201611188565b906111cb565b565b9061120f916111eb565b565b9050359061121e82611174565b565b5061122f906020810190611211565b90565b61123b9061116d565b9052565b905f6112516112599382810190611220565b910190611232565b565b91602061127c92949361127560408201965f83019061123f565b0190610d3c565b565b61128a81610209611205565b6112a86112a061129b61020d610bb6565b610bd7565b61020d610c4b565b6112b361020d610bb6565b7fb24d8d9dcfbb6be13176c1c7bfb0e76445a9ba2a3553b413d8671446f1030830916112e96112e06100d2565b9283928361125b565b0390a1565b6112f79061113e565b565b906113039061025d565b810190811067ffffffffffffffff82111761131d57604052565b610967565b9061133561132e6100d2565b92836112f9565b565b61134160c0611322565b90565b61134e6040611322565b90565b606090565b5f90565b611362611344565b906020808361136f611351565b81520161137a611356565b81525050565b61138861135a565b90565b6113956040611322565b90565b5f90565b5f90565b6113a861138b565b90602080836113b5611398565b8152016113c061139c565b81525050565b6113ce6113a0565b90565b6113db6020611322565b90565b5f90565b6113ea6113d1565b906020826113f66113de565b81525050565b6114046113e2565b90565b5f90565b611413611337565b906020808080808087611424611380565b81520161142f6113c6565b81520161143a611380565b8152016114456113fc565b815201611450611398565b81520161145b611407565b81525050565b61146961140b565b90565b5f90565b67ffffffffffffffff1690565b61148961148e916106fb565b611470565b90565b61149b905461147d565b90565b90565b6114b56114b06114ba9261149e565b6107c4565b610380565b90565b634e487b7160e01b5f52601260045260245ffd5b6114dd6114e391610380565b91610380565b9081156114ee570690565b6114bd565b61150761150261150c92610380565b6107c4565b61039a565b90565b9061151990610380565b9052565b90565b61152c611531916106fb565b61151d565b90565b61153e9054611520565b90565b9061154b9061039a565b9052565b90565b61156661156161156b9261154f565b6107c4565b610380565b90565b61157a61158091610380565b91610380565b90039067ffffffffffffffff821161159457565b610bc3565b634e487b7160e01b5f52603260045260245ffd5b50600290565b90565b6115bf816115ad565b8210156115da576115d2610103916115b3565b910201905f90565b611599565b6115f36115ee6115f89261154f565b6107c4565b61039a565b90565b61160a6116109193929361039a565b9261039a565b820180921161161b57565b610bc3565b67ffffffffffffffff81116116385760208091020190565b610967565b9061164f61164a83611620565b611322565b918252565b61165e6040611322565b90565b606090565b61166e611654565b906020808361167b6113de565b815201611686611661565b81525050565b611694611666565b90565b5f5b8281106116a557505050565b6020906116b061168c565b8184015201611699565b906116df6116c78361163d565b926020806116d58693611620565b9201910390611697565b565b60ff1690565b6116f36116f8916106fb565b6116e1565b90565b61170590546116e7565b90565b9061171290610340565b9052565b61171f9061039a565b5f19811461172d5760010190565b610bc3565b61174661174161174b9261039a565b6107c4565b610340565b90565b5061010090565b90565b6117618161174e565b82101561177b57611773600191611755565b910201905f90565b611599565b6117909060086117959302610a86565b610700565b90565b906117a39154611780565b90565b906117b08261020e565b8110156117c1576020809102010190565b611599565b906117d09061022c565b9052565b905f92918054906117ee6117e783610825565b8094610249565b916001811690815f146118455750600114611809575b505050565b611816919293945061097b565b915f925b81841061182d57505001905f8080611804565b6001816020929593955484860152019101929061181a565b92949550505060ff19168252151560200201905f8080611804565b9061186a916117d4565b90565b9061188d6118869261187d6100d2565b93848092611860565b03836112f9565b565b6118989061186d565b90565b906118a5906103e1565b9052565b6118b1611461565b506118ba611461565b6118c26109f8565b506118cb61146c565b506118d46109f8565b506118dd613117565b5f14611ccb576118ff6118f35f61020a01611491565b5f60208401510161150f565b61191c611910600161020a01611534565b60208084015101611541565b611955611950611940611930610208611491565b61193a6001611552565b9061156e565b61194a60026114a1565b906114d1565b6114f3565b9061197c611977611967610208611491565b61197160026114a1565b906114d1565b6114f3565b9161199e611999610101611992600287906115b6565b5001611534565b613145565b926119bb6119b6856119b060016115df565b906115fb565b6116ba565b5f604085015101526119ec6119df6101026119d8600285906115b6565b50016116fb565b6020604086015101611708565b6119f55f61085f565b5b80611a09611a038761039a565b9161039a565b11611b3957611ac090611a3d611a2e610101611a27600287906115b6565b5001611534565b611a3783611732565b9061319d565b611b3457611a64611a5e6001611a55600287906115b6565b50018390611758565b90611798565b611a82815f611a7b8160408b0151015186906117a6565b51016117c6565b611aad611a9e610101611a97600289906115b6565b5001611534565b611aa784611732565b9061319d565b8015611af7575b611ac5575b505b611716565b6119f6565b611ad09060016107fb565b611aef6020611ae75f60408a0151015185906117a6565b51019161188f565b90525f611ab9565b50611b1b611b156001611b0c600289906115b6565b50018490611758565b90611798565b611b2d611b278361022c565b9161022c565b1415611ab4565b611abb565b505091505b611b5f611b5a610101611b53600286906115b6565b5001611534565b613145565b91611b7c611b7784611b7160016115df565b906115fb565b6116ba565b5f808401510152611bab611b9f610102611b98600285906115b6565b50016116fb565b60205f85015101611708565b611bb45f61085f565b5b80611bc8611bc28661039a565b9161039a565b11611c7a57611c7090611bfc611bed610101611be6600287906115b6565b5001611534565b611bf683611732565b9061319d565b611c7557611c4a611c26611c206001611c17600288906115b6565b50018490611758565b90611798565b611c43815f611c3c81808b0151015187906117a6565b51016117c6565b60016107fb565b611c686020611c605f80890151015185906117a6565b51019161188f565b90525b611716565b611bb5565b611c6b565b50509050611c95611c8c610208611491565b6080830161150f565b611cb1611ca55f61020c0161071f565b5f6060840151016117c6565b611cc8611cbf61020d610bb6565b60a0830161189b565b90565b611cf1611cec611cdc610208611491565b611ce660026114a1565b906114d1565b6114f3565b90611b3e565b5f7f6e6f206d6967726174696f6e0000000000000000000000000000000000000000910152565b611d2b600c602092610739565b611d3481611cf7565b0190565b611d4d9060208101905f818303910152611d1e565b90565b15611d5757565b611d5f6100d2565b62461bcd60e51b815280611d7560048201611d38565b0390fd5b611d9290611d8d611d88613117565b611d50565b611fef565b565b5f7f77726f6e67206d6967726174696f6e2069640000000000000000000000000000910152565b611dc86012602092610739565b611dd181611d94565b0190565b611dea9060208101905f818303910152611dbb565b90565b15611df457565b611dfc6100d2565b62461bcd60e51b815280611e1260048201611dd5565b0390fd5b90611e20906107ef565b5f5260205260405f2090565b60ff1690565b611e3e611e43916106fb565b611e2c565b90565b611e509054611e32565b90565b151590565b90611e6290611e53565b9052565b60081c90565b611e78611e7d91611e66565b6116e1565b90565b611e8a9054611e6c565b90565b611e976040611322565b90565b90611ed0611ec75f611eaa611e8d565b94611ec1611eb9838301611e46565b838801611e58565b01611e80565b60208401611708565b565b611edb90611e9a565b90565b611ee89051611e53565b90565b611ef59051610340565b90565b5f7f6e6f742070756c6c696e67000000000000000000000000000000000000000000910152565b611f2c600b602092610739565b611f3581611ef8565b0190565b611f4e9060208101905f818303910152611f1f565b90565b15611f5857565b611f606100d2565b62461bcd60e51b815280611f7660048201611f39565b0390fd5b90611f865f1991610c02565b9181191691161790565b90611fa5611fa0611fac926109b7565b6109d3565b8254611f7a565b9055565b611fb990610380565b9052565b604090611fe6611fed9496959396611fdc60608401985f850190611fb0565b6020830190610fb0565b0190610d3c565b565b6120179061201161200b6120065f61020a01611491565b610380565b91610380565b14611ded565b6120c46120b961205b6120565f61204d6002612047612037610208611491565b61204160026114a1565b906114d1565b906115b6565b50013390611e16565b611ed2565b61206e6120695f8301611ede565b6108d4565b612099612094612082600161020a01611534565b61208e60208501611eeb565b906131db565b611f51565b6120b360206120ac600161020a01611534565b9201611eeb565b9061321a565b600161020a01611f90565b6120e26120da6120d561020d610bb6565b610bd7565b61020d610c4b565b6120f0600161020a01611534565b6121026120fc5f61085f565b9161039a565b145f1461215f576121165f61020a01611491565b3361212261020d610bb6565b916121597f01269879535f40ee8957e15e160bf1866c5e2728ff0cbc583d848821e2639b4e936121506100d2565b93849384611fbd565b0390a15b565b61216c5f61020a01611491565b3361217861020d610bb6565b916121af7faf5e90e72015f43138f66b4cd08bd1dfa2839030104f22a00af843fe847c6d19936121a66100d2565b93849384611fbd565b0390a161215d565b6121c090611d79565b565b6121ef906121ea336121e46121de6121d95f61071f565b61022c565b9161022c565b14611115565b612273565b565b5f7f6f70657261746f7220616c726561647920657869737473000000000000000000910152565b6122256017602092610739565b61222e816121f1565b0190565b6122479060208101905f818303910152612218565b90565b1561225157565b6122596100d2565b62461bcd60e51b81528061226f60048201612232565b0390fd5b6122ac61229461228f60016122895f860161072c565b906107fb565b61084f565b6122a66122a05f61085f565b9161039a565b1461224a565b6122cb6122c66122c0836020810190610909565b90610950565b613097565b6122f86122dc826020810190610909565b906122f360016122ed5f870161072c565b906107fb565b610b80565b61231661230e61230961020d610bb6565b610bd7565b61020d610c4b565b61232161020d610bb6565b7febdc606e899772e1d31d9535a98eea5ddb0d41e47128c921e64919c73f3edfa69161235761234e6100d2565b92839283610d49565b0390a1565b612365906121c2565b565b61238b3361238561237f61237a5f61071f565b61022c565b9161022c565b14611115565b612393612395565b565b6123a56123a0613117565b611d50565b6123ad61244a565b565b6123b890610380565b5f81146123c6576001900390565b610bc3565b906123de67ffffffffffffffff91610c02565b9181191691161790565b6123fc6123f761240192610380565b6107c4565b610380565b90565b90565b9061241c612417612423926123e8565b612404565b82546123cb565b9055565b91602061244892949361244160408201965f830190611fb0565b0190610d3c565b565b61246861246061245b610208611491565b6123af565b610208612407565b61247f6124745f61085f565b600161020a01611f90565b61249d61249561249061020d610bb6565b610bd7565b61020d610c4b565b6124aa5f61020a01611491565b6124b561020d610bb6565b7ff73240422246f63ed633ef3ce0726b8ab8fb69d46c8a4e5ecb0b2922668674a1916124eb6124e26100d2565b92839283612427565b0390a1565b6124f8612367565b565b612527906125223361251c6125166125115f61071f565b61022c565b9161022c565b14611115565b6125ab565b565b5f7f6d6967726174696f6e20696e2070726f67726573730000000000000000000000910152565b61255d6015602092610739565b61256681612529565b0190565b61257f9060208101905f818303910152612550565b90565b1561258957565b6125916100d2565b62461bcd60e51b8152806125a76004820161256a565b0390fd5b6125cd906125c86125c36125bd613117565b15611e53565b612582565b612651565b565b5f7f6d61696e74656e616e636520696e2070726f6772657373000000000000000000910152565b6126036017602092610739565b61260c816125cf565b0190565b6126259060208101905f8183039101526125f6565b90565b1561262f57565b6126376100d2565b62461bcd60e51b81528061264d60048201612610565b0390fd5b6126739061266e6126696126636130e2565b15611e53565b612628565b61283a565b565b61267e90610380565b67ffffffffffffffff81146126935760010190565b610bc3565b90565b90356001602003823603038112156126dc57016020813591019167ffffffffffffffff82116126d75760408202360383136126d257565b610c81565b610c7d565b610c85565b60209181520190565b90565b6126f681610340565b036126fd57565b5f80fd5b9050359061270e826126ed565b565b5061271f906020810190612701565b90565b90602061274d6127559361274461273b5f830183612710565b5f860190610346565b82810190610c6b565b910190610238565b565b9061276481604093612722565b0190565b5090565b60400190565b9161278082612786926126e1565b926126ea565b90815f905b828210612799575050505090565b909192936127bb6127b56001926127b08886612768565b612757565b9561276c565b92019092919261278b565b906128029060206127fa6127f0604084016127e35f88018861269b565b908683035f880152612772565b9482810190612710565b910190610346565b90565b9392906128306040916128389461282360608901925f8a0190611fb0565b87820360208901526127c6565b940190610d3c565b565b6128595f61020a0161285361284e82611491565b612675565b90612407565b61290b61290061010161289461288e6002612888612878610208611491565b61288260026114a1565b906114d1565b906115b6565b50612698565b6128b26128aa6128a5610208611491565b612675565b610208612407565b6128ef6128e76128e160026128db6128cb610208611491565b6128d560026114a1565b906114d1565b906115b6565b50612698565b9182906133c4565b6128fa818690613702565b01611534565b600161020a01611f90565b61292961292161291c61020d610bb6565b610bd7565b61020d610c4b565b6129365f61020a01611491565b9061294261020d610bb6565b916129797f78dad2bc0b47c688ed84f3fee79abc18e6c9822db05a79ca19dff54533c7470d936129706100d2565b93849384612805565b0390a1565b612987906124fa565b565b6129b6906129b1336129ab6129a56129a05f61071f565b61022c565b9161022c565b14611115565b612beb565b565b5f7f696e206b65797370616365000000000000000000000000000000000000000000910152565b6129ec600b602092610739565b6129f5816129b8565b0190565b612a0e9060208101905f8183039101526129df565b90565b15612a1857565b612a206100d2565b62461bcd60e51b815280612a36600482016129f9565b0390fd5b90612a4d905f1990602003600802610a86565b8154169055565b905f91612a6b612a638261097b565b928354610a9f565b905555565b919290602082105f14612ac957601f8411600114612a9957612a93929350610a9f565b90555b5b565b5090612abf612ac4936001612ab6612ab08561097b565b92610984565b82019101610a10565b612a54565b612a96565b50612b008293612ada60019461097b565b612af9612ae685610984565b820192601f861680612b0b575b50610984565b0190610a10565b600202179055612a97565b612b1790888603612a3a565b5f612af3565b929091680100000000000000008211612b7d576020115f14612b6e57602081105f14612b5257612b4c91610a9f565b90555b5b565b60019160ff1916612b628461097b565b55600202019055612b4f565b60019150600202019055612b50565b610967565b908154612b8e81610825565b90818311612bb7575b818310612ba5575b50505050565b612bae93612a70565b5f808080612b9f565b612bc383838387612b1d565b612b97565b5f612bd291612b82565b565b905f03612be657612be490612bc8565b565b610954565b612c1b612c02612bfd600184906107fb565b61084f565b612c14612c0e5f61085f565b9161039a565b14156108d4565b612c23613117565b5f14612d0c57612c5d612c58612c525f612c4c81612c43600282906115b6565b50018690611e16565b01611e46565b15611e53565b612a11565b612c92612c8d612c875f612c8181612c7860026001906115b6565b50018690611e16565b01611e46565b15611e53565b612a11565b5b612ca85f612ca3600184906107fb565b612bd4565b612cc6612cbe612cb961020d610bb6565b610bd7565b61020d610c4b565b612cd161020d610bb6565b7f9df3075e519fdff3ab71e9fc679060e9d2dd37c49ccc1c1fc1996d517752220a91612d07612cfe6100d2565b92839283610fbd565b0390a1565b612d5d612d58612d525f612d4c81612d436002612d3d612d2d610208611491565b612d3760026114a1565b906114d1565b906115b6565b50018690611e16565b01611e46565b15611e53565b612a11565b612c93565b612d6b90612989565b565b612d9a90612d9533612d8f612d89612d845f61071f565b61022c565b9161022c565b14611115565b612d9c565b565b612da6815f610f90565b612dc4612dbc612db761020d610bb6565b610bd7565b61020d610c4b565b612dcf61020d610bb6565b7f476610ebc6647c15376100955efbf22ef2a0c3b923fc00b380b660c873ef20ac91612e05612dfc6100d2565b92839283610fbd565b0390a1565b612e1390612d6d565b565b612e2e612e29612e23613117565b15611e53565b612582565b612e36612e38565b565b612e51612e4c612e466130e2565b15611e53565b612628565b612e59612e5b565b565b612e9b5f612e9581612e8c6002612e86612e76610208611491565b612e8060026114a1565b906114d1565b906115b6565b50013390611e16565b01611e46565b8015612f1e575b612eab9061079b565b612eb9335f61020c01610f90565b612ed7612ecf612eca61020d610bb6565b610bd7565b61020d610c4b565b33612ee361020d610bb6565b7fbc2748cf02f7a1291525e866efc76ab3b96d32d7afcbb26c53daec617b38b47991612f19612f106100d2565b92839283610fbd565b0390a1565b50612eab33612f3d612f37612f325f61071f565b61022c565b9161022c565b149050612ea2565b612f4d612e15565b565b5f7f656d707479206f70657261746f72206461746100000000000000000000000000910152565b612f836013602092610739565b612f8c81612f4f565b0190565b612fa59060208101905f818303910152612f76565b90565b15612faf57565b612fb76100d2565b62461bcd60e51b815280612fcd60048201612f90565b0390fd5b61ffff1690565b612fe4612fe9916106fb565b612fd1565b90565b612ff69054612fd8565b90565b61300d6130086130129261116d565b6107c4565b61039a565b90565b5f7f6f70657261746f72206461746120746f6f206c61726765000000000000000000910152565b6130496017602092610739565b61305281613015565b0190565b61306b9060208101905f81830391015261303c565b90565b1561307557565b61307d6100d2565b62461bcd60e51b81528061309360048201613056565b0390fd5b6130dc906130b7816130b16130ab5f61085f565b9161039a565b11612fa8565b6130d56130cf6130ca5f61020901612fec565b612ff9565b9161039a565b111561306e565b565b5f90565b6130ea6130de565b506130f85f61020c0161071f565b61311261310c6131075f610f66565b61022c565b9161022c565b141590565b61311f6130de565b5061312e600161020a01611534565b61314061313a5f61085f565b9161039a565b141590565b613157906131516109f8565b50613af8565b90565b61316e61316961317392610340565b6107c4565b61039a565b90565b6131959061318f61318961319a9461039a565b9161039a565b9061098e565b61039a565b90565b6131c4906131a96130de565b50916131bf6131b960019261315a565b916115df565b613176565b166131d76131d15f61085f565b9161039a565b1490565b613202906131e76130de565b50916131fd6131f760019261315a565b916115df565b613176565b1661321561320f5f61085f565b9161039a565b141590565b61324461324a916132296109f8565b509261323f61323960019261315a565b916115df565b613176565b1961039a565b1690565b5f80910155565b905f03613267576132659061324e565b565b610954565b6132766040611322565b90565b9061328560ff91610c02565b9181191691161790565b61329890611e53565b90565b90565b906132b36132ae6132ba9261328f565b61329b565b8254613279565b9055565b60081b90565b906132d161ff00916132be565b9181191691161790565b6132ef6132ea6132f492610340565b6107c4565b610340565b90565b90565b9061330f61330a613316926132db565b6132f7565b82546132c4565b9055565b9061334460205f61334a9461333c828201613336848801611ede565b9061329e565b019201611eeb565b906132fa565b565b906133569161331a565b565b9190600861337891029161337260018060a01b038461098e565b9261098e565b9181191691161790565b91906133986133936133a0936107ef565b610f8d565b908354613358565b9055565b906133b96133b46133c0926132db565b6132f7565b8254613279565b9055565b91906133f96133de6133d96101018601611534565b613145565b6133f36133ee6101018501611534565b613145565b90613c8d565b9161340261146c565b5061340b61146c565b506134155f61085f565b5b806134296134238661039a565b9161039a565b11613546576134da90613449613443600188018390611758565b90611798565b61346061345a600187018490611758565b90611798565b908061347461346e8461022c565b9161022c565b1461353f57816134d49261349861349261348d5f610f66565b61022c565b9161022c565b03613524575b50806134ba6134b46134af5f610f66565b61022c565b9161022c565b036134df575b6134ce600187018490611758565b90613382565b5b611716565b613416565b61351f600161350d6134f086611732565b6135046134fb61326c565b935f8501611e58565b60208301611708565b61351a5f89018490611e16565b61334c565b6134c0565b5f61353461353992828a01611e16565b613255565b5f61349e565b50506134d5565b509261357c9250613575610101809261356f61356561010283016116fb565b61010287016133a4565b01611534565b9101611f90565b565b5f90565b600161358e910161039a565b90565b9035906001602003813603038212156135d3570180359067ffffffffffffffff82116135ce576020019160408202360383136135c957565b610905565b610901565b6108fd565b5090565b91908110156135ec576040020190565b611599565b356135fb816126ed565b90565b5f7f756e6368616e67656420736c6f74000000000000000000000000000000000000910152565b613632600e602092610739565b61363b816135fe565b0190565b6136549060208101905f818303910152613625565b90565b1561365e57565b6136666100d2565b62461bcd60e51b81528061367c6004820161363f565b0390fd5b5f7f6f70657261746f72206475706c69636174650000000000000000000000000000910152565b6136b46012602092610739565b6136bd81613680565b0190565b6136d69060208101905f8183039101526136a7565b90565b156136e057565b6136e86100d2565b62461bcd60e51b8152806136fe600482016136c1565b0390fd5b61370f6101018201611534565b9061371861357e565b5061372161146c565b5061372a61146c565b506137345f61085f565b5b8061375d61375761375261374c885f810190613591565b906135d8565b61039a565b9161039a565b101561390e576138879061388261378b5f61378561377e8983810190613591565b86916135dc565b016135f1565b61387d6137b060206137aa6137a38b5f810190613591565b88916135dc565b0161072c565b80976137c96137c360018a018690611758565b90611798565b6137e6816137df6137d98661022c565b9161022c565b1415613657565b806138016137fb6137f65f610f66565b61022c565b9161022c565b036138f3575b50878261382461381e6138195f610f66565b61022c565b9161022c565b145f1461388c57506138389150839061321a565b965b6138528161384c60018a018690611758565b90613382565b61387560019361386c61386361326c565b955f8701611e58565b60208501611708565b5f8701611e16565b61334c565b613582565b613735565b6138e16138db5f6138d56138ed96826138e6966138cf6138b66138b1600186906107fb565b61084f565b6138c86138c28561085f565b9161039a565b14156108d4565b01611e16565b01611e46565b15611e53565b6136d9565b8390613cb9565b9661383a565b5f61390361390892828c01611e16565b613255565b5f613807565b509061393060206139379461392a610102946101018701611f90565b016135f1565b91016133a4565b565b90565b61395061394b61395592613939565b6107c4565b61039a565b90565b90565b61396f61396a61397492613958565b6107c4565b610340565b90565b6139969061399061398a61399b94610340565b9161039a565b9061098e565b61039a565b90565b6139bd906139b76139b16139c29461039a565b9161039a565b90610a86565b61039a565b90565b90565b6139dc6139d76139e1926139c5565b6107c4565b61039a565b90565b90565b6139fb6139f6613a00926139e4565b6107c4565b610340565b90565b90565b613a1a613a15613a1f92613a03565b6107c4565b61039a565b90565b90565b613a39613a34613a3e92613a22565b6107c4565b610340565b90565b90565b613a58613a53613a5d92613a41565b6107c4565b61039a565b90565b90565b613a77613a72613a7c92613a60565b6107c4565b610340565b90565b90565b613a96613a91613a9b92613a7f565b6107c4565b61039a565b90565b90565b613ab5613ab0613aba92613a9e565b6107c4565b610340565b90565b90565b613ad4613acf613ad992613abd565b6107c4565b61039a565b90565b613af0613aeb613af59261149e565b6107c4565b610340565b90565b613b006109f8565b50613b40613b3082613b2a613b246fffffffffffffffffffffffffffffffff61393c565b9161039a565b11613ce4565b613b3a600761395b565b90613977565b613b81613b71613b5184849061399e565b613b6b613b6567ffffffffffffffff6139c8565b9161039a565b11613ce4565b613b7b60066139e7565b90613977565b17613bbf613baf613b9384849061399e565b613ba9613ba363ffffffff613a06565b9161039a565b11613ce4565b613bb96005613a25565b90613977565b17613bfb613beb613bd184849061399e565b613be5613bdf61ffff613a44565b9161039a565b11613ce4565b613bf56004613a63565b90613977565b17613c36613c26613c0d84849061399e565b613c20613c1a60ff613a82565b9161039a565b11613ce4565b613c306003613aa1565b90613977565b17613c71613c61613c4884849061399e565b613c5b613c55600f613ac0565b9161039a565b11613ce4565b613c6b6002613adc565b90613977565b17906d010102020202030303030303030360801b90821c1a1790565b613cb691613c996109f8565b5081613cad613ca78361039a565b9161039a565b11919091613d00565b90565b613ce090613cc56109f8565b5091613cdb613cd560019261315a565b916115df565b613176565b1790565b613cec6109f8565b50151590565b90613cfd910261039a565b90565b613d1a613d209293613d106109f8565b5080941891613ce4565b90613cf2565b189056fea26469706673582212208b10234b08244c919ee8fc151ed15483fad0d05bc89d37a4de3b8fc6879959b364736f6c634300081c0033","sourceMap":"1030:10844:22:-:0;;;;;;;;;-1:-1:-1;1030:10844:22;:::i;:::-;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;;;:::o;:::-;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;:::i;:::-;;;;:::o;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;:::o;:::-;;;;:::o;:::-;;;;;;;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;:::o;:::-;;;;;;;:::o;:::-;;;;;;;;;;:::o;:::-;;;;;;;;:::o;:::-;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;;;;;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;;;:::i;:::-;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;:::i;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;:::o;:::-;;;;;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;:::o;:::-;;;:::o;:::-;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;:::i;:::-;;;;;:::i;:::-;;;:::o;:::-;;;:::o;:::-;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;;;;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;:::o;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;:::i;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;:::o;:::-;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;:::i;:::-;;;;:::o;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;;;;;;;;;:::o;:::-;;;;;;;;;;:::i;:::-;;;;:::i;:::-;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;:::o;7520:421::-;7607:10;:19;;7621:5;;;:::i;:::-;7607:19;:::i;:::-;;;:::i;:::-;;:50;;;;7520:421;7599:75;;;:::i;:::-;7684:68;7692:34;:27;:12;7705:13;;:8;:13;;:::i;:::-;7692:27;;:::i;:::-;:34;:::i;:::-;:39;;7730:1;7692:39;:::i;:::-;;;:::i;:::-;;;7684:68;:::i;:::-;7787:20;;:13;:8;:13;;;;;:::i;:::-;:20;;:::i;:::-;;:::i;:::-;7819:43;7849:13;:8;:13;;;;;:::i;:::-;7819:12;:27;:12;7832:13;;:8;:13;;:::i;:::-;7819:27;;:::i;:::-;:43;:::i;:::-;7872:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;7926:7;;;:::i;:::-;7896:38;;;;;:::i;:::-;;;;;;:::i;:::-;;;;7520:421::o;7607:50::-;7630:10;7599:75;7630:10;:27;;7644:13;;:8;:13;;:::i;:::-;7630:27;:::i;:::-;;;:::i;:::-;;7607:50;;;;1030:10844;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;2527:106;2563:52;2571:25;;:::i;:::-;2563:52;:::i;:::-;2625:1;;:::i;:::-;2527:106::o;1030:10844::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;:::o;6892:263::-;6963:10;:19;;6977:5;;;:::i;:::-;6963:19;:::i;:::-;;;:::i;:::-;;:53;;;;6892:263;6955:78;;;:::i;:::-;7044:29;7063:10;7071:1;7063:10;:::i;:::-;7044:16;:11;:16;:29;:::i;:::-;7084:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;7128:10;7140:7;;;:::i;:::-;7108:40;;;;;:::i;:::-;;;;;;:::i;:::-;;;;6892:263::o;6963:53::-;6986:11;6955:78;6986:16;;:11;:16;;:::i;:::-;:30;;7006:10;6986:30;:::i;:::-;;;:::i;:::-;;6963:53;;;;6892:263;;;:::i;:::-;:::o;1030:10844::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;2206:94;2292:1;2206:94;2237:45;2245:10;:19;;2259:5;;;:::i;:::-;2245:19;:::i;:::-;;;:::i;:::-;;2237:45;:::i;:::-;2292:1;:::i;:::-;2206:94::o;1030:10844::-;;;;:::o;:::-;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;:::i;:::-;:::o;:::-;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;:::o;8600:184::-;8684:22;8695:11;8684:22;;:::i;:::-;8716:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;8769:7;;;:::i;:::-;8740:37;;;;;:::i;:::-;;;;;;:::i;:::-;;;;8600:184::o;:::-;;;;:::i;:::-;:::o;1030:10844::-;;;;;:::i;:::-;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;:::i;:::-;;;;:::i;:::-;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;:::o;:::-;;;:::o;:::-;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::o;:::-;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;:::o;:::-;;;:::o;:::-;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::o;:::-;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;:::o;:::-;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::o;:::-;;;:::i;:::-;;:::o;:::-;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::o;:::-;;;:::i;:::-;;:::o;:::-;;;:::o;:::-;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;;;:::o;:::-;;:::o;:::-;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;:::o;:::-;;:::i;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;:::i;:::-;;:::i;:::-;;;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;:::o;:::-;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::o;:::-;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;:::o;:::-;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;:::o;:::-;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;:::i;:::-;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;:::o;:::-;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;:::i;:::-;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;:::o;8966:2441::-;9006:18;;:::i;:::-;9036:30;;;:::i;:::-;9077:19;;:::i;:::-;9115:12;;;:::i;:::-;9137:22;;;:::i;:::-;9182:23;;;:::i;:::-;9178:1406;;;;9221:39;9248:12;;:9;:12;;:::i;:::-;9221:24;:21;:11;:21;;:24;:39;:::i;:::-;9274:81;9322:33;;:9;:33;;:::i;:::-;9274:45;:11;;:21;;:45;:81;:::i;:::-;9370:39;9384:25;9385:19;:15;;;:::i;:::-;:19;9403:1;9385:19;:::i;:::-;;;:::i;:::-;9384:25;9408:1;9384:25;:::i;:::-;;;:::i;:::-;9370:39;:::i;:::-;9454:15;9423:50;9454:19;:15;;;:::i;:::-;:19;9472:1;9454:19;:::i;:::-;;;:::i;:::-;9423:50;:::i;:::-;9505:9;:59;:48;;:31;:9;9515:20;9505:31;;:::i;:::-;;:48;;:::i;:::-;:59;:::i;:::-;9639:14;9620:38;9639:18;:14;:18;9656:1;9639:18;:::i;:::-;;;:::i;:::-;9620:38;:::i;:::-;9578:39;:29;:11;:29;;:39;:80;9672:103;9724:51;;:31;:9;9734:20;9724:31;;:::i;:::-;;:51;;:::i;:::-;9672:49;:29;:11;:29;;:49;:103;:::i;:::-;9807:13;9819:1;9807:13;:::i;:::-;9843:3;9822:1;:19;;9827:14;9822:19;:::i;:::-;;;:::i;:::-;;;;9843:3;9870:9;:62;:48;;:31;:9;9880:20;9870:31;;:::i;:::-;;:48;;:::i;:::-;9923:8;9929:1;9923:8;:::i;:::-;9870:62;;:::i;:::-;9866:117;;10020:44;;:41;:31;:9;10030:20;10020:31;;:::i;:::-;;:41;10062:1;10020:44;;:::i;:::-;;;:::i;:::-;10082:54;10132:4;10082:47;:42;:11;:29;:11;:29;;:39;;10122:1;10082:42;;:::i;:::-;;:47;:54;:::i;:::-;10285:53;:39;;:22;:9;10295:11;10285:22;;:::i;:::-;;:39;;:::i;:::-;10329:8;10335:1;10329:8;:::i;:::-;10285:53;;:::i;:::-;:100;;;;9843:3;10281:215;;9843:3;;9807:13;9843:3;:::i;:::-;9807:13;;10281:215;10459:18;:12;;:18;:::i;:::-;10409:68;:47;:42;:39;:29;:11;:29;;:39;;10449:1;10409:42;;:::i;:::-;;:47;:68;;:::i;:::-;;;10281:215;;;10285:100;10342:9;:35;;:32;:22;:9;10352:11;10342:22;;:::i;:::-;;:32;10375:1;10342:35;;:::i;:::-;;;:::i;:::-;:43;;10381:4;10342:43;:::i;:::-;;;:::i;:::-;;;10285:100;;9866:117;9956:8;;9822:19;;;;;9178:1406;10611:50;:39;;:22;:9;10621:11;10611:22;;:::i;:::-;;:39;;:::i;:::-;:50;:::i;:::-;10723:14;10704:38;10723:18;:14;:18;10740:1;10723:18;:::i;:::-;;;:::i;:::-;10704:38;:::i;:::-;10671:30;:11;;:20;;:30;:71;10753:85;10796:42;;:22;:9;10806:11;10796:22;;:::i;:::-;;:42;;:::i;:::-;10753:40;:20;:11;:20;;:40;:85;:::i;:::-;10854:13;10866:1;10854:13;:::i;:::-;10890:3;10869:1;:19;;10874:14;10869:19;:::i;:::-;;;:::i;:::-;;;;10890:3;10913:9;:53;:39;;:22;:9;10923:11;10913:22;;:::i;:::-;;:39;;:::i;:::-;10957:8;10963:1;10957:8;:::i;:::-;10913:53;;:::i;:::-;10909:100;;11179:18;11030:35;;:32;:22;:9;11040:11;11030:22;;:::i;:::-;;:32;11063:1;11030:35;;:::i;:::-;;;:::i;:::-;11079:45;11120:4;11079:38;:33;:11;;;:20;;:30;;11110:1;11079:33;;:::i;:::-;;:38;:45;:::i;:::-;11179:12;:18;:::i;:::-;11138:59;:38;:33;:30;:11;;:20;;:30;;11169:1;11138:33;;:::i;:::-;;:38;:59;;:::i;:::-;;;10854:13;10890:3;:::i;:::-;10854:13;;10909:100;10986:8;;10869:19;;;;;11218:45;11248:15;;;:::i;:::-;11218:27;:11;:27;:45;:::i;:::-;11273:47;11304:16;;:11;:16;;:::i;:::-;11273:28;:23;:11;:23;;:28;:47;:::i;:::-;11338:29;11360:7;;;:::i;:::-;11338:19;:11;:19;:29;:::i;:::-;11382:18;:::o;9178:1406::-;10540:33;10554:19;:15;;;:::i;:::-;:19;10572:1;10554:19;:::i;:::-;;;:::i;:::-;10540:33;:::i;:::-;9178:1406;;;1030:10844;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;2306:100;2398:1;2306:100;2340:48;2348:23;;:::i;:::-;2340:48;:::i;:::-;2398:1;:::i;:::-;2306:100::o;1030:10844::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;:::i;:::-;:::o;5603:742::-;5673:49;5603:742;5681:18;;5687:12;;:9;:12;;:::i;:::-;5681:18;:::i;:::-;;;:::i;:::-;;5673:49;:::i;:::-;5988:93;6024:57;5733:88;5763:58;:46;:30;:9;5773:19;:15;;;:::i;:::-;:19;5791:1;5773:19;:::i;:::-;;;:::i;:::-;5763:30;;:::i;:::-;;:46;5810:10;5763:58;;:::i;:::-;5733:88;:::i;:::-;5831:48;5839:19;;:11;:19;;:::i;:::-;5831:48;:::i;:::-;5897:80;5905:56;:33;;:9;:33;;:::i;:::-;5943:17;;:11;:17;;:::i;:::-;5905:56;;:::i;:::-;5897:80;:::i;:::-;6063:17;;6024:33;;:9;:33;;:::i;:::-;6063:11;:17;;:::i;:::-;6024:57;;:::i;:::-;5988:33;:9;:33;:93;:::i;:::-;6096:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;6119:33;;:9;:33;;:::i;:::-;:38;;6156:1;6119:38;:::i;:::-;;;:::i;:::-;;6115:224;;;;6197:12;;:9;:12;;:::i;:::-;6211:10;6223:7;;;:::i;:::-;6178:53;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;6115:224;5603:742::o;6115:224::-;6294:12;;:9;:12;;:::i;:::-;6308:10;6320:7;;;:::i;:::-;6267:61;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;6115:224;;5603:742;;;;:::i;:::-;:::o;2206:94::-;2292:1;2206:94;2237:45;2245:10;:19;;2259:5;;;:::i;:::-;2245:19;:::i;:::-;;;:::i;:::-;;2237:45;:::i;:::-;2292:1;:::i;:::-;2206:94::o;1030:10844::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;7161:353;7250:75;7258:34;:27;:12;7271:13;;:8;:13;;:::i;:::-;7258:27;;:::i;:::-;:34;:::i;:::-;:39;;7296:1;7258:39;:::i;:::-;;;:::i;:::-;;7250:75;:::i;:::-;7360:20;;:13;:8;:13;;;;;:::i;:::-;:20;;:::i;:::-;;:::i;:::-;7392:43;7422:13;:8;:13;;;;;:::i;:::-;7392:12;:27;:12;7405:13;;:8;:13;;:::i;:::-;7392:27;;:::i;:::-;:43;:::i;:::-;7445:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;7499:7;;;:::i;:::-;7469:38;;;;;:::i;:::-;;;;;;:::i;:::-;;;;7161:353::o;:::-;;;;:::i;:::-;:::o;2206:94::-;2237:45;2245:10;:19;;2259:5;;;:::i;:::-;2245:19;:::i;:::-;;;:::i;:::-;;2237:45;:::i;:::-;2292:1;;:::i;:::-;2206:94::o;2306:100::-;2340:48;2348:23;;:::i;:::-;2340:48;:::i;:::-;2398:1;;:::i;:::-;2306:100::o;1030:10844::-;;;;:::i;:::-;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;:::o;6351:213::-;6419:17;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;6446:37;;6482:1;6446:37;:::i;:::-;:33;:9;:33;:37;:::i;:::-;6494:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;6535:12;;:9;:12;;:::i;:::-;6549:7;;;:::i;:::-;6518:39;;;;;:::i;:::-;;;;;;:::i;:::-;;;;6351:213::o;:::-;;;:::i;:::-;:::o;2206:94::-;2292:1;2206:94;2237:45;2245:10;:19;;2259:5;;;:::i;:::-;2245:19;:::i;:::-;;;:::i;:::-;;2237:45;:::i;:::-;2292:1;:::i;:::-;2206:94::o;1030:10844::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;2412:109;2513:1;2412:109;2445:58;2453:24;2454:23;;:::i;:::-;2453:24;;:::i;:::-;2445:58;:::i;:::-;2513:1;:::i;:::-;2412:109::o;1030:10844::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;2639:115;2746:1;2639:115;2674:62;2682:26;2683:25;;:::i;:::-;2682:26;;:::i;:::-;2674:62;:::i;:::-;2746:1;:::i;:::-;2639:115::o;1030:10844::-;;;;:::i;:::-;;;;;;;;;:::o;:::-;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;;;;;;:::o;:::-;;:::o;:::-;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;;;;:::i;:::-;;;:::o;:::-;;;:::o;:::-;;;;:::o;:::-;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;:::i;:::-;:::o;2760:632::-;2868:14;:12;:9;:12;:14;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;3241:64;3277:28;;2897:58;2925:30;:9;2935:19;:15;;;:::i;:::-;:19;2953:1;2935:19;:::i;:::-;;;:::i;:::-;2925:30;;:::i;:::-;;2897:58;:::i;:::-;2965:17;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;3170:11;2992:61;3023:30;:9;3033:19;:15;;;:::i;:::-;:19;3051:1;3033:19;:::i;:::-;;;:::i;:::-;3023:30;;:::i;:::-;;2992:61;:::i;:::-;3160:8;3170:11;;;:::i;:::-;3225:4;3212:11;3225:4;;;:::i;:::-;3277:28;;:::i;:::-;3241:33;:9;:33;:64;:::i;:::-;3316:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;3357:12;;:9;:12;;:::i;:::-;3371:4;3377:7;;;:::i;:::-;3340:45;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;2760:632::o;:::-;;;;:::i;:::-;:::o;2206:94::-;2292:1;2206:94;2237:45;2245:10;:19;;2259:5;;;:::i;:::-;2245:19;:::i;:::-;;;:::i;:::-;;2237:45;:::i;:::-;2292:1;:::i;:::-;2206:94::o;1030:10844::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;:::o;:::-;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;:::o;:::-;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;-1:-1:-1;1030:10844:22;;;;;;;;;;;;;;:::i;:::-;;;;;:::o;:::-;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;:::o;:::-;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;:::i;:::-;:::o;:::-;;:::i;7947:647::-;8029:70;8037:36;:29;:12;8050:15;8037:29;;:::i;:::-;:36;:::i;:::-;:41;;8077:1;8037:41;:::i;:::-;;;:::i;:::-;;;8029:70;:::i;:::-;8114:23;;:::i;:::-;8110:351;;;;8153:78;8161:54;8162:53;;:45;:9;:12;:9;8172:1;8162:12;;:::i;:::-;;:28;8191:15;8162:45;;:::i;:::-;:53;;:::i;:::-;8161:54;;:::i;:::-;8153:78;:::i;:::-;8245;8253:54;8254:53;;:45;:9;:12;:9;8264:1;8254:12;;:::i;:::-;;:28;8283:15;8254:45;;:::i;:::-;:53;;:::i;:::-;8253:54;;:::i;:::-;8245:78;:::i;:::-;8110:351;8471:37;;8478:29;:12;8491:15;8478:29;;:::i;:::-;8471:37;:::i;:::-;8518:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;8579:7;;;:::i;:::-;8542:45;;;;;:::i;:::-;;;;;;:::i;:::-;;;;7947:647::o;8110:351::-;8354:96;8362:72;8363:71;;:63;:9;:30;:9;8373:19;:15;;;:::i;:::-;:19;8391:1;8373:19;:::i;:::-;;;:::i;:::-;8363:30;;:::i;:::-;;:46;8410:15;8363:63;;:::i;:::-;:71;;:::i;:::-;8362:72;;:::i;:::-;8354:96;:::i;:::-;8110:351;;7947:647;;;;:::i;:::-;:::o;2206:94::-;2292:1;2206:94;2237:45;2245:10;:19;;2259:5;;;:::i;:::-;2245:19;:::i;:::-;;;:::i;:::-;;2237:45;:::i;:::-;2292:1;:::i;:::-;2206:94::o;8790:170::-;8864:16;8872:8;8864:16;;:::i;:::-;8890:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;8945:7;;;:::i;:::-;8914:39;;;;;:::i;:::-;;;;;;:::i;:::-;;;;8790:170::o;:::-;;;;:::i;:::-;:::o;2412:109::-;2445:58;2453:24;2454:23;;:::i;:::-;2453:24;;:::i;:::-;2445:58;:::i;:::-;2513:1;;:::i;:::-;2412:109::o;2639:115::-;2674:62;2682:26;2683:25;;:::i;:::-;2682:26;;:::i;:::-;2674:62;:::i;:::-;2746:1;;:::i;:::-;2639:115::o;6570:316::-;6651:66;;:58;:9;:30;:9;6661:19;:15;;;:::i;:::-;:19;6679:1;6661:19;:::i;:::-;;;:::i;:::-;6651:30;;:::i;:::-;;:46;6698:10;6651:58;;:::i;:::-;:66;;:::i;:::-;:89;;;;6570:316;6643:114;;;:::i;:::-;6776:29;6795:10;6776:16;:11;:16;:29;:::i;:::-;6816:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;6859:10;6871:7;;;:::i;:::-;6840:39;;;;;:::i;:::-;;;;;;:::i;:::-;;;;6570:316::o;6651:89::-;6721:10;6643:114;6721:10;:19;;6735:5;;;:::i;:::-;6721:19;:::i;:::-;;;:::i;:::-;;6651:89;;;;6570:316;;;:::i;:::-;:::o;1030:10844::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;11413:205;11537:74;11413:205;11486:41;11494:5;:9;;11502:1;11494:9;:::i;:::-;;;:::i;:::-;;11486:41;:::i;:::-;11545:38;;11554:29;;:8;:29;;:::i;:::-;11545:38;:::i;:::-;;;:::i;:::-;;;11537:74;:::i;:::-;11413:205::o;1030:10844::-;;;:::o;11754:118::-;11812:4;;:::i;:::-;11835:11;:16;;:11;:16;;:::i;:::-;:30;;11855:10;11863:1;11855:10;:::i;:::-;11835:30;:::i;:::-;;;:::i;:::-;;;11828:37;:::o;11624:124::-;11680:4;;:::i;:::-;11703:9;:33;;:9;:33;;:::i;:::-;:38;;11740:1;11703:38;:::i;:::-;;;:::i;:::-;;;11696:45;:::o;13610:113::-;13694:18;13610:113;13668:7;;:::i;:::-;13704;13694:18;:::i;:::-;13687:25;:::o;1030:10844::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;:::i;:::-;;:::o;13293:127::-;13391:15;13293:127;13355:4;;:::i;:::-;13380:7;13391:1;:15;13396:10;13391:1;13404;13396:10;:::i;:::-;13391:15;;:::i;:::-;;:::i;:::-;13380:27;13379:34;;13412:1;13379:34;:::i;:::-;;;:::i;:::-;;13372:41;:::o;13160:127::-;13258:15;13160:127;13222:4;;:::i;:::-;13247:7;13258:1;:15;13263:10;13258:1;13271;13263:10;:::i;:::-;13258:15;;:::i;:::-;;:::i;:::-;13247:27;13246:34;;13279:1;13246:34;:::i;:::-;;;:::i;:::-;;;13239:41;:::o;13029:125::-;13131:15;13129:18;13029:125;13092:7;;:::i;:::-;13119;13131:1;:15;13136:10;13131:1;13144;13136:10;:::i;:::-;13131:15;;:::i;:::-;;:::i;:::-;13129:18;;:::i;:::-;13119:28;13112:35;:::o;1030:10844::-;;;;;;:::o;:::-;;;;;;;;;:::i;:::-;:::o;:::-;;:::i;:::-;;;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;:::o;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;;;:::i;:::-;;:::i;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;3398:965::-;;;3597:74;3606:31;:20;;:3;:20;;:::i;:::-;:31;:::i;:::-;3639;:20;;:3;:20;;:::i;:::-;:31;:::i;:::-;3597:74;;:::i;:::-;3681:15;;;:::i;:::-;3706;;;:::i;:::-;3748:1;3736:13;3748:1;3736:13;:::i;:::-;3769:3;3751:1;:16;;3756:11;3751:16;:::i;:::-;;;:::i;:::-;;;;3769:3;3798;:16;;:13;:3;:13;3812:1;3798:16;;:::i;:::-;;;:::i;:::-;3838;;:13;:3;:13;3852:1;3838:16;;:::i;:::-;;;:::i;:::-;3873:7;;:18;;3884:7;3873:18;:::i;:::-;;;:::i;:::-;;3869:65;;3952:7;4207:26;3952:7;:21;;3963:10;3971:1;3963:10;:::i;:::-;3952:21;:::i;:::-;;;:::i;:::-;;3948:96;;3769:3;4062:7;;:21;;4073:10;4081:1;4073:10;:::i;:::-;4062:21;:::i;:::-;;;:::i;:::-;;4058:135;;3769:3;4207:16;:13;:3;:13;4221:1;4207:16;;:::i;:::-;:26;;:::i;:::-;3736:13;3769:3;:::i;:::-;3736:13;;4058:135;4103:75;4154:4;4134:44;4167:8;4173:1;4167:8;:::i;:::-;4134:44;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::i;:::-;4103:28;:19;:3;:19;4123:7;4103:28;;:::i;:::-;:75;:::i;:::-;4058:135;;3948:96;3993:36;4000:28;3993:36;4000:3;;;:19;:28;:::i;:::-;3993:36;:::i;:::-;3948:96;;;3869:65;3911:8;;;;3751:16;;;4313:43;3751:16;;4336:20;;3751:16;;4254:49;4280:23;;:3;:23;;:::i;:::-;4254;:3;:23;:49;:::i;:::-;4336:20;;:::i;:::-;4313:3;:20;:43;:::i;:::-;3398:965::o;1030:10844::-;;;:::o;:::-;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;4369:1228;4499:25;;:8;:25;;:::i;:::-;4535:9;;;:::i;:::-;4554:12;;;:::i;:::-;4576:15;;;:::i;:::-;4618:1;4606:13;4618:1;4606:13;:::i;:::-;4644:3;4621:1;:21;;4625:17;:10;:4;:10;;;;;:::i;:::-;:17;;:::i;:::-;4621:21;:::i;:::-;;;:::i;:::-;;;;;4644:3;4669:4;5385:75;4669:17;;:13;:10;:4;:10;;;;;:::i;:::-;4680:1;4669:13;;:::i;:::-;:17;;:::i;:::-;5385:33;4710:29;;:13;:10;:4;:10;;;;;:::i;:::-;4721:1;4710:13;;:::i;:::-;:29;;:::i;:::-;4760:8;;:23;;:18;:8;:18;4779:3;4760:23;;:::i;:::-;;;:::i;:::-;4798:42;4806:4;:15;;4814:7;4806:15;:::i;:::-;;;:::i;:::-;;;4798:42;:::i;:::-;4859:4;:18;;4867:10;4875:1;4867:10;:::i;:::-;4859:18;:::i;:::-;;;:::i;:::-;;4855:95;;4644:3;4968:7;;;:21;;4979:10;4987:1;4979:10;:::i;:::-;4968:21;:::i;:::-;;;:::i;:::-;;4964:360;;;;5028:16;:26;:16;;5050:3;5028:26;;:::i;:::-;4964:360;;5338:33;5364:7;5338:23;:18;:8;:18;5357:3;5338:23;;:::i;:::-;:33;;:::i;:::-;5421:39;5441:4;5454:3;5421:39;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::i;:::-;5385:24;:8;:24;:33;:::i;:::-;:75;:::i;:::-;4644:3;:::i;:::-;4606:13;;4964:360;5181:42;5182:41;;:33;5283:26;5101:12;;5173:73;5101:12;5093:62;5101:28;:21;:12;5114:7;5101:21;;:::i;:::-;:28;:::i;:::-;:33;;5133:1;5101:33;:::i;:::-;;;:::i;:::-;;;5093:62;:::i;:::-;5182:24;:33;:::i;:::-;:41;;:::i;:::-;5181:42;;:::i;:::-;5173:73;:::i;:::-;5305:3;5283:26;;:::i;:::-;4964:360;;;4855:95;4897:38;4904:30;4897:38;4904:8;;;:24;:30;:::i;:::-;4897:38;:::i;:::-;4855:95;;;4621:21;;;5566:24;;5535:55;4621:21;5481:44;5535:28;4621:21;5481:25;:8;:25;:44;:::i;:::-;5566:24;;:::i;:::-;5535:8;:28;:55;:::i;:::-;4369:1228::o;1030:10844::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;26222:2393:20:-;26270:9;;:::i;:::-;26383:1;26367:60;:55;26383:1;:38;;26387:34;26383:38;:::i;:::-;;;:::i;:::-;;26367:55;:::i;:::-;:60;26426:1;26367:60;:::i;:::-;;;:::i;:::-;26508:51;:46;26525:6;:1;26530;26525:6;;:::i;:::-;26524:29;;26535:18;26524:29;:::i;:::-;;;:::i;:::-;;26508:46;:::i;:::-;:51;26558:1;26508:51;:::i;:::-;;;:::i;:::-;26503:56;26639:43;:38;26656:6;:1;26661;26656:6;;:::i;:::-;26655:21;;26666:10;26655:21;:::i;:::-;;;:::i;:::-;;26639:38;:::i;:::-;:43;26681:1;26639:43;:::i;:::-;;;:::i;:::-;26634:48;26762:39;:34;26779:6;:1;26784;26779:6;;:::i;:::-;26778:17;;26789:6;26778:17;:::i;:::-;;;:::i;:::-;;26762:34;:::i;:::-;:39;26800:1;26762:39;:::i;:::-;;;:::i;:::-;26757:44;26879:37;:32;26896:6;:1;26901;26896:6;;:::i;:::-;26895:15;;26906:4;26895:15;:::i;:::-;;;:::i;:::-;;26879:32;:::i;:::-;:37;26915:1;26879:37;:::i;:::-;;;:::i;:::-;26874:42;26993:36;:31;27010:6;:1;27015;27010:6;;:::i;:::-;27009:14;;27020:3;27009:14;:::i;:::-;;;:::i;:::-;;26993:31;:::i;:::-;:36;27028:1;26993:36;:::i;:::-;;;:::i;:::-;26988:41;28465:144;;;;;;;;;26222:2393;:::o;5435:111::-;5519:20;5435:111;5493:7;;:::i;:::-;5527:1;;:5;;5531:1;5527:5;:::i;:::-;;;:::i;:::-;;5534:1;5537;5519:20;;:::i;:::-;5512:27;:::o;12901:122:22:-;13001:15;12901:122;12964:7;;:::i;:::-;12991;13001:1;:15;13006:10;13001:1;13014;13006:10;:::i;:::-;13001:15;;:::i;:::-;;:::i;:::-;12991:25;12984:32;:::o;34795:145:21:-;34842:9;;:::i;:::-;34863:71;;;34795:145;:::o;1030:10844:22:-;;;;;;:::i;:::-;;:::o;5071:294:20:-;5321:26;5311:36;5071:294;;5149:7;;:::i;:::-;5306:1;;5312;:5;5337:9;5321:26;:::i;:::-;5311:36;;:::i;:::-;5306:42;5299:49;:::o","linkReferences":{}},"methodIdentifiers":{"abortMigration()":"c130809a","completeMigration(uint64)":"9d44e717","createNodeOperator((address,bytes))":"b55a4142","deleteNodeOperator(address)":"db1b0fd7","finishMaintenance()":"53bfb584","getView()":"75418b9d","startMaintenance()":"f5f2d9f1","startMigration(((uint8,address)[],uint8))":"cdbfc62d","transferOwnership(address)":"f2fde38b","updateNodeOperator((address,bytes))":"26322217","updateSettings((uint16))":"65706f9c"},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.28+commit.7893614a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"components\":[{\"internalType\":\"uint16\",\"name\":\"maxOperatorDataBytes\",\"type\":\"uint16\"}],\"internalType\":\"struct Settings\",\"name\":\"initialSettings\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"struct NodeOperator[]\",\"name\":\"initialOperators\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"operatorAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"MaintenanceFinished\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"operatorAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"MaintenanceStarted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"MigrationAborted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"operatorAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"MigrationCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"operatorAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"MigrationDataPullCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"uint8\",\"name\":\"idx\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"operatorAddress\",\"type\":\"address\"}],\"internalType\":\"struct KeyspaceSlot[]\",\"name\":\"slots\",\"type\":\"tuple[]\"},{\"internalType\":\"uint8\",\"name\":\"replicationStrategy\",\"type\":\"uint8\"}],\"indexed\":false,\"internalType\":\"struct MigrationPlan\",\"name\":\"plan\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"MigrationStarted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"struct NodeOperator\",\"name\":\"operator\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"NodeOperatorCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"operatorAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"NodeOperatorDeleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"struct NodeOperator\",\"name\":\"operator\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"NodeOperatorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"cluserVersion\",\"type\":\"uint128\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint16\",\"name\":\"maxOperatorDataBytes\",\"type\":\"uint16\"}],\"indexed\":false,\"internalType\":\"struct Settings\",\"name\":\"newSettings\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"SettingsUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"abortMigration\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"}],\"name\":\"completeMigration\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"struct NodeOperator\",\"name\":\"operator\",\"type\":\"tuple\"}],\"name\":\"createNodeOperator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operatorAddress\",\"type\":\"address\"}],\"name\":\"deleteNodeOperator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"finishMaintenance\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getView\",\"outputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"struct NodeOperator[]\",\"name\":\"operators\",\"type\":\"tuple[]\"},{\"internalType\":\"uint8\",\"name\":\"replicationStrategy\",\"type\":\"uint8\"}],\"internalType\":\"struct KeyspaceView\",\"name\":\"keyspace\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"pullingOperatorsBitmask\",\"type\":\"uint256\"}],\"internalType\":\"struct Migration\",\"name\":\"migration\",\"type\":\"tuple\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"struct NodeOperator[]\",\"name\":\"operators\",\"type\":\"tuple[]\"},{\"internalType\":\"uint8\",\"name\":\"replicationStrategy\",\"type\":\"uint8\"}],\"internalType\":\"struct KeyspaceView\",\"name\":\"migrationKeyspace\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"slot\",\"type\":\"address\"}],\"internalType\":\"struct Maintenance\",\"name\":\"maintenance\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"keyspaceVersion\",\"type\":\"uint64\"},{\"internalType\":\"uint128\",\"name\":\"version\",\"type\":\"uint128\"}],\"internalType\":\"struct ClusterView\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startMaintenance\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"uint8\",\"name\":\"idx\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"operatorAddress\",\"type\":\"address\"}],\"internalType\":\"struct KeyspaceSlot[]\",\"name\":\"slots\",\"type\":\"tuple[]\"},{\"internalType\":\"uint8\",\"name\":\"replicationStrategy\",\"type\":\"uint8\"}],\"internalType\":\"struct MigrationPlan\",\"name\":\"plan\",\"type\":\"tuple\"}],\"name\":\"startMigration\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"struct NodeOperator\",\"name\":\"operator\",\"type\":\"tuple\"}],\"name\":\"updateNodeOperator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint16\",\"name\":\"maxOperatorDataBytes\",\"type\":\"uint16\"}],\"internalType\":\"struct Settings\",\"name\":\"newSettings\",\"type\":\"tuple\"}],\"name\":\"updateSettings\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/Cluster.sol\":\"Cluster\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[\":@openzeppelin/contracts/=dependencies/openzeppelin-contracts/contracts/\",\":erc4626-tests/=dependencies/openzeppelin-contracts/lib/erc4626-tests/\",\":forge-std-1.9.7/=dependencies/forge-std-1.9.7/src/\",\":forge-std/=dependencies/openzeppelin-contracts/lib/forge-std/src/\",\":halmos-cheatcodes/=dependencies/openzeppelin-contracts/lib/halmos-cheatcodes/src/\",\":openzeppelin-contracts/=dependencies/openzeppelin-contracts/\"],\"viaIR\":true},\"sources\":{\"dependencies/openzeppelin-contracts/contracts/utils/Panic.sol\":{\"keccak256\":\"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a\",\"dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG\"]},\"dependencies/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0x1225214420c83ebcca88f2ae2b50f053aaa7df7bd684c3e878d334627f2edfc6\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6c5fab4970634f9ab9a620983dc1c8a30153981a0b1a521666e269d0a11399d3\",\"dweb:/ipfs/QmVRnBC575MESGkEHndjujtR7qub2FzU9RWy9eKLp4hPZB\"]},\"dependencies/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\":{\"keccak256\":\"0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b1d578337048cad08c1c03041cca5978eff5428aa130c781b271ad9e5566e1f8\",\"dweb:/ipfs/QmPFKL2r9CBsMwmUqqdcFPfHZB2qcs9g1HDrPxzWSxomvy\"]},\"src/Cluster.sol\":{\"keccak256\":\"0xfd4a17d0b8327f8248d37ae5b16b7076095a7b4f6ed1d75f859446b33c086a88\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://91b3747c61898f3f65d064a173e6795fede772a88d3848870bf73266498dc71f\",\"dweb:/ipfs/QmStHTacgfN8y7nzkFrju9GGVV7kv5WD9ez2yeTP8YgcAe\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.28+commit.7893614a"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"struct Settings","name":"initialSettings","type":"tuple","components":[{"internalType":"uint16","name":"maxOperatorDataBytes","type":"uint16"}]},{"internalType":"struct NodeOperator[]","name":"initialOperators","type":"tuple[]","components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}]}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"operatorAddress","type":"address","indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"MaintenanceFinished","anonymous":false},{"inputs":[{"internalType":"address","name":"operatorAddress","type":"address","indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"MaintenanceStarted","anonymous":false},{"inputs":[{"internalType":"uint64","name":"id","type":"uint64","indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"MigrationAborted","anonymous":false},{"inputs":[{"internalType":"uint64","name":"id","type":"uint64","indexed":false},{"internalType":"address","name":"operatorAddress","type":"address","indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"MigrationCompleted","anonymous":false},{"inputs":[{"internalType":"uint64","name":"id","type":"uint64","indexed":false},{"internalType":"address","name":"operatorAddress","type":"address","indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"MigrationDataPullCompleted","anonymous":false},{"inputs":[{"internalType":"uint64","name":"id","type":"uint64","indexed":false},{"internalType":"struct MigrationPlan","name":"plan","type":"tuple","components":[{"internalType":"struct KeyspaceSlot[]","name":"slots","type":"tuple[]","components":[{"internalType":"uint8","name":"idx","type":"uint8"},{"internalType":"address","name":"operatorAddress","type":"address"}]},{"internalType":"uint8","name":"replicationStrategy","type":"uint8"}],"indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"MigrationStarted","anonymous":false},{"inputs":[{"internalType":"struct NodeOperator","name":"operator","type":"tuple","components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"NodeOperatorCreated","anonymous":false},{"inputs":[{"internalType":"address","name":"operatorAddress","type":"address","indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"NodeOperatorDeleted","anonymous":false},{"inputs":[{"internalType":"struct NodeOperator","name":"operator","type":"tuple","components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"NodeOperatorUpdated","anonymous":false},{"inputs":[{"internalType":"address","name":"newOwner","type":"address","indexed":false},{"internalType":"uint128","name":"cluserVersion","type":"uint128","indexed":false}],"type":"event","name":"OwnershipTransferred","anonymous":false},{"inputs":[{"internalType":"struct Settings","name":"newSettings","type":"tuple","components":[{"internalType":"uint16","name":"maxOperatorDataBytes","type":"uint16"}],"indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"SettingsUpdated","anonymous":false},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"abortMigration"},{"inputs":[{"internalType":"uint64","name":"id","type":"uint64"}],"stateMutability":"nonpayable","type":"function","name":"completeMigration"},{"inputs":[{"internalType":"struct NodeOperator","name":"operator","type":"tuple","components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}]}],"stateMutability":"nonpayable","type":"function","name":"createNodeOperator"},{"inputs":[{"internalType":"address","name":"operatorAddress","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"deleteNodeOperator"},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"finishMaintenance"},{"inputs":[],"stateMutability":"view","type":"function","name":"getView","outputs":[{"internalType":"struct ClusterView","name":"","type":"tuple","components":[{"internalType":"struct KeyspaceView","name":"keyspace","type":"tuple","components":[{"internalType":"struct NodeOperator[]","name":"operators","type":"tuple[]","components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}]},{"internalType":"uint8","name":"replicationStrategy","type":"uint8"}]},{"internalType":"struct Migration","name":"migration","type":"tuple","components":[{"internalType":"uint64","name":"id","type":"uint64"},{"internalType":"uint256","name":"pullingOperatorsBitmask","type":"uint256"}]},{"internalType":"struct KeyspaceView","name":"migrationKeyspace","type":"tuple","components":[{"internalType":"struct NodeOperator[]","name":"operators","type":"tuple[]","components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}]},{"internalType":"uint8","name":"replicationStrategy","type":"uint8"}]},{"internalType":"struct Maintenance","name":"maintenance","type":"tuple","components":[{"internalType":"address","name":"slot","type":"address"}]},{"internalType":"uint64","name":"keyspaceVersion","type":"uint64"},{"internalType":"uint128","name":"version","type":"uint128"}]}]},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"startMaintenance"},{"inputs":[{"internalType":"struct MigrationPlan","name":"plan","type":"tuple","components":[{"internalType":"struct KeyspaceSlot[]","name":"slots","type":"tuple[]","components":[{"internalType":"uint8","name":"idx","type":"uint8"},{"internalType":"address","name":"operatorAddress","type":"address"}]},{"internalType":"uint8","name":"replicationStrategy","type":"uint8"}]}],"stateMutability":"nonpayable","type":"function","name":"startMigration"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"transferOwnership"},{"inputs":[{"internalType":"struct NodeOperator","name":"operator","type":"tuple","components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}]}],"stateMutability":"nonpayable","type":"function","name":"updateNodeOperator"},{"inputs":[{"internalType":"struct Settings","name":"newSettings","type":"tuple","components":[{"internalType":"uint16","name":"maxOperatorDataBytes","type":"uint16"}]}],"stateMutability":"nonpayable","type":"function","name":"updateSettings"}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"remappings":["@openzeppelin/contracts/=dependencies/openzeppelin-contracts/contracts/","erc4626-tests/=dependencies/openzeppelin-contracts/lib/erc4626-tests/","forge-std-1.9.7/=dependencies/forge-std-1.9.7/src/","forge-std/=dependencies/openzeppelin-contracts/lib/forge-std/src/","halmos-cheatcodes/=dependencies/openzeppelin-contracts/lib/halmos-cheatcodes/src/","openzeppelin-contracts/=dependencies/openzeppelin-contracts/"],"optimizer":{"enabled":false,"runs":200},"metadata":{"bytecodeHash":"ipfs"},"compilationTarget":{"src/Cluster.sol":"Cluster"},"evmVersion":"cancun","libraries":{},"viaIR":true},"sources":{"dependencies/openzeppelin-contracts/contracts/utils/Panic.sol":{"keccak256":"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a","urls":["bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a","dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG"],"license":"MIT"},"dependencies/openzeppelin-contracts/contracts/utils/math/Math.sol":{"keccak256":"0x1225214420c83ebcca88f2ae2b50f053aaa7df7bd684c3e878d334627f2edfc6","urls":["bzz-raw://6c5fab4970634f9ab9a620983dc1c8a30153981a0b1a521666e269d0a11399d3","dweb:/ipfs/QmVRnBC575MESGkEHndjujtR7qub2FzU9RWy9eKLp4hPZB"],"license":"MIT"},"dependencies/openzeppelin-contracts/contracts/utils/math/SafeCast.sol":{"keccak256":"0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54","urls":["bzz-raw://b1d578337048cad08c1c03041cca5978eff5428aa130c781b271ad9e5566e1f8","dweb:/ipfs/QmPFKL2r9CBsMwmUqqdcFPfHZB2qcs9g1HDrPxzWSxomvy"],"license":"MIT"},"src/Cluster.sol":{"keccak256":"0xfd4a17d0b8327f8248d37ae5b16b7076095a7b4f6ed1d75f859446b33c086a88","urls":["bzz-raw://91b3747c61898f3f65d064a173e6795fede772a88d3848870bf73266498dc71f","dweb:/ipfs/QmStHTacgfN8y7nzkFrju9GGVV7kv5WD9ez2yeTP8YgcAe"],"license":"MIT"}},"version":1},"id":22} \ No newline at end of file +{"abi":[{"type":"constructor","inputs":[{"name":"initialSettings","type":"tuple","internalType":"struct Settings","components":[{"name":"maxOperatorDataBytes","type":"uint16","internalType":"uint16"}]},{"name":"initialOperators","type":"tuple[]","internalType":"struct NodeOperator[]","components":[{"name":"addr","type":"address","internalType":"address"},{"name":"data","type":"bytes","internalType":"bytes"}]}],"stateMutability":"nonpayable"},{"type":"function","name":"abortMigration","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"addNodeOperator","inputs":[{"name":"idx","type":"uint8","internalType":"uint8"},{"name":"operator","type":"tuple","internalType":"struct NodeOperator","components":[{"name":"addr","type":"address","internalType":"address"},{"name":"data","type":"bytes","internalType":"bytes"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"completeMigration","inputs":[{"name":"id","type":"uint64","internalType":"uint64"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"finishMaintenance","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"getView","inputs":[],"outputs":[{"name":"","type":"tuple","internalType":"struct ClusterView","components":[{"name":"owner","type":"address","internalType":"address"},{"name":"nodeOperatorSlots","type":"tuple[]","internalType":"struct NodeOperator[]","components":[{"name":"addr","type":"address","internalType":"address"},{"name":"data","type":"bytes","internalType":"bytes"}]},{"name":"keyspaces","type":"tuple[2]","internalType":"struct Keyspace[2]","components":[{"name":"operatorsBitmask","type":"uint256","internalType":"uint256"},{"name":"replicationStrategy","type":"uint8","internalType":"uint8"}]},{"name":"keyspaceVersion","type":"uint64","internalType":"uint64"},{"name":"settings","type":"tuple","internalType":"struct Settings","components":[{"name":"maxOperatorDataBytes","type":"uint16","internalType":"uint16"}]},{"name":"migration","type":"tuple","internalType":"struct Migration","components":[{"name":"id","type":"uint64","internalType":"uint64"},{"name":"pullingOperatorsBitmask","type":"uint256","internalType":"uint256"}]},{"name":"maintenance","type":"tuple","internalType":"struct Maintenance","components":[{"name":"slot","type":"address","internalType":"address"}]},{"name":"version","type":"uint128","internalType":"uint128"}]}],"stateMutability":"view"},{"type":"function","name":"removeNodeOperator","inputs":[{"name":"operatorAddress","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"startMaintenance","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"startMigration","inputs":[{"name":"newKeyspace","type":"tuple","internalType":"struct Keyspace","components":[{"name":"operatorsBitmask","type":"uint256","internalType":"uint256"},{"name":"replicationStrategy","type":"uint8","internalType":"uint8"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"transferOwnership","inputs":[{"name":"newOwner","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateNodeOperator","inputs":[{"name":"operator","type":"tuple","internalType":"struct NodeOperator","components":[{"name":"addr","type":"address","internalType":"address"},{"name":"data","type":"bytes","internalType":"bytes"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateSettings","inputs":[{"name":"newSettings","type":"tuple","internalType":"struct Settings","components":[{"name":"maxOperatorDataBytes","type":"uint16","internalType":"uint16"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"event","name":"MaintenanceFinished","inputs":[{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"MaintenanceStarted","inputs":[{"name":"addr","type":"address","indexed":false,"internalType":"address"},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"MigrationAborted","inputs":[{"name":"id","type":"uint64","indexed":false,"internalType":"uint64"},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"MigrationCompleted","inputs":[{"name":"id","type":"uint64","indexed":false,"internalType":"uint64"},{"name":"operatorAddress","type":"address","indexed":false,"internalType":"address"},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"MigrationDataPullCompleted","inputs":[{"name":"id","type":"uint64","indexed":false,"internalType":"uint64"},{"name":"operatorAddress","type":"address","indexed":false,"internalType":"address"},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"MigrationStarted","inputs":[{"name":"id","type":"uint64","indexed":false,"internalType":"uint64"},{"name":"newKeyspace","type":"tuple","indexed":false,"internalType":"struct Keyspace","components":[{"name":"operatorsBitmask","type":"uint256","internalType":"uint256"},{"name":"replicationStrategy","type":"uint8","internalType":"uint8"}]},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"NodeOperatorAdded","inputs":[{"name":"idx","type":"uint8","indexed":false,"internalType":"uint8"},{"name":"operator","type":"tuple","indexed":false,"internalType":"struct NodeOperator","components":[{"name":"addr","type":"address","internalType":"address"},{"name":"data","type":"bytes","internalType":"bytes"}]},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"NodeOperatorRemoved","inputs":[{"name":"operatorAddress","type":"address","indexed":false,"internalType":"address"},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"NodeOperatorUpdated","inputs":[{"name":"operator","type":"tuple","indexed":false,"internalType":"struct NodeOperator","components":[{"name":"addr","type":"address","internalType":"address"},{"name":"data","type":"bytes","internalType":"bytes"}]},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"name":"newOwner","type":"address","indexed":false,"internalType":"address"},{"name":"cluserVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"SettingsUpdated","inputs":[{"name":"newSettings","type":"tuple","indexed":false,"internalType":"struct Settings","components":[{"name":"maxOperatorDataBytes","type":"uint16","internalType":"uint16"}]},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false}],"bytecode":{"object":"0x6080604052346100305761001a61001461030f565b90610acf565b610022610035565b6138ed610ed382396138ed90f35b61003b565b60405190565b5f80fd5b601f801991011690565b634e487b7160e01b5f52604160045260245ffd5b906100679061003f565b810190811060018060401b0382111761007f57604052565b610049565b90610097610090610035565b928361005d565b565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b61ffff1690565b6100b9816100a9565b036100c057565b5f80fd5b905051906100d1826100b0565b565b91906020838203126100fb576100f5906100ed6020610084565b935f016100c4565b5f830152565b6100a1565b5f80fd5b60018060401b03811161011a5760208091020190565b610049565b5f80fd5b60018060a01b031690565b61013790610123565b90565b6101438161012e565b0361014a57565b5f80fd5b9050519061015b8261013a565b565b5f80fd5b60018060401b03811161017d5761017960209161003f565b0190565b610049565b90825f9392825e0152565b909291926101a261019d82610161565b610084565b938185526020850190828401116101be576101bc92610182565b565b61015d565b9080601f830112156101e1578160206101de9351910161018d565b90565b610100565b919091604081840312610236576101fd6040610084565b9261020a815f840161014e565b5f850152602082015160018060401b0381116102315761022a92016101c3565b6020830152565b6100a5565b6100a1565b92919061024f61024a82610104565b610084565b93818552602080860192028101918383116102a45781905b838210610275575050505050565b815160018060401b03811161029f5760209161029487849387016101e6565b815201910190610267565b610100565b61011f565b9080601f830112156102c7578160206102c49351910161023b565b90565b610100565b91909160408184031261030a576102e5835f83016100d3565b92602082015160018060401b0381116103055761030292016102a9565b90565b61009d565b610099565b61032d6147c08038038061032281610084565b9283398101906102cc565b9091565b5190565b90565b90565b90565b61035261034d61035792610338565b61033b565b610335565b90565b60209181520190565b5f7f746f6f206d616e79206f70657261746f72730000000000000000000000000000910152565b610397601260209261035a565b6103a081610363565b0190565b6103b99060208101905f81830391015261038a565b90565b156103c357565b6103cb610035565b62461bcd60e51b8152806103e1600482016103a4565b0390fd5b5f1b90565b906103fb60018060a01b03916103e5565b9181191691161790565b61041961041461041e92610123565b61033b565b610123565b90565b61042a90610405565b90565b61043690610421565b90565b90565b9061045161044c6104589261042d565b610439565b82546103ea565b9055565b634e487b7160e01b5f525f60045260245ffd5b61047990516100a9565b90565b9061048961ffff916103e5565b9181191691161790565b6104a76104a26104ac926100a9565b61033b565b6100a9565b90565b90565b906104c76104c26104ce92610493565b6104af565b825461047c565b9055565b906104e45f806104ea9401920161046f565b906104b2565b565b906104f6916104d2565b565b90565b61050f61050a610514926104f8565b61033b565b610335565b90565b60016105239101610335565b90565b634e487b7160e01b5f52603260045260245ffd5b9061054482610331565b811015610555576020809102010190565b610526565b5190565b610568905161012e565b90565b906105759061042d565b5f5260205260405f2090565b5f1c90565b60ff1690565b61059861059d91610581565b610586565b90565b6105aa905461058c565b90565b151590565b5f7f6475706c6963617465206f70657261746f720000000000000000000000000000910152565b6105e6601260209261035a565b6105ef816105b2565b0190565b6106089060208101905f8183039101526105d9565b90565b1561061257565b61061a610035565b62461bcd60e51b815280610630600482016105f3565b0390fd5b60ff1690565b61064e61064961065392610335565b61033b565b610634565b90565b6106606040610084565b90565b9061066d906105ad565b9052565b9061067b90610634565b9052565b61068990516105ad565b90565b9061069860ff916103e5565b9181191691161790565b6106ab906105ad565b90565b90565b906106c66106c16106cd926106a2565b6106ae565b825461068c565b9055565b6106db9051610634565b90565b60081b90565b906106f161ff00916106de565b9181191691161790565b61070f61070a61071492610634565b61033b565b610634565b90565b90565b9061072f61072a610736926106fb565b610717565b82546106e4565b9055565b9061076460205f61076a9461075c82820161075684880161067f565b906106b1565b0192016106d1565b9061071a565b565b906107769161073a565b565b5061010090565b90565b61078b81610778565b8210156107a55761079d60029161077f565b910201905f90565b610526565b5190565b634e487b7160e01b5f52602260045260245ffd5b90600160028304921680156107e2575b60208310146107dd57565b6107ae565b91607f16916107d2565b5f5260205f2090565b601f602091010490565b1b90565b9190600861081e9102916108185f19846107ff565b926107ff565b9181191691161790565b61083c61083761084192610335565b61033b565b610335565b90565b90565b919061085d61085861086593610828565b610844565b908354610803565b9055565b5f90565b61087f91610879610869565b91610847565b565b5b81811061088d575050565b8061089a5f60019361086d565b01610882565b9190601f81116108b0575b505050565b6108bc6108e1936107ec565b9060206108c8846107f5565b830193106108e9575b6108da906107f5565b0190610881565b5f80806108ab565b91506108da819290506108d1565b1c90565b9061090b905f19906008026108f7565b191690565b8161091a916108fb565b906002021790565b9061092c8161055a565b9060018060401b0382116109ea5761094e8261094885546107c2565b856108a0565b602090601f831160011461098257918091610971935f92610976575b5050610910565b90555b565b90915001515f8061096a565b601f19831691610991856107ec565b925f5b8181106109d2575091600293918560019694106109b8575b50505002019055610974565b6109c8910151601f8416906108fb565b90555f80806109ac565b91936020600181928787015181550195019201610994565b610049565b906109f991610922565b565b90610a2660206001610a2c94610a1e5f8201610a185f880161055e565b9061043c565b0192016107aa565b906109ef565b565b9190610a3f57610a3d916109fb565b565b61045c565b90610a505f19916103e5565b9181191691161790565b90610a6f610a6a610a7692610828565b610844565b8254610a44565b9055565b90565b610a89610a8e91610581565b610a7a565b90565b610a9b9054610a7d565b90565b50600290565b90565b610ab081610a9e565b821015610aca57610ac2600291610aa4565b910201905f90565b610526565b610b0c90610afa610adf84610331565b610af3610aed61010061033e565b91610335565b11156103bc565b610b04335f61043c565b6102086104ec565b610b155f6104fb565b5b80610b31610b2b610b2685610331565b610335565b91610335565b1015610c1c57610c1790610b5b610b566020610b4e86859061053a565b51015161055a565b610db4565b610b99610b94610b8e5f610b8881600101610b8283610b7b8b8a9061053a565b510161055e565b9061056b565b016105a0565b156105ad565b61060b565b610bef6001610bc7610baa8461063a565b610bbe610bb5610656565b935f8501610663565b60208301610671565b610bea5f600101610be45f610bdd89889061053a565b510161055e565b9061056b565b61076c565b610c12610bfd84839061053a565b51610c0c600180018490610782565b90610a2e565b610517565b610b16565b50610c39610c34610c2f610c4493610331565b61063a565b610e96565b610201600101610a5a565b610c6a610c55610201600101610a91565b5f610c636102038290610aa7565b5001610a5a565b565b5f7f656d707479206f70657261746f72206461746100000000000000000000000000910152565b610ca0601360209261035a565b610ca981610c6c565b0190565b610cc29060208101905f818303910152610c93565b90565b15610ccc57565b610cd4610035565b62461bcd60e51b815280610cea60048201610cad565b0390fd5b61ffff1690565b610d01610d0691610581565b610cee565b90565b610d139054610cf5565b90565b610d2a610d25610d2f926100a9565b61033b565b610335565b90565b5f7f6f70657261746f72206461746120746f6f206c61726765000000000000000000910152565b610d66601760209261035a565b610d6f81610d32565b0190565b610d889060208101905f818303910152610d59565b90565b15610d9257565b610d9a610035565b62461bcd60e51b815280610db060048201610d73565b0390fd5b610df990610dd481610dce610dc85f6104fb565b91610335565b11610cc5565b610df2610dec610de75f61020801610d09565b610d16565b91610335565b1115610d8b565b565b610e0f610e0a610e1492610634565b61033b565b610335565b90565b90565b610e2e610e29610e3392610e17565b61033b565b610335565b90565b610e5590610e4f610e49610e5a94610335565b91610335565b906107ff565b610335565b90565b634e487b7160e01b5f52601160045260245ffd5b610e80610e8691939293610335565b92610335565b8203918211610e9157565b610e5d565b610ebf610ecf91610ea5610869565b50610eba610eb4600192610dfb565b91610e1a565b610e36565b610ec96001610e1a565b90610e71565b9056fe60806040526004361015610013575b6107fc565b61001d5f356100cc565b806326322217146100c75780632b726062146100c257806347011c5c146100bd57806353bfb584146100b857806365706f9c146100b357806375418b9d146100ae5780639d44e717146100a9578063c05665dd146100a4578063c130809a1461009f578063f2fde38b1461009a5763f5f2d9f10361000e576107c9565b610796565b610763565b610730565b6106bc565b610646565b6102e1565b61027d565b61023b565b6101d6565b610135565b60e01c90565b60405190565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b908160409103126100f65790565b6100e4565b9060208282031261012b575f82013567ffffffffffffffff81116101265761012392016100e8565b90565b6100e0565b6100dc565b5f0190565b346101635761014d6101483660046100fb565b610f6e565b6101556100d2565b8061015f81610130565b0390f35b6100d8565b60ff1690565b61017781610168565b0361017e57565b5f80fd5b9050359061018f8261016e565b565b9190916040818403126101d1576101aa835f8301610182565b92602082013567ffffffffffffffff81116101cc576101c992016100e8565b90565b6100e0565b6100dc565b34610205576101ef6101e9366004610191565b906115ec565b6101f76100d2565b8061020181610130565b0390f35b6100d8565b908160409103126102185790565b6100e4565b9060408282031261023657610233915f0161020a565b90565b6100dc565b346102695761025361024e36600461021d565b611b8d565b61025b6100d2565b8061026581610130565b0390f35b6100d8565b5f91031261027857565b6100dc565b346102ab5761028d36600461026e565b610295611d42565b61029d6100d2565b806102a781610130565b0390f35b6100d8565b908160209103126102be5790565b6100e4565b906020828203126102dc576102d9915f016102b0565b90565b6100dc565b3461030f576102f96102f43660046102c3565b611ee8565b6103016100d2565b8061030b81610130565b0390f35b6100d8565b60018060a01b031690565b61032890610314565b90565b6103349061031f565b9052565b5190565b60209181520190565b60200190565b5190565b60209181520190565b90825f9392825e0152565b601f801991011690565b61038c61039560209361039a936103838161034b565b9384809361034f565b95869101610358565b610363565b0190565b6103c991602060408201926103b95f8201515f85019061032b565b015190602081840391015261036d565b90565b906103d69161039e565b90565b60200190565b906103f36103ec83610338565b809261033c565b908161040460208302840194610345565b925f915b83831061041757505050505090565b90919293946020610439610433838560019503875289516103cc565b976103d9565b9301930191939290610408565b50600290565b905090565b90565b90565b61046090610454565b9052565b61046d90610168565b9052565b90602080610493936104895f8201515f860190610457565b0151910190610464565b565b906104a281604093610471565b0190565b60200190565b6104c86104c26104bb83610446565b809461044c565b91610451565b5f915b8383106104d85750505050565b6104ee6104e86001928451610495565b926104a6565b920191906104cb565b67ffffffffffffffff1690565b61050d906104f7565b9052565b61ffff1690565b61052190610511565b9052565b905f80610536930151910190610518565b565b9060208061055a936105505f8201515f860190610504565b0151910190610457565b565b905f8061056d93015191019061032b565b565b6fffffffffffffffffffffffffffffffff1690565b61058d9061056f565b9052565b9061062b9061016060e06105c561018084016105b35f8801515f87019061032b565b602087015185820360208701526103df565b946105d8604082015160408601906104ac565b6105ea606082015160c0860190610504565b6105fb608082015183860190610525565b61060e60a0820151610100860190610538565b61062160c082015161014086019061055c565b0151910190610584565b90565b6106439160208201915f818403910152610591565b90565b346106765761065636600461026e565b61067261066161253d565b6106696100d2565b9182918261062e565b0390f35b6100d8565b610684816104f7565b0361068b57565b5f80fd5b9050359061069c8261067b565b565b906020828203126106b7576106b4915f0161068f565b90565b6100dc565b346106ea576106d46106cf36600461069e565b612ab0565b6106dc6100d2565b806106e681610130565b0390f35b6100d8565b6106f88161031f565b036106ff57565b5f80fd5b90503590610710826106ef565b565b9060208282031261072b57610728915f01610703565b90565b6100dc565b3461075e57610748610743366004610712565b612f2c565b6107506100d2565b8061075a81610130565b0390f35b6100d8565b346107915761077336600461026e565b61077b613064565b6107836100d2565b8061078d81610130565b0390f35b6100d8565b346107c4576107ae6107a9366004610712565b61310b565b6107b66100d2565b806107c081610130565b0390f35b6100d8565b346107f7576107d936600461026e565b6107e161321e565b6107e96100d2565b806107f381610130565b0390f35b6100d8565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b90359060016020038136030382121561084e570180359067ffffffffffffffff82116108495760200191600182023603831361084457565b610808565b610804565b610800565b5090565b35610861816106ef565b90565b5f1c90565b60018060a01b031690565b61088061088591610864565b610869565b90565b6108929054610874565b90565b60209181520190565b5f7f756e617574686f72697a65640000000000000000000000000000000000000000910152565b6108d2600c602092610895565b6108db8161089e565b0190565b6108f49060208101905f8183039101526108c5565b90565b156108fe57565b6109066100d2565b62461bcd60e51b81528061091c600482016108df565b0390fd5b90565b61093761093261093c92610314565b610920565b610314565b90565b61094890610923565b90565b6109549061093f565b90565b906109619061094b565b5f5260205260405f2090565b90565b60ff1690565b61098261098791610864565b610970565b90565b6109949054610976565b90565b5f7f756e6b6e6f776e206f70657261746f7200000000000000000000000000000000910152565b6109cb6010602092610895565b6109d481610997565b0190565b6109ed9060208101905f8183039101526109be565b90565b156109f757565b6109ff6100d2565b62461bcd60e51b815280610a15600482016109d8565b0390fd5b60081c90565b60ff1690565b610a31610a3691610a19565b610a1f565b90565b610a439054610a25565b90565b634e487b7160e01b5f52603260045260245ffd5b5061010090565b90565b610a6d81610a5a565b821015610a8757610a7f600291610a61565b910201905f90565b610a46565b634e487b7160e01b5f525f60045260245ffd5b5f1b90565b90610ab560018060a01b0391610a9f565b9181191691161790565b90565b90610ad7610ad2610ade9261094b565b610abf565b8254610aa4565b9055565b634e487b7160e01b5f52604160045260245ffd5b634e487b7160e01b5f52602260045260245ffd5b9060016002830492168015610b2a575b6020831014610b2557565b610af6565b91607f1691610b1a565b5f5260205f2090565b601f602091010490565b1b90565b91906008610b66910291610b605f1984610b47565b92610b47565b9181191691161790565b610b84610b7f610b8992610454565b610920565b610454565b90565b90565b9190610ba5610ba0610bad93610b70565b610b8c565b908354610b4b565b9055565b5f90565b610bc791610bc1610bb1565b91610b8f565b565b5b818110610bd5575050565b80610be25f600193610bb5565b01610bca565b9190601f8111610bf8575b505050565b610c04610c2993610b34565b906020610c1084610b3d565b83019310610c31575b610c2290610b3d565b0190610bc9565b5f8080610bf3565b9150610c2281929050610c19565b1c90565b90610c53905f1990600802610c3f565b191690565b81610c6291610c43565b906002021790565b91610c759082610853565b9067ffffffffffffffff8211610d3457610c9982610c938554610b0a565b85610be8565b5f90601f8311600114610ccc57918091610cbb935f92610cc0575b5050610c58565b90555b565b90915001355f80610cb4565b601f19831691610cdb85610b34565b925f5b818110610d1c57509160029391856001969410610d02575b50505002019055610cbe565b610d12910135601f841690610c43565b90555f8080610cf6565b91936020600181928787013581550195019201610cde565b610ae2565b90610d449291610c6a565b565b90610d736001610d7993610d675f8201610d615f8701610857565b90610ac2565b0191602081019061080c565b91610d39565b565b9190610d8c57610d8a91610d46565b565b610a8c565b6fffffffffffffffffffffffffffffffff1690565b610db2610db791610864565b610d91565b90565b610dc49054610da6565b90565b634e487b7160e01b5f52601160045260245ffd5b610de49061056f565b6fffffffffffffffffffffffffffffffff8114610e015760010190565b610dc7565b90610e216fffffffffffffffffffffffffffffffff91610a9f565b9181191691161790565b610e3f610e3a610e449261056f565b610920565b61056f565b90565b90565b90610e5f610e5a610e6692610e2b565b610e47565b8254610e06565b9055565b50610e79906020810190610703565b90565b5f80fd5b5f80fd5b5f80fd5b9035600160200382360303811215610ec957016020813591019167ffffffffffffffff8211610ec4576001820236038313610ebf57565b610e80565b610e7c565b610e84565b90825f939282370152565b9190610ef381610eec81610ef89561034f565b8095610ece565b610363565b0190565b610f3891610f2a6040820192610f20610f175f830183610e6a565b5f85019061032b565b6020810190610e88565b916020818503910152610ed9565b90565b610f449061056f565b9052565b92916020610f64610f6c9360408701908782035f890152610efc565b940190610f3b565b565b610f8d610f88610f8283602081019061080c565b90610853565b613348565b33610faa610fa4610f9f5f8501610857565b61031f565b9161031f565b148015611075575b610fbb906108f7565b611011610fde610fd95f600101610fd35f8601610857565b90610957565b61096d565b610ff1610fec5f830161098a565b6109f0565b61100b83916110055f600180019201610a39565b90610a64565b90610d7b565b61102f61102761102261020c610dba565b610ddb565b61020c610e4a565b61103a61020c610dba565b7f5aab2c32b1e447db4dba1d2790fe8b863d4775042b10b92e00dab9d6b671b5b5916110706110676100d2565b92839283610f48565b0390a1565b50610fbb3361109461108e6110895f610888565b61031f565b9161031f565b149050610fb2565b5f7f6e6f7420746865206f776e657200000000000000000000000000000000000000910152565b6110d0600d602092610895565b6110d98161109c565b0190565b6110f29060208101905f8183039101526110c3565b90565b156110fc57565b6111046100d2565b62461bcd60e51b81528061111a600482016110dd565b0390fd5b9061114c916111473361114161113b6111365f610888565b61031f565b9161031f565b146110f5565b61147f565b565b151590565b5f7f616c726561647920657869737473000000000000000000000000000000000000910152565b611187600e602092610895565b61119081611153565b0190565b6111a99060208101905f81830391015261117a565b90565b156111b357565b6111bb6100d2565b62461bcd60e51b8152806111d160048201611194565b0390fd5b6111df9054610b0a565b90565b90565b6111f96111f46111fe926111e2565b610920565b610454565b90565b5f7f736c6f74206f6363757069656400000000000000000000000000000000000000910152565b611235600d602092610895565b61123e81611201565b0190565b6112579060208101905f818303910152611228565b90565b1561126157565b6112696100d2565b62461bcd60e51b81528061127f60048201611242565b0390fd5b9061128d90610363565b810190811067ffffffffffffffff8211176112a757604052565b610ae2565b906112bf6112b86100d2565b9283611283565b565b6112cb60406112ac565b90565b906112d89061114e565b9052565b906112e690610168565b9052565b6112f4905161114e565b90565b9061130360ff91610a9f565b9181191691161790565b6113169061114e565b90565b90565b9061133161132c6113389261130d565b611319565b82546112f7565b9055565b6113469051610168565b90565b60081b90565b9061135c61ff0091611349565b9181191691161790565b61137a61137561137f92610168565b610920565b610168565b90565b90565b9061139a6113956113a192611366565b611382565b825461134f565b9055565b906113cf60205f6113d5946113c78282016113c18488016112ea565b9061131c565b01920161133c565b90611385565b565b906113e1916113a5565b565b90565b6113f26113f791610864565b6113e3565b90565b61140490546113e6565b90565b906114135f1991610a9f565b9181191691161790565b9061143261142d61143992610b70565b610b8c565b8254611407565b9055565b61144690610168565b9052565b93929061147560409161147d9461146860608901925f8a019061143d565b8782036020890152610efc565b940190610f3b565b565b61149e61149961149384602081019061080c565b90610853565b613348565b6114d16114cc6114c65f6114c0816001016114ba838901610857565b90610957565b0161098a565b1561114e565b6111ac565b6115056114ed60016114e68180018590610a64565b50016111d5565b6114ff6114f95f6111e5565b91610454565b1461125a565b611548600161152b836115226115196112c1565b935f85016112ce565b602083016112dc565b6115435f60010161153d5f8701610857565b90610957565b6113d7565b6115608261155a600180018490610a64565b90610d7b565b61158661157b6115746102016001016113fa565b83906133d2565b61020160010161141d565b6115a461159c61159761020c610dba565b610ddb565b61020c610e4a565b906115b061020c610dba565b916115e77f952e65f049c574f487580ba41dcf6b0ea8350ef8abc8647a8a11dfaa7af6bad6936115de6100d2565b9384938461144a565b0390a1565b906115f69161111e565b565b611625906116203361161a61161461160f5f610888565b61031f565b9161031f565b146110f5565b6116a9565b565b5f7f6d6967726174696f6e20696e2070726f67726573730000000000000000000000910152565b61165b6015602092610895565b61166481611627565b0190565b61167d9060208101905f81830391015261164e565b90565b1561168757565b61168f6100d2565b62461bcd60e51b8152806116a560048201611668565b0390fd5b6116cb906116c66116c16116bb613401565b1561114e565b611680565b61174f565b565b5f7f6d61696e74656e616e636520696e2070726f6772657373000000000000000000910152565b6117016017602092610895565b61170a816116cd565b0190565b6117239060208101905f8183039101526116f4565b90565b1561172d57565b6117356100d2565b62461bcd60e51b81528061174b6004820161170e565b0390fd5b6117719061176c61176761176161342f565b1561114e565b611726565b611a66565b565b61177c81610454565b0361178357565b5f80fd5b3561179181611773565b90565b5f7f696e76616c6964206269746d61736b0000000000000000000000000000000000910152565b6117c8600f602092610895565b6117d181611794565b0190565b6117ea9060208101905f8183039101526117bb565b90565b156117f457565b6117fc6100d2565b62461bcd60e51b815280611812600482016117d5565b0390fd5b67ffffffffffffffff1690565b61182f61183491610864565b611816565b90565b6118419054611823565b90565b61184d906104f7565b67ffffffffffffffff81146118625760010190565b610dc7565b9061187a67ffffffffffffffff91610a9f565b9181191691161790565b61189861189361189d926104f7565b610920565b6104f7565b90565b90565b906118b86118b36118bf92611884565b6118a0565b8254611867565b9055565b90565b6118da6118d56118df926118c3565b610920565b6104f7565b90565b634e487b7160e01b5f52601260045260245ffd5b611902611908916104f7565b916104f7565b908115611913570690565b6118e2565b50600290565b90565b61192a81611918565b8210156119445761193c60029161191e565b910201905f90565b610a46565b356119538161016e565b90565b9061196b61196661197292611366565b611382565b82546112f7565b9055565b906119a1602060016119a7946119995f82016119935f8801611787565b9061141d565b019201611949565b90611956565b565b91906119ba576119b891611976565b565b610a8c565b6119c8906104f7565b9052565b905035906119d982611773565b565b506119ea9060208101906119cc565b90565b506119fc906020810190610182565b90565b906020611a2a611a3293611a21611a185f8301836119db565b5f860190610457565b828101906119ed565b910190610464565b565b606090611a5d611a649496959396611a5360808401985f8501906119bf565b60208301906119ff565b0190610f3b565b565b611a90611a8b611a775f8401611787565b611a856102016001016113fa565b90613464565b6117ed565b611aaf5f61020901611aa9611aa482611837565b611844565b906118a3565b611acd611ac5611ac0610207611837565b611844565b6102076118a3565b611b0181611afb610203611af5611ae5610207611837565b611aef60026118c6565b906118f6565b90611921565b906119a9565b611b1a611b0f5f8301611787565b60016102090161141d565b611b38611b30611b2b61020c610dba565b610ddb565b61020c610e4a565b611b455f61020901611837565b90611b5161020c610dba565b91611b887f490341fd8fc7a8294fbad1cc0db9f41ae0ac5aeb655ea31b46a475ec3a77749c93611b7f6100d2565b93849384611a34565b0390a1565b611b96906115f8565b565b5f7f6e6f206d61696e74656e616e6365000000000000000000000000000000000000910152565b611bcc600e602092610895565b611bd581611b98565b0190565b611bee9060208101905f818303910152611bbf565b90565b15611bf857565b611c006100d2565b62461bcd60e51b815280611c1660048201611bd9565b0390fd5b611c2a611c2561342f565b611bf1565b611c32611c71565b565b611c48611c43611c4d926111e2565b610920565b610314565b90565b611c5990611c34565b90565b9190611c6f905f60208501940190610f3b565b565b611c7e5f61020b01610888565b611c90611c8a3361031f565b9161031f565b148015611d1b575b611ca1906108f7565b611cb7611cad5f611c50565b5f61020b01610ac2565b611cd5611ccd611cc861020c610dba565b610ddb565b61020c610e4a565b611ce061020c610dba565b611d167f11943d6deda6f0591d72674788d272eb0209e18b8a3a021fa51cb3b5e9a2ab6191611d0d6100d2565b91829182611c5c565b0390a1565b50611ca133611d3a611d34611d2f5f610888565b61031f565b9161031f565b149050611c98565b611d4a611c1a565b565b611d7990611d7433611d6e611d68611d635f610888565b61031f565b9161031f565b146110f5565b611e78565b565b611d8481610511565b03611d8b57565b5f80fd5b35611d9981611d7b565b90565b90611da961ffff91610a9f565b9181191691161790565b611dc7611dc2611dcc92610511565b610920565b610511565b90565b90565b90611de7611de2611dee92611db3565b611dcf565b8254611d9c565b9055565b90611e045f80611e0a94019201611d8f565b90611dd2565b565b90611e1691611df2565b565b90503590611e2582611d7b565b565b50611e36906020810190611e18565b90565b905f611e4b611e539382810190611e27565b910190610518565b565b916020611e76929493611e6f60408201965f830190611e39565b0190610f3b565b565b611e8481610208611e0c565b611ea2611e9a611e9561020c610dba565b610ddb565b61020c610e4a565b611ead61020c610dba565b7fb24d8d9dcfbb6be13176c1c7bfb0e76445a9ba2a3553b413d8671446f103083091611ee3611eda6100d2565b92839283611e55565b0390a1565b611ef190611d4c565b565b611efe6101006112ac565b90565b5f90565b606090565b67ffffffffffffffff8111611f1f5760200290565b610ae2565b611f30611f3591611f0a565b6112ac565b90565b611f4260406112ac565b90565b5f90565b5f90565b611f55611f38565b9060208083611f62611f45565b815201611f6d611f49565b81525050565b611f7b611f4d565b90565b5f5b828110611f8c57505050565b602090611f97611f73565b8184015201611f80565b90611fbf611fae83611f24565b92611fb98491611f0a565b90611f7e565b565b611fcb6002611fa1565b90565b5f90565b611fdc60206112ac565b90565b5f90565b611feb611fd2565b90602082611ff7611fdf565b81525050565b612005611fe3565b90565b61201260406112ac565b90565b61201d612008565b906020808361202a611fce565b815201612035611f45565b81525050565b612043612015565b90565b61205060206112ac565b90565b61205b612046565b90602082612067611f01565b81525050565b612075612053565b90565b5f90565b612084611ef3565b9060208080808080808089612097611f01565b8152016120a2611f05565b8152016120ad611fc1565b8152016120b8611fce565b8152016120c3611ffd565b8152016120ce61203b565b8152016120d961206d565b8152016120e4612078565b81525050565b6120f261207c565b90565b90565b61210c612107612111926120f5565b610920565b610454565b90565b61212361212991939293610454565b92610454565b820180921161213457565b610dc7565b67ffffffffffffffff81116121515760208091020190565b610ae2565b9061216861216383612139565b6112ac565b918252565b61217760406112ac565b90565b606090565b61218761216d565b9060208083612194611f01565b81520161219f61217a565b81525050565b6121ad61217f565b90565b5f5b8281106121be57505050565b6020906121c96121a5565b81840152016121b2565b906121f86121e083612156565b926020806121ee8693612139565b92019103906121b0565b565b6122056101006112ac565b90565b906122129061031f565b9052565b52565b9061222390610454565b9052565b61223361223891610864565b610a1f565b90565b6122459054612227565b90565b9061227f6122766001612259611f38565b946122706122685f83016113fa565b5f8801612219565b0161223b565b602084016112dc565b565b61228a90612248565b90565b9061229782611918565b6122a081611f24565b926122ab849161191e565b5f915b8383106122bb5750505050565b600260206001926122cb85612281565b8152019201920191906122ae565b6122e29061228d565b90565b52565b906122f2906104f7565b9052565b61ffff1690565b61230961230e91610864565b6122f6565b90565b61231b90546122fd565b90565b9061232890610511565b9052565b9061234b6123435f61233c611fd2565b9401612311565b5f840161231e565b565b6123569061232c565b90565b52565b9061239361238a600161236d612008565b9461238461237c5f8301611837565b5f88016122e8565b016113fa565b60208401612219565b565b61239e9061235c565b90565b52565b906123c36123bb5f6123b4612046565b9401610888565b5f8401612208565b565b6123ce906123a4565b90565b52565b906123de9061056f565b9052565b6123eb90610454565b5f1981146123f95760010190565b610dc7565b61241261240d61241792610454565b610920565b610168565b90565b9061242482610338565b811015612435576020809102010190565b610a46565b905f929180549061245461244d83610b0a565b809461034f565b916001811690815f146124ab575060011461246f575b505050565b61247c9192939450610b34565b915f925b81841061249357505001905f808061246a565b60018160209295939554848601520191019290612480565b92949550505060ff19168252151560200201905f808061246a565b906124d09161243a565b90565b906124f36124ec926124e36100d2565b938480926124c6565b0383611283565b565b52565b9061252f612526600161250961216d565b946125206125185f8301610888565b5f8801612208565b016124d3565b602084016124f5565b565b61253a906124f8565b90565b6125456120ea565b50600161020101612555906113fa565b61255e9061348f565b6125675f610888565b816001612573906120f8565b61257c91612114565b612585906121d3565b610203612593610207611837565b6102086102099161020b936125a961020c610dba565b956125b26121fa565b975f8901906125c091612208565b60208801906125ce91612216565b6125d7906122d9565b60408701906125e5916122e5565b60608601906125f3916122e8565b6125fc9061234d565b608085019061260a91612359565b61261390612395565b60a0840190612621916123a1565b61262a906123c5565b60c0830190612638916123d1565b60e0820190612646916123d4565b600161020101612655906113fa565b925f612660906111e5565b5b8061267461266e86610454565b91610454565b116126d7576126cd906126908661268a836123fe565b906134a4565b6126d2576126c56126a5600180018390610a64565b5060208601516126b58492612531565b6126bf838361241a565b5261241a565b51505b6123e2565b612661565b6126c8565b509250905090565b5f7f6e6f206d6967726174696f6e0000000000000000000000000000000000000000910152565b612713600c602092610895565b61271c816126df565b0190565b6127359060208101905f818303910152612706565b90565b1561273f57565b6127476100d2565b62461bcd60e51b81528061275d60048201612720565b0390fd5b61277a90612775612770613401565b612738565b612910565b565b5f7f77726f6e67206d6967726174696f6e2069640000000000000000000000000000910152565b6127b06012602092610895565b6127b98161277c565b0190565b6127d29060208101905f8183039101526127a3565b90565b156127dc57565b6127e46100d2565b62461bcd60e51b8152806127fa600482016127bd565b0390fd5b61280860406112ac565b90565b906128416128385f61281b6127fe565b9461283261282a83830161098a565b8388016112ce565b01610a39565b602084016112dc565b565b61284c9061280b565b90565b5f7f6e6f742070756c6c696e67000000000000000000000000000000000000000000910152565b612883600b602092610895565b61288c8161284f565b0190565b6128a59060208101905f818303910152612876565b90565b156128af57565b6128b76100d2565b62461bcd60e51b8152806128cd60048201612890565b0390fd5b6128da9061031f565b9052565b60409061290761290e94969593966128fd60608401985f8501906119bf565b60208301906128d1565b0190610f3b565b565b6129389061293261292c6129275f61020901611837565b6104f7565b916104f7565b146127d5565b6129bd6129b261295461294f5f6001013390610957565b612843565b6129676129625f83016112ea565b6109f0565b61299261298d61297b6001610209016113fa565b6129876020850161133c565b906134e2565b6128a8565b6129ac60206129a56001610209016113fa565b920161133c565b90613521565b60016102090161141d565b6129db6129d36129ce61020c610dba565b610ddb565b61020c610e4a565b6129e96001610209016113fa565b6129fb6129f55f6111e5565b91610454565b145f14612a5857612a0f5f61020901611837565b33612a1b61020c610dba565b91612a527f01269879535f40ee8957e15e160bf1866c5e2728ff0cbc583d848821e2639b4e93612a496100d2565b938493846128de565b0390a15b565b612a655f61020901611837565b33612a7161020c610dba565b91612aa87faf5e90e72015f43138f66b4cd08bd1dfa2839030104f22a00af843fe847c6d1993612a9f6100d2565b938493846128de565b0390a1612a56565b612ab990612761565b565b612ae890612ae333612add612ad7612ad25f610888565b61031f565b9161031f565b146110f5565b612d89565b565b5f7f696e206b65797370616365000000000000000000000000000000000000000000910152565b612b1e600b602092610895565b612b2781612aea565b0190565b612b409060208101905f818303910152612b11565b90565b15612b4a57565b612b526100d2565b62461bcd60e51b815280612b6860048201612b2b565b0390fd5b5f80910155565b905f03612b8557612b8390612b6c565b565b610a8c565b90612b9d905f1990602003600802610c3f565b8154169055565b905f91612bbb612bb382610b34565b928354610c58565b905555565b919290602082105f14612c1957601f8411600114612be957612be3929350610c58565b90555b5b565b5090612c0f612c14936001612c06612c0085610b34565b92610b3d565b82019101610bc9565b612ba4565b612be6565b50612c508293612c2a600194610b34565b612c49612c3685610b3d565b820192601f861680612c5b575b50610b3d565b0190610bc9565b600202179055612be7565b612c6790888603612b8a565b5f612c43565b929091680100000000000000008211612ccd576020115f14612cbe57602081105f14612ca257612c9c91610c58565b90555b5b565b60019160ff1916612cb284610b34565b55600202019055612c9f565b60019150600202019055612ca0565b610ae2565b908154612cde81610b0a565b90818311612d07575b818310612cf5575b50505050565b612cfe93612bc0565b5f808080612cef565b612d1383838387612c6d565b612ce7565b5f612d2291612cd2565b565b905f03612d3657612d3490612d18565b565b610a8c565b5f6001612d4d92828082015501612d24565b565b905f03612d6157612d5f90612d3b565b565b610a8c565b916020612d87929493612d8060408201965f8301906128d1565b0190610f3b565b565b612e4e612e43612dc25f612da9612da4826001018790610957565b61096d565b612dbc612db783830161098a565b6109f0565b01610a39565b612dca613401565b5f14612ee057612df2612deb5f612de46102038290611921565b50016113fa565b82906134a4565b80612eb2575b612e0190612b43565b5b612e195f612e14816001018790610957565b612b73565b612e30612e2a600180018390610a64565b90612d4f565b612e3e6102016001016113fa565b613521565b61020160010161141d565b612e6c612e64612e5f61020c610dba565b610ddb565b61020c610e4a565b612e7761020c610dba565b7f6a1d7ddc82d57e783a3ae60737a6c1a4704fcf38d966561fea0af8564f2d895d91612ead612ea46100d2565b92839283612d66565b0390a1565b50612e01612ed9612ed25f612ecb610203600190611921565b50016113fa565b83906134a4565b9050612df8565b612f27612f22612f1b5f612f14610203612f0e612efe610207611837565b612f0860026118c6565b906118f6565b90611921565b50016113fa565b83906134a4565b612b43565b612e02565b612f3590612abb565b565b612f5b33612f55612f4f612f4a5f610888565b61031f565b9161031f565b146110f5565b612f63612f65565b565b612f75612f70613401565b612738565b612f7d612fbe565b565b612f88906104f7565b5f8114612f96576001900390565b610dc7565b916020612fbc929493612fb560408201965f8301906119bf565b0190610f3b565b565b612fdc612fd4612fcf610207611837565b612f7f565b6102076118a3565b612ff3612fe85f6111e5565b60016102090161141d565b61301161300961300461020c610dba565b610ddb565b61020c610e4a565b61301e5f61020901611837565b61302961020c610dba565b7ff73240422246f63ed633ef3ce0726b8ab8fb69d46c8a4e5ecb0b2922668674a19161305f6130566100d2565b92839283612f9b565b0390a1565b61306c612f37565b565b61309b906130963361309061308a6130855f610888565b61031f565b9161031f565b146110f5565b61309d565b565b6130a7815f610ac2565b6130c56130bd6130b861020c610dba565b610ddb565b61020c610e4a565b6130d061020c610dba565b7f476610ebc6647c15376100955efbf22ef2a0c3b923fc00b380b660c873ef20ac916131066130fd6100d2565b92839283612d66565b0390a1565b6131149061306e565b565b61312f61312a613124613401565b1561114e565b611680565b613137613139565b565b61315261314d61314761342f565b1561114e565b611726565b61315a61315c565b565b6131745f61316e816001013390610957565b0161098a565b80156131f7575b613184906108f7565b613192335f61020b01610ac2565b6131b06131a86131a361020c610dba565b610ddb565b61020c610e4a565b336131bc61020c610dba565b7fbc2748cf02f7a1291525e866efc76ab3b96d32d7afcbb26c53daec617b38b479916131f26131e96100d2565b92839283612d66565b0390a1565b506131843361321661321061320b5f610888565b61031f565b9161031f565b14905061317b565b613226613116565b565b5f7f656d707479206f70657261746f72206461746100000000000000000000000000910152565b61325c6013602092610895565b61326581613228565b0190565b61327e9060208101905f81830391015261324f565b90565b1561328857565b6132906100d2565b62461bcd60e51b8152806132a660048201613269565b0390fd5b6132be6132b96132c392610511565b610920565b610454565b90565b5f7f6f70657261746f72206461746120746f6f206c61726765000000000000000000910152565b6132fa6017602092610895565b613303816132c6565b0190565b61331c9060208101905f8183039101526132ed565b90565b1561332657565b61332e6100d2565b62461bcd60e51b81528061334460048201613307565b0390fd5b61338d906133688161336261335c5f6111e5565b91610454565b11613281565b61338661338061337b5f61020801612311565b6132aa565b91610454565b111561331f565b565b6133a361339e6133a892610168565b610920565b610454565b90565b6133ca906133c46133be6133cf94610454565b91610454565b90610b47565b610454565b90565b6133f9906133de610bb1565b50916133f46133ee60019261338f565b916120f8565b6133ab565b1790565b5f90565b6134096133fd565b506134186001610209016113fa565b61342a6134245f6111e5565b91610454565b141590565b6134376133fd565b506134455f61020b01610888565b61345f6134596134545f611c50565b61031f565b9161031f565b141590565b613478906134706133fd565b509119610454565b1661348b6134855f6111e5565b91610454565b1490565b6134a19061349b610bb1565b50613714565b90565b6134cb906134b06133fd565b50916134c66134c060019261338f565b916120f8565b6133ab565b166134de6134d85f6111e5565b91610454565b1490565b613509906134ee6133fd565b50916135046134fe60019261338f565b916120f8565b6133ab565b1661351c6135165f6111e5565b91610454565b141590565b61354b61355191613530610bb1565b509261354661354060019261338f565b916120f8565b6133ab565b19610454565b1690565b90565b61356c61356761357192613555565b610920565b610454565b90565b90565b61358b61358661359092613574565b610920565b610168565b90565b6135b2906135ac6135a66135b794610168565b91610454565b90610b47565b610454565b90565b6135d9906135d36135cd6135de94610454565b91610454565b90610c3f565b610454565b90565b90565b6135f86135f36135fd926135e1565b610920565b610454565b90565b90565b61361761361261361c92613600565b610920565b610168565b90565b90565b61363661363161363b9261361f565b610920565b610454565b90565b90565b61365561365061365a9261363e565b610920565b610168565b90565b90565b61367461366f6136799261365d565b610920565b610454565b90565b90565b61369361368e6136989261367c565b610920565b610168565b90565b90565b6136b26136ad6136b79261369b565b610920565b610454565b90565b90565b6136d16136cc6136d6926136ba565b610920565b610168565b90565b90565b6136f06136eb6136f5926136d9565b610920565b610454565b90565b61370c613707613711926118c3565b610920565b610168565b90565b61371c610bb1565b5061375c61374c826137466137406fffffffffffffffffffffffffffffffff613558565b91610454565b116138a9565b6137566007613577565b90613593565b61379d61378d61376d8484906135ba565b61378761378167ffffffffffffffff6135e4565b91610454565b116138a9565b6137976006613603565b90613593565b176137db6137cb6137af8484906135ba565b6137c56137bf63ffffffff613622565b91610454565b116138a9565b6137d56005613641565b90613593565b176138176138076137ed8484906135ba565b6138016137fb61ffff613660565b91610454565b116138a9565b613811600461367f565b90613593565b176138526138426138298484906135ba565b61383c61383660ff61369e565b91610454565b116138a9565b61384c60036136bd565b90613593565b1761388d61387d6138648484906135ba565b613877613871600f6136dc565b91610454565b116138a9565b61388760026136f8565b90613593565b17906d010102020202030303030303030360801b90821c1a1790565b6138b1610bb1565b5015159056fea264697066735822122015abc4566b5a4eece53e06dab0721de14be34963877d9977ca41a88371cca70b64736f6c634300081c0033","sourceMap":"993:7199:24:-:0;;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;:::i;:::-;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;:::i;:::-;;;;;;;;;;:::o;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;:::o;:::-;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;:::o;:::-;;;:::o;:::-;;:::o;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;:::o;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;:::i;:::-;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;:::o;:::-;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;:::i;:::-;:::o;:::-;;;;:::o;:::-;;:::o;:::-;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;:::o;:::-;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;:::o;:::-;;;;;;;:::o;:::-;;;:::o;:::-;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;:::i;:::-;;;;;:::i;:::-;;;:::o;:::-;;;:::o;:::-;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;;;;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;:::o;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;:::i;:::-;;;;;;:::o;:::-;;;;;:::i;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;;;;:::i;:::-;:::o;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;:::o;:::-;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;:::o;:::-;;:::i;1315:800::-;1510:26;1315:800;1410:61;1418:23;:16;:23;:::i;:::-;:30;;1445:3;1418:30;:::i;:::-;;;:::i;:::-;;;1410:61;:::i;:::-;1482:18;1490:10;1482:18;;:::i;:::-;1510:26;;:::i;:::-;1568:13;1580:1;1568:13;:::i;:::-;1612:3;1583:1;:27;;1587:23;:16;:23;:::i;:::-;1583:27;:::i;:::-;;;:::i;:::-;;;;;1612:3;1656:16;:31;;:24;:19;:16;1673:1;1656:19;;:::i;:::-;;:24;;:31;:::i;:::-;;:::i;:::-;1702:87;1710:56;1711:55;;:47;:13;;:21;1733:24;:16;:19;:16;1750:1;1733:19;;:::i;:::-;;:24;;:::i;:::-;1711:47;;:::i;:::-;:55;;:::i;:::-;1710:56;;:::i;:::-;1702:87;:::i;:::-;1804:94;1874:4;1854:44;1887:8;1893:1;1887:8;:::i;:::-;1854:44;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::i;:::-;1804:47;:21;:13;:21;1826:24;;:19;:16;1843:1;1826:19;;:::i;:::-;;:24;;:::i;:::-;1804:47;;:::i;:::-;:94;:::i;:::-;1912:44;1937:19;:16;1954:1;1937:19;;:::i;:::-;;1912:22;:19;:13;:19;1932:1;1912:22;;:::i;:::-;:44;;:::i;:::-;1612:3;:::i;:::-;1568:13;;1583:27;;2001:44;2014:30;2020:23;1977:68;1583:27;2020:23;:::i;:::-;2014:30;:::i;:::-;2001:44;:::i;:::-;1977:21;:13;:21;:68;:::i;:::-;2055:53;2087:21;;:13;:21;;:::i;:::-;2055:29;:12;:9;2065:1;2055:12;;:::i;:::-;;:29;:53;:::i;:::-;1315:800::o;993:7199::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;7731:205;7855:74;7731:205;7804:41;7812:5;:9;;7820:1;7812:9;:::i;:::-;;;:::i;:::-;;7804:41;:::i;:::-;7863:38;;7872:29;;:8;:29;;:::i;:::-;7863:38;:::i;:::-;;;:::i;:::-;;;7855:74;:::i;:::-;7731:205::o;993:7199::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;:::o;:::-;;:::i;8885:101::-;8959:15;8958:21;8885:101;8931:7;;:::i;:::-;8959:1;:15;8964:10;8959:1;8972;8964:10;:::i;:::-;8959:15;;:::i;:::-;;:::i;:::-;8958:21;8978:1;8958:21;:::i;:::-;;;:::i;:::-;8951:28;:::o","linkReferences":{}},"deployedBytecode":{"object":"0x60806040526004361015610013575b6107fc565b61001d5f356100cc565b806326322217146100c75780632b726062146100c257806347011c5c146100bd57806353bfb584146100b857806365706f9c146100b357806375418b9d146100ae5780639d44e717146100a9578063c05665dd146100a4578063c130809a1461009f578063f2fde38b1461009a5763f5f2d9f10361000e576107c9565b610796565b610763565b610730565b6106bc565b610646565b6102e1565b61027d565b61023b565b6101d6565b610135565b60e01c90565b60405190565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b908160409103126100f65790565b6100e4565b9060208282031261012b575f82013567ffffffffffffffff81116101265761012392016100e8565b90565b6100e0565b6100dc565b5f0190565b346101635761014d6101483660046100fb565b610f6e565b6101556100d2565b8061015f81610130565b0390f35b6100d8565b60ff1690565b61017781610168565b0361017e57565b5f80fd5b9050359061018f8261016e565b565b9190916040818403126101d1576101aa835f8301610182565b92602082013567ffffffffffffffff81116101cc576101c992016100e8565b90565b6100e0565b6100dc565b34610205576101ef6101e9366004610191565b906115ec565b6101f76100d2565b8061020181610130565b0390f35b6100d8565b908160409103126102185790565b6100e4565b9060408282031261023657610233915f0161020a565b90565b6100dc565b346102695761025361024e36600461021d565b611b8d565b61025b6100d2565b8061026581610130565b0390f35b6100d8565b5f91031261027857565b6100dc565b346102ab5761028d36600461026e565b610295611d42565b61029d6100d2565b806102a781610130565b0390f35b6100d8565b908160209103126102be5790565b6100e4565b906020828203126102dc576102d9915f016102b0565b90565b6100dc565b3461030f576102f96102f43660046102c3565b611ee8565b6103016100d2565b8061030b81610130565b0390f35b6100d8565b60018060a01b031690565b61032890610314565b90565b6103349061031f565b9052565b5190565b60209181520190565b60200190565b5190565b60209181520190565b90825f9392825e0152565b601f801991011690565b61038c61039560209361039a936103838161034b565b9384809361034f565b95869101610358565b610363565b0190565b6103c991602060408201926103b95f8201515f85019061032b565b015190602081840391015261036d565b90565b906103d69161039e565b90565b60200190565b906103f36103ec83610338565b809261033c565b908161040460208302840194610345565b925f915b83831061041757505050505090565b90919293946020610439610433838560019503875289516103cc565b976103d9565b9301930191939290610408565b50600290565b905090565b90565b90565b61046090610454565b9052565b61046d90610168565b9052565b90602080610493936104895f8201515f860190610457565b0151910190610464565b565b906104a281604093610471565b0190565b60200190565b6104c86104c26104bb83610446565b809461044c565b91610451565b5f915b8383106104d85750505050565b6104ee6104e86001928451610495565b926104a6565b920191906104cb565b67ffffffffffffffff1690565b61050d906104f7565b9052565b61ffff1690565b61052190610511565b9052565b905f80610536930151910190610518565b565b9060208061055a936105505f8201515f860190610504565b0151910190610457565b565b905f8061056d93015191019061032b565b565b6fffffffffffffffffffffffffffffffff1690565b61058d9061056f565b9052565b9061062b9061016060e06105c561018084016105b35f8801515f87019061032b565b602087015185820360208701526103df565b946105d8604082015160408601906104ac565b6105ea606082015160c0860190610504565b6105fb608082015183860190610525565b61060e60a0820151610100860190610538565b61062160c082015161014086019061055c565b0151910190610584565b90565b6106439160208201915f818403910152610591565b90565b346106765761065636600461026e565b61067261066161253d565b6106696100d2565b9182918261062e565b0390f35b6100d8565b610684816104f7565b0361068b57565b5f80fd5b9050359061069c8261067b565b565b906020828203126106b7576106b4915f0161068f565b90565b6100dc565b346106ea576106d46106cf36600461069e565b612ab0565b6106dc6100d2565b806106e681610130565b0390f35b6100d8565b6106f88161031f565b036106ff57565b5f80fd5b90503590610710826106ef565b565b9060208282031261072b57610728915f01610703565b90565b6100dc565b3461075e57610748610743366004610712565b612f2c565b6107506100d2565b8061075a81610130565b0390f35b6100d8565b346107915761077336600461026e565b61077b613064565b6107836100d2565b8061078d81610130565b0390f35b6100d8565b346107c4576107ae6107a9366004610712565b61310b565b6107b66100d2565b806107c081610130565b0390f35b6100d8565b346107f7576107d936600461026e565b6107e161321e565b6107e96100d2565b806107f381610130565b0390f35b6100d8565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b90359060016020038136030382121561084e570180359067ffffffffffffffff82116108495760200191600182023603831361084457565b610808565b610804565b610800565b5090565b35610861816106ef565b90565b5f1c90565b60018060a01b031690565b61088061088591610864565b610869565b90565b6108929054610874565b90565b60209181520190565b5f7f756e617574686f72697a65640000000000000000000000000000000000000000910152565b6108d2600c602092610895565b6108db8161089e565b0190565b6108f49060208101905f8183039101526108c5565b90565b156108fe57565b6109066100d2565b62461bcd60e51b81528061091c600482016108df565b0390fd5b90565b61093761093261093c92610314565b610920565b610314565b90565b61094890610923565b90565b6109549061093f565b90565b906109619061094b565b5f5260205260405f2090565b90565b60ff1690565b61098261098791610864565b610970565b90565b6109949054610976565b90565b5f7f756e6b6e6f776e206f70657261746f7200000000000000000000000000000000910152565b6109cb6010602092610895565b6109d481610997565b0190565b6109ed9060208101905f8183039101526109be565b90565b156109f757565b6109ff6100d2565b62461bcd60e51b815280610a15600482016109d8565b0390fd5b60081c90565b60ff1690565b610a31610a3691610a19565b610a1f565b90565b610a439054610a25565b90565b634e487b7160e01b5f52603260045260245ffd5b5061010090565b90565b610a6d81610a5a565b821015610a8757610a7f600291610a61565b910201905f90565b610a46565b634e487b7160e01b5f525f60045260245ffd5b5f1b90565b90610ab560018060a01b0391610a9f565b9181191691161790565b90565b90610ad7610ad2610ade9261094b565b610abf565b8254610aa4565b9055565b634e487b7160e01b5f52604160045260245ffd5b634e487b7160e01b5f52602260045260245ffd5b9060016002830492168015610b2a575b6020831014610b2557565b610af6565b91607f1691610b1a565b5f5260205f2090565b601f602091010490565b1b90565b91906008610b66910291610b605f1984610b47565b92610b47565b9181191691161790565b610b84610b7f610b8992610454565b610920565b610454565b90565b90565b9190610ba5610ba0610bad93610b70565b610b8c565b908354610b4b565b9055565b5f90565b610bc791610bc1610bb1565b91610b8f565b565b5b818110610bd5575050565b80610be25f600193610bb5565b01610bca565b9190601f8111610bf8575b505050565b610c04610c2993610b34565b906020610c1084610b3d565b83019310610c31575b610c2290610b3d565b0190610bc9565b5f8080610bf3565b9150610c2281929050610c19565b1c90565b90610c53905f1990600802610c3f565b191690565b81610c6291610c43565b906002021790565b91610c759082610853565b9067ffffffffffffffff8211610d3457610c9982610c938554610b0a565b85610be8565b5f90601f8311600114610ccc57918091610cbb935f92610cc0575b5050610c58565b90555b565b90915001355f80610cb4565b601f19831691610cdb85610b34565b925f5b818110610d1c57509160029391856001969410610d02575b50505002019055610cbe565b610d12910135601f841690610c43565b90555f8080610cf6565b91936020600181928787013581550195019201610cde565b610ae2565b90610d449291610c6a565b565b90610d736001610d7993610d675f8201610d615f8701610857565b90610ac2565b0191602081019061080c565b91610d39565b565b9190610d8c57610d8a91610d46565b565b610a8c565b6fffffffffffffffffffffffffffffffff1690565b610db2610db791610864565b610d91565b90565b610dc49054610da6565b90565b634e487b7160e01b5f52601160045260245ffd5b610de49061056f565b6fffffffffffffffffffffffffffffffff8114610e015760010190565b610dc7565b90610e216fffffffffffffffffffffffffffffffff91610a9f565b9181191691161790565b610e3f610e3a610e449261056f565b610920565b61056f565b90565b90565b90610e5f610e5a610e6692610e2b565b610e47565b8254610e06565b9055565b50610e79906020810190610703565b90565b5f80fd5b5f80fd5b5f80fd5b9035600160200382360303811215610ec957016020813591019167ffffffffffffffff8211610ec4576001820236038313610ebf57565b610e80565b610e7c565b610e84565b90825f939282370152565b9190610ef381610eec81610ef89561034f565b8095610ece565b610363565b0190565b610f3891610f2a6040820192610f20610f175f830183610e6a565b5f85019061032b565b6020810190610e88565b916020818503910152610ed9565b90565b610f449061056f565b9052565b92916020610f64610f6c9360408701908782035f890152610efc565b940190610f3b565b565b610f8d610f88610f8283602081019061080c565b90610853565b613348565b33610faa610fa4610f9f5f8501610857565b61031f565b9161031f565b148015611075575b610fbb906108f7565b611011610fde610fd95f600101610fd35f8601610857565b90610957565b61096d565b610ff1610fec5f830161098a565b6109f0565b61100b83916110055f600180019201610a39565b90610a64565b90610d7b565b61102f61102761102261020c610dba565b610ddb565b61020c610e4a565b61103a61020c610dba565b7f5aab2c32b1e447db4dba1d2790fe8b863d4775042b10b92e00dab9d6b671b5b5916110706110676100d2565b92839283610f48565b0390a1565b50610fbb3361109461108e6110895f610888565b61031f565b9161031f565b149050610fb2565b5f7f6e6f7420746865206f776e657200000000000000000000000000000000000000910152565b6110d0600d602092610895565b6110d98161109c565b0190565b6110f29060208101905f8183039101526110c3565b90565b156110fc57565b6111046100d2565b62461bcd60e51b81528061111a600482016110dd565b0390fd5b9061114c916111473361114161113b6111365f610888565b61031f565b9161031f565b146110f5565b61147f565b565b151590565b5f7f616c726561647920657869737473000000000000000000000000000000000000910152565b611187600e602092610895565b61119081611153565b0190565b6111a99060208101905f81830391015261117a565b90565b156111b357565b6111bb6100d2565b62461bcd60e51b8152806111d160048201611194565b0390fd5b6111df9054610b0a565b90565b90565b6111f96111f46111fe926111e2565b610920565b610454565b90565b5f7f736c6f74206f6363757069656400000000000000000000000000000000000000910152565b611235600d602092610895565b61123e81611201565b0190565b6112579060208101905f818303910152611228565b90565b1561126157565b6112696100d2565b62461bcd60e51b81528061127f60048201611242565b0390fd5b9061128d90610363565b810190811067ffffffffffffffff8211176112a757604052565b610ae2565b906112bf6112b86100d2565b9283611283565b565b6112cb60406112ac565b90565b906112d89061114e565b9052565b906112e690610168565b9052565b6112f4905161114e565b90565b9061130360ff91610a9f565b9181191691161790565b6113169061114e565b90565b90565b9061133161132c6113389261130d565b611319565b82546112f7565b9055565b6113469051610168565b90565b60081b90565b9061135c61ff0091611349565b9181191691161790565b61137a61137561137f92610168565b610920565b610168565b90565b90565b9061139a6113956113a192611366565b611382565b825461134f565b9055565b906113cf60205f6113d5946113c78282016113c18488016112ea565b9061131c565b01920161133c565b90611385565b565b906113e1916113a5565b565b90565b6113f26113f791610864565b6113e3565b90565b61140490546113e6565b90565b906114135f1991610a9f565b9181191691161790565b9061143261142d61143992610b70565b610b8c565b8254611407565b9055565b61144690610168565b9052565b93929061147560409161147d9461146860608901925f8a019061143d565b8782036020890152610efc565b940190610f3b565b565b61149e61149961149384602081019061080c565b90610853565b613348565b6114d16114cc6114c65f6114c0816001016114ba838901610857565b90610957565b0161098a565b1561114e565b6111ac565b6115056114ed60016114e68180018590610a64565b50016111d5565b6114ff6114f95f6111e5565b91610454565b1461125a565b611548600161152b836115226115196112c1565b935f85016112ce565b602083016112dc565b6115435f60010161153d5f8701610857565b90610957565b6113d7565b6115608261155a600180018490610a64565b90610d7b565b61158661157b6115746102016001016113fa565b83906133d2565b61020160010161141d565b6115a461159c61159761020c610dba565b610ddb565b61020c610e4a565b906115b061020c610dba565b916115e77f952e65f049c574f487580ba41dcf6b0ea8350ef8abc8647a8a11dfaa7af6bad6936115de6100d2565b9384938461144a565b0390a1565b906115f69161111e565b565b611625906116203361161a61161461160f5f610888565b61031f565b9161031f565b146110f5565b6116a9565b565b5f7f6d6967726174696f6e20696e2070726f67726573730000000000000000000000910152565b61165b6015602092610895565b61166481611627565b0190565b61167d9060208101905f81830391015261164e565b90565b1561168757565b61168f6100d2565b62461bcd60e51b8152806116a560048201611668565b0390fd5b6116cb906116c66116c16116bb613401565b1561114e565b611680565b61174f565b565b5f7f6d61696e74656e616e636520696e2070726f6772657373000000000000000000910152565b6117016017602092610895565b61170a816116cd565b0190565b6117239060208101905f8183039101526116f4565b90565b1561172d57565b6117356100d2565b62461bcd60e51b81528061174b6004820161170e565b0390fd5b6117719061176c61176761176161342f565b1561114e565b611726565b611a66565b565b61177c81610454565b0361178357565b5f80fd5b3561179181611773565b90565b5f7f696e76616c6964206269746d61736b0000000000000000000000000000000000910152565b6117c8600f602092610895565b6117d181611794565b0190565b6117ea9060208101905f8183039101526117bb565b90565b156117f457565b6117fc6100d2565b62461bcd60e51b815280611812600482016117d5565b0390fd5b67ffffffffffffffff1690565b61182f61183491610864565b611816565b90565b6118419054611823565b90565b61184d906104f7565b67ffffffffffffffff81146118625760010190565b610dc7565b9061187a67ffffffffffffffff91610a9f565b9181191691161790565b61189861189361189d926104f7565b610920565b6104f7565b90565b90565b906118b86118b36118bf92611884565b6118a0565b8254611867565b9055565b90565b6118da6118d56118df926118c3565b610920565b6104f7565b90565b634e487b7160e01b5f52601260045260245ffd5b611902611908916104f7565b916104f7565b908115611913570690565b6118e2565b50600290565b90565b61192a81611918565b8210156119445761193c60029161191e565b910201905f90565b610a46565b356119538161016e565b90565b9061196b61196661197292611366565b611382565b82546112f7565b9055565b906119a1602060016119a7946119995f82016119935f8801611787565b9061141d565b019201611949565b90611956565b565b91906119ba576119b891611976565b565b610a8c565b6119c8906104f7565b9052565b905035906119d982611773565b565b506119ea9060208101906119cc565b90565b506119fc906020810190610182565b90565b906020611a2a611a3293611a21611a185f8301836119db565b5f860190610457565b828101906119ed565b910190610464565b565b606090611a5d611a649496959396611a5360808401985f8501906119bf565b60208301906119ff565b0190610f3b565b565b611a90611a8b611a775f8401611787565b611a856102016001016113fa565b90613464565b6117ed565b611aaf5f61020901611aa9611aa482611837565b611844565b906118a3565b611acd611ac5611ac0610207611837565b611844565b6102076118a3565b611b0181611afb610203611af5611ae5610207611837565b611aef60026118c6565b906118f6565b90611921565b906119a9565b611b1a611b0f5f8301611787565b60016102090161141d565b611b38611b30611b2b61020c610dba565b610ddb565b61020c610e4a565b611b455f61020901611837565b90611b5161020c610dba565b91611b887f490341fd8fc7a8294fbad1cc0db9f41ae0ac5aeb655ea31b46a475ec3a77749c93611b7f6100d2565b93849384611a34565b0390a1565b611b96906115f8565b565b5f7f6e6f206d61696e74656e616e6365000000000000000000000000000000000000910152565b611bcc600e602092610895565b611bd581611b98565b0190565b611bee9060208101905f818303910152611bbf565b90565b15611bf857565b611c006100d2565b62461bcd60e51b815280611c1660048201611bd9565b0390fd5b611c2a611c2561342f565b611bf1565b611c32611c71565b565b611c48611c43611c4d926111e2565b610920565b610314565b90565b611c5990611c34565b90565b9190611c6f905f60208501940190610f3b565b565b611c7e5f61020b01610888565b611c90611c8a3361031f565b9161031f565b148015611d1b575b611ca1906108f7565b611cb7611cad5f611c50565b5f61020b01610ac2565b611cd5611ccd611cc861020c610dba565b610ddb565b61020c610e4a565b611ce061020c610dba565b611d167f11943d6deda6f0591d72674788d272eb0209e18b8a3a021fa51cb3b5e9a2ab6191611d0d6100d2565b91829182611c5c565b0390a1565b50611ca133611d3a611d34611d2f5f610888565b61031f565b9161031f565b149050611c98565b611d4a611c1a565b565b611d7990611d7433611d6e611d68611d635f610888565b61031f565b9161031f565b146110f5565b611e78565b565b611d8481610511565b03611d8b57565b5f80fd5b35611d9981611d7b565b90565b90611da961ffff91610a9f565b9181191691161790565b611dc7611dc2611dcc92610511565b610920565b610511565b90565b90565b90611de7611de2611dee92611db3565b611dcf565b8254611d9c565b9055565b90611e045f80611e0a94019201611d8f565b90611dd2565b565b90611e1691611df2565b565b90503590611e2582611d7b565b565b50611e36906020810190611e18565b90565b905f611e4b611e539382810190611e27565b910190610518565b565b916020611e76929493611e6f60408201965f830190611e39565b0190610f3b565b565b611e8481610208611e0c565b611ea2611e9a611e9561020c610dba565b610ddb565b61020c610e4a565b611ead61020c610dba565b7fb24d8d9dcfbb6be13176c1c7bfb0e76445a9ba2a3553b413d8671446f103083091611ee3611eda6100d2565b92839283611e55565b0390a1565b611ef190611d4c565b565b611efe6101006112ac565b90565b5f90565b606090565b67ffffffffffffffff8111611f1f5760200290565b610ae2565b611f30611f3591611f0a565b6112ac565b90565b611f4260406112ac565b90565b5f90565b5f90565b611f55611f38565b9060208083611f62611f45565b815201611f6d611f49565b81525050565b611f7b611f4d565b90565b5f5b828110611f8c57505050565b602090611f97611f73565b8184015201611f80565b90611fbf611fae83611f24565b92611fb98491611f0a565b90611f7e565b565b611fcb6002611fa1565b90565b5f90565b611fdc60206112ac565b90565b5f90565b611feb611fd2565b90602082611ff7611fdf565b81525050565b612005611fe3565b90565b61201260406112ac565b90565b61201d612008565b906020808361202a611fce565b815201612035611f45565b81525050565b612043612015565b90565b61205060206112ac565b90565b61205b612046565b90602082612067611f01565b81525050565b612075612053565b90565b5f90565b612084611ef3565b9060208080808080808089612097611f01565b8152016120a2611f05565b8152016120ad611fc1565b8152016120b8611fce565b8152016120c3611ffd565b8152016120ce61203b565b8152016120d961206d565b8152016120e4612078565b81525050565b6120f261207c565b90565b90565b61210c612107612111926120f5565b610920565b610454565b90565b61212361212991939293610454565b92610454565b820180921161213457565b610dc7565b67ffffffffffffffff81116121515760208091020190565b610ae2565b9061216861216383612139565b6112ac565b918252565b61217760406112ac565b90565b606090565b61218761216d565b9060208083612194611f01565b81520161219f61217a565b81525050565b6121ad61217f565b90565b5f5b8281106121be57505050565b6020906121c96121a5565b81840152016121b2565b906121f86121e083612156565b926020806121ee8693612139565b92019103906121b0565b565b6122056101006112ac565b90565b906122129061031f565b9052565b52565b9061222390610454565b9052565b61223361223891610864565b610a1f565b90565b6122459054612227565b90565b9061227f6122766001612259611f38565b946122706122685f83016113fa565b5f8801612219565b0161223b565b602084016112dc565b565b61228a90612248565b90565b9061229782611918565b6122a081611f24565b926122ab849161191e565b5f915b8383106122bb5750505050565b600260206001926122cb85612281565b8152019201920191906122ae565b6122e29061228d565b90565b52565b906122f2906104f7565b9052565b61ffff1690565b61230961230e91610864565b6122f6565b90565b61231b90546122fd565b90565b9061232890610511565b9052565b9061234b6123435f61233c611fd2565b9401612311565b5f840161231e565b565b6123569061232c565b90565b52565b9061239361238a600161236d612008565b9461238461237c5f8301611837565b5f88016122e8565b016113fa565b60208401612219565b565b61239e9061235c565b90565b52565b906123c36123bb5f6123b4612046565b9401610888565b5f8401612208565b565b6123ce906123a4565b90565b52565b906123de9061056f565b9052565b6123eb90610454565b5f1981146123f95760010190565b610dc7565b61241261240d61241792610454565b610920565b610168565b90565b9061242482610338565b811015612435576020809102010190565b610a46565b905f929180549061245461244d83610b0a565b809461034f565b916001811690815f146124ab575060011461246f575b505050565b61247c9192939450610b34565b915f925b81841061249357505001905f808061246a565b60018160209295939554848601520191019290612480565b92949550505060ff19168252151560200201905f808061246a565b906124d09161243a565b90565b906124f36124ec926124e36100d2565b938480926124c6565b0383611283565b565b52565b9061252f612526600161250961216d565b946125206125185f8301610888565b5f8801612208565b016124d3565b602084016124f5565b565b61253a906124f8565b90565b6125456120ea565b50600161020101612555906113fa565b61255e9061348f565b6125675f610888565b816001612573906120f8565b61257c91612114565b612585906121d3565b610203612593610207611837565b6102086102099161020b936125a961020c610dba565b956125b26121fa565b975f8901906125c091612208565b60208801906125ce91612216565b6125d7906122d9565b60408701906125e5916122e5565b60608601906125f3916122e8565b6125fc9061234d565b608085019061260a91612359565b61261390612395565b60a0840190612621916123a1565b61262a906123c5565b60c0830190612638916123d1565b60e0820190612646916123d4565b600161020101612655906113fa565b925f612660906111e5565b5b8061267461266e86610454565b91610454565b116126d7576126cd906126908661268a836123fe565b906134a4565b6126d2576126c56126a5600180018390610a64565b5060208601516126b58492612531565b6126bf838361241a565b5261241a565b51505b6123e2565b612661565b6126c8565b509250905090565b5f7f6e6f206d6967726174696f6e0000000000000000000000000000000000000000910152565b612713600c602092610895565b61271c816126df565b0190565b6127359060208101905f818303910152612706565b90565b1561273f57565b6127476100d2565b62461bcd60e51b81528061275d60048201612720565b0390fd5b61277a90612775612770613401565b612738565b612910565b565b5f7f77726f6e67206d6967726174696f6e2069640000000000000000000000000000910152565b6127b06012602092610895565b6127b98161277c565b0190565b6127d29060208101905f8183039101526127a3565b90565b156127dc57565b6127e46100d2565b62461bcd60e51b8152806127fa600482016127bd565b0390fd5b61280860406112ac565b90565b906128416128385f61281b6127fe565b9461283261282a83830161098a565b8388016112ce565b01610a39565b602084016112dc565b565b61284c9061280b565b90565b5f7f6e6f742070756c6c696e67000000000000000000000000000000000000000000910152565b612883600b602092610895565b61288c8161284f565b0190565b6128a59060208101905f818303910152612876565b90565b156128af57565b6128b76100d2565b62461bcd60e51b8152806128cd60048201612890565b0390fd5b6128da9061031f565b9052565b60409061290761290e94969593966128fd60608401985f8501906119bf565b60208301906128d1565b0190610f3b565b565b6129389061293261292c6129275f61020901611837565b6104f7565b916104f7565b146127d5565b6129bd6129b261295461294f5f6001013390610957565b612843565b6129676129625f83016112ea565b6109f0565b61299261298d61297b6001610209016113fa565b6129876020850161133c565b906134e2565b6128a8565b6129ac60206129a56001610209016113fa565b920161133c565b90613521565b60016102090161141d565b6129db6129d36129ce61020c610dba565b610ddb565b61020c610e4a565b6129e96001610209016113fa565b6129fb6129f55f6111e5565b91610454565b145f14612a5857612a0f5f61020901611837565b33612a1b61020c610dba565b91612a527f01269879535f40ee8957e15e160bf1866c5e2728ff0cbc583d848821e2639b4e93612a496100d2565b938493846128de565b0390a15b565b612a655f61020901611837565b33612a7161020c610dba565b91612aa87faf5e90e72015f43138f66b4cd08bd1dfa2839030104f22a00af843fe847c6d1993612a9f6100d2565b938493846128de565b0390a1612a56565b612ab990612761565b565b612ae890612ae333612add612ad7612ad25f610888565b61031f565b9161031f565b146110f5565b612d89565b565b5f7f696e206b65797370616365000000000000000000000000000000000000000000910152565b612b1e600b602092610895565b612b2781612aea565b0190565b612b409060208101905f818303910152612b11565b90565b15612b4a57565b612b526100d2565b62461bcd60e51b815280612b6860048201612b2b565b0390fd5b5f80910155565b905f03612b8557612b8390612b6c565b565b610a8c565b90612b9d905f1990602003600802610c3f565b8154169055565b905f91612bbb612bb382610b34565b928354610c58565b905555565b919290602082105f14612c1957601f8411600114612be957612be3929350610c58565b90555b5b565b5090612c0f612c14936001612c06612c0085610b34565b92610b3d565b82019101610bc9565b612ba4565b612be6565b50612c508293612c2a600194610b34565b612c49612c3685610b3d565b820192601f861680612c5b575b50610b3d565b0190610bc9565b600202179055612be7565b612c6790888603612b8a565b5f612c43565b929091680100000000000000008211612ccd576020115f14612cbe57602081105f14612ca257612c9c91610c58565b90555b5b565b60019160ff1916612cb284610b34565b55600202019055612c9f565b60019150600202019055612ca0565b610ae2565b908154612cde81610b0a565b90818311612d07575b818310612cf5575b50505050565b612cfe93612bc0565b5f808080612cef565b612d1383838387612c6d565b612ce7565b5f612d2291612cd2565b565b905f03612d3657612d3490612d18565b565b610a8c565b5f6001612d4d92828082015501612d24565b565b905f03612d6157612d5f90612d3b565b565b610a8c565b916020612d87929493612d8060408201965f8301906128d1565b0190610f3b565b565b612e4e612e43612dc25f612da9612da4826001018790610957565b61096d565b612dbc612db783830161098a565b6109f0565b01610a39565b612dca613401565b5f14612ee057612df2612deb5f612de46102038290611921565b50016113fa565b82906134a4565b80612eb2575b612e0190612b43565b5b612e195f612e14816001018790610957565b612b73565b612e30612e2a600180018390610a64565b90612d4f565b612e3e6102016001016113fa565b613521565b61020160010161141d565b612e6c612e64612e5f61020c610dba565b610ddb565b61020c610e4a565b612e7761020c610dba565b7f6a1d7ddc82d57e783a3ae60737a6c1a4704fcf38d966561fea0af8564f2d895d91612ead612ea46100d2565b92839283612d66565b0390a1565b50612e01612ed9612ed25f612ecb610203600190611921565b50016113fa565b83906134a4565b9050612df8565b612f27612f22612f1b5f612f14610203612f0e612efe610207611837565b612f0860026118c6565b906118f6565b90611921565b50016113fa565b83906134a4565b612b43565b612e02565b612f3590612abb565b565b612f5b33612f55612f4f612f4a5f610888565b61031f565b9161031f565b146110f5565b612f63612f65565b565b612f75612f70613401565b612738565b612f7d612fbe565b565b612f88906104f7565b5f8114612f96576001900390565b610dc7565b916020612fbc929493612fb560408201965f8301906119bf565b0190610f3b565b565b612fdc612fd4612fcf610207611837565b612f7f565b6102076118a3565b612ff3612fe85f6111e5565b60016102090161141d565b61301161300961300461020c610dba565b610ddb565b61020c610e4a565b61301e5f61020901611837565b61302961020c610dba565b7ff73240422246f63ed633ef3ce0726b8ab8fb69d46c8a4e5ecb0b2922668674a19161305f6130566100d2565b92839283612f9b565b0390a1565b61306c612f37565b565b61309b906130963361309061308a6130855f610888565b61031f565b9161031f565b146110f5565b61309d565b565b6130a7815f610ac2565b6130c56130bd6130b861020c610dba565b610ddb565b61020c610e4a565b6130d061020c610dba565b7f476610ebc6647c15376100955efbf22ef2a0c3b923fc00b380b660c873ef20ac916131066130fd6100d2565b92839283612d66565b0390a1565b6131149061306e565b565b61312f61312a613124613401565b1561114e565b611680565b613137613139565b565b61315261314d61314761342f565b1561114e565b611726565b61315a61315c565b565b6131745f61316e816001013390610957565b0161098a565b80156131f7575b613184906108f7565b613192335f61020b01610ac2565b6131b06131a86131a361020c610dba565b610ddb565b61020c610e4a565b336131bc61020c610dba565b7fbc2748cf02f7a1291525e866efc76ab3b96d32d7afcbb26c53daec617b38b479916131f26131e96100d2565b92839283612d66565b0390a1565b506131843361321661321061320b5f610888565b61031f565b9161031f565b14905061317b565b613226613116565b565b5f7f656d707479206f70657261746f72206461746100000000000000000000000000910152565b61325c6013602092610895565b61326581613228565b0190565b61327e9060208101905f81830391015261324f565b90565b1561328857565b6132906100d2565b62461bcd60e51b8152806132a660048201613269565b0390fd5b6132be6132b96132c392610511565b610920565b610454565b90565b5f7f6f70657261746f72206461746120746f6f206c61726765000000000000000000910152565b6132fa6017602092610895565b613303816132c6565b0190565b61331c9060208101905f8183039101526132ed565b90565b1561332657565b61332e6100d2565b62461bcd60e51b81528061334460048201613307565b0390fd5b61338d906133688161336261335c5f6111e5565b91610454565b11613281565b61338661338061337b5f61020801612311565b6132aa565b91610454565b111561331f565b565b6133a361339e6133a892610168565b610920565b610454565b90565b6133ca906133c46133be6133cf94610454565b91610454565b90610b47565b610454565b90565b6133f9906133de610bb1565b50916133f46133ee60019261338f565b916120f8565b6133ab565b1790565b5f90565b6134096133fd565b506134186001610209016113fa565b61342a6134245f6111e5565b91610454565b141590565b6134376133fd565b506134455f61020b01610888565b61345f6134596134545f611c50565b61031f565b9161031f565b141590565b613478906134706133fd565b509119610454565b1661348b6134855f6111e5565b91610454565b1490565b6134a19061349b610bb1565b50613714565b90565b6134cb906134b06133fd565b50916134c66134c060019261338f565b916120f8565b6133ab565b166134de6134d85f6111e5565b91610454565b1490565b613509906134ee6133fd565b50916135046134fe60019261338f565b916120f8565b6133ab565b1661351c6135165f6111e5565b91610454565b141590565b61354b61355191613530610bb1565b509261354661354060019261338f565b916120f8565b6133ab565b19610454565b1690565b90565b61356c61356761357192613555565b610920565b610454565b90565b90565b61358b61358661359092613574565b610920565b610168565b90565b6135b2906135ac6135a66135b794610168565b91610454565b90610b47565b610454565b90565b6135d9906135d36135cd6135de94610454565b91610454565b90610c3f565b610454565b90565b90565b6135f86135f36135fd926135e1565b610920565b610454565b90565b90565b61361761361261361c92613600565b610920565b610168565b90565b90565b61363661363161363b9261361f565b610920565b610454565b90565b90565b61365561365061365a9261363e565b610920565b610168565b90565b90565b61367461366f6136799261365d565b610920565b610454565b90565b90565b61369361368e6136989261367c565b610920565b610168565b90565b90565b6136b26136ad6136b79261369b565b610920565b610454565b90565b90565b6136d16136cc6136d6926136ba565b610920565b610168565b90565b90565b6136f06136eb6136f5926136d9565b610920565b610454565b90565b61370c613707613711926118c3565b610920565b610168565b90565b61371c610bb1565b5061375c61374c826137466137406fffffffffffffffffffffffffffffffff613558565b91610454565b116138a9565b6137566007613577565b90613593565b61379d61378d61376d8484906135ba565b61378761378167ffffffffffffffff6135e4565b91610454565b116138a9565b6137976006613603565b90613593565b176137db6137cb6137af8484906135ba565b6137c56137bf63ffffffff613622565b91610454565b116138a9565b6137d56005613641565b90613593565b176138176138076137ed8484906135ba565b6138016137fb61ffff613660565b91610454565b116138a9565b613811600461367f565b90613593565b176138526138426138298484906135ba565b61383c61383660ff61369e565b91610454565b116138a9565b61384c60036136bd565b90613593565b1761388d61387d6138648484906135ba565b613877613871600f6136dc565b91610454565b116138a9565b61388760026136f8565b90613593565b17906d010102020202030303030303030360801b90821c1a1790565b6138b1610bb1565b5015159056fea264697066735822122015abc4566b5a4eece53e06dab0721de14be34963877d9977ca41a88371cca70b64736f6c634300081c0033","sourceMap":"993:7199:24:-:0;;;;;;;;;-1:-1:-1;993:7199:24;:::i;:::-;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;;;:::o;:::-;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;:::i;:::-;;;;:::o;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;:::o;:::-;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;:::i;:::-;;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;:::o;:::-;;;;;;;:::o;:::-;;;;:::o;:::-;;;:::o;:::-;;;;;;;:::o;:::-;;;;;;;;;;:::o;:::-;;;;;;;;:::o;:::-;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;;;;;;:::o;:::-;;;;:::o;:::-;;:::o;:::-;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;:::o;:::-;;;;;;;:::i;:::-;;;:::o;:::-;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;;;;:::o;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;;;:::i;:::-;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;;;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;:::o;:::-;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;:::o;:::-;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;:::o;:::-;;:::o;:::-;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;:::o;:::-;;;;;;;:::o;:::-;;;:::o;:::-;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;:::i;:::-;;;;;:::i;:::-;;;:::o;:::-;;;:::o;:::-;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;;;;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;:::o;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;:::i;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;;;;:::i;:::-;:::o;:::-;;:::i;:::-;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;;;;;;;;;:::o;:::-;;;;;;;;;;:::i;:::-;;;;:::i;:::-;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;:::o;5247:469::-;5351:20;;:13;:8;:13;;;;;:::i;:::-;:20;;:::i;:::-;;:::i;:::-;5390:10;:27;;5404:13;;:8;:13;;:::i;:::-;5390:27;:::i;:::-;;;:::i;:::-;;:50;;;;5247:469;5382:75;;;:::i;:::-;5596:41;5468:59;5491:36;:21;:13;:21;5513:13;;:8;:13;;:::i;:::-;5491:36;;:::i;:::-;5468:59;:::i;:::-;5537:40;5545:11;;:3;:11;;:::i;:::-;5537:40;:::i;:::-;5596:30;5629:8;5596:13;5616:9;;5596:19;:13;:19;5616:3;:9;;:::i;:::-;5596:30;;:::i;:::-;:41;;:::i;:::-;5647:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;5701:7;;;:::i;:::-;5671:38;;;;;:::i;:::-;;;;;;:::i;:::-;;;;5247:469::o;5390:50::-;5421:10;5382:75;5421:10;:19;;5435:5;;;:::i;:::-;5421:19;:::i;:::-;;;:::i;:::-;;5390:50;;;;993:7199;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;2121:94;;2207:1;2121:94;2152:45;2160:10;:19;;2174:5;;;:::i;:::-;2160:19;:::i;:::-;;;:::i;:::-;;2152:45;:::i;:::-;2207:1;:::i;:::-;2121:94::o;993:7199::-;;;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;:::i;:::-;;;;:::i;:::-;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;:::i;:::-;:::o;:::-;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;:::i;:::-;:::o;4649:592::-;4771:20;;:13;:8;:13;;;;;:::i;:::-;:20;;:::i;:::-;;:::i;:::-;4802:72;4810:45;4811:44;;:36;:13;;:21;4833:13;:8;;:13;;:::i;:::-;4811:36;;:::i;:::-;:44;;:::i;:::-;4810:45;;:::i;:::-;4802:72;:::i;:::-;4884:67;4892:36;:29;:24;:13;;:19;4912:3;4892:24;;:::i;:::-;;:29;:36;:::i;:::-;:41;;4932:1;4892:41;:::i;:::-;;;:::i;:::-;;4884:67;:::i;:::-;4970:78;5029:4;5009:39;5042:3;5009:39;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::i;:::-;4970:36;:21;:13;:21;4992:13;;:8;:13;;:::i;:::-;4970:36;;:::i;:::-;:78;:::i;:::-;5058:35;5085:8;5058:24;:19;:13;:19;5078:3;5058:24;;:::i;:::-;:35;;:::i;:::-;5103:55;5127:31;:21;;:13;:21;;:::i;:::-;5154:3;5127:31;;:::i;:::-;5103:21;:13;:21;:55;:::i;:::-;5169:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;5216:8;5226:7;;;:::i;:::-;5193:41;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;4649:592::o;:::-;;;;;:::i;:::-;:::o;2121:94::-;2207:1;2121:94;2152:45;2160:10;:19;;2174:5;;;:::i;:::-;2160:19;:::i;:::-;;;:::i;:::-;;2152:45;:::i;:::-;2207:1;:::i;:::-;2121:94::o;993:7199::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;2327:109;2428:1;2327:109;2360:58;2368:24;2369:23;;:::i;:::-;2368:24;;:::i;:::-;2360:58;:::i;:::-;2428:1;:::i;:::-;2327:109::o;993:7199::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;2554:115;2661:1;2554:115;2589:62;2597:26;2598:25;;:::i;:::-;2597:26;;:::i;:::-;2589:62;:::i;:::-;2661:1;:::i;:::-;2554:115::o;993:7199::-;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;:::o;:::-;;:::i;:::-;;;;:::o;:::-;;:::o;:::-;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;:::o;:::-;;:::i;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;;;;:::i;:::-;:::o;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;:::i;:::-;:::o;2675:480::-;2785:90;2793:62;:28;;:11;:28;;:::i;:::-;2833:21;;:13;:21;;:::i;:::-;2793:62;;:::i;:::-;2785:90;:::i;:::-;2890:14;:12;:9;:12;:14;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;2915:17;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;2942:44;2975:11;2942:30;:9;2952:19;:15;;;:::i;:::-;:19;2970:1;2952:19;:::i;:::-;;;:::i;:::-;2942:30;;:::i;:::-;:44;;:::i;:::-;2997:64;3033:28;;:11;:28;;:::i;:::-;2997:33;:9;:33;:64;:::i;:::-;3072:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;3113:12;;:9;:12;;:::i;:::-;3127:11;3140:7;;;:::i;:::-;3096:52;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;2675:480::o;:::-;;;;:::i;:::-;:::o;993:7199::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;2442:106;2478:52;2486:25;;:::i;:::-;2478:52;:::i;:::-;2540:1;;:::i;:::-;2442:106::o;993:7199::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;:::i;:::-;:::o;4392:251::-;4463:16;;:11;:16;;:::i;:::-;:30;;4483:10;4463:30;:::i;:::-;;;:::i;:::-;;:53;;;;4392:251;4455:78;;;:::i;:::-;4544:29;4563:10;4571:1;4563:10;:::i;:::-;4544:16;:11;:16;:29;:::i;:::-;4584:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;4628:7;;;:::i;:::-;4608:28;;;;;:::i;:::-;;;;;;:::i;:::-;;;;4392:251::o;4463:53::-;4497:10;4455:78;4497:10;:19;;4511:5;;;:::i;:::-;4497:19;:::i;:::-;;;:::i;:::-;;4463:53;;;;4392:251;;;:::i;:::-;:::o;2121:94::-;2207:1;2121:94;2152:45;2160:10;:19;;2174:5;;;:::i;:::-;2160:19;:::i;:::-;;;:::i;:::-;;2152:45;:::i;:::-;2207:1;:::i;:::-;2121:94::o;993:7199::-;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;:::i;:::-;:::o;:::-;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;:::o;6514:184::-;6598:22;6609:11;6598:22;;:::i;:::-;6630:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;6683:7;;;:::i;:::-;6654:37;;;;;:::i;:::-;;;;;;:::i;:::-;;;;6514:184::o;:::-;;;;:::i;:::-;:::o;993:7199::-;;;;:::i;:::-;;:::o;:::-;;;:::o;:::-;;;:::o;:::-;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;:::o;:::-;;;:::o;:::-;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::o;:::-;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;:::o;:::-;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;:::o;:::-;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::o;:::-;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::o;:::-;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::o;:::-;;;:::i;:::-;;:::o;:::-;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::o;:::-;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;:::i;:::-;;:::i;:::-;;;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;:::o;:::-;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::o;:::-;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;:::o;:::-;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;;;;:::o;:::-;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;:::i;:::-;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;:::i;:::-;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;:::i;:::-;;:::o;6880:845::-;6920:18;;:::i;:::-;6975:13;;:21;;;;;:::i;:::-;:32;;;:::i;:::-;7088:5;;;:::i;:::-;7145:14;7162:1;7145:18;;;:::i;:::-;;;;:::i;:::-;7126:38;;;:::i;:::-;7189:9;7229:15;;;:::i;:::-;7268:8;7301:9;7337:11;;7371:7;;;;:::i;:::-;7055:334;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;7431:13;:21;;;;;:::i;:::-;7480:1;;7468:13;;;:::i;:::-;7504:3;7483:1;:19;;7488:14;7483:19;:::i;:::-;;;:::i;:::-;;;;7504:3;7527:20;:34;:20;7552:8;7558:1;7552:8;:::i;:::-;7527:34;;:::i;:::-;7523:81;;7618:57;7653:22;:19;:13;:19;7673:1;7653:22;;:::i;:::-;;7618:29;:11;:29;;:57;7648:1;7618:57;;:::i;:::-;;;;;:::i;:::-;;;:::i;:::-;;;7468:13;7504:3;:::i;:::-;7468:13;;7523:81;7581:8;;7483:19;;;;;;7700:18;:::o;993:7199::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;2221:100;2313:1;2221:100;2255:48;2263:23;;:::i;:::-;2255:48;:::i;:::-;2313:1;:::i;:::-;2221:100::o;993:7199::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;:::i;:::-;:::o;3161:709::-;3231:49;3161:709;3239:18;;3245:12;;:9;:12;;:::i;:::-;3239:18;:::i;:::-;;;:::i;:::-;;3231:49;:::i;:::-;3513:93;3549:57;3291:63;3321:33;:21;:13;:21;3343:10;3321:33;;:::i;:::-;3291:63;:::i;:::-;3364:48;3372:19;;:11;:19;;:::i;:::-;3364:48;:::i;:::-;3422:80;3430:56;:33;;:9;:33;;:::i;:::-;3468:17;;:11;:17;;:::i;:::-;3430:56;;:::i;:::-;3422:80;:::i;:::-;3588:17;;3549:33;;:9;:33;;:::i;:::-;3588:11;:17;;:::i;:::-;3549:57;;:::i;:::-;3513:33;:9;:33;:93;:::i;:::-;3621:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;3644:33;;:9;:33;;:::i;:::-;:38;;3681:1;3644:38;:::i;:::-;;;:::i;:::-;;3640:224;;;;3722:12;;:9;:12;;:::i;:::-;3736:10;3748:7;;;:::i;:::-;3703:53;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;3640:224;3161:709::o;3640:224::-;3819:12;;:9;:12;;:::i;:::-;3833:10;3845:7;;;:::i;:::-;3792:61;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;3640:224;;3161:709;;;;:::i;:::-;:::o;2121:94::-;2207:1;2121:94;2152:45;2160:10;:19;;2174:5;;;:::i;:::-;2160:19;:::i;:::-;;;:::i;:::-;;2152:45;:::i;:::-;2207:1;:::i;:::-;2121:94::o;993:7199::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;;;:::o;:::-;;;;;;;;;:::i;:::-;:::o;:::-;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;:::o;:::-;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;:::o;:::-;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;-1:-1:-1;993:7199:24;;;;;;;;;;;;;;:::i;:::-;;;;;:::o;:::-;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;:::o;:::-;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;:::i;:::-;:::o;:::-;;:::i;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;:::i;:::-;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;:::o;5722:786::-;6366:55;6390:31;5945:13;;5804:65;5831:38;:13;;:21;5853:15;5831:38;;:::i;:::-;5804:65;:::i;:::-;5879:44;5887:15;:7;;:15;;:::i;:::-;5879:44;:::i;:::-;5945:13;;:::i;:::-;5973:23;;:::i;:::-;5969:281;;;;6032:38;:29;;:12;:9;6042:1;6032:12;;:::i;:::-;;:29;;:::i;:::-;6066:3;6032:38;;:::i;:::-;:80;;;5969:281;6024:104;;;:::i;:::-;5969:281;6268:46;;6275:38;:13;;:21;6297:15;6275:38;;:::i;:::-;6268:46;:::i;:::-;6324:32;6331:24;:19;:13;:19;6351:3;6331:24;;:::i;:::-;6324:32;;:::i;:::-;6390:21;;:13;:21;;:::i;:::-;:31;:::i;:::-;6366:21;:13;:21;:55;:::i;:::-;6432:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;6493:7;;;:::i;:::-;6456:45;;;;;:::i;:::-;;;;;;:::i;:::-;;;;5722:786::o;6032:80::-;6074:9;6024:104;6074:38;:29;;:12;:9;6084:1;6074:12;;:::i;:::-;;:29;;:::i;:::-;6108:3;6074:38;;:::i;:::-;6032:80;;;;5969:281;6159:80;6167:56;:47;;:30;:9;6177:19;:15;;;:::i;:::-;:19;6195:1;6177:19;:::i;:::-;;;:::i;:::-;6167:30;;:::i;:::-;;:47;;:::i;:::-;6219:3;6167:56;;:::i;:::-;6159:80;:::i;:::-;5969:281;;5722:786;;;;:::i;:::-;:::o;2121:94::-;2152:45;2160:10;:19;;2174:5;;;:::i;:::-;2160:19;:::i;:::-;;;:::i;:::-;;2152:45;:::i;:::-;2207:1;;:::i;:::-;2121:94::o;2221:100::-;2255:48;2263:23;;:::i;:::-;2255:48;:::i;:::-;2313:1;;:::i;:::-;2221:100::o;993:7199::-;;;;:::i;:::-;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;:::o;3876:213::-;3944:17;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;3971:37;;4007:1;3971:37;:::i;:::-;:33;:9;:33;:37;:::i;:::-;4019:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;4060:12;;:9;:12;;:::i;:::-;4074:7;;;:::i;:::-;4043:39;;;;;:::i;:::-;;;;;;:::i;:::-;;;;3876:213::o;:::-;;;:::i;:::-;:::o;2121:94::-;2207:1;2121:94;2152:45;2160:10;:19;;2174:5;;;:::i;:::-;2160:19;:::i;:::-;;;:::i;:::-;;2152:45;:::i;:::-;2207:1;:::i;:::-;2121:94::o;6704:170::-;6778:16;6786:8;6778:16;;:::i;:::-;6804:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;6859:7;;;:::i;:::-;6828:39;;;;;:::i;:::-;;;;;;:::i;:::-;;;;6704:170::o;:::-;;;;:::i;:::-;:::o;2327:109::-;2360:58;2368:24;2369:23;;:::i;:::-;2368:24;;:::i;:::-;2360:58;:::i;:::-;2428:1;;:::i;:::-;2327:109::o;2554:115::-;2589:62;2597:26;2598:25;;:::i;:::-;2597:26;;:::i;:::-;2589:62;:::i;:::-;2661:1;;:::i;:::-;2554:115::o;4095:291::-;4176:41;;:33;:13;;:21;4198:10;4176:33;;:::i;:::-;:41;;:::i;:::-;:64;;;;4095:291;4168:89;;;:::i;:::-;4276:29;4295:10;4276:16;:11;:16;:29;:::i;:::-;4316:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;4359:10;4371:7;;;:::i;:::-;4340:39;;;;;:::i;:::-;;;;;;:::i;:::-;;;;4095:291::o;4176:64::-;4221:10;4168:89;4221:10;:19;;4235:5;;;:::i;:::-;4221:19;:::i;:::-;;;:::i;:::-;;4176:64;;;;4095:291;;;:::i;:::-;:::o;993:7199::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;7731:205;7855:74;7731:205;7804:41;7812:5;:9;;7820:1;7812:9;:::i;:::-;;;:::i;:::-;;7804:41;:::i;:::-;7863:38;;7872:29;;:8;:29;;:::i;:::-;7863:38;:::i;:::-;;;:::i;:::-;;;7855:74;:::i;:::-;7731:205::o;993:7199::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;:::i;:::-;;:::o;8992:122::-;9092:15;8992:122;9055:7;;:::i;:::-;9082;9092:1;:15;9097:10;9092:1;9105;9097:10;:::i;:::-;9092:15;;:::i;:::-;;:::i;:::-;9082:25;9075:32;:::o;993:7199::-;;;:::o;7942:124::-;7998:4;;:::i;:::-;8021:9;:33;;:9;:33;;:::i;:::-;:38;;8058:1;8021:38;:::i;:::-;;;:::i;:::-;;;8014:45;:::o;8072:118::-;8130:4;;:::i;:::-;8153:11;:16;;:11;:16;;:::i;:::-;:30;;8173:10;8181:1;8173:10;:::i;:::-;8153:30;:::i;:::-;;;:::i;:::-;;;8146:37;:::o;9820:120::-;9922:6;9820:120;9892:4;;:::i;:::-;9915;9923:5;9922:6;;:::i;:::-;9915:13;:18;;9932:1;9915:18;:::i;:::-;;;:::i;:::-;;9908:25;:::o;9701:113::-;9785:18;9701:113;9759:7;;:::i;:::-;9795;9785:18;:::i;:::-;9778:25;:::o;9384:127::-;9482:15;9384:127;9446:4;;:::i;:::-;9471:7;9482:1;:15;9487:10;9482:1;9495;9487:10;:::i;:::-;9482:15;;:::i;:::-;;:::i;:::-;9471:27;9470:34;;9503:1;9470:34;:::i;:::-;;;:::i;:::-;;9463:41;:::o;9251:127::-;9349:15;9251:127;9313:4;;:::i;:::-;9338:7;9349:1;:15;9354:10;9349:1;9362;9354:10;:::i;:::-;9349:15;;:::i;:::-;;:::i;:::-;9338:27;9337:34;;9370:1;9337:34;:::i;:::-;;;:::i;:::-;;;9330:41;:::o;9120:125::-;9222:15;9220:18;9120:125;9183:7;;:::i;:::-;9210;9222:1;:15;9227:10;9222:1;9235;9227:10;:::i;:::-;9222:15;;:::i;:::-;;:::i;:::-;9220:18;;:::i;:::-;9210:28;9203:35;:::o;993:7199::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;26222:2393:21:-;26270:9;;:::i;:::-;26383:1;26367:60;:55;26383:1;:38;;26387:34;26383:38;:::i;:::-;;;:::i;:::-;;26367:55;:::i;:::-;:60;26426:1;26367:60;:::i;:::-;;;:::i;:::-;26508:51;:46;26525:6;:1;26530;26525:6;;:::i;:::-;26524:29;;26535:18;26524:29;:::i;:::-;;;:::i;:::-;;26508:46;:::i;:::-;:51;26558:1;26508:51;:::i;:::-;;;:::i;:::-;26503:56;26639:43;:38;26656:6;:1;26661;26656:6;;:::i;:::-;26655:21;;26666:10;26655:21;:::i;:::-;;;:::i;:::-;;26639:38;:::i;:::-;:43;26681:1;26639:43;:::i;:::-;;;:::i;:::-;26634:48;26762:39;:34;26779:6;:1;26784;26779:6;;:::i;:::-;26778:17;;26789:6;26778:17;:::i;:::-;;;:::i;:::-;;26762:34;:::i;:::-;:39;26800:1;26762:39;:::i;:::-;;;:::i;:::-;26757:44;26879:37;:32;26896:6;:1;26901;26896:6;;:::i;:::-;26895:15;;26906:4;26895:15;:::i;:::-;;;:::i;:::-;;26879:32;:::i;:::-;:37;26915:1;26879:37;:::i;:::-;;;:::i;:::-;26874:42;26993:36;:31;27010:6;:1;27015;27010:6;;:::i;:::-;27009:14;;27020:3;27009:14;:::i;:::-;;;:::i;:::-;;26993:31;:::i;:::-;:36;27028:1;26993:36;:::i;:::-;;;:::i;:::-;26988:41;28465:144;;;;;;;;;26222:2393;:::o;34795:145:22:-;34842:9;;:::i;:::-;34863:71;;;34795:145;:::o","linkReferences":{}},"methodIdentifiers":{"abortMigration()":"c130809a","addNodeOperator(uint8,(address,bytes))":"2b726062","completeMigration(uint64)":"9d44e717","finishMaintenance()":"53bfb584","getView()":"75418b9d","removeNodeOperator(address)":"c05665dd","startMaintenance()":"f5f2d9f1","startMigration((uint256,uint8))":"47011c5c","transferOwnership(address)":"f2fde38b","updateNodeOperator((address,bytes))":"26322217","updateSettings((uint16))":"65706f9c"},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.28+commit.7893614a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"components\":[{\"internalType\":\"uint16\",\"name\":\"maxOperatorDataBytes\",\"type\":\"uint16\"}],\"internalType\":\"struct Settings\",\"name\":\"initialSettings\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"struct NodeOperator[]\",\"name\":\"initialOperators\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"MaintenanceFinished\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"MaintenanceStarted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"MigrationAborted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"operatorAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"MigrationCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"operatorAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"MigrationDataPullCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"operatorsBitmask\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"replicationStrategy\",\"type\":\"uint8\"}],\"indexed\":false,\"internalType\":\"struct Keyspace\",\"name\":\"newKeyspace\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"MigrationStarted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"idx\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"struct NodeOperator\",\"name\":\"operator\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"NodeOperatorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"operatorAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"NodeOperatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"struct NodeOperator\",\"name\":\"operator\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"NodeOperatorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"cluserVersion\",\"type\":\"uint128\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint16\",\"name\":\"maxOperatorDataBytes\",\"type\":\"uint16\"}],\"indexed\":false,\"internalType\":\"struct Settings\",\"name\":\"newSettings\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"SettingsUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"abortMigration\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"idx\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"struct NodeOperator\",\"name\":\"operator\",\"type\":\"tuple\"}],\"name\":\"addNodeOperator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"}],\"name\":\"completeMigration\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"finishMaintenance\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getView\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"struct NodeOperator[]\",\"name\":\"nodeOperatorSlots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"operatorsBitmask\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"replicationStrategy\",\"type\":\"uint8\"}],\"internalType\":\"struct Keyspace[2]\",\"name\":\"keyspaces\",\"type\":\"tuple[2]\"},{\"internalType\":\"uint64\",\"name\":\"keyspaceVersion\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint16\",\"name\":\"maxOperatorDataBytes\",\"type\":\"uint16\"}],\"internalType\":\"struct Settings\",\"name\":\"settings\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"pullingOperatorsBitmask\",\"type\":\"uint256\"}],\"internalType\":\"struct Migration\",\"name\":\"migration\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"slot\",\"type\":\"address\"}],\"internalType\":\"struct Maintenance\",\"name\":\"maintenance\",\"type\":\"tuple\"},{\"internalType\":\"uint128\",\"name\":\"version\",\"type\":\"uint128\"}],\"internalType\":\"struct ClusterView\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operatorAddress\",\"type\":\"address\"}],\"name\":\"removeNodeOperator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startMaintenance\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"operatorsBitmask\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"replicationStrategy\",\"type\":\"uint8\"}],\"internalType\":\"struct Keyspace\",\"name\":\"newKeyspace\",\"type\":\"tuple\"}],\"name\":\"startMigration\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"struct NodeOperator\",\"name\":\"operator\",\"type\":\"tuple\"}],\"name\":\"updateNodeOperator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint16\",\"name\":\"maxOperatorDataBytes\",\"type\":\"uint16\"}],\"internalType\":\"struct Settings\",\"name\":\"newSettings\",\"type\":\"tuple\"}],\"name\":\"updateSettings\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/Cluster.sol\":\"Cluster\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[\":@openzeppelin-contracts-5.3.0/=dependencies/@openzeppelin-contracts-5.3.0/\",\":forge-std-1.9.7/=dependencies/forge-std-1.9.7/src/\",\":forge-std/=dependencies/forge-std/src/\",\":openzeppelin-contracts/=dependencies/@openzeppelin-contracts-5.3.0/\"],\"viaIR\":true},\"sources\":{\"dependencies/openzeppelin-contracts/utils/Panic.sol\":{\"keccak256\":\"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a\",\"dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG\"]},\"dependencies/openzeppelin-contracts/utils/math/Math.sol\":{\"keccak256\":\"0x1225214420c83ebcca88f2ae2b50f053aaa7df7bd684c3e878d334627f2edfc6\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6c5fab4970634f9ab9a620983dc1c8a30153981a0b1a521666e269d0a11399d3\",\"dweb:/ipfs/QmVRnBC575MESGkEHndjujtR7qub2FzU9RWy9eKLp4hPZB\"]},\"dependencies/openzeppelin-contracts/utils/math/SafeCast.sol\":{\"keccak256\":\"0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b1d578337048cad08c1c03041cca5978eff5428aa130c781b271ad9e5566e1f8\",\"dweb:/ipfs/QmPFKL2r9CBsMwmUqqdcFPfHZB2qcs9g1HDrPxzWSxomvy\"]},\"src/Cluster.sol\":{\"keccak256\":\"0x8ade3b168437cafe86f09cb2c71514eb497e9e25b9f9b836497e05942427217b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://1a4141701f07e7ccd86e1573762adfd8dd292eb286ce6a113d7baae6bbc9f087\",\"dweb:/ipfs/QmYGCqntKqzcfeCnDx667mgQn9vVYKXFokJvt8Kp2Lycxn\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.28+commit.7893614a"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"struct Settings","name":"initialSettings","type":"tuple","components":[{"internalType":"uint16","name":"maxOperatorDataBytes","type":"uint16"}]},{"internalType":"struct NodeOperator[]","name":"initialOperators","type":"tuple[]","components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}]}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"MaintenanceFinished","anonymous":false},{"inputs":[{"internalType":"address","name":"addr","type":"address","indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"MaintenanceStarted","anonymous":false},{"inputs":[{"internalType":"uint64","name":"id","type":"uint64","indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"MigrationAborted","anonymous":false},{"inputs":[{"internalType":"uint64","name":"id","type":"uint64","indexed":false},{"internalType":"address","name":"operatorAddress","type":"address","indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"MigrationCompleted","anonymous":false},{"inputs":[{"internalType":"uint64","name":"id","type":"uint64","indexed":false},{"internalType":"address","name":"operatorAddress","type":"address","indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"MigrationDataPullCompleted","anonymous":false},{"inputs":[{"internalType":"uint64","name":"id","type":"uint64","indexed":false},{"internalType":"struct Keyspace","name":"newKeyspace","type":"tuple","components":[{"internalType":"uint256","name":"operatorsBitmask","type":"uint256"},{"internalType":"uint8","name":"replicationStrategy","type":"uint8"}],"indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"MigrationStarted","anonymous":false},{"inputs":[{"internalType":"uint8","name":"idx","type":"uint8","indexed":false},{"internalType":"struct NodeOperator","name":"operator","type":"tuple","components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"NodeOperatorAdded","anonymous":false},{"inputs":[{"internalType":"address","name":"operatorAddress","type":"address","indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"NodeOperatorRemoved","anonymous":false},{"inputs":[{"internalType":"struct NodeOperator","name":"operator","type":"tuple","components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"NodeOperatorUpdated","anonymous":false},{"inputs":[{"internalType":"address","name":"newOwner","type":"address","indexed":false},{"internalType":"uint128","name":"cluserVersion","type":"uint128","indexed":false}],"type":"event","name":"OwnershipTransferred","anonymous":false},{"inputs":[{"internalType":"struct Settings","name":"newSettings","type":"tuple","components":[{"internalType":"uint16","name":"maxOperatorDataBytes","type":"uint16"}],"indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"SettingsUpdated","anonymous":false},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"abortMigration"},{"inputs":[{"internalType":"uint8","name":"idx","type":"uint8"},{"internalType":"struct NodeOperator","name":"operator","type":"tuple","components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}]}],"stateMutability":"nonpayable","type":"function","name":"addNodeOperator"},{"inputs":[{"internalType":"uint64","name":"id","type":"uint64"}],"stateMutability":"nonpayable","type":"function","name":"completeMigration"},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"finishMaintenance"},{"inputs":[],"stateMutability":"view","type":"function","name":"getView","outputs":[{"internalType":"struct ClusterView","name":"","type":"tuple","components":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"struct NodeOperator[]","name":"nodeOperatorSlots","type":"tuple[]","components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}]},{"internalType":"struct Keyspace[2]","name":"keyspaces","type":"tuple[2]","components":[{"internalType":"uint256","name":"operatorsBitmask","type":"uint256"},{"internalType":"uint8","name":"replicationStrategy","type":"uint8"}]},{"internalType":"uint64","name":"keyspaceVersion","type":"uint64"},{"internalType":"struct Settings","name":"settings","type":"tuple","components":[{"internalType":"uint16","name":"maxOperatorDataBytes","type":"uint16"}]},{"internalType":"struct Migration","name":"migration","type":"tuple","components":[{"internalType":"uint64","name":"id","type":"uint64"},{"internalType":"uint256","name":"pullingOperatorsBitmask","type":"uint256"}]},{"internalType":"struct Maintenance","name":"maintenance","type":"tuple","components":[{"internalType":"address","name":"slot","type":"address"}]},{"internalType":"uint128","name":"version","type":"uint128"}]}]},{"inputs":[{"internalType":"address","name":"operatorAddress","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"removeNodeOperator"},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"startMaintenance"},{"inputs":[{"internalType":"struct Keyspace","name":"newKeyspace","type":"tuple","components":[{"internalType":"uint256","name":"operatorsBitmask","type":"uint256"},{"internalType":"uint8","name":"replicationStrategy","type":"uint8"}]}],"stateMutability":"nonpayable","type":"function","name":"startMigration"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"transferOwnership"},{"inputs":[{"internalType":"struct NodeOperator","name":"operator","type":"tuple","components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}]}],"stateMutability":"nonpayable","type":"function","name":"updateNodeOperator"},{"inputs":[{"internalType":"struct Settings","name":"newSettings","type":"tuple","components":[{"internalType":"uint16","name":"maxOperatorDataBytes","type":"uint16"}]}],"stateMutability":"nonpayable","type":"function","name":"updateSettings"}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"remappings":["@openzeppelin-contracts-5.3.0/=dependencies/@openzeppelin-contracts-5.3.0/","forge-std-1.9.7/=dependencies/forge-std-1.9.7/src/","forge-std/=dependencies/forge-std/src/","openzeppelin-contracts/=dependencies/@openzeppelin-contracts-5.3.0/"],"optimizer":{"enabled":false,"runs":200},"metadata":{"bytecodeHash":"ipfs"},"compilationTarget":{"src/Cluster.sol":"Cluster"},"evmVersion":"cancun","libraries":{},"viaIR":true},"sources":{"dependencies/openzeppelin-contracts/utils/Panic.sol":{"keccak256":"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a","urls":["bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a","dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG"],"license":"MIT"},"dependencies/openzeppelin-contracts/utils/math/Math.sol":{"keccak256":"0x1225214420c83ebcca88f2ae2b50f053aaa7df7bd684c3e878d334627f2edfc6","urls":["bzz-raw://6c5fab4970634f9ab9a620983dc1c8a30153981a0b1a521666e269d0a11399d3","dweb:/ipfs/QmVRnBC575MESGkEHndjujtR7qub2FzU9RWy9eKLp4hPZB"],"license":"MIT"},"dependencies/openzeppelin-contracts/utils/math/SafeCast.sol":{"keccak256":"0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54","urls":["bzz-raw://b1d578337048cad08c1c03041cca5978eff5428aa130c781b271ad9e5566e1f8","dweb:/ipfs/QmPFKL2r9CBsMwmUqqdcFPfHZB2qcs9g1HDrPxzWSxomvy"],"license":"MIT"},"src/Cluster.sol":{"keccak256":"0x8ade3b168437cafe86f09cb2c71514eb497e9e25b9f9b836497e05942427217b","urls":["bzz-raw://1a4141701f07e7ccd86e1573762adfd8dd292eb286ce6a113d7baae6bbc9f087","dweb:/ipfs/QmYGCqntKqzcfeCnDx667mgQn9vVYKXFokJvt8Kp2Lycxn"],"license":"MIT"}},"version":1},"id":24} \ No newline at end of file diff --git a/contracts/soldeer.lock b/contracts/soldeer.lock index d68d1044..f274bd04 100644 --- a/contracts/soldeer.lock +++ b/contracts/soldeer.lock @@ -1,3 +1,10 @@ +[[dependencies]] +name = "@openzeppelin-contracts" +version = "5.3.0" +url = "https://soldeer-revisions.s3.amazonaws.com/@openzeppelin-contracts/5_3_0_10-04-2025_10:51:50_contracts.zip" +checksum = "fa2bc3db351137c4d5eb32b738a814a541b78e87fbcbfeca825e189c4c787153" +integrity = "d69addf252dfe0688dcd893a7821cbee2421f8ce53d95ca0845a59530043cfd1" + [[dependencies]] name = "forge-std" version = "1.9.7" diff --git a/contracts/src/Cluster.sol b/contracts/src/Cluster.sol index 9cb5046b..27ea715e 100644 --- a/contracts/src/Cluster.sol +++ b/contracts/src/Cluster.sol @@ -1,23 +1,23 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; -import './../dependencies/openzeppelin-contracts/contracts/utils/math/Math.sol'; +import '../dependencies/openzeppelin-contracts/utils/math/Math.sol'; struct Settings { uint16 maxOperatorDataBytes; } -event MigrationStarted(uint64 id, MigrationPlan plan, uint128 clusterVersion); +event MigrationStarted(uint64 id, Keyspace newKeyspace, uint128 clusterVersion); event MigrationDataPullCompleted(uint64 id, address operatorAddress, uint128 clusterVersion); event MigrationCompleted(uint64 id, address operatorAddress, uint128 clusterVersion); event MigrationAborted(uint64 id, uint128 clusterVersion); -event MaintenanceStarted(address operatorAddress, uint128 clusterVersion); -event MaintenanceFinished(address operatorAddress, uint128 clusterVersion); +event MaintenanceStarted(address addr, uint128 clusterVersion); +event MaintenanceFinished(uint128 clusterVersion); -event NodeOperatorCreated(NodeOperator operator, uint128 clusterVersion); +event NodeOperatorAdded(uint8 idx, NodeOperator operator, uint128 clusterVersion); event NodeOperatorUpdated(NodeOperator operator, uint128 clusterVersion); -event NodeOperatorDeleted(address operatorAddress, uint128 clusterVersion); +event NodeOperatorRemoved(address operatorAddress, uint128 clusterVersion); event SettingsUpdated(Settings newSettings, uint128 clusterVersion); @@ -29,8 +29,8 @@ contract Cluster { // TODO: Should we just make all the fields public? address owner; - - mapping(address => bytes) operatorData; + + NodeOperators nodeOperators; Keyspace[2] keyspaces; uint64 keyspaceVersion; @@ -49,14 +49,14 @@ contract Cluster { for (uint256 i = 0; i < initialOperators.length; i++) { validateOperatorDataSize(initialOperators[i].data.length); - require(operatorData[initialOperators[i].addr].length == 0, "duplicate operator"); + require(!nodeOperators.indexes[initialOperators[i].addr].is_some, "duplicate operator"); - keyspaces[0].operators[i] = initialOperators[i].addr; - keyspaces[0].operatorIndexes[initialOperators[i].addr] = OptionU8({ is_some: true, value: uint8(i) }); - operatorData[initialOperators[i].addr] = initialOperators[i].data; + nodeOperators.indexes[initialOperators[i].addr] = OptionU8({ is_some: true, value: uint8(i) }); + nodeOperators.slots[i] = initialOperators[i]; } - keyspaces[0].operatorsBitmask = Bitmask.fill(uint8(initialOperators.length)); + nodeOperators.bitmask = Bitmask.fill(uint8(initialOperators.length)); + keyspaces[0].operatorsBitmask = nodeOperators.bitmask; } modifier onlyOwner() { @@ -84,90 +84,25 @@ contract Cluster { _; } - function startMigration(MigrationPlan calldata plan) external onlyOwner noMigration noMaintenance { - migration.id++; + function startMigration(Keyspace calldata newKeyspace) external onlyOwner noMigration noMaintenance { + require(newKeyspace.operatorsBitmask.isSubsetOf(nodeOperators.bitmask), "invalid bitmask"); - Keyspace storage keyspace = keyspaces[keyspaceVersion % 2]; - keyspaceVersion++; - Keyspace storage newKeyspace = keyspaces[keyspaceVersion % 2]; - - // Make sure that initially the new keyspace is identical to the old one. - cloneKeyspace(keyspace, newKeyspace); + migration.id++; - applyMigrationPlan(newKeyspace, plan); + keyspaceVersion++; + keyspaces[keyspaceVersion % 2] = newKeyspace; migration.pullingOperatorsBitmask = newKeyspace.operatorsBitmask; version++; - emit MigrationStarted(migration.id, plan, version); - } - - function cloneKeyspace(Keyspace storage src, Keyspace storage dst) internal { - // Pick highest out of two to ensure that all non-empty slots are being processed. - uint256 highestSlot = Math.max(src.operatorsBitmask.highest1(), dst.operatorsBitmask.highest1()); - address srcAddr; - address dstAddr; - for (uint256 i = 0; i <= highestSlot; i++) { - srcAddr = src.operators[i]; - dstAddr = dst.operators[i]; - - if (srcAddr == dstAddr) { - continue; - } - - if (dstAddr != address(0)) { - delete(dst.operatorIndexes[dstAddr]); - } - - if (srcAddr != address(0)) { - dst.operatorIndexes[srcAddr] = OptionU8({ is_some: true, value: uint8(i) }); - } - - dst.operators[i] = srcAddr; - } - - dst.replicationStrategy = src.replicationStrategy; - dst.operatorsBitmask = src.operatorsBitmask; - } - - function applyMigrationPlan(Keyspace storage keyspace, MigrationPlan calldata plan) internal { - uint256 operatorsBitmask = keyspace.operatorsBitmask; - - uint8 idx; - address addr; - address newAddr; - for (uint256 i = 0; i < plan.slots.length; i++) { - idx = plan.slots[i].idx; - newAddr = plan.slots[i].operatorAddress; - addr = keyspace.operators[idx]; - - require(addr != newAddr, "unchanged slot"); - - if (addr != address(0)) { - delete(keyspace.operatorIndexes[addr]); - } - - if (newAddr == address(0)) { - operatorsBitmask = operatorsBitmask.set0(idx); - } else { - require(operatorData[newAddr].length != 0, "unknown operator"); - require(!keyspace.operatorIndexes[newAddr].is_some, "operator duplicate"); - operatorsBitmask = operatorsBitmask.set1(idx); - } - - keyspace.operators[idx] = newAddr; - keyspace.operatorIndexes[newAddr] = OptionU8({ is_some: true, value: idx }); - } - - keyspace.operatorsBitmask = operatorsBitmask; - keyspace.replicationStrategy = plan.replicationStrategy; + emit MigrationStarted(migration.id, newKeyspace, version); } function completeMigration(uint64 id) external hasMigration { require(id == migration.id, "wrong migration id"); - OptionU8 memory operatorIdx = keyspaces[keyspaceVersion % 2].operatorIndexes[msg.sender]; - require(operatorIdx.is_some, "unknown operator"); + OptionU8 memory operatorIdx = nodeOperators.indexes[msg.sender]; + require(operatorIdx.is_some, "unknown operator"); require(migration.pullingOperatorsBitmask.is1(operatorIdx.value), "not pulling"); migration.pullingOperatorsBitmask = migration.pullingOperatorsBitmask.set0(operatorIdx.value); @@ -189,7 +124,7 @@ contract Cluster { } function startMaintenance() external noMigration noMaintenance { - require(keyspaces[keyspaceVersion % 2].operatorIndexes[msg.sender].is_some || msg.sender == owner, "unauthorized"); + require(nodeOperators.indexes[msg.sender].is_some || msg.sender == owner, "unauthorized"); maintenance.slot = msg.sender; @@ -198,46 +133,56 @@ contract Cluster { } function finishMaintenance() external hasMaintenance { - require(msg.sender == owner || maintenance.slot == msg.sender, "unauthorized"); + require(maintenance.slot == msg.sender || msg.sender == owner, "unauthorized"); maintenance.slot = address(0); version++; - emit MaintenanceFinished(msg.sender, version); + emit MaintenanceFinished(version); } - function createNodeOperator(NodeOperator calldata operator) external onlyOwner { - require(operatorData[operator.addr].length == 0, "operator already exists"); + function addNodeOperator(uint8 idx, NodeOperator calldata operator) external onlyOwner { validateOperatorDataSize(operator.data.length); + require(!nodeOperators.indexes[operator.addr].is_some, "already exists"); + require(nodeOperators.slots[idx].data.length == 0, "slot occupied"); + + nodeOperators.indexes[operator.addr] = OptionU8({ is_some: true, value: idx }); + nodeOperators.slots[idx] = operator; + nodeOperators.bitmask = nodeOperators.bitmask.set1(idx); - operatorData[operator.addr] = operator.data; version++; - emit NodeOperatorCreated(operator, version); + emit NodeOperatorAdded(idx, operator, version); } function updateNodeOperator(NodeOperator calldata operator) external { - require(msg.sender == owner || msg.sender == operator.addr, "unauthorized"); - require(operatorData[operator.addr].length != 0, "unknown operator"); validateOperatorDataSize(operator.data.length); + require(msg.sender == operator.addr || msg.sender == owner, "unauthorized"); - operatorData[operator.addr] = operator.data; + OptionU8 storage idx = nodeOperators.indexes[operator.addr]; + require(idx.is_some, "unknown operator"); + + nodeOperators.slots[idx.value] = operator; version++; emit NodeOperatorUpdated(operator, version); } - function deleteNodeOperator(address operatorAddress) external onlyOwner { - require(operatorData[operatorAddress].length != 0, "unknown operator"); + function removeNodeOperator(address operatorAddress) external onlyOwner { + OptionU8 storage idx_opt = nodeOperators.indexes[operatorAddress]; + require(idx_opt.is_some, "unknown operator"); + uint8 idx = idx_opt.value; - if (isMigrationInProgress()) { - require(!keyspaces[0].operatorIndexes[operatorAddress].is_some, "in keyspace"); - require(!keyspaces[1].operatorIndexes[operatorAddress].is_some, "in keyspace"); + if (isMigrationInProgress()) { + require(keyspaces[0].operatorsBitmask.is0(idx) && keyspaces[1].operatorsBitmask.is0(idx), "in keyspace"); } else { - require(!keyspaces[keyspaceVersion % 2].operatorIndexes[operatorAddress].is_some, "in keyspace"); + require(keyspaces[keyspaceVersion % 2].operatorsBitmask.is0(idx), "in keyspace"); } + + delete(nodeOperators.indexes[operatorAddress]); + delete(nodeOperators.slots[idx]); + nodeOperators.bitmask = nodeOperators.bitmask.set0(idx); - delete(operatorData[operatorAddress]); version++; - emit NodeOperatorDeleted(operatorAddress, version); + emit NodeOperatorRemoved(operatorAddress, version); } function updateSettings(Settings calldata newSettings) external onlyOwner { @@ -253,58 +198,28 @@ contract Cluster { } function getView() public view returns (ClusterView memory) { - ClusterView memory clusterView; - - uint256 keyspaceIdx; - - address addr; - uint256 highestSlotIdx; - - if (isMigrationInProgress()) { - clusterView.migration.id = migration.id; - clusterView.migration.pullingOperatorsBitmask = migration.pullingOperatorsBitmask; - - keyspaceIdx = (keyspaceVersion - 1) % 2; - uint256 migrationKeyspaceIdx = keyspaceVersion % 2; - - highestSlotIdx = keyspaces[migrationKeyspaceIdx].operatorsBitmask.highest1(); - clusterView.migrationKeyspace.operators = new NodeOperator[](highestSlotIdx + 1); - clusterView.migrationKeyspace.replicationStrategy = keyspaces[migrationKeyspaceIdx].replicationStrategy; - - for (uint256 i = 0; i <= highestSlotIdx; i++) { - if (keyspaces[migrationKeyspaceIdx].operatorsBitmask.is0(uint8(i))) { - continue; - } - - addr = keyspaces[migrationKeyspaceIdx].operators[i]; - clusterView.migrationKeyspace.operators[i].addr = addr; - - // Populate data only if it won't be present in the primary keyspace view, to optimize the cluster view size. - if (keyspaces[keyspaceIdx].operatorsBitmask.is0(uint8(i)) || keyspaces[keyspaceIdx].operators[i] != addr) { - clusterView.migrationKeyspace.operators[i].data = operatorData[addr]; - } - } - } else { - keyspaceIdx = keyspaceVersion % 2; - } - - highestSlotIdx = keyspaces[keyspaceIdx].operatorsBitmask.highest1(); - clusterView.keyspace.operators = new NodeOperator[](highestSlotIdx + 1); - clusterView.keyspace.replicationStrategy = keyspaces[keyspaceIdx].replicationStrategy; + uint256 highestSlotIdx = nodeOperators.bitmask.highest1(); + + ClusterView memory clusterView = ClusterView({ + owner: owner, + nodeOperatorSlots: new NodeOperator[](highestSlotIdx + 1), + keyspaces: keyspaces, + keyspaceVersion: keyspaceVersion, + settings: settings, + migration: migration, + maintenance: maintenance, + version: version + }); + + uint256 nodeOperatorsBitmask = nodeOperators.bitmask; for (uint256 i = 0; i <= highestSlotIdx; i++) { - if (keyspaces[keyspaceIdx].operatorsBitmask.is0(uint8(i))) { + if (nodeOperatorsBitmask.is0(uint8(i))) { continue; } - addr = keyspaces[keyspaceIdx].operators[i]; - clusterView.keyspace.operators[i].addr = addr; - clusterView.keyspace.operators[i].data = operatorData[addr]; + clusterView.nodeOperatorSlots[i] = nodeOperators.slots[i]; } - - clusterView.keyspaceVersion = keyspaceVersion; - clusterView.maintenance.slot = maintenance.slot; - clusterView.version = version; return clusterView; } @@ -323,42 +238,24 @@ contract Cluster { } } -struct NodeOperator { - address addr; - bytes data; -} - -struct Keyspace { - mapping(address => OptionU8) operatorIndexes; - address[256] operators; - uint256 operatorsBitmask; - - uint8 replicationStrategy; -} - struct OptionU8 { bool is_some; uint8 value; } -struct OptionalUInt8 { - bool exists; - uint8 value; +struct NodeOperator { + address addr; + bytes data; } -struct KeyspaceView { - NodeOperator[] operators; - - uint8 replicationStrategy; -} - -struct KeyspaceSlot { - uint8 idx; - address operatorAddress; +struct NodeOperators { + mapping(address => OptionU8) indexes; + NodeOperator[256] slots; + uint256 bitmask; } -struct MigrationPlan { - KeyspaceSlot[] slots; +struct Keyspace { + uint256 operatorsBitmask; uint8 replicationStrategy; } @@ -372,14 +269,17 @@ struct Maintenance { } struct ClusterView { - KeyspaceView keyspace; + address owner; - Migration migration; - KeyspaceView migrationKeyspace; + NodeOperator[] nodeOperatorSlots; + Keyspace[2] keyspaces; + uint64 keyspaceVersion; + + Settings settings; + Migration migration; Maintenance maintenance; - uint64 keyspaceVersion; uint128 version; } @@ -414,4 +314,8 @@ library Bitmask { function highest1(uint256 bitmask) internal pure returns (uint256) { return Math.log2(bitmask); } + + function isSubsetOf(uint256 self, uint256 other) internal pure returns (bool) { + return self & ~other == 0; + } } diff --git a/contracts/test/Suite.sol b/contracts/test/Suite.sol index 1b838e38..acff02e0 100644 --- a/contracts/test/Suite.sol +++ b/contracts/test/Suite.sol @@ -1,12 +1,14 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; -import "../dependencies/forge-std-1.9.7/src/Test.sol"; -import {Vm} from "../dependencies/forge-std-1.9.7/src/Vm.sol"; -import "../dependencies/forge-std-1.9.7/src/console.sol"; +import "../dependencies/forge-std/src/Test.sol"; +import {Vm} from "../dependencies/forge-std/src/Vm.sol"; +import "../dependencies/forge-std/src/console.sol"; import "../src/Cluster.sol"; +import "../dependencies/openzeppelin-contracts/utils/Strings.sol"; + uint256 constant OWNER = 12345; uint256 constant NEW_OWNER = 56789; uint256 constant ANYONE = 9000; @@ -17,12 +19,13 @@ uint16 constant MAX_OPERATOR_DATA_BYTES = 4096; contract ClusterTest is Test { using Bitmask for uint256; + using Strings for uint256; Cluster cluster; ClusterView clusterView; constructor() { - newCluster(vm); + newCluster(); } function test_bitmask() public pure { @@ -57,26 +60,34 @@ contract ClusterTest is Test { assertEq(bitmask, 0xDF); assertEq(bitmask.count1(), 7); assertEq(bitmask.highest1(), 7); + + assertEq(parseBitmask("1010"), 10); + + assert(parseBitmask("1010").isSubsetOf(parseBitmask("1110"))); + assert(!parseBitmask("1010").isSubsetOf(parseBitmask("1101"))); } // contructor function test_canNotCreateClusterWithTooManyOperators() public { vm.expectRevert(); - newCluster(vm, 257); + newCluster(257); } function test_canCreateClusterWithMaxNumberOfOperators() public { - newCluster(vm, 256); + newCluster(256); } - function test_clusterContainsInitialOperatorsInKeyspace() public view { - assertKeyspaceSlotsCount(clusterView.keyspace, 5); - assertKeyspaceSlot(clusterView.keyspace, 0, 1); - assertKeyspaceSlot(clusterView.keyspace, 1, 2); - assertKeyspaceSlot(clusterView.keyspace, 2, 3); - assertKeyspaceSlot(clusterView.keyspace, 3, 4); - assertKeyspaceSlot(clusterView.keyspace, 4, 5); + function test_clusterContainsInitialNodeOperators() public view { + assertNodeOperatorSlotsLength(5); + for (uint256 i = 0; i < 5; i++) { + assertNodeOperatorSlot(i, newNodeOperator(i + 1)); + } + } + + function test_clusterContainsInitialKeyspace() public view { + assertKeyspace(0, newKeyspace("11111")); + assertKeyspace(1, newKeyspace("0")); } function test_clusterInitialVersionIs0() public view { @@ -87,81 +98,206 @@ contract ClusterTest is Test { assertKeyspaceVersion(0); } + // addNodeOperator + + function test_anyoneCanNotAddNodeOperator() public { + expectRevert("not the owner"); + addNodeOperator(ANYONE, 5, newNodeOperator(6)); + } + + function test_operatorCanNotAddAnotherNodeOperator() public { + expectRevert("not the owner"); + addNodeOperator(ANYONE, 5, newNodeOperator(6)); + } + + function test_ownerCanAddNodeOperator() public { + addNodeOperator(OWNER, 5, newNodeOperator(6)); + } + + function test_addNodeOperatorBumpsVersion() public { + addNodeOperator(OWNER, 5, newNodeOperator(6)); + assertVersion(1); + } + + function test_addNodeOperatorDoesNotBumpKeyspaceVersion() public { + addNodeOperator(OWNER, 5, newNodeOperator(6)); + assertKeyspaceVersion(0); + } + + function test_addNodeOperatorEmitsEventNodeOperatorAdded() public { + NodeOperator memory operator = newNodeOperator(6); + vm.expectEmit(); + emit NodeOperatorAdded(5, operator, 1); + addNodeOperator(OWNER, 5, operator); + } + + // updateNodeOperator + + function test_anyoneCanNotUpdateNodeOperator() public { + expectRevert("unauthorized"); + updateNodeOperator(ANYONE, newNodeOperator(1, "new data")); + } + + function test_ownerCanUpdateNodeOperator() public { + updateNodeOperator(OWNER, newNodeOperator(1, "new data")); + } + + function test_operatorCanNotUpdateAnotherNodeOperator() public { + expectRevert("unauthorized"); + updateNodeOperator(1, newNodeOperator(2, "new data")); + } + + function test_operatorCanUpdateItself() public { + updateNodeOperator(1, newNodeOperator(1, "new data")); + } + + function test_updateNodeOperatorDoesUpdateTheData() public { + NodeOperator memory operator = newNodeOperator(1, "new data"); + updateNodeOperator(1, operator); + assertNodeOperatorSlot(0, operator); + } + + function test_updateNodeOperatorBumpsVersion() public { + updateNodeOperator(1, newNodeOperator(1, "new data")); + assertVersion(1); + } + + function test_updateNodeOperatorDoesNotBumpKeyspaceVersion() public { + updateNodeOperator(1, newNodeOperator(1, "new data")); + assertKeyspaceVersion(0); + } + + function test_updateNodeOperatorEmitsEventNodeOperatorUpdated() public { + NodeOperator memory operator = newNodeOperator(1, "new data"); + vm.expectEmit(); + emit NodeOperatorUpdated(operator, 1); + updateNodeOperator(1, operator); + } + + // removeNodeOperator + + function test_anyoneCanNotRemoveNodeOperator() public { + expectRevert("not the owner"); + removeNodeOperator(ANYONE, 1); + } + + function test_operatorCanNotRemoveAnotherNodeOperator() public { + expectRevert("not the owner"); + removeNodeOperator(1, 2); + } + + function test_operatorCanNotRemoveItself() public { + expectRevert("not the owner"); + removeNodeOperator(1, 1); + } + + function test_ownerCanRemoveNodeOperator() public { + addNodeOperator(OWNER, 5, newNodeOperator(6)); + removeNodeOperator(OWNER, 6); + } + + function test_canNotRemoveNodeOperatorInKeyspace() public { + expectRevert("in keyspace"); + removeNodeOperator(OWNER, 1); + } + + function test_removeNodeOperatorClearsTheSlot() public { + addNodeOperator(OWNER, 5, newNodeOperator(6)); + assertNodeOperatorSlotsLength(6); + removeNodeOperator(OWNER, 6); + assertNodeOperatorSlotsLength(5); + } + + function test_removeNodeOperatorBumpsVersion() public { + addNodeOperator(OWNER, 5, newNodeOperator(6)); + assertVersion(1); + removeNodeOperator(OWNER, 6); + assertVersion(2); + } + + function test_removeNodeOperatorDoesNotBumpKeyspaceVersion() public { + addNodeOperator(OWNER, 5, newNodeOperator(6)); + removeNodeOperator(OWNER, 6); + assertKeyspaceVersion(0); + } + + function test_removeNodeOperatorEmitsEventNodeOperatorRemoved() public { + addNodeOperator(OWNER, 5, newNodeOperator(6)); + vm.expectEmit(); + emit NodeOperatorRemoved(vm.addr(6), 2); + removeNodeOperator(OWNER, 6); + } + // startMigration function test_anyoneCanNotStartMigration() public { expectRevert("not the owner"); - startMigration(ANYONE, newMigration().clear(0)); + startMigration(ANYONE, newKeyspace("01111")); } function test_operatorCanNotStartMigration() public { expectRevert("not the owner"); - startMigration(OPERATOR, newMigration().clear(0)); - } + startMigration(OPERATOR, newKeyspace("01111")); + } function test_ownerCanStartMigration() public { - startMigration(OWNER, newMigration().clear(0)); + startMigration(OWNER, newKeyspace("01111")); } function test_canNotStartMigrationWhenMaintenanceInProgress() public { startMaintenance(1); expectRevert("maintenance in progress"); - startMigration(OWNER, newMigration().clear(0)); + startMigration(OWNER, newKeyspace("01111")); + } + + function test_canNotStartMigrationWhenMigrationInProgress() public { + startMigration(OWNER, newKeyspace("01111")); + expectRevert("migration in progress"); + startMigration(OWNER, newKeyspace("11111")); } function test_startMigrationBumpsVersion() public { - startMigration(OWNER, newMigration().clear(0)); + startMigration(OWNER, newKeyspace("01111")); assertVersion(1); } function test_startMigrationBumpsKeyspaceVersion() public { - startMigration(OWNER, newMigration().clear(0)); + startMigration(OWNER, newKeyspace("01111")); assertKeyspaceVersion(1); } function test_startMigrationEmitsMigrationStartedEvent() public { - TestMigration memory migration = newMigration().clear(0); + Keyspace memory keyspace = newKeyspace("01111"); vm.expectEmit(); - emit MigrationStarted(1, migration.plan, 1); - startMigration(OWNER, migration); + emit MigrationStarted(1, keyspace, 1); + startMigration(OWNER, keyspace); } function test_startMigrationInitializesMigration() public { - createNodeOperator(OWNER, 6); - createNodeOperator(OWNER, 7); - startMigration(OWNER, newMigration().set(4, 6).set(5, 7).clear(2)); - assertMigration(1, 5); - assertMigrationPullingOperator(0); - assertMigrationPullingOperator(1); - assertMigrationPullingOperator(3); - assertMigrationPullingOperator(4); - assertMigrationPullingOperator(5); + addNodeOperator(OWNER, 5, newNodeOperator(6)); + addNodeOperator(OWNER, 6, newNodeOperator(7)); + startMigration(OWNER, newKeyspace("1111101")); + assertMigration(1, "1111101"); } function test_startMigrationPopulatesMigrationKeyspace() public { - createNodeOperator(OWNER, 6, "operator6"); - createNodeOperator(OWNER, 7, "operator7"); - - startMigration(OWNER, newMigration().set(4, 6).set(5, 7).clear(2)); - assertKeyspaceSlotsCount(clusterView.migrationKeyspace, 6); - assertKeyspaceSlot(clusterView.migrationKeyspace, 0, 1, ""); - assertKeyspaceSlot(clusterView.migrationKeyspace, 1, 2, ""); - assertKeyspaceSlotEmpty(clusterView.migrationKeyspace, 2); - assertKeyspaceSlot(clusterView.migrationKeyspace, 3, 4, ""); - assertKeyspaceSlot(clusterView.migrationKeyspace, 4, 6, "operator6"); - assertKeyspaceSlot(clusterView.migrationKeyspace, 5, 7, "operator7"); + addNodeOperator(OWNER, 5, newNodeOperator(6)); + addNodeOperator(OWNER, 6, newNodeOperator(7)); + Keyspace memory keyspace = newKeyspace("1111101"); + startMigration(OWNER, keyspace); + assertKeyspace(1, keyspace); } // completeMigration function test_anyoneCanNotCompleteMigration() public { - startMigration(OWNER, newMigration().clear(0)); + startMigration(OWNER, newKeyspace("01111")); expectRevert("unknown operator"); completeMigration(ANYONE, 1); } function test_ownerCanNotCompleteMigration() public { - startMigration(OWNER, newMigration().clear(0)); + startMigration(OWNER, newKeyspace("01111")); expectRevert("unknown operator"); completeMigration(OWNER, 1); } @@ -172,114 +308,88 @@ contract ClusterTest is Test { } function test_operatorCanCompleteMigration() public { - startMigration(OWNER, newMigration().clear(1)); + startMigration(OWNER, newKeyspace("01111")); completeMigration(OPERATOR, 1); } function test_canNotCompleteMigrationTwice() public { - startMigration(OWNER, newMigration().clear(1)); + startMigration(OWNER, newKeyspace("01111")); completeMigration(OPERATOR, 1); expectRevert("not pulling"); completeMigration(OPERATOR, 1); } function test_completeMigrationBumpsVersion() public { - startMigration(OWNER, newMigration().clear(1)); + startMigration(OWNER, newKeyspace("01111")); completeMigration(OPERATOR, 1); assertVersion(2); } - function test_completeMigrationDoesNotUpdateKeyspaceIfNotCompleted() public { - createNodeOperator(OWNER, 6); - startMigration(OWNER, newMigration().set(5, 6)); - completeMigration(OPERATOR, 1); - assertKeyspaceSlotsCount(clusterView.keyspace, 5); - assertKeyspaceSlot(clusterView.keyspace, 0, 1); - assertKeyspaceSlot(clusterView.keyspace, 1, 2); - assertKeyspaceSlot(clusterView.keyspace, 2, 3); - assertKeyspaceSlot(clusterView.keyspace, 3, 4); - assertKeyspaceSlot(clusterView.keyspace, 4, 5); - } - - function test_completeMigrationUpdatesOperatorsIfCompleted() public { - createNodeOperator(OWNER, 6, "operator6"); - startMigration(OWNER, newMigration().set(4, 6)); - completeMigration(1, 1); - completeMigration(2, 1); + function test_completeMigrationRemovesOperatorFromPullingOperators() public { + startMigration(OWNER, newKeyspace("11110")); + assertMigration(1, "11110"); + completeMigration(5, 1); + assertMigration(1, "01110"); completeMigration(3, 1); - completeMigration(4, 1); - completeMigration(6, 1); - assertKeyspaceSlotsCount(clusterView.keyspace, 5); - assertKeyspaceSlot(clusterView.keyspace, 0, 1); - assertKeyspaceSlot(clusterView.keyspace, 1, 2); - assertKeyspaceSlot(clusterView.keyspace, 2, 3); - assertKeyspaceSlot(clusterView.keyspace, 3, 4); - assertKeyspaceSlot(clusterView.keyspace, 4, 6, "operator6"); - } - - function test_completeMigrationDeletesMigrationIfCompleted() public { - startMigration(OWNER, newMigration().clear(3).clear(4)); - completeMigration(1, 1); + assertMigration(1, "01010"); completeMigration(2, 1); - completeMigration(3, 1); - assertNoMigration(); - } - - function test_completeMigrationRemovesPullingOperatorBitIfNotCompleted() public { - createNodeOperator(OWNER, 10); - startMigration(OWNER, newMigration().set(2, 10)); - completeMigration(1, 1); - assert(clusterView.migration.pullingOperatorsBitmask.is0(0)); + assertMigration(1, "01000"); + completeMigration(4, 1); + assertMigration(1, "00000"); } function test_completeMigrationDoesNotBumpKeyspaceVersionIfNotCompleted() public { - createNodeOperator(OWNER, 10); - startMigration(OWNER, newMigration().set(2, 10)); + assertKeyspaceVersion(0); + startMigration(OWNER, newKeyspace("01111")); + assertKeyspaceVersion(1); completeMigration(1, 1); assertKeyspaceVersion(1); } function test_completeMigrationDoesNotBumpKeyspaceVersionIfCompleted() public { - startMigration(OWNER, newMigration().clear(3).clear(4)); - completeMigration(1, 1); - completeMigration(2, 1); - completeMigration(3, 1); + assertKeyspaceVersion(0); + startMigration(OWNER, newKeyspace("01111")); + assertKeyspaceVersion(1); + for (uint256 i = 0; i < 4; i++) { + completeMigration(i + 1, 1); + } assertKeyspaceVersion(1); } function test_completeMigrationEmitsMigrationDataPullCompletedEventIfNotCompleted() public { - createNodeOperator(OWNER, 10); - startMigration(OWNER, newMigration().set(2, 10)); + startMigration(OWNER, newKeyspace("01111")); vm.expectEmit(); - emit MigrationDataPullCompleted(1, vm.addr(1), 3); + emit MigrationDataPullCompleted(1, vm.addr(1), 2); completeMigration(1, 1); } function test_completeMigrationEmitsMigrationCompletedEventIfCompleted() public { - startMigration(OWNER, newMigration().clear(3).clear(4)); + startMigration(OWNER, newKeyspace("01111")); completeMigration(1, 1); completeMigration(2, 1); - vm.expectEmit(); - emit MigrationCompleted(1, vm.addr(3), 4); completeMigration(3, 1); + + vm.expectEmit(); + emit MigrationCompleted(1, vm.addr(4), 5); + completeMigration(4, 1); } // abortMigration function test_anyoneCanNotAbortMigration() public { - startMigration(OWNER, newMigration().clear(0)); + startMigration(OWNER, newKeyspace("01111")); expectRevert("not the owner"); abortMigration(ANYONE); } function test_operatorCanNotAbortMigration() public { - startMigration(OWNER, newMigration().clear(0)); + startMigration(OWNER, newKeyspace("01111")); expectRevert("not the owner"); abortMigration(OPERATOR); } function test_ownerCanAbortMigration() public { - startMigration(OWNER, newMigration().clear(0)); + startMigration(OWNER, newKeyspace("01111")); abortMigration(OWNER); } @@ -289,36 +399,27 @@ contract ClusterTest is Test { } function test_abortMigrationBumpsVersion() public { - startMigration(OWNER, newMigration().clear(0)); + startMigration(OWNER, newKeyspace("01111")); abortMigration(OWNER); assertVersion(2); } function test_abortMigrationRevertsKeyspaceVersion() public { - startMigration(OWNER, newMigration().clear(0)); - abortMigration(OWNER); assertKeyspaceVersion(0); - } - - function test_abortMigrationDoesNotUpdateKeyspace() public { - startMigration(OWNER, newMigration().clear(0)); + startMigration(OWNER, newKeyspace("01111")); + assertKeyspaceVersion(1); abortMigration(OWNER); - assertKeyspaceSlotsCount(clusterView.keyspace, 5); - assertKeyspaceSlot(clusterView.keyspace, 0, 1); - assertKeyspaceSlot(clusterView.keyspace, 1, 2); - assertKeyspaceSlot(clusterView.keyspace, 2, 3); - assertKeyspaceSlot(clusterView.keyspace, 3, 4); - assertKeyspaceSlot(clusterView.keyspace, 4, 5); + assertKeyspaceVersion(0); } - function test_abortMigrationDeletesMigration() public { - startMigration(OWNER, newMigration().clear(0)); + function test_abortMigrationClearsPullingOperators() public { + startMigration(OWNER, newKeyspace("01111")); abortMigration(OWNER); - assertNoMigration(); + assertMigration(1, "00000"); } function test_abortMigrationEmitsMigrationAbortedEvent() public { - startMigration(OWNER, newMigration().clear(0)); + startMigration(OWNER, newKeyspace("01111")); vm.expectEmit(); emit MigrationAborted(1, 2); abortMigration(OWNER); @@ -339,14 +440,14 @@ contract ClusterTest is Test { startMaintenance(OPERATOR); } - function test_canNotStartMoreThanOneMaintenance() public { + function test_canNotStartMaintenanceWhenMaintenanceInProgress() public { startMaintenance(1); expectRevert("maintenance in progress"); startMaintenance(2); } - function test_operatorCanNotStartMaintenanceWhenMigrationInProgress() public { - startMigration(OWNER, newMigration().clear(1)); + function test_canNotStartMaintenanceWhenMigrationInProgress() public { + startMigration(OWNER, newKeyspace("01111")); expectRevert("migration in progress"); startMaintenance(1); } @@ -374,31 +475,31 @@ contract ClusterTest is Test { // finishMaintenance - function test_anyoneCanNotCompleteMaintenance() public { + function test_anyoneCanNotFinishMaintenance() public { startMaintenance(1); expectRevert("unauthorized"); finishMaintenance(ANYONE); } - function test_anotherOperatorCanNotCompleteMaintenance() public { + function test_anotherOperatorCanNotFinishMaintenance() public { startMaintenance(2); expectRevert("unauthorized"); - finishMaintenance(OPERATOR); + finishMaintenance(1); } - function test_ownerCanCompleteMaintenance() public { + function test_ownerCanFinishMaintenance() public { startMaintenance(1); finishMaintenance(OWNER); } - function test_sameOperatorCanCompleteMaintenance() public { - startMaintenance(1); + function test_operatorCanFinishMaintenance() public { + startMaintenance(OPERATOR); finishMaintenance(OPERATOR); } - function test_canNotCompleteNonExistentMaintenance() public { + function test_canNotFinishNonExistentMaintenance() public { expectRevert("no maintenance"); - finishMaintenance(OPERATOR); + finishMaintenance(1); } function test_finishMaintenanceBumpsVersion() public { @@ -413,7 +514,7 @@ contract ClusterTest is Test { assertKeyspaceVersion(0); } - function test_finishMaintenanceDeletesMaintenance() public { + function test_finishMaintenanceFreesMaintenanceSlot() public { startMaintenance(1); finishMaintenance(1); assertNoMaintenance(); @@ -422,78 +523,9 @@ contract ClusterTest is Test { function test_finishMaintenanceEmitsMaintenanceFinishedEvent() public { startMaintenance(1); vm.expectEmit(); - emit MaintenanceFinished(vm.addr(1), 2); + emit MaintenanceFinished(2); finishMaintenance(1); } - - // createNodeOperator - - function test_anyoneCanNotCreateNodeOperator() public { - expectRevert("not the owner"); - createNodeOperator(ANYONE, 42, "data"); - } - - function test_operatorCanNotCreateAnotherNodeOperator() public { - expectRevert("not the owner"); - createNodeOperator(OPERATOR, 42, "data"); - } - - function test_ownerCanCreateNodeOperator() public { - createNodeOperator(OWNER, 42, "data"); - } - - function test_createNodeOperatorBumpsVersion() public { - createNodeOperator(OWNER, 42, "data"); - assertVersion(1); - } - - function test_createNodeOperatorDoesNotBumpKeyspaceVersion() public { - createNodeOperator(OWNER, 42, "data"); - assertKeyspaceVersion(0); - } - - function test_createNodeOperatorEmitsEventNodeOperatorCreated() public { - vm.expectEmit(); - emit NodeOperatorCreated(NodeOperator({ addr: vm.addr(42), data: "data" }), 1); - createNodeOperator(OWNER, 42, "data"); - } - - // updateNodeOperator - - function test_anyoneCanNotUpdateNodeOperator() public { - expectRevert("unauthorized"); - updateNodeOperator(ANYONE, 1, "new data"); - } - - function test_ownerCanNotUpdateNodeOperator() public { - // expectRevert("wrong operator"); - updateNodeOperator(OWNER, 1, "new data"); - } - - function test_operatorCanUpdateNodeOperator() public { - updateNodeOperator(OPERATOR, 1, "new data"); - } - - function test_updateNodeOperatorDoesUpdateTheData() public { - updateNodeOperator(OPERATOR, 1, "new data"); - assertKeyspaceSlot(clusterView.keyspace, 0, OPERATOR, "new data"); - } - - function test_updateNodeOperatorBumpsVersion() public { - updateNodeOperator(OPERATOR, 1, "new data"); - assertVersion(1); - } - - function test_updateNodeOperatorDoesNotBumpKeyspaceVersion() public { - updateNodeOperator(OPERATOR, 1, "new data"); - assertKeyspaceVersion(0); - } - - function test_updateNodeOperatorEmitsEventNodeOperatorUpdated() public { - vm.expectEmit(); - emit NodeOperatorUpdated(NodeOperator({ addr: vm.addr(OPERATOR), data: "new data" }), 1); - updateNodeOperator(OPERATOR, 1, "new data"); - } // updateSettings @@ -514,7 +546,17 @@ contract ClusterTest is Test { function test_updateSettingsUpdatesMaxOperatorDataBytes() public { updateSettings(OWNER, Settings({ maxOperatorDataBytes: 5 })); expectRevert("operator data too large"); - createNodeOperator(OWNER, 10, "123456"); + addNodeOperator(OWNER, 5, newNodeOperator(10, "123456")); + } + + function test_updateSettingsBumpsVersion() public { + updateSettings(OWNER, Settings({ maxOperatorDataBytes: 100 })); + assertVersion(1); + } + + function test_updateSettingsDoesNotBumpKeyspaceVersion() public { + updateSettings(OWNER, Settings({ maxOperatorDataBytes: 100 })); + assertKeyspaceVersion(0); } // transferOwnership @@ -535,39 +577,39 @@ contract ClusterTest is Test { function test_transferOwnershipChangesOwner() public { transferOwnership(OWNER, NEW_OWNER); - startMigration(NEW_OWNER, newMigration().clear(0)); + startMigration(NEW_OWNER, newKeyspace("01111")); } // full lifecycle function test_fullClusterLifecycle() public { - updateNodeOperator(1, 1, "operator1"); + updateNodeOperator(1, newNodeOperator(1, "operator1")); startMaintenance(2); - updateNodeOperator(3, 3, "operator3"); + updateNodeOperator(3, newNodeOperator(3, "operator3")); finishMaintenance(2); - createNodeOperator(OWNER, 6, "operator6"); - createNodeOperator(OWNER, 7, "operator7"); - createNodeOperator(OWNER, 8, "operator8"); - startMigration(OWNER, newMigration().set(5, 6).set(6, 7).set(7, 8)); - updateNodeOperator(1, 1, "operator1'"); + addNodeOperator(OWNER, 5, newNodeOperator(6, "operator6")); + addNodeOperator(OWNER, 6, newNodeOperator(7, "operator7")); + addNodeOperator(OWNER, 7, newNodeOperator(8, "operator8")); + startMigration(OWNER, newKeyspace("11111111")); + updateNodeOperator(1, newNodeOperator(1, "operator1")); for (uint256 i = 0; i < 8; i++) { completeMigration(i + 1, 1); } - updateNodeOperator(3, 3, "operator3'"); + updateNodeOperator(3, newNodeOperator(3, "operator1")); startMaintenance(7); - updateNodeOperator(7, 7, "operator8"); + updateNodeOperator(7, newNodeOperator(7, "operator1")); finishMaintenance(OWNER); - startMigration(OWNER, newMigration().clear(6)); + startMigration(OWNER, newKeyspace("10111111")); for (uint256 i = 0; i < 8; i++) { if (i != 6) { completeMigration(i + 1, 2); } } - createNodeOperator(OWNER, 9, "operator9"); - startMigration(OWNER, newMigration().set(6, 9)); + addNodeOperator(OWNER, 8, newNodeOperator(9, "operator9")); + startMigration(OWNER, newKeyspace("110111111")); for (uint256 i = 0; i < 8; i++) { if (i != 6) { completeMigration(i + 1, 3); @@ -583,21 +625,20 @@ contract ClusterTest is Test { // internal - function newCluster(Vm vm) internal { - newCluster(vm, 5); + function newCluster() internal { + newCluster(5); } - function newCluster(Vm vm, uint256 operatorsCount) internal { - newCluster(vm, Settings({ maxOperatorDataBytes: MAX_OPERATOR_DATA_BYTES }), operatorsCount); + function newCluster(uint256 operatorsCount) internal { + newCluster(Settings({ maxOperatorDataBytes: MAX_OPERATOR_DATA_BYTES }), operatorsCount); } - function newCluster(Vm vm, Settings memory settings, uint256 operatorsCount) internal { + function newCluster(Settings memory settings, uint256 operatorsCount) internal { setCaller(OWNER); NodeOperator[] memory operators = new NodeOperator[](operatorsCount); for (uint256 i = 0; i < operatorsCount; i++) { - operators[i].addr = vm.addr(i + 1); - operators[i].data = DEFAULT_OPERATOR_DATA; + operators[i] = newNodeOperator(i + 1); } cluster = new Cluster(settings, operators); @@ -621,44 +662,33 @@ contract ClusterTest is Test { vm.expectRevert(revertBytes); } - function assertVersion(uint128 expectedVersion) internal view { - assertEq(clusterView.version, expectedVersion); + function assertNodeOperatorSlotsLength(uint256 expected) internal view { + assertEq(clusterView.nodeOperatorSlots.length, expected); } - function assertKeyspaceVersion(uint64 expectedVersion) internal view { - assertEq(clusterView.keyspaceVersion, expectedVersion); + function assertNodeOperatorSlot(uint256 idx, NodeOperator memory slot) internal view { + assertEq(clusterView.nodeOperatorSlots[idx].addr, slot.addr); + assertEq(clusterView.nodeOperatorSlots[idx].data, slot.data); } - function assertKeyspaceSlotsCount(KeyspaceView storage keyspace, uint256 count) internal view { - assertEq(keyspace.operators.length, count); + function assertVersion(uint128 expectedVersion) internal view { + assertEq(clusterView.version, expectedVersion); } - function assertKeyspaceSlot(KeyspaceView storage keyspace, uint256 index, uint256 privateKey) internal view { - assertKeyspaceSlot(keyspace, index, privateKey, DEFAULT_OPERATOR_DATA); + function assertKeyspaceVersion(uint64 expectedVersion) internal view { + assertEq(clusterView.keyspaceVersion, expectedVersion); } - function assertKeyspaceSlot(KeyspaceView storage keyspace, uint256 index, uint256 privateKey, bytes memory data) internal view { - assertEq(keyspace.operators[index].addr, vm.addr(privateKey)); - assertEq(keyspace.operators[index].data, data); + function assertKeyspace(uint256 idx, Keyspace memory expected) internal view { + assertEq(clusterView.keyspaces[idx].operatorsBitmask, expected.operatorsBitmask); + assertEq(clusterView.keyspaces[idx].replicationStrategy, expected.replicationStrategy); } - function assertKeyspaceSlotEmpty(KeyspaceView storage keyspace, uint256 index) internal view { - assertEq(keyspace.operators[index].addr, address(0)); - assertEq(keyspace.operators[index].data, new bytes(0)); - } + function assertMigration(uint64 id, string memory pullingOperatorsBitmaskStr) internal view { + uint256 pullingOperatorsBitmask = parseBitmask(pullingOperatorsBitmaskStr); - function assertMigration(uint64 id, uint256 pullingOperatorsCount) internal view { assertEq(clusterView.migration.id, id); - assertEq(clusterView.migration.pullingOperatorsBitmask.count1(), pullingOperatorsCount); - } - - function assertNoMigration() internal view { - assertEq(clusterView.migration.id, 0); - assertEq(clusterView.migration.pullingOperatorsBitmask, 0); - } - - function assertMigrationPullingOperator(uint8 idx) internal view { - assert(clusterView.migration.pullingOperatorsBitmask.is1(idx)); + assertEq(clusterView.migration.pullingOperatorsBitmask, pullingOperatorsBitmask); } function assertMaintenance(uint256 operator) internal view { @@ -669,19 +699,9 @@ contract ClusterTest is Test { assertEq(clusterView.maintenance.slot, address(0)); } - function newMigration() internal pure returns (TestMigration memory) { - return TestMigration({ - vm: vm, - plan: MigrationPlan({ - slots: new KeyspaceSlot[](0), - replicationStrategy: 0 - }) - }); - } - - function startMigration(uint256 caller, TestMigration memory migration) internal { + function startMigration(uint256 caller, Keyspace memory keyspace) internal { setCaller(caller); - cluster.startMigration(migration.plan); + cluster.startMigration(keyspace); updateClusterView(); } @@ -709,68 +729,69 @@ contract ClusterTest is Test { updateClusterView(); } - function createNodeOperator(uint256 caller, uint256 privKey) internal { - createNodeOperator(caller, privKey, DEFAULT_OPERATOR_DATA); + function addNodeOperator(uint256 caller, uint8 idx, NodeOperator memory operator) internal { + setCaller(caller); + cluster.addNodeOperator(idx, operator); + updateClusterView(); } - function createNodeOperator(uint256 caller, uint256 privKey, bytes memory data) internal { + function updateNodeOperator(uint256 caller, NodeOperator memory operator) internal { setCaller(caller); - cluster.createNodeOperator(NodeOperator({ addr: vm.addr(privKey), data: data })); + cluster.updateNodeOperator(operator); updateClusterView(); } - function updateNodeOperator(uint256 caller, uint256 privKey, bytes memory data) internal { + function removeNodeOperator(uint256 caller, uint256 privateKey) internal { setCaller(caller); - cluster.updateNodeOperator(NodeOperator({ addr: vm.addr(privKey), data: data })); + cluster.removeNodeOperator(vm.addr(privateKey)); updateClusterView(); } function updateSettings(uint256 caller, Settings memory settings) internal { setCaller(caller); cluster.updateSettings(settings); + updateClusterView(); } function transferOwnership(uint256 caller, uint256 newOwner) internal { setCaller(caller); cluster.transferOwnership(vm.addr(newOwner)); + updateClusterView(); } -} -struct TestMigration { - Vm vm; + // function emptyNodeOperatorSlot() internal pure returns (NodeOperator memory) { + // NodeOperator memory operator; + // return operator; + // } - MigrationPlan plan; -} - -library TestMigrationLib { - function set(TestMigration memory self, uint8 idx, uint256 privateKey) internal pure returns (TestMigration memory) { - TestMigrationLib.setSlot(self, idx, KeyspaceSlot({ idx: idx, operatorAddress: self.vm.addr(privateKey) })); - return self; - } - - function clear(TestMigration memory self, uint8 idx) internal pure returns (TestMigration memory) { - TestMigrationLib.setSlot(self, idx, KeyspaceSlot({ idx: idx, operatorAddress: address(0) })); - return self; + function newNodeOperator(uint256 privateKey) internal pure returns (NodeOperator memory) { + return newNodeOperator(privateKey, abi.encodePacked("operator ", privateKey.toString())); } - function setSlot(TestMigration memory self, uint8 idx, KeyspaceSlot memory slot) internal pure returns (TestMigration memory) { - KeyspaceSlot[] memory slots = new KeyspaceSlot[](self.plan.slots.length + 1); - for (uint256 i = 0; i < self.plan.slots.length; i++) { - slots[i] = self.plan.slots[i]; - } - - slots[self.plan.slots.length] = slot; - self.plan.slots = slots; - - return self; + function newNodeOperator(uint256 privateKey, bytes memory data) internal pure returns (NodeOperator memory) { + return NodeOperator({ addr: vm.addr(privateKey), data: data }); } } -using TestMigrationLib for TestMigration; +function newKeyspace(string memory operatorsBitmaskStr) pure returns (Keyspace memory) { + return newKeyspace(operatorsBitmaskStr, 0); +} -function newNodeOperator(address addr, bytes memory operatorData) pure returns (NodeOperator memory) { - return NodeOperator({ - addr: addr, - data: operatorData +function newKeyspace(string memory operatorsBitmaskStr, uint8 replicationStrategy) pure returns (Keyspace memory) { + return Keyspace({ + operatorsBitmask: parseBitmask(operatorsBitmaskStr), + replicationStrategy: replicationStrategy }); } + +function parseBitmask(string memory binary) pure returns (uint256 result) { + bytes memory b = bytes(binary); + for (uint256 i = 0; i < b.length; i++) { + result <<= 1; + bytes1 c = b[i]; + require(c == "0" || c == "1", "Invalid binary char"); + if (c == "1") { + result |= 1; + } + } +} diff --git a/crates/cluster/src/keyspace.rs b/crates/cluster/src/keyspace.rs index 413c6528..507ff0a8 100644 --- a/crates/cluster/src/keyspace.rs +++ b/crates/cluster/src/keyspace.rs @@ -1,10 +1,12 @@ use { crate::{ node_operator::{self, NodeOperators}, - NodeOperator, + VersionedNodeOperator, }, + arc_swap::ArcSwap, derive_more::TryFrom, sharding::ShardId, + std::sync::Arc, tap::TapOptional, }; @@ -46,7 +48,7 @@ pub struct Keyspace { impl Keyspace { /// Creates a new [`Keyspace`]. /// - /// It's highly CPU intensive to contruct a new [`Keyspace`] (order of + /// It's highly CPU intensive to construct a new [`Keyspace`] (order of /// seconds), so the task is being [spawned](tokio::task::spawn_blocking) /// to the [`tokio`] threadpool. /// @@ -66,7 +68,7 @@ impl Keyspace { /// Returns the set of [`NodeOperator`]s the data under the specified key /// should be replicated to. - pub fn replicas(&self, key: u64) -> impl Iterator + '_ { + pub fn replicas(&self, key: u64) -> impl Iterator + '_ { self.sharding .shard_replicas(ShardId::from_key(key)) .iter() @@ -97,3 +99,8 @@ impl Keyspace { } struct Snapshot {} + +pub struct Replica { + idx: node_operator::Idx, + node_operator: Arc, +} diff --git a/crates/cluster/src/lib.rs b/crates/cluster/src/lib.rs index 760aafeb..db642509 100644 --- a/crates/cluster/src/lib.rs +++ b/crates/cluster/src/lib.rs @@ -2,7 +2,11 @@ use { arc_swap::ArcSwap, itertools::Itertools, smart_contract::evm, - std::{collections::HashSet, future::Future, sync::Arc}, + std::{ + collections::{HashMap, HashSet}, + future::Future, + sync::Arc, + }, }; pub mod smart_contract; @@ -21,7 +25,7 @@ pub mod node; pub use node::{Node, NodeRef}; pub mod node_operator; -pub use node_operator::{NewNodeOperator, NodeOperator, SerializedNodeOperator}; +pub use node_operator::{NodeOperator, SerializedNodeOperator, VersionedNodeOperator}; pub mod keyspace; pub use keyspace::Keyspace; @@ -96,11 +100,11 @@ impl Cluster { signer: smart_contract::Signer, rpc_url: smart_contract::RpcUrl, initial_settings: Settings, - initial_operators: Vec, + initial_operators: Vec, ) -> Result { if initial_operators .iter() - .map(NodeOperator::id) + .map(VersionedNodeOperator::id) .dedup() .count() != initial_operators.len() @@ -127,7 +131,7 @@ impl Cluster { pub async fn start_migration( &self, remove: Vec, - add: Vec, + add: Vec, ) -> Result<(), StartMigrationError> { let plan = self.using_view(move |view| { view.ownership.validate_signer(&self.smart_contract)?; @@ -238,8 +242,8 @@ impl Cluster { Ok(()) } - /// Calls [`SmartContract::complete_maintenance`]. - pub async fn complete_maintenance(&self) -> Result<(), CompleteMaintenanceError> { + /// Calls [`SmartContract::finish_maintenance`]. + pub async fn finish_maintenance(&self) -> Result<(), CompleteMaintenanceError> { self.using_view(|view| { let maintenance = view .maintenance() @@ -252,39 +256,19 @@ impl Cluster { Ok(()) })?; - self.smart_contract.complete_maintenance().await?; + self.smart_contract.finish_maintenance().await?; Ok(()) } - /// Calls [`SmartContract::abort_maintenance`]. - pub async fn abort_maintenance(&self) -> Result<(), AbortMaintenanceError> { - self.using_view(|view| { - view.ownership.validate_signer(&self.smart_contract)?; - - view.maintenance() - .ok_or(AbortMaintenanceError::NoMaintenance)?; - - Ok::<_, AbortMaintenanceError>(()) - })?; - - self.smart_contract - .abort_maintenance() - .await - .map_err(Into::into) - } - - /// Updates on-chain data of a [`NodeOperator`]. - /// - /// Emits [`node_operator::Updated`] event on success. + /// Calls [`SmartContract::update_node_operator`]. pub async fn update_node_operator( &self, - id: node_operator::Id, - data: node_operator::Data, + operator: NodeOperator, ) -> Result<(), UpdateNodeOperatorError> { let (idx, data) = self.using_view(|view| { let idx = view - .operator_idx(&id) + .operator_idx(operator.id()) .ok_or(UpdateNodeOperatorError::UnknownOperator)?; let data = data.serialize()?; @@ -455,6 +439,8 @@ impl Event { /// Read-only view of a WCN cluster. pub struct View { + node_operators: HashMap>, + ownership: Ownership, settings: Settings, diff --git a/crates/cluster/src/migration.rs b/crates/cluster/src/migration.rs index dfcf900e..6ff02c0a 100644 --- a/crates/cluster/src/migration.rs +++ b/crates/cluster/src/migration.rs @@ -4,9 +4,9 @@ use { node_operator, Keyspace, LogicalError, - NodeOperator, SerializedNodeOperator, Version as ClusterVersion, + VersionedNodeOperator, View as ClusterView, }, itertools::Itertools, @@ -78,7 +78,7 @@ impl Migration { pub type NewPlan = Plan; /// [`Migration`] plan. -pub struct Plan { +pub struct Plan { slots: Vec<(node_operator::Idx, Option)>, replication_strategy: ReplicationStrategy, } @@ -92,7 +92,7 @@ impl Plan { ) -> Result { let slot_count = remove .iter() - .chain(add.iter().map(NodeOperator::id)) + .chain(add.iter().map(VersionedNodeOperator::id)) .dedup() .count(); diff --git a/crates/cluster/src/node_operator.rs b/crates/cluster/src/node_operator.rs index f529e11c..a27d6c70 100644 --- a/crates/cluster/src/node_operator.rs +++ b/crates/cluster/src/node_operator.rs @@ -10,9 +10,10 @@ use { Version as ClusterVersion, View as ClusterView, }, + arc_swap::ArcSwap, derive_more::From, serde::{Deserialize, Serialize}, - std::{collections::HashMap, ops::Sub}, + std::{collections::HashMap, ops::Sub, sync::Arc}, }; /// Globally unique identifier of a [`NodeOperator`]; @@ -49,7 +50,7 @@ impl Name { } /// On-chain data of a [`NodeOperator`]. -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct Data { /// Name of the [`NodeOperator`]. pub name: Name, @@ -66,23 +67,29 @@ pub struct Data { #[derive(Debug)] pub struct SerializedData(Vec); -/// New [`NodeOperator`] that is not a member of WCN cluster yet. -pub type NewNodeOperator = NodeOperator; - -/// [`NodeOperator`] with [`SerializedData`]. -pub type SerializedNodeOperator = NodeOperator; +/// [`NodeOperator`] [`Data`] that can be shared and modified across threads. +pub struct SharedData(Arc>); /// Entity operating a set of [`Node`]s within a WCN cluster. #[derive(Clone, Debug)] -pub struct NodeOperator { +pub struct NodeOperator { id: Id, data: D, } +/// [`NodeOperator`] with [`SerializedData`]. +pub type SerializedNodeOperator = NodeOperator; + +/// [`NodeOperator`] with [`VersionedData`]. +pub type VersionedNodeOperator = NodeOperator; + +/// [`NodeOperator`] with [`SharedData`]. +pub type SharedNodeOperator = NodeOperator; + impl NodeOperator { /// Creates a [`NewNodeOperator`]. - pub fn new(id: Id, data: Data) -> NewNodeOperator { - NewNodeOperator { id, data } + pub fn new(id: Id, data: Data) -> NodeOperator { + NodeOperator { id, data } } /// Returns [`Id`] of this [`NodeOperator`]. @@ -99,7 +106,7 @@ impl NodeOperator { /// Event of a new [`NodeOperator`] being added to a WCN cluster. pub struct Added { /// [`NodeOperator`] being added. - pub operator: NodeOperator, + pub operator: VersionedNodeOperator, /// Updated [`ClusterVersion`]. pub cluster_version: ClusterVersion, @@ -111,10 +118,10 @@ impl Added { } } -/// Event of a [`NodeOperator`] [`Data`] being updated. +/// Event of a [`NodeOperator`] being updated. pub struct Updated { /// Updated [`NodeOperator`]. - pub operator: NodeOperator, + pub operator: VersionedNodeOperator, /// Updated [`ClusterVersion`]. pub cluster_version: ClusterVersion, @@ -162,9 +169,9 @@ impl Removed { } } -impl NewNodeOperator { +impl NodeOperator { pub(super) fn serialize(self) -> Result { - Ok(NodeOperator { + Ok(VersionedNodeOperator { id: self.id, data: self.data.serialize()?, }) @@ -208,7 +215,7 @@ enum VersionedDataInner { V0(DataV0), } -impl NodeOperator { +impl VersionedNodeOperator { fn deserialize(id: Id, data_bytes: &[u8]) -> Result { use DataDeserializationError as Error; @@ -297,11 +304,11 @@ pub(super) struct NodeOperators { id_to_idx: HashMap, // TODO: assert length - slots: Vec>, + slots: Vec>, } impl NodeOperators { - pub(super) fn set(&mut self, idx: Idx, slot: Option) { + pub(super) fn set(&mut self, idx: Idx, slot: Option) { if let Some(id) = self.get_by_idx(idx).map(|op| op.id) { self.id_to_idx.remove(&id); } @@ -333,7 +340,7 @@ impl NodeOperators { } /// Gets an [`NodeOperator`] by [`Id`]. - pub(super) fn get(&self, id: &Id) -> Option<&NodeOperator> { + pub(super) fn get(&self, id: &Id) -> Option<&VersionedNodeOperator> { self.get_by_idx(self.get_idx(id)?) } @@ -344,12 +351,12 @@ impl NodeOperators { } /// Gets an [`NodeOperator`] by [`Idx`]. - pub(super) fn get_by_idx(&self, idx: Idx) -> Option<&NodeOperator> { + pub(super) fn get_by_idx(&self, idx: Idx) -> Option<&VersionedNodeOperator> { self.slots.get(idx as usize)?.as_ref() } /// Mutable version of [`NodeOperators::get_by_idx`]. - fn get_by_idx_mut(&mut self, idx: Idx) -> Option<&mut NodeOperator> { + fn get_by_idx_mut(&mut self, idx: Idx) -> Option<&mut VersionedNodeOperator> { self.slots.get_mut(idx as usize)?.as_mut() } @@ -359,7 +366,7 @@ impl NodeOperators { } /// Returns the list of [`NodeOperator`] slots. - pub(super) fn slots(&self) -> &[Option] { + pub(super) fn slots(&self) -> &[Option] { &self.slots } diff --git a/crates/cluster/src/smart_contract/evm.rs b/crates/cluster/src/smart_contract/evm.rs index a35e46a7..0ef5e371 100644 --- a/crates/cluster/src/smart_contract/evm.rs +++ b/crates/cluster/src/smart_contract/evm.rs @@ -1,6 +1,6 @@ use { super::{PublicKey, Result, RpcUrl, Signer}, - crate::{node, node_operator, NewNodeOperator, Settings}, + crate::{node, node_operator, NodeOperator, Settings}, alloy::{providers::DynProvider, sol, sol_types::SolConstructor}, }; @@ -24,7 +24,7 @@ impl super::SmartContract for SmartContract { signer: Signer, rpc_url: RpcUrl, initial_settings: Settings, - initial_operators: Vec, + initial_operators: Vec, ) -> Result { todo!() @@ -91,11 +91,7 @@ impl super::SmartContract for SmartContract { todo!() } - async fn complete_maintenance(&self) -> Result<()> { - todo!() - } - - async fn abort_maintenance(&self) -> Result<()> { + async fn finish_maintenance(&self) -> Result<()> { todo!() } diff --git a/crates/cluster/src/smart_contract/mod.rs b/crates/cluster/src/smart_contract/mod.rs index 4ddad3c1..df72b925 100644 --- a/crates/cluster/src/smart_contract/mod.rs +++ b/crates/cluster/src/smart_contract/mod.rs @@ -1,7 +1,14 @@ pub mod evm; use { - crate::{migration, node_operator, NewNodeOperator, Settings, View as ClusterView}, + crate::{ + migration, + node_operator, + NodeOperator, + SerializedNodeOperator, + Settings, + View as ClusterView, + }, alloy::{signers::local::PrivateKeySigner, transports::http::reqwest}, derive_more::derive::Display, serde::{Deserialize, Serialize}, @@ -20,7 +27,7 @@ pub trait SmartContract: ReadOnlySmartContract { signer: Signer, rpc_url: RpcUrl, initial_settings: Settings, - initial_operators: Vec, + initial_operators: Vec, ) -> Result; /// Connects to an existing smart-contract. @@ -100,17 +107,9 @@ pub trait SmartContract: ReadOnlySmartContract { /// /// The implementation MUST emit [`maintenance::Completed`] event on /// success. - async fn complete_maintenance(&self) -> Result<()>; + async fn finish_maintenance(&self) -> Result<()>; - /// Aborts the ongoing [`maintenance`] process. - /// - /// The implementation MUST validate the following invariants: - /// - there's an ongoing maintenance - /// - [`signer`](SmartContract::signer) is the owner of the - /// [`SmartContract`] - /// - /// The implementation MUST emit [`maintenance::Aborted`] event on success. - async fn abort_maintenance(&self) -> Result<()>; + async fn add_node_operator(&self, operator: SerializedNodeOperator) -> Result<()>; /// Updates on-chain data of a [`node::Operator`]. /// @@ -121,10 +120,13 @@ pub trait SmartContract: ReadOnlySmartContract { /// The implementation MUST emit [`node::OperatorUpdated`] event on success. async fn update_node_operator( &self, + operator: SerializedNodeOperator, id: node_operator::Id, idx: node_operator::Idx, data: node_operator::SerializedData, ) -> Result<()>; + + async fn remove_node_operator(&self, operator_id: node_operator::Id) -> Result<()>; } /// Read-only handle to a smart-contract managing the state of a WCN cluster. From ace793e4437cfc47b642d39beaba0391404d1ff2 Mon Sep 17 00:00:00 2001 From: Github Bot Date: Mon, 2 Jun 2025 15:35:54 +0000 Subject: [PATCH 29/79] Bump VERSION to 250602.0 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 019c40eb..acfd827a 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -250529.0 +250602.0 From c6939cd5904640ba89e824fd3ae4fe95de7e9bbc Mon Sep 17 00:00:00 2001 From: Darksome Date: Wed, 4 Jun 2025 21:29:08 +0000 Subject: [PATCH 30/79] WIP --- Cargo.lock | 2 + Cargo.toml | 1 + contracts/out/Cluster.sol/Bitmask.json | 2 +- contracts/out/Cluster.sol/Cluster.json | 2 +- contracts/src/Cluster.sol | 11 +- contracts/test/Suite.sol | 22 +- crates/cluster/Cargo.toml | 4 +- crates/cluster/src/client.rs | 2 +- crates/cluster/src/keyspace.rs | 220 ++++++--- crates/cluster/src/lib.rs | 545 ++++++++++------------- crates/cluster/src/maintenance.rs | 41 +- crates/cluster/src/migration.rs | 250 ++++------- crates/cluster/src/node.rs | 2 +- crates/cluster/src/node_operator.rs | 217 +++++---- crates/cluster/src/ownership.rs | 40 +- crates/cluster/src/settings.rs | 14 +- crates/cluster/src/smart_contract/evm.rs | 382 +++++++++++++--- crates/cluster/src/smart_contract/mod.rs | 191 ++++---- crates/cluster/src/view.rs | 325 ++++++++++++++ 19 files changed, 1421 insertions(+), 852 deletions(-) create mode 100644 crates/cluster/src/view.rs diff --git a/Cargo.lock b/Cargo.lock index 9577016a..8997b81e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1680,6 +1680,7 @@ dependencies = [ "arc-swap", "derive_more 1.0.0", "fpe", + "futures", "itertools 0.12.1", "libp2p", "postcard", @@ -1689,6 +1690,7 @@ dependencies = [ "thiserror 1.0.64", "tokio", "tracing", + "xxhash-rust", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index ae4fcb6e..1b757253 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -50,6 +50,7 @@ libp2p = { version = "0.54", default-features = false, features = ["serde"] } tokio-serde = { git = "https://github.com/xDarksome/tokio-serde.git", rev = "6df9ff9" } tokio-serde-postcard = { git = "https://github.com/xDarksome/tokio-serde-postcard.git", rev = "5e1b77a" } itertools = "0.12" +futures = "0.3" [workspace.lints.clippy] all = { level = "deny", priority = -1 } diff --git a/contracts/out/Cluster.sol/Bitmask.json b/contracts/out/Cluster.sol/Bitmask.json index 52be07a0..05c72c42 100644 --- a/contracts/out/Cluster.sol/Bitmask.json +++ b/contracts/out/Cluster.sol/Bitmask.json @@ -1 +1 @@ -{"abi":[],"bytecode":{"object":"0x608060405234601d57600e6021565b603e602c823930815050603e90f35b6027565b60405190565b5f80fdfe60806040525f80fdfea26469706673582212209214e53cf637b9ecf7ac29bc4f2b6d20a74434c2aa0e3cb577b8e0dcd1b9e88564736f6c634300081c0033","sourceMap":"8863:1079:24:-:0;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;","linkReferences":{}},"deployedBytecode":{"object":"0x60806040525f80fdfea26469706673582212209214e53cf637b9ecf7ac29bc4f2b6d20a74434c2aa0e3cb577b8e0dcd1b9e88564736f6c634300081c0033","sourceMap":"8863:1079:24:-:0;;;;;","linkReferences":{}},"methodIdentifiers":{},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.28+commit.7893614a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/Cluster.sol\":\"Bitmask\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[\":@openzeppelin-contracts-5.3.0/=dependencies/@openzeppelin-contracts-5.3.0/\",\":forge-std-1.9.7/=dependencies/forge-std-1.9.7/src/\",\":forge-std/=dependencies/forge-std/src/\",\":openzeppelin-contracts/=dependencies/@openzeppelin-contracts-5.3.0/\"],\"viaIR\":true},\"sources\":{\"dependencies/openzeppelin-contracts/utils/Panic.sol\":{\"keccak256\":\"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a\",\"dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG\"]},\"dependencies/openzeppelin-contracts/utils/math/Math.sol\":{\"keccak256\":\"0x1225214420c83ebcca88f2ae2b50f053aaa7df7bd684c3e878d334627f2edfc6\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6c5fab4970634f9ab9a620983dc1c8a30153981a0b1a521666e269d0a11399d3\",\"dweb:/ipfs/QmVRnBC575MESGkEHndjujtR7qub2FzU9RWy9eKLp4hPZB\"]},\"dependencies/openzeppelin-contracts/utils/math/SafeCast.sol\":{\"keccak256\":\"0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b1d578337048cad08c1c03041cca5978eff5428aa130c781b271ad9e5566e1f8\",\"dweb:/ipfs/QmPFKL2r9CBsMwmUqqdcFPfHZB2qcs9g1HDrPxzWSxomvy\"]},\"src/Cluster.sol\":{\"keccak256\":\"0x8ade3b168437cafe86f09cb2c71514eb497e9e25b9f9b836497e05942427217b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://1a4141701f07e7ccd86e1573762adfd8dd292eb286ce6a113d7baae6bbc9f087\",\"dweb:/ipfs/QmYGCqntKqzcfeCnDx667mgQn9vVYKXFokJvt8Kp2Lycxn\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.28+commit.7893614a"},"language":"Solidity","output":{"abi":[],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"remappings":["@openzeppelin-contracts-5.3.0/=dependencies/@openzeppelin-contracts-5.3.0/","forge-std-1.9.7/=dependencies/forge-std-1.9.7/src/","forge-std/=dependencies/forge-std/src/","openzeppelin-contracts/=dependencies/@openzeppelin-contracts-5.3.0/"],"optimizer":{"enabled":false,"runs":200},"metadata":{"bytecodeHash":"ipfs"},"compilationTarget":{"src/Cluster.sol":"Bitmask"},"evmVersion":"cancun","libraries":{},"viaIR":true},"sources":{"dependencies/openzeppelin-contracts/utils/Panic.sol":{"keccak256":"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a","urls":["bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a","dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG"],"license":"MIT"},"dependencies/openzeppelin-contracts/utils/math/Math.sol":{"keccak256":"0x1225214420c83ebcca88f2ae2b50f053aaa7df7bd684c3e878d334627f2edfc6","urls":["bzz-raw://6c5fab4970634f9ab9a620983dc1c8a30153981a0b1a521666e269d0a11399d3","dweb:/ipfs/QmVRnBC575MESGkEHndjujtR7qub2FzU9RWy9eKLp4hPZB"],"license":"MIT"},"dependencies/openzeppelin-contracts/utils/math/SafeCast.sol":{"keccak256":"0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54","urls":["bzz-raw://b1d578337048cad08c1c03041cca5978eff5428aa130c781b271ad9e5566e1f8","dweb:/ipfs/QmPFKL2r9CBsMwmUqqdcFPfHZB2qcs9g1HDrPxzWSxomvy"],"license":"MIT"},"src/Cluster.sol":{"keccak256":"0x8ade3b168437cafe86f09cb2c71514eb497e9e25b9f9b836497e05942427217b","urls":["bzz-raw://1a4141701f07e7ccd86e1573762adfd8dd292eb286ce6a113d7baae6bbc9f087","dweb:/ipfs/QmYGCqntKqzcfeCnDx667mgQn9vVYKXFokJvt8Kp2Lycxn"],"license":"MIT"}},"version":1},"id":24} \ No newline at end of file +{"abi":[],"bytecode":{"object":"0x608060405234601d57600e6021565b603e602c823930815050603e90f35b6027565b60405190565b5f80fdfe60806040525f80fdfea26469706673582212202e5c85f91ed6f87a0d6666b0c5006389206e839cbaa1af000488b75c0e4c9fca64736f6c634300081c0033","sourceMap":"9215:1079:24:-:0;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;","linkReferences":{}},"deployedBytecode":{"object":"0x60806040525f80fdfea26469706673582212202e5c85f91ed6f87a0d6666b0c5006389206e839cbaa1af000488b75c0e4c9fca64736f6c634300081c0033","sourceMap":"9215:1079:24:-:0;;;;;","linkReferences":{}},"methodIdentifiers":{},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.28+commit.7893614a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/Cluster.sol\":\"Bitmask\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[\":@openzeppelin-contracts-5.3.0/=dependencies/@openzeppelin-contracts-5.3.0/\",\":forge-std-1.9.7/=dependencies/forge-std-1.9.7/src/\",\":forge-std/=dependencies/forge-std/src/\",\":openzeppelin-contracts/=dependencies/@openzeppelin-contracts-5.3.0/\"],\"viaIR\":true},\"sources\":{\"dependencies/openzeppelin-contracts/utils/Panic.sol\":{\"keccak256\":\"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a\",\"dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG\"]},\"dependencies/openzeppelin-contracts/utils/math/Math.sol\":{\"keccak256\":\"0x1225214420c83ebcca88f2ae2b50f053aaa7df7bd684c3e878d334627f2edfc6\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6c5fab4970634f9ab9a620983dc1c8a30153981a0b1a521666e269d0a11399d3\",\"dweb:/ipfs/QmVRnBC575MESGkEHndjujtR7qub2FzU9RWy9eKLp4hPZB\"]},\"dependencies/openzeppelin-contracts/utils/math/SafeCast.sol\":{\"keccak256\":\"0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b1d578337048cad08c1c03041cca5978eff5428aa130c781b271ad9e5566e1f8\",\"dweb:/ipfs/QmPFKL2r9CBsMwmUqqdcFPfHZB2qcs9g1HDrPxzWSxomvy\"]},\"src/Cluster.sol\":{\"keccak256\":\"0xc78e6f85b957de947ea15d06612efc306c2cd979f8f08d37e4484a65880ffb48\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c14a8b6856276888d44ba5368193e7b0ca9cd898d3cdc90d272edc32aef830be\",\"dweb:/ipfs/QmQkuwMCYXcuv1g68FsC7ZrpAdCKQS7KmHQZwRUftXKJVa\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.28+commit.7893614a"},"language":"Solidity","output":{"abi":[],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"remappings":["@openzeppelin-contracts-5.3.0/=dependencies/@openzeppelin-contracts-5.3.0/","forge-std-1.9.7/=dependencies/forge-std-1.9.7/src/","forge-std/=dependencies/forge-std/src/","openzeppelin-contracts/=dependencies/@openzeppelin-contracts-5.3.0/"],"optimizer":{"enabled":false,"runs":200},"metadata":{"bytecodeHash":"ipfs"},"compilationTarget":{"src/Cluster.sol":"Bitmask"},"evmVersion":"cancun","libraries":{},"viaIR":true},"sources":{"dependencies/openzeppelin-contracts/utils/Panic.sol":{"keccak256":"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a","urls":["bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a","dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG"],"license":"MIT"},"dependencies/openzeppelin-contracts/utils/math/Math.sol":{"keccak256":"0x1225214420c83ebcca88f2ae2b50f053aaa7df7bd684c3e878d334627f2edfc6","urls":["bzz-raw://6c5fab4970634f9ab9a620983dc1c8a30153981a0b1a521666e269d0a11399d3","dweb:/ipfs/QmVRnBC575MESGkEHndjujtR7qub2FzU9RWy9eKLp4hPZB"],"license":"MIT"},"dependencies/openzeppelin-contracts/utils/math/SafeCast.sol":{"keccak256":"0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54","urls":["bzz-raw://b1d578337048cad08c1c03041cca5978eff5428aa130c781b271ad9e5566e1f8","dweb:/ipfs/QmPFKL2r9CBsMwmUqqdcFPfHZB2qcs9g1HDrPxzWSxomvy"],"license":"MIT"},"src/Cluster.sol":{"keccak256":"0xc78e6f85b957de947ea15d06612efc306c2cd979f8f08d37e4484a65880ffb48","urls":["bzz-raw://c14a8b6856276888d44ba5368193e7b0ca9cd898d3cdc90d272edc32aef830be","dweb:/ipfs/QmQkuwMCYXcuv1g68FsC7ZrpAdCKQS7KmHQZwRUftXKJVa"],"license":"MIT"}},"version":1},"id":24} \ No newline at end of file diff --git a/contracts/out/Cluster.sol/Cluster.json b/contracts/out/Cluster.sol/Cluster.json index 24436f05..f63c6618 100644 --- a/contracts/out/Cluster.sol/Cluster.json +++ b/contracts/out/Cluster.sol/Cluster.json @@ -1 +1 @@ -{"abi":[{"type":"constructor","inputs":[{"name":"initialSettings","type":"tuple","internalType":"struct Settings","components":[{"name":"maxOperatorDataBytes","type":"uint16","internalType":"uint16"}]},{"name":"initialOperators","type":"tuple[]","internalType":"struct NodeOperator[]","components":[{"name":"addr","type":"address","internalType":"address"},{"name":"data","type":"bytes","internalType":"bytes"}]}],"stateMutability":"nonpayable"},{"type":"function","name":"abortMigration","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"addNodeOperator","inputs":[{"name":"idx","type":"uint8","internalType":"uint8"},{"name":"operator","type":"tuple","internalType":"struct NodeOperator","components":[{"name":"addr","type":"address","internalType":"address"},{"name":"data","type":"bytes","internalType":"bytes"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"completeMigration","inputs":[{"name":"id","type":"uint64","internalType":"uint64"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"finishMaintenance","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"getView","inputs":[],"outputs":[{"name":"","type":"tuple","internalType":"struct ClusterView","components":[{"name":"owner","type":"address","internalType":"address"},{"name":"nodeOperatorSlots","type":"tuple[]","internalType":"struct NodeOperator[]","components":[{"name":"addr","type":"address","internalType":"address"},{"name":"data","type":"bytes","internalType":"bytes"}]},{"name":"keyspaces","type":"tuple[2]","internalType":"struct Keyspace[2]","components":[{"name":"operatorsBitmask","type":"uint256","internalType":"uint256"},{"name":"replicationStrategy","type":"uint8","internalType":"uint8"}]},{"name":"keyspaceVersion","type":"uint64","internalType":"uint64"},{"name":"settings","type":"tuple","internalType":"struct Settings","components":[{"name":"maxOperatorDataBytes","type":"uint16","internalType":"uint16"}]},{"name":"migration","type":"tuple","internalType":"struct Migration","components":[{"name":"id","type":"uint64","internalType":"uint64"},{"name":"pullingOperatorsBitmask","type":"uint256","internalType":"uint256"}]},{"name":"maintenance","type":"tuple","internalType":"struct Maintenance","components":[{"name":"slot","type":"address","internalType":"address"}]},{"name":"version","type":"uint128","internalType":"uint128"}]}],"stateMutability":"view"},{"type":"function","name":"removeNodeOperator","inputs":[{"name":"operatorAddress","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"startMaintenance","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"startMigration","inputs":[{"name":"newKeyspace","type":"tuple","internalType":"struct Keyspace","components":[{"name":"operatorsBitmask","type":"uint256","internalType":"uint256"},{"name":"replicationStrategy","type":"uint8","internalType":"uint8"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"transferOwnership","inputs":[{"name":"newOwner","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateNodeOperator","inputs":[{"name":"operator","type":"tuple","internalType":"struct NodeOperator","components":[{"name":"addr","type":"address","internalType":"address"},{"name":"data","type":"bytes","internalType":"bytes"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateSettings","inputs":[{"name":"newSettings","type":"tuple","internalType":"struct Settings","components":[{"name":"maxOperatorDataBytes","type":"uint16","internalType":"uint16"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"event","name":"MaintenanceFinished","inputs":[{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"MaintenanceStarted","inputs":[{"name":"addr","type":"address","indexed":false,"internalType":"address"},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"MigrationAborted","inputs":[{"name":"id","type":"uint64","indexed":false,"internalType":"uint64"},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"MigrationCompleted","inputs":[{"name":"id","type":"uint64","indexed":false,"internalType":"uint64"},{"name":"operatorAddress","type":"address","indexed":false,"internalType":"address"},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"MigrationDataPullCompleted","inputs":[{"name":"id","type":"uint64","indexed":false,"internalType":"uint64"},{"name":"operatorAddress","type":"address","indexed":false,"internalType":"address"},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"MigrationStarted","inputs":[{"name":"id","type":"uint64","indexed":false,"internalType":"uint64"},{"name":"newKeyspace","type":"tuple","indexed":false,"internalType":"struct Keyspace","components":[{"name":"operatorsBitmask","type":"uint256","internalType":"uint256"},{"name":"replicationStrategy","type":"uint8","internalType":"uint8"}]},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"NodeOperatorAdded","inputs":[{"name":"idx","type":"uint8","indexed":false,"internalType":"uint8"},{"name":"operator","type":"tuple","indexed":false,"internalType":"struct NodeOperator","components":[{"name":"addr","type":"address","internalType":"address"},{"name":"data","type":"bytes","internalType":"bytes"}]},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"NodeOperatorRemoved","inputs":[{"name":"operatorAddress","type":"address","indexed":false,"internalType":"address"},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"NodeOperatorUpdated","inputs":[{"name":"operator","type":"tuple","indexed":false,"internalType":"struct NodeOperator","components":[{"name":"addr","type":"address","internalType":"address"},{"name":"data","type":"bytes","internalType":"bytes"}]},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"name":"newOwner","type":"address","indexed":false,"internalType":"address"},{"name":"cluserVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"SettingsUpdated","inputs":[{"name":"newSettings","type":"tuple","indexed":false,"internalType":"struct Settings","components":[{"name":"maxOperatorDataBytes","type":"uint16","internalType":"uint16"}]},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false}],"bytecode":{"object":"0x6080604052346100305761001a61001461030f565b90610acf565b610022610035565b6138ed610ed382396138ed90f35b61003b565b60405190565b5f80fd5b601f801991011690565b634e487b7160e01b5f52604160045260245ffd5b906100679061003f565b810190811060018060401b0382111761007f57604052565b610049565b90610097610090610035565b928361005d565b565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b61ffff1690565b6100b9816100a9565b036100c057565b5f80fd5b905051906100d1826100b0565b565b91906020838203126100fb576100f5906100ed6020610084565b935f016100c4565b5f830152565b6100a1565b5f80fd5b60018060401b03811161011a5760208091020190565b610049565b5f80fd5b60018060a01b031690565b61013790610123565b90565b6101438161012e565b0361014a57565b5f80fd5b9050519061015b8261013a565b565b5f80fd5b60018060401b03811161017d5761017960209161003f565b0190565b610049565b90825f9392825e0152565b909291926101a261019d82610161565b610084565b938185526020850190828401116101be576101bc92610182565b565b61015d565b9080601f830112156101e1578160206101de9351910161018d565b90565b610100565b919091604081840312610236576101fd6040610084565b9261020a815f840161014e565b5f850152602082015160018060401b0381116102315761022a92016101c3565b6020830152565b6100a5565b6100a1565b92919061024f61024a82610104565b610084565b93818552602080860192028101918383116102a45781905b838210610275575050505050565b815160018060401b03811161029f5760209161029487849387016101e6565b815201910190610267565b610100565b61011f565b9080601f830112156102c7578160206102c49351910161023b565b90565b610100565b91909160408184031261030a576102e5835f83016100d3565b92602082015160018060401b0381116103055761030292016102a9565b90565b61009d565b610099565b61032d6147c08038038061032281610084565b9283398101906102cc565b9091565b5190565b90565b90565b90565b61035261034d61035792610338565b61033b565b610335565b90565b60209181520190565b5f7f746f6f206d616e79206f70657261746f72730000000000000000000000000000910152565b610397601260209261035a565b6103a081610363565b0190565b6103b99060208101905f81830391015261038a565b90565b156103c357565b6103cb610035565b62461bcd60e51b8152806103e1600482016103a4565b0390fd5b5f1b90565b906103fb60018060a01b03916103e5565b9181191691161790565b61041961041461041e92610123565b61033b565b610123565b90565b61042a90610405565b90565b61043690610421565b90565b90565b9061045161044c6104589261042d565b610439565b82546103ea565b9055565b634e487b7160e01b5f525f60045260245ffd5b61047990516100a9565b90565b9061048961ffff916103e5565b9181191691161790565b6104a76104a26104ac926100a9565b61033b565b6100a9565b90565b90565b906104c76104c26104ce92610493565b6104af565b825461047c565b9055565b906104e45f806104ea9401920161046f565b906104b2565b565b906104f6916104d2565b565b90565b61050f61050a610514926104f8565b61033b565b610335565b90565b60016105239101610335565b90565b634e487b7160e01b5f52603260045260245ffd5b9061054482610331565b811015610555576020809102010190565b610526565b5190565b610568905161012e565b90565b906105759061042d565b5f5260205260405f2090565b5f1c90565b60ff1690565b61059861059d91610581565b610586565b90565b6105aa905461058c565b90565b151590565b5f7f6475706c6963617465206f70657261746f720000000000000000000000000000910152565b6105e6601260209261035a565b6105ef816105b2565b0190565b6106089060208101905f8183039101526105d9565b90565b1561061257565b61061a610035565b62461bcd60e51b815280610630600482016105f3565b0390fd5b60ff1690565b61064e61064961065392610335565b61033b565b610634565b90565b6106606040610084565b90565b9061066d906105ad565b9052565b9061067b90610634565b9052565b61068990516105ad565b90565b9061069860ff916103e5565b9181191691161790565b6106ab906105ad565b90565b90565b906106c66106c16106cd926106a2565b6106ae565b825461068c565b9055565b6106db9051610634565b90565b60081b90565b906106f161ff00916106de565b9181191691161790565b61070f61070a61071492610634565b61033b565b610634565b90565b90565b9061072f61072a610736926106fb565b610717565b82546106e4565b9055565b9061076460205f61076a9461075c82820161075684880161067f565b906106b1565b0192016106d1565b9061071a565b565b906107769161073a565b565b5061010090565b90565b61078b81610778565b8210156107a55761079d60029161077f565b910201905f90565b610526565b5190565b634e487b7160e01b5f52602260045260245ffd5b90600160028304921680156107e2575b60208310146107dd57565b6107ae565b91607f16916107d2565b5f5260205f2090565b601f602091010490565b1b90565b9190600861081e9102916108185f19846107ff565b926107ff565b9181191691161790565b61083c61083761084192610335565b61033b565b610335565b90565b90565b919061085d61085861086593610828565b610844565b908354610803565b9055565b5f90565b61087f91610879610869565b91610847565b565b5b81811061088d575050565b8061089a5f60019361086d565b01610882565b9190601f81116108b0575b505050565b6108bc6108e1936107ec565b9060206108c8846107f5565b830193106108e9575b6108da906107f5565b0190610881565b5f80806108ab565b91506108da819290506108d1565b1c90565b9061090b905f19906008026108f7565b191690565b8161091a916108fb565b906002021790565b9061092c8161055a565b9060018060401b0382116109ea5761094e8261094885546107c2565b856108a0565b602090601f831160011461098257918091610971935f92610976575b5050610910565b90555b565b90915001515f8061096a565b601f19831691610991856107ec565b925f5b8181106109d2575091600293918560019694106109b8575b50505002019055610974565b6109c8910151601f8416906108fb565b90555f80806109ac565b91936020600181928787015181550195019201610994565b610049565b906109f991610922565b565b90610a2660206001610a2c94610a1e5f8201610a185f880161055e565b9061043c565b0192016107aa565b906109ef565b565b9190610a3f57610a3d916109fb565b565b61045c565b90610a505f19916103e5565b9181191691161790565b90610a6f610a6a610a7692610828565b610844565b8254610a44565b9055565b90565b610a89610a8e91610581565b610a7a565b90565b610a9b9054610a7d565b90565b50600290565b90565b610ab081610a9e565b821015610aca57610ac2600291610aa4565b910201905f90565b610526565b610b0c90610afa610adf84610331565b610af3610aed61010061033e565b91610335565b11156103bc565b610b04335f61043c565b6102086104ec565b610b155f6104fb565b5b80610b31610b2b610b2685610331565b610335565b91610335565b1015610c1c57610c1790610b5b610b566020610b4e86859061053a565b51015161055a565b610db4565b610b99610b94610b8e5f610b8881600101610b8283610b7b8b8a9061053a565b510161055e565b9061056b565b016105a0565b156105ad565b61060b565b610bef6001610bc7610baa8461063a565b610bbe610bb5610656565b935f8501610663565b60208301610671565b610bea5f600101610be45f610bdd89889061053a565b510161055e565b9061056b565b61076c565b610c12610bfd84839061053a565b51610c0c600180018490610782565b90610a2e565b610517565b610b16565b50610c39610c34610c2f610c4493610331565b61063a565b610e96565b610201600101610a5a565b610c6a610c55610201600101610a91565b5f610c636102038290610aa7565b5001610a5a565b565b5f7f656d707479206f70657261746f72206461746100000000000000000000000000910152565b610ca0601360209261035a565b610ca981610c6c565b0190565b610cc29060208101905f818303910152610c93565b90565b15610ccc57565b610cd4610035565b62461bcd60e51b815280610cea60048201610cad565b0390fd5b61ffff1690565b610d01610d0691610581565b610cee565b90565b610d139054610cf5565b90565b610d2a610d25610d2f926100a9565b61033b565b610335565b90565b5f7f6f70657261746f72206461746120746f6f206c61726765000000000000000000910152565b610d66601760209261035a565b610d6f81610d32565b0190565b610d889060208101905f818303910152610d59565b90565b15610d9257565b610d9a610035565b62461bcd60e51b815280610db060048201610d73565b0390fd5b610df990610dd481610dce610dc85f6104fb565b91610335565b11610cc5565b610df2610dec610de75f61020801610d09565b610d16565b91610335565b1115610d8b565b565b610e0f610e0a610e1492610634565b61033b565b610335565b90565b90565b610e2e610e29610e3392610e17565b61033b565b610335565b90565b610e5590610e4f610e49610e5a94610335565b91610335565b906107ff565b610335565b90565b634e487b7160e01b5f52601160045260245ffd5b610e80610e8691939293610335565b92610335565b8203918211610e9157565b610e5d565b610ebf610ecf91610ea5610869565b50610eba610eb4600192610dfb565b91610e1a565b610e36565b610ec96001610e1a565b90610e71565b9056fe60806040526004361015610013575b6107fc565b61001d5f356100cc565b806326322217146100c75780632b726062146100c257806347011c5c146100bd57806353bfb584146100b857806365706f9c146100b357806375418b9d146100ae5780639d44e717146100a9578063c05665dd146100a4578063c130809a1461009f578063f2fde38b1461009a5763f5f2d9f10361000e576107c9565b610796565b610763565b610730565b6106bc565b610646565b6102e1565b61027d565b61023b565b6101d6565b610135565b60e01c90565b60405190565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b908160409103126100f65790565b6100e4565b9060208282031261012b575f82013567ffffffffffffffff81116101265761012392016100e8565b90565b6100e0565b6100dc565b5f0190565b346101635761014d6101483660046100fb565b610f6e565b6101556100d2565b8061015f81610130565b0390f35b6100d8565b60ff1690565b61017781610168565b0361017e57565b5f80fd5b9050359061018f8261016e565b565b9190916040818403126101d1576101aa835f8301610182565b92602082013567ffffffffffffffff81116101cc576101c992016100e8565b90565b6100e0565b6100dc565b34610205576101ef6101e9366004610191565b906115ec565b6101f76100d2565b8061020181610130565b0390f35b6100d8565b908160409103126102185790565b6100e4565b9060408282031261023657610233915f0161020a565b90565b6100dc565b346102695761025361024e36600461021d565b611b8d565b61025b6100d2565b8061026581610130565b0390f35b6100d8565b5f91031261027857565b6100dc565b346102ab5761028d36600461026e565b610295611d42565b61029d6100d2565b806102a781610130565b0390f35b6100d8565b908160209103126102be5790565b6100e4565b906020828203126102dc576102d9915f016102b0565b90565b6100dc565b3461030f576102f96102f43660046102c3565b611ee8565b6103016100d2565b8061030b81610130565b0390f35b6100d8565b60018060a01b031690565b61032890610314565b90565b6103349061031f565b9052565b5190565b60209181520190565b60200190565b5190565b60209181520190565b90825f9392825e0152565b601f801991011690565b61038c61039560209361039a936103838161034b565b9384809361034f565b95869101610358565b610363565b0190565b6103c991602060408201926103b95f8201515f85019061032b565b015190602081840391015261036d565b90565b906103d69161039e565b90565b60200190565b906103f36103ec83610338565b809261033c565b908161040460208302840194610345565b925f915b83831061041757505050505090565b90919293946020610439610433838560019503875289516103cc565b976103d9565b9301930191939290610408565b50600290565b905090565b90565b90565b61046090610454565b9052565b61046d90610168565b9052565b90602080610493936104895f8201515f860190610457565b0151910190610464565b565b906104a281604093610471565b0190565b60200190565b6104c86104c26104bb83610446565b809461044c565b91610451565b5f915b8383106104d85750505050565b6104ee6104e86001928451610495565b926104a6565b920191906104cb565b67ffffffffffffffff1690565b61050d906104f7565b9052565b61ffff1690565b61052190610511565b9052565b905f80610536930151910190610518565b565b9060208061055a936105505f8201515f860190610504565b0151910190610457565b565b905f8061056d93015191019061032b565b565b6fffffffffffffffffffffffffffffffff1690565b61058d9061056f565b9052565b9061062b9061016060e06105c561018084016105b35f8801515f87019061032b565b602087015185820360208701526103df565b946105d8604082015160408601906104ac565b6105ea606082015160c0860190610504565b6105fb608082015183860190610525565b61060e60a0820151610100860190610538565b61062160c082015161014086019061055c565b0151910190610584565b90565b6106439160208201915f818403910152610591565b90565b346106765761065636600461026e565b61067261066161253d565b6106696100d2565b9182918261062e565b0390f35b6100d8565b610684816104f7565b0361068b57565b5f80fd5b9050359061069c8261067b565b565b906020828203126106b7576106b4915f0161068f565b90565b6100dc565b346106ea576106d46106cf36600461069e565b612ab0565b6106dc6100d2565b806106e681610130565b0390f35b6100d8565b6106f88161031f565b036106ff57565b5f80fd5b90503590610710826106ef565b565b9060208282031261072b57610728915f01610703565b90565b6100dc565b3461075e57610748610743366004610712565b612f2c565b6107506100d2565b8061075a81610130565b0390f35b6100d8565b346107915761077336600461026e565b61077b613064565b6107836100d2565b8061078d81610130565b0390f35b6100d8565b346107c4576107ae6107a9366004610712565b61310b565b6107b66100d2565b806107c081610130565b0390f35b6100d8565b346107f7576107d936600461026e565b6107e161321e565b6107e96100d2565b806107f381610130565b0390f35b6100d8565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b90359060016020038136030382121561084e570180359067ffffffffffffffff82116108495760200191600182023603831361084457565b610808565b610804565b610800565b5090565b35610861816106ef565b90565b5f1c90565b60018060a01b031690565b61088061088591610864565b610869565b90565b6108929054610874565b90565b60209181520190565b5f7f756e617574686f72697a65640000000000000000000000000000000000000000910152565b6108d2600c602092610895565b6108db8161089e565b0190565b6108f49060208101905f8183039101526108c5565b90565b156108fe57565b6109066100d2565b62461bcd60e51b81528061091c600482016108df565b0390fd5b90565b61093761093261093c92610314565b610920565b610314565b90565b61094890610923565b90565b6109549061093f565b90565b906109619061094b565b5f5260205260405f2090565b90565b60ff1690565b61098261098791610864565b610970565b90565b6109949054610976565b90565b5f7f756e6b6e6f776e206f70657261746f7200000000000000000000000000000000910152565b6109cb6010602092610895565b6109d481610997565b0190565b6109ed9060208101905f8183039101526109be565b90565b156109f757565b6109ff6100d2565b62461bcd60e51b815280610a15600482016109d8565b0390fd5b60081c90565b60ff1690565b610a31610a3691610a19565b610a1f565b90565b610a439054610a25565b90565b634e487b7160e01b5f52603260045260245ffd5b5061010090565b90565b610a6d81610a5a565b821015610a8757610a7f600291610a61565b910201905f90565b610a46565b634e487b7160e01b5f525f60045260245ffd5b5f1b90565b90610ab560018060a01b0391610a9f565b9181191691161790565b90565b90610ad7610ad2610ade9261094b565b610abf565b8254610aa4565b9055565b634e487b7160e01b5f52604160045260245ffd5b634e487b7160e01b5f52602260045260245ffd5b9060016002830492168015610b2a575b6020831014610b2557565b610af6565b91607f1691610b1a565b5f5260205f2090565b601f602091010490565b1b90565b91906008610b66910291610b605f1984610b47565b92610b47565b9181191691161790565b610b84610b7f610b8992610454565b610920565b610454565b90565b90565b9190610ba5610ba0610bad93610b70565b610b8c565b908354610b4b565b9055565b5f90565b610bc791610bc1610bb1565b91610b8f565b565b5b818110610bd5575050565b80610be25f600193610bb5565b01610bca565b9190601f8111610bf8575b505050565b610c04610c2993610b34565b906020610c1084610b3d565b83019310610c31575b610c2290610b3d565b0190610bc9565b5f8080610bf3565b9150610c2281929050610c19565b1c90565b90610c53905f1990600802610c3f565b191690565b81610c6291610c43565b906002021790565b91610c759082610853565b9067ffffffffffffffff8211610d3457610c9982610c938554610b0a565b85610be8565b5f90601f8311600114610ccc57918091610cbb935f92610cc0575b5050610c58565b90555b565b90915001355f80610cb4565b601f19831691610cdb85610b34565b925f5b818110610d1c57509160029391856001969410610d02575b50505002019055610cbe565b610d12910135601f841690610c43565b90555f8080610cf6565b91936020600181928787013581550195019201610cde565b610ae2565b90610d449291610c6a565b565b90610d736001610d7993610d675f8201610d615f8701610857565b90610ac2565b0191602081019061080c565b91610d39565b565b9190610d8c57610d8a91610d46565b565b610a8c565b6fffffffffffffffffffffffffffffffff1690565b610db2610db791610864565b610d91565b90565b610dc49054610da6565b90565b634e487b7160e01b5f52601160045260245ffd5b610de49061056f565b6fffffffffffffffffffffffffffffffff8114610e015760010190565b610dc7565b90610e216fffffffffffffffffffffffffffffffff91610a9f565b9181191691161790565b610e3f610e3a610e449261056f565b610920565b61056f565b90565b90565b90610e5f610e5a610e6692610e2b565b610e47565b8254610e06565b9055565b50610e79906020810190610703565b90565b5f80fd5b5f80fd5b5f80fd5b9035600160200382360303811215610ec957016020813591019167ffffffffffffffff8211610ec4576001820236038313610ebf57565b610e80565b610e7c565b610e84565b90825f939282370152565b9190610ef381610eec81610ef89561034f565b8095610ece565b610363565b0190565b610f3891610f2a6040820192610f20610f175f830183610e6a565b5f85019061032b565b6020810190610e88565b916020818503910152610ed9565b90565b610f449061056f565b9052565b92916020610f64610f6c9360408701908782035f890152610efc565b940190610f3b565b565b610f8d610f88610f8283602081019061080c565b90610853565b613348565b33610faa610fa4610f9f5f8501610857565b61031f565b9161031f565b148015611075575b610fbb906108f7565b611011610fde610fd95f600101610fd35f8601610857565b90610957565b61096d565b610ff1610fec5f830161098a565b6109f0565b61100b83916110055f600180019201610a39565b90610a64565b90610d7b565b61102f61102761102261020c610dba565b610ddb565b61020c610e4a565b61103a61020c610dba565b7f5aab2c32b1e447db4dba1d2790fe8b863d4775042b10b92e00dab9d6b671b5b5916110706110676100d2565b92839283610f48565b0390a1565b50610fbb3361109461108e6110895f610888565b61031f565b9161031f565b149050610fb2565b5f7f6e6f7420746865206f776e657200000000000000000000000000000000000000910152565b6110d0600d602092610895565b6110d98161109c565b0190565b6110f29060208101905f8183039101526110c3565b90565b156110fc57565b6111046100d2565b62461bcd60e51b81528061111a600482016110dd565b0390fd5b9061114c916111473361114161113b6111365f610888565b61031f565b9161031f565b146110f5565b61147f565b565b151590565b5f7f616c726561647920657869737473000000000000000000000000000000000000910152565b611187600e602092610895565b61119081611153565b0190565b6111a99060208101905f81830391015261117a565b90565b156111b357565b6111bb6100d2565b62461bcd60e51b8152806111d160048201611194565b0390fd5b6111df9054610b0a565b90565b90565b6111f96111f46111fe926111e2565b610920565b610454565b90565b5f7f736c6f74206f6363757069656400000000000000000000000000000000000000910152565b611235600d602092610895565b61123e81611201565b0190565b6112579060208101905f818303910152611228565b90565b1561126157565b6112696100d2565b62461bcd60e51b81528061127f60048201611242565b0390fd5b9061128d90610363565b810190811067ffffffffffffffff8211176112a757604052565b610ae2565b906112bf6112b86100d2565b9283611283565b565b6112cb60406112ac565b90565b906112d89061114e565b9052565b906112e690610168565b9052565b6112f4905161114e565b90565b9061130360ff91610a9f565b9181191691161790565b6113169061114e565b90565b90565b9061133161132c6113389261130d565b611319565b82546112f7565b9055565b6113469051610168565b90565b60081b90565b9061135c61ff0091611349565b9181191691161790565b61137a61137561137f92610168565b610920565b610168565b90565b90565b9061139a6113956113a192611366565b611382565b825461134f565b9055565b906113cf60205f6113d5946113c78282016113c18488016112ea565b9061131c565b01920161133c565b90611385565b565b906113e1916113a5565b565b90565b6113f26113f791610864565b6113e3565b90565b61140490546113e6565b90565b906114135f1991610a9f565b9181191691161790565b9061143261142d61143992610b70565b610b8c565b8254611407565b9055565b61144690610168565b9052565b93929061147560409161147d9461146860608901925f8a019061143d565b8782036020890152610efc565b940190610f3b565b565b61149e61149961149384602081019061080c565b90610853565b613348565b6114d16114cc6114c65f6114c0816001016114ba838901610857565b90610957565b0161098a565b1561114e565b6111ac565b6115056114ed60016114e68180018590610a64565b50016111d5565b6114ff6114f95f6111e5565b91610454565b1461125a565b611548600161152b836115226115196112c1565b935f85016112ce565b602083016112dc565b6115435f60010161153d5f8701610857565b90610957565b6113d7565b6115608261155a600180018490610a64565b90610d7b565b61158661157b6115746102016001016113fa565b83906133d2565b61020160010161141d565b6115a461159c61159761020c610dba565b610ddb565b61020c610e4a565b906115b061020c610dba565b916115e77f952e65f049c574f487580ba41dcf6b0ea8350ef8abc8647a8a11dfaa7af6bad6936115de6100d2565b9384938461144a565b0390a1565b906115f69161111e565b565b611625906116203361161a61161461160f5f610888565b61031f565b9161031f565b146110f5565b6116a9565b565b5f7f6d6967726174696f6e20696e2070726f67726573730000000000000000000000910152565b61165b6015602092610895565b61166481611627565b0190565b61167d9060208101905f81830391015261164e565b90565b1561168757565b61168f6100d2565b62461bcd60e51b8152806116a560048201611668565b0390fd5b6116cb906116c66116c16116bb613401565b1561114e565b611680565b61174f565b565b5f7f6d61696e74656e616e636520696e2070726f6772657373000000000000000000910152565b6117016017602092610895565b61170a816116cd565b0190565b6117239060208101905f8183039101526116f4565b90565b1561172d57565b6117356100d2565b62461bcd60e51b81528061174b6004820161170e565b0390fd5b6117719061176c61176761176161342f565b1561114e565b611726565b611a66565b565b61177c81610454565b0361178357565b5f80fd5b3561179181611773565b90565b5f7f696e76616c6964206269746d61736b0000000000000000000000000000000000910152565b6117c8600f602092610895565b6117d181611794565b0190565b6117ea9060208101905f8183039101526117bb565b90565b156117f457565b6117fc6100d2565b62461bcd60e51b815280611812600482016117d5565b0390fd5b67ffffffffffffffff1690565b61182f61183491610864565b611816565b90565b6118419054611823565b90565b61184d906104f7565b67ffffffffffffffff81146118625760010190565b610dc7565b9061187a67ffffffffffffffff91610a9f565b9181191691161790565b61189861189361189d926104f7565b610920565b6104f7565b90565b90565b906118b86118b36118bf92611884565b6118a0565b8254611867565b9055565b90565b6118da6118d56118df926118c3565b610920565b6104f7565b90565b634e487b7160e01b5f52601260045260245ffd5b611902611908916104f7565b916104f7565b908115611913570690565b6118e2565b50600290565b90565b61192a81611918565b8210156119445761193c60029161191e565b910201905f90565b610a46565b356119538161016e565b90565b9061196b61196661197292611366565b611382565b82546112f7565b9055565b906119a1602060016119a7946119995f82016119935f8801611787565b9061141d565b019201611949565b90611956565b565b91906119ba576119b891611976565b565b610a8c565b6119c8906104f7565b9052565b905035906119d982611773565b565b506119ea9060208101906119cc565b90565b506119fc906020810190610182565b90565b906020611a2a611a3293611a21611a185f8301836119db565b5f860190610457565b828101906119ed565b910190610464565b565b606090611a5d611a649496959396611a5360808401985f8501906119bf565b60208301906119ff565b0190610f3b565b565b611a90611a8b611a775f8401611787565b611a856102016001016113fa565b90613464565b6117ed565b611aaf5f61020901611aa9611aa482611837565b611844565b906118a3565b611acd611ac5611ac0610207611837565b611844565b6102076118a3565b611b0181611afb610203611af5611ae5610207611837565b611aef60026118c6565b906118f6565b90611921565b906119a9565b611b1a611b0f5f8301611787565b60016102090161141d565b611b38611b30611b2b61020c610dba565b610ddb565b61020c610e4a565b611b455f61020901611837565b90611b5161020c610dba565b91611b887f490341fd8fc7a8294fbad1cc0db9f41ae0ac5aeb655ea31b46a475ec3a77749c93611b7f6100d2565b93849384611a34565b0390a1565b611b96906115f8565b565b5f7f6e6f206d61696e74656e616e6365000000000000000000000000000000000000910152565b611bcc600e602092610895565b611bd581611b98565b0190565b611bee9060208101905f818303910152611bbf565b90565b15611bf857565b611c006100d2565b62461bcd60e51b815280611c1660048201611bd9565b0390fd5b611c2a611c2561342f565b611bf1565b611c32611c71565b565b611c48611c43611c4d926111e2565b610920565b610314565b90565b611c5990611c34565b90565b9190611c6f905f60208501940190610f3b565b565b611c7e5f61020b01610888565b611c90611c8a3361031f565b9161031f565b148015611d1b575b611ca1906108f7565b611cb7611cad5f611c50565b5f61020b01610ac2565b611cd5611ccd611cc861020c610dba565b610ddb565b61020c610e4a565b611ce061020c610dba565b611d167f11943d6deda6f0591d72674788d272eb0209e18b8a3a021fa51cb3b5e9a2ab6191611d0d6100d2565b91829182611c5c565b0390a1565b50611ca133611d3a611d34611d2f5f610888565b61031f565b9161031f565b149050611c98565b611d4a611c1a565b565b611d7990611d7433611d6e611d68611d635f610888565b61031f565b9161031f565b146110f5565b611e78565b565b611d8481610511565b03611d8b57565b5f80fd5b35611d9981611d7b565b90565b90611da961ffff91610a9f565b9181191691161790565b611dc7611dc2611dcc92610511565b610920565b610511565b90565b90565b90611de7611de2611dee92611db3565b611dcf565b8254611d9c565b9055565b90611e045f80611e0a94019201611d8f565b90611dd2565b565b90611e1691611df2565b565b90503590611e2582611d7b565b565b50611e36906020810190611e18565b90565b905f611e4b611e539382810190611e27565b910190610518565b565b916020611e76929493611e6f60408201965f830190611e39565b0190610f3b565b565b611e8481610208611e0c565b611ea2611e9a611e9561020c610dba565b610ddb565b61020c610e4a565b611ead61020c610dba565b7fb24d8d9dcfbb6be13176c1c7bfb0e76445a9ba2a3553b413d8671446f103083091611ee3611eda6100d2565b92839283611e55565b0390a1565b611ef190611d4c565b565b611efe6101006112ac565b90565b5f90565b606090565b67ffffffffffffffff8111611f1f5760200290565b610ae2565b611f30611f3591611f0a565b6112ac565b90565b611f4260406112ac565b90565b5f90565b5f90565b611f55611f38565b9060208083611f62611f45565b815201611f6d611f49565b81525050565b611f7b611f4d565b90565b5f5b828110611f8c57505050565b602090611f97611f73565b8184015201611f80565b90611fbf611fae83611f24565b92611fb98491611f0a565b90611f7e565b565b611fcb6002611fa1565b90565b5f90565b611fdc60206112ac565b90565b5f90565b611feb611fd2565b90602082611ff7611fdf565b81525050565b612005611fe3565b90565b61201260406112ac565b90565b61201d612008565b906020808361202a611fce565b815201612035611f45565b81525050565b612043612015565b90565b61205060206112ac565b90565b61205b612046565b90602082612067611f01565b81525050565b612075612053565b90565b5f90565b612084611ef3565b9060208080808080808089612097611f01565b8152016120a2611f05565b8152016120ad611fc1565b8152016120b8611fce565b8152016120c3611ffd565b8152016120ce61203b565b8152016120d961206d565b8152016120e4612078565b81525050565b6120f261207c565b90565b90565b61210c612107612111926120f5565b610920565b610454565b90565b61212361212991939293610454565b92610454565b820180921161213457565b610dc7565b67ffffffffffffffff81116121515760208091020190565b610ae2565b9061216861216383612139565b6112ac565b918252565b61217760406112ac565b90565b606090565b61218761216d565b9060208083612194611f01565b81520161219f61217a565b81525050565b6121ad61217f565b90565b5f5b8281106121be57505050565b6020906121c96121a5565b81840152016121b2565b906121f86121e083612156565b926020806121ee8693612139565b92019103906121b0565b565b6122056101006112ac565b90565b906122129061031f565b9052565b52565b9061222390610454565b9052565b61223361223891610864565b610a1f565b90565b6122459054612227565b90565b9061227f6122766001612259611f38565b946122706122685f83016113fa565b5f8801612219565b0161223b565b602084016112dc565b565b61228a90612248565b90565b9061229782611918565b6122a081611f24565b926122ab849161191e565b5f915b8383106122bb5750505050565b600260206001926122cb85612281565b8152019201920191906122ae565b6122e29061228d565b90565b52565b906122f2906104f7565b9052565b61ffff1690565b61230961230e91610864565b6122f6565b90565b61231b90546122fd565b90565b9061232890610511565b9052565b9061234b6123435f61233c611fd2565b9401612311565b5f840161231e565b565b6123569061232c565b90565b52565b9061239361238a600161236d612008565b9461238461237c5f8301611837565b5f88016122e8565b016113fa565b60208401612219565b565b61239e9061235c565b90565b52565b906123c36123bb5f6123b4612046565b9401610888565b5f8401612208565b565b6123ce906123a4565b90565b52565b906123de9061056f565b9052565b6123eb90610454565b5f1981146123f95760010190565b610dc7565b61241261240d61241792610454565b610920565b610168565b90565b9061242482610338565b811015612435576020809102010190565b610a46565b905f929180549061245461244d83610b0a565b809461034f565b916001811690815f146124ab575060011461246f575b505050565b61247c9192939450610b34565b915f925b81841061249357505001905f808061246a565b60018160209295939554848601520191019290612480565b92949550505060ff19168252151560200201905f808061246a565b906124d09161243a565b90565b906124f36124ec926124e36100d2565b938480926124c6565b0383611283565b565b52565b9061252f612526600161250961216d565b946125206125185f8301610888565b5f8801612208565b016124d3565b602084016124f5565b565b61253a906124f8565b90565b6125456120ea565b50600161020101612555906113fa565b61255e9061348f565b6125675f610888565b816001612573906120f8565b61257c91612114565b612585906121d3565b610203612593610207611837565b6102086102099161020b936125a961020c610dba565b956125b26121fa565b975f8901906125c091612208565b60208801906125ce91612216565b6125d7906122d9565b60408701906125e5916122e5565b60608601906125f3916122e8565b6125fc9061234d565b608085019061260a91612359565b61261390612395565b60a0840190612621916123a1565b61262a906123c5565b60c0830190612638916123d1565b60e0820190612646916123d4565b600161020101612655906113fa565b925f612660906111e5565b5b8061267461266e86610454565b91610454565b116126d7576126cd906126908661268a836123fe565b906134a4565b6126d2576126c56126a5600180018390610a64565b5060208601516126b58492612531565b6126bf838361241a565b5261241a565b51505b6123e2565b612661565b6126c8565b509250905090565b5f7f6e6f206d6967726174696f6e0000000000000000000000000000000000000000910152565b612713600c602092610895565b61271c816126df565b0190565b6127359060208101905f818303910152612706565b90565b1561273f57565b6127476100d2565b62461bcd60e51b81528061275d60048201612720565b0390fd5b61277a90612775612770613401565b612738565b612910565b565b5f7f77726f6e67206d6967726174696f6e2069640000000000000000000000000000910152565b6127b06012602092610895565b6127b98161277c565b0190565b6127d29060208101905f8183039101526127a3565b90565b156127dc57565b6127e46100d2565b62461bcd60e51b8152806127fa600482016127bd565b0390fd5b61280860406112ac565b90565b906128416128385f61281b6127fe565b9461283261282a83830161098a565b8388016112ce565b01610a39565b602084016112dc565b565b61284c9061280b565b90565b5f7f6e6f742070756c6c696e67000000000000000000000000000000000000000000910152565b612883600b602092610895565b61288c8161284f565b0190565b6128a59060208101905f818303910152612876565b90565b156128af57565b6128b76100d2565b62461bcd60e51b8152806128cd60048201612890565b0390fd5b6128da9061031f565b9052565b60409061290761290e94969593966128fd60608401985f8501906119bf565b60208301906128d1565b0190610f3b565b565b6129389061293261292c6129275f61020901611837565b6104f7565b916104f7565b146127d5565b6129bd6129b261295461294f5f6001013390610957565b612843565b6129676129625f83016112ea565b6109f0565b61299261298d61297b6001610209016113fa565b6129876020850161133c565b906134e2565b6128a8565b6129ac60206129a56001610209016113fa565b920161133c565b90613521565b60016102090161141d565b6129db6129d36129ce61020c610dba565b610ddb565b61020c610e4a565b6129e96001610209016113fa565b6129fb6129f55f6111e5565b91610454565b145f14612a5857612a0f5f61020901611837565b33612a1b61020c610dba565b91612a527f01269879535f40ee8957e15e160bf1866c5e2728ff0cbc583d848821e2639b4e93612a496100d2565b938493846128de565b0390a15b565b612a655f61020901611837565b33612a7161020c610dba565b91612aa87faf5e90e72015f43138f66b4cd08bd1dfa2839030104f22a00af843fe847c6d1993612a9f6100d2565b938493846128de565b0390a1612a56565b612ab990612761565b565b612ae890612ae333612add612ad7612ad25f610888565b61031f565b9161031f565b146110f5565b612d89565b565b5f7f696e206b65797370616365000000000000000000000000000000000000000000910152565b612b1e600b602092610895565b612b2781612aea565b0190565b612b409060208101905f818303910152612b11565b90565b15612b4a57565b612b526100d2565b62461bcd60e51b815280612b6860048201612b2b565b0390fd5b5f80910155565b905f03612b8557612b8390612b6c565b565b610a8c565b90612b9d905f1990602003600802610c3f565b8154169055565b905f91612bbb612bb382610b34565b928354610c58565b905555565b919290602082105f14612c1957601f8411600114612be957612be3929350610c58565b90555b5b565b5090612c0f612c14936001612c06612c0085610b34565b92610b3d565b82019101610bc9565b612ba4565b612be6565b50612c508293612c2a600194610b34565b612c49612c3685610b3d565b820192601f861680612c5b575b50610b3d565b0190610bc9565b600202179055612be7565b612c6790888603612b8a565b5f612c43565b929091680100000000000000008211612ccd576020115f14612cbe57602081105f14612ca257612c9c91610c58565b90555b5b565b60019160ff1916612cb284610b34565b55600202019055612c9f565b60019150600202019055612ca0565b610ae2565b908154612cde81610b0a565b90818311612d07575b818310612cf5575b50505050565b612cfe93612bc0565b5f808080612cef565b612d1383838387612c6d565b612ce7565b5f612d2291612cd2565b565b905f03612d3657612d3490612d18565b565b610a8c565b5f6001612d4d92828082015501612d24565b565b905f03612d6157612d5f90612d3b565b565b610a8c565b916020612d87929493612d8060408201965f8301906128d1565b0190610f3b565b565b612e4e612e43612dc25f612da9612da4826001018790610957565b61096d565b612dbc612db783830161098a565b6109f0565b01610a39565b612dca613401565b5f14612ee057612df2612deb5f612de46102038290611921565b50016113fa565b82906134a4565b80612eb2575b612e0190612b43565b5b612e195f612e14816001018790610957565b612b73565b612e30612e2a600180018390610a64565b90612d4f565b612e3e6102016001016113fa565b613521565b61020160010161141d565b612e6c612e64612e5f61020c610dba565b610ddb565b61020c610e4a565b612e7761020c610dba565b7f6a1d7ddc82d57e783a3ae60737a6c1a4704fcf38d966561fea0af8564f2d895d91612ead612ea46100d2565b92839283612d66565b0390a1565b50612e01612ed9612ed25f612ecb610203600190611921565b50016113fa565b83906134a4565b9050612df8565b612f27612f22612f1b5f612f14610203612f0e612efe610207611837565b612f0860026118c6565b906118f6565b90611921565b50016113fa565b83906134a4565b612b43565b612e02565b612f3590612abb565b565b612f5b33612f55612f4f612f4a5f610888565b61031f565b9161031f565b146110f5565b612f63612f65565b565b612f75612f70613401565b612738565b612f7d612fbe565b565b612f88906104f7565b5f8114612f96576001900390565b610dc7565b916020612fbc929493612fb560408201965f8301906119bf565b0190610f3b565b565b612fdc612fd4612fcf610207611837565b612f7f565b6102076118a3565b612ff3612fe85f6111e5565b60016102090161141d565b61301161300961300461020c610dba565b610ddb565b61020c610e4a565b61301e5f61020901611837565b61302961020c610dba565b7ff73240422246f63ed633ef3ce0726b8ab8fb69d46c8a4e5ecb0b2922668674a19161305f6130566100d2565b92839283612f9b565b0390a1565b61306c612f37565b565b61309b906130963361309061308a6130855f610888565b61031f565b9161031f565b146110f5565b61309d565b565b6130a7815f610ac2565b6130c56130bd6130b861020c610dba565b610ddb565b61020c610e4a565b6130d061020c610dba565b7f476610ebc6647c15376100955efbf22ef2a0c3b923fc00b380b660c873ef20ac916131066130fd6100d2565b92839283612d66565b0390a1565b6131149061306e565b565b61312f61312a613124613401565b1561114e565b611680565b613137613139565b565b61315261314d61314761342f565b1561114e565b611726565b61315a61315c565b565b6131745f61316e816001013390610957565b0161098a565b80156131f7575b613184906108f7565b613192335f61020b01610ac2565b6131b06131a86131a361020c610dba565b610ddb565b61020c610e4a565b336131bc61020c610dba565b7fbc2748cf02f7a1291525e866efc76ab3b96d32d7afcbb26c53daec617b38b479916131f26131e96100d2565b92839283612d66565b0390a1565b506131843361321661321061320b5f610888565b61031f565b9161031f565b14905061317b565b613226613116565b565b5f7f656d707479206f70657261746f72206461746100000000000000000000000000910152565b61325c6013602092610895565b61326581613228565b0190565b61327e9060208101905f81830391015261324f565b90565b1561328857565b6132906100d2565b62461bcd60e51b8152806132a660048201613269565b0390fd5b6132be6132b96132c392610511565b610920565b610454565b90565b5f7f6f70657261746f72206461746120746f6f206c61726765000000000000000000910152565b6132fa6017602092610895565b613303816132c6565b0190565b61331c9060208101905f8183039101526132ed565b90565b1561332657565b61332e6100d2565b62461bcd60e51b81528061334460048201613307565b0390fd5b61338d906133688161336261335c5f6111e5565b91610454565b11613281565b61338661338061337b5f61020801612311565b6132aa565b91610454565b111561331f565b565b6133a361339e6133a892610168565b610920565b610454565b90565b6133ca906133c46133be6133cf94610454565b91610454565b90610b47565b610454565b90565b6133f9906133de610bb1565b50916133f46133ee60019261338f565b916120f8565b6133ab565b1790565b5f90565b6134096133fd565b506134186001610209016113fa565b61342a6134245f6111e5565b91610454565b141590565b6134376133fd565b506134455f61020b01610888565b61345f6134596134545f611c50565b61031f565b9161031f565b141590565b613478906134706133fd565b509119610454565b1661348b6134855f6111e5565b91610454565b1490565b6134a19061349b610bb1565b50613714565b90565b6134cb906134b06133fd565b50916134c66134c060019261338f565b916120f8565b6133ab565b166134de6134d85f6111e5565b91610454565b1490565b613509906134ee6133fd565b50916135046134fe60019261338f565b916120f8565b6133ab565b1661351c6135165f6111e5565b91610454565b141590565b61354b61355191613530610bb1565b509261354661354060019261338f565b916120f8565b6133ab565b19610454565b1690565b90565b61356c61356761357192613555565b610920565b610454565b90565b90565b61358b61358661359092613574565b610920565b610168565b90565b6135b2906135ac6135a66135b794610168565b91610454565b90610b47565b610454565b90565b6135d9906135d36135cd6135de94610454565b91610454565b90610c3f565b610454565b90565b90565b6135f86135f36135fd926135e1565b610920565b610454565b90565b90565b61361761361261361c92613600565b610920565b610168565b90565b90565b61363661363161363b9261361f565b610920565b610454565b90565b90565b61365561365061365a9261363e565b610920565b610168565b90565b90565b61367461366f6136799261365d565b610920565b610454565b90565b90565b61369361368e6136989261367c565b610920565b610168565b90565b90565b6136b26136ad6136b79261369b565b610920565b610454565b90565b90565b6136d16136cc6136d6926136ba565b610920565b610168565b90565b90565b6136f06136eb6136f5926136d9565b610920565b610454565b90565b61370c613707613711926118c3565b610920565b610168565b90565b61371c610bb1565b5061375c61374c826137466137406fffffffffffffffffffffffffffffffff613558565b91610454565b116138a9565b6137566007613577565b90613593565b61379d61378d61376d8484906135ba565b61378761378167ffffffffffffffff6135e4565b91610454565b116138a9565b6137976006613603565b90613593565b176137db6137cb6137af8484906135ba565b6137c56137bf63ffffffff613622565b91610454565b116138a9565b6137d56005613641565b90613593565b176138176138076137ed8484906135ba565b6138016137fb61ffff613660565b91610454565b116138a9565b613811600461367f565b90613593565b176138526138426138298484906135ba565b61383c61383660ff61369e565b91610454565b116138a9565b61384c60036136bd565b90613593565b1761388d61387d6138648484906135ba565b613877613871600f6136dc565b91610454565b116138a9565b61388760026136f8565b90613593565b17906d010102020202030303030303030360801b90821c1a1790565b6138b1610bb1565b5015159056fea264697066735822122015abc4566b5a4eece53e06dab0721de14be34963877d9977ca41a88371cca70b64736f6c634300081c0033","sourceMap":"993:7199:24:-:0;;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;:::i;:::-;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;:::i;:::-;;;;;;;;;;:::o;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;:::o;:::-;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;:::o;:::-;;;:::o;:::-;;:::o;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;:::o;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;:::i;:::-;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;:::o;:::-;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;:::i;:::-;:::o;:::-;;;;:::o;:::-;;:::o;:::-;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;:::o;:::-;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;:::o;:::-;;;;;;;:::o;:::-;;;:::o;:::-;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;:::i;:::-;;;;;:::i;:::-;;;:::o;:::-;;;:::o;:::-;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;;;;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;:::o;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;:::i;:::-;;;;;;:::o;:::-;;;;;:::i;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;;;;:::i;:::-;:::o;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;:::o;:::-;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;:::o;:::-;;:::i;1315:800::-;1510:26;1315:800;1410:61;1418:23;:16;:23;:::i;:::-;:30;;1445:3;1418:30;:::i;:::-;;;:::i;:::-;;;1410:61;:::i;:::-;1482:18;1490:10;1482:18;;:::i;:::-;1510:26;;:::i;:::-;1568:13;1580:1;1568:13;:::i;:::-;1612:3;1583:1;:27;;1587:23;:16;:23;:::i;:::-;1583:27;:::i;:::-;;;:::i;:::-;;;;;1612:3;1656:16;:31;;:24;:19;:16;1673:1;1656:19;;:::i;:::-;;:24;;:31;:::i;:::-;;:::i;:::-;1702:87;1710:56;1711:55;;:47;:13;;:21;1733:24;:16;:19;:16;1750:1;1733:19;;:::i;:::-;;:24;;:::i;:::-;1711:47;;:::i;:::-;:55;;:::i;:::-;1710:56;;:::i;:::-;1702:87;:::i;:::-;1804:94;1874:4;1854:44;1887:8;1893:1;1887:8;:::i;:::-;1854:44;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::i;:::-;1804:47;:21;:13;:21;1826:24;;:19;:16;1843:1;1826:19;;:::i;:::-;;:24;;:::i;:::-;1804:47;;:::i;:::-;:94;:::i;:::-;1912:44;1937:19;:16;1954:1;1937:19;;:::i;:::-;;1912:22;:19;:13;:19;1932:1;1912:22;;:::i;:::-;:44;;:::i;:::-;1612:3;:::i;:::-;1568:13;;1583:27;;2001:44;2014:30;2020:23;1977:68;1583:27;2020:23;:::i;:::-;2014:30;:::i;:::-;2001:44;:::i;:::-;1977:21;:13;:21;:68;:::i;:::-;2055:53;2087:21;;:13;:21;;:::i;:::-;2055:29;:12;:9;2065:1;2055:12;;:::i;:::-;;:29;:53;:::i;:::-;1315:800::o;993:7199::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;7731:205;7855:74;7731:205;7804:41;7812:5;:9;;7820:1;7812:9;:::i;:::-;;;:::i;:::-;;7804:41;:::i;:::-;7863:38;;7872:29;;:8;:29;;:::i;:::-;7863:38;:::i;:::-;;;:::i;:::-;;;7855:74;:::i;:::-;7731:205::o;993:7199::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;:::o;:::-;;:::i;8885:101::-;8959:15;8958:21;8885:101;8931:7;;:::i;:::-;8959:1;:15;8964:10;8959:1;8972;8964:10;:::i;:::-;8959:15;;:::i;:::-;;:::i;:::-;8958:21;8978:1;8958:21;:::i;:::-;;;:::i;:::-;8951:28;:::o","linkReferences":{}},"deployedBytecode":{"object":"0x60806040526004361015610013575b6107fc565b61001d5f356100cc565b806326322217146100c75780632b726062146100c257806347011c5c146100bd57806353bfb584146100b857806365706f9c146100b357806375418b9d146100ae5780639d44e717146100a9578063c05665dd146100a4578063c130809a1461009f578063f2fde38b1461009a5763f5f2d9f10361000e576107c9565b610796565b610763565b610730565b6106bc565b610646565b6102e1565b61027d565b61023b565b6101d6565b610135565b60e01c90565b60405190565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b908160409103126100f65790565b6100e4565b9060208282031261012b575f82013567ffffffffffffffff81116101265761012392016100e8565b90565b6100e0565b6100dc565b5f0190565b346101635761014d6101483660046100fb565b610f6e565b6101556100d2565b8061015f81610130565b0390f35b6100d8565b60ff1690565b61017781610168565b0361017e57565b5f80fd5b9050359061018f8261016e565b565b9190916040818403126101d1576101aa835f8301610182565b92602082013567ffffffffffffffff81116101cc576101c992016100e8565b90565b6100e0565b6100dc565b34610205576101ef6101e9366004610191565b906115ec565b6101f76100d2565b8061020181610130565b0390f35b6100d8565b908160409103126102185790565b6100e4565b9060408282031261023657610233915f0161020a565b90565b6100dc565b346102695761025361024e36600461021d565b611b8d565b61025b6100d2565b8061026581610130565b0390f35b6100d8565b5f91031261027857565b6100dc565b346102ab5761028d36600461026e565b610295611d42565b61029d6100d2565b806102a781610130565b0390f35b6100d8565b908160209103126102be5790565b6100e4565b906020828203126102dc576102d9915f016102b0565b90565b6100dc565b3461030f576102f96102f43660046102c3565b611ee8565b6103016100d2565b8061030b81610130565b0390f35b6100d8565b60018060a01b031690565b61032890610314565b90565b6103349061031f565b9052565b5190565b60209181520190565b60200190565b5190565b60209181520190565b90825f9392825e0152565b601f801991011690565b61038c61039560209361039a936103838161034b565b9384809361034f565b95869101610358565b610363565b0190565b6103c991602060408201926103b95f8201515f85019061032b565b015190602081840391015261036d565b90565b906103d69161039e565b90565b60200190565b906103f36103ec83610338565b809261033c565b908161040460208302840194610345565b925f915b83831061041757505050505090565b90919293946020610439610433838560019503875289516103cc565b976103d9565b9301930191939290610408565b50600290565b905090565b90565b90565b61046090610454565b9052565b61046d90610168565b9052565b90602080610493936104895f8201515f860190610457565b0151910190610464565b565b906104a281604093610471565b0190565b60200190565b6104c86104c26104bb83610446565b809461044c565b91610451565b5f915b8383106104d85750505050565b6104ee6104e86001928451610495565b926104a6565b920191906104cb565b67ffffffffffffffff1690565b61050d906104f7565b9052565b61ffff1690565b61052190610511565b9052565b905f80610536930151910190610518565b565b9060208061055a936105505f8201515f860190610504565b0151910190610457565b565b905f8061056d93015191019061032b565b565b6fffffffffffffffffffffffffffffffff1690565b61058d9061056f565b9052565b9061062b9061016060e06105c561018084016105b35f8801515f87019061032b565b602087015185820360208701526103df565b946105d8604082015160408601906104ac565b6105ea606082015160c0860190610504565b6105fb608082015183860190610525565b61060e60a0820151610100860190610538565b61062160c082015161014086019061055c565b0151910190610584565b90565b6106439160208201915f818403910152610591565b90565b346106765761065636600461026e565b61067261066161253d565b6106696100d2565b9182918261062e565b0390f35b6100d8565b610684816104f7565b0361068b57565b5f80fd5b9050359061069c8261067b565b565b906020828203126106b7576106b4915f0161068f565b90565b6100dc565b346106ea576106d46106cf36600461069e565b612ab0565b6106dc6100d2565b806106e681610130565b0390f35b6100d8565b6106f88161031f565b036106ff57565b5f80fd5b90503590610710826106ef565b565b9060208282031261072b57610728915f01610703565b90565b6100dc565b3461075e57610748610743366004610712565b612f2c565b6107506100d2565b8061075a81610130565b0390f35b6100d8565b346107915761077336600461026e565b61077b613064565b6107836100d2565b8061078d81610130565b0390f35b6100d8565b346107c4576107ae6107a9366004610712565b61310b565b6107b66100d2565b806107c081610130565b0390f35b6100d8565b346107f7576107d936600461026e565b6107e161321e565b6107e96100d2565b806107f381610130565b0390f35b6100d8565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b90359060016020038136030382121561084e570180359067ffffffffffffffff82116108495760200191600182023603831361084457565b610808565b610804565b610800565b5090565b35610861816106ef565b90565b5f1c90565b60018060a01b031690565b61088061088591610864565b610869565b90565b6108929054610874565b90565b60209181520190565b5f7f756e617574686f72697a65640000000000000000000000000000000000000000910152565b6108d2600c602092610895565b6108db8161089e565b0190565b6108f49060208101905f8183039101526108c5565b90565b156108fe57565b6109066100d2565b62461bcd60e51b81528061091c600482016108df565b0390fd5b90565b61093761093261093c92610314565b610920565b610314565b90565b61094890610923565b90565b6109549061093f565b90565b906109619061094b565b5f5260205260405f2090565b90565b60ff1690565b61098261098791610864565b610970565b90565b6109949054610976565b90565b5f7f756e6b6e6f776e206f70657261746f7200000000000000000000000000000000910152565b6109cb6010602092610895565b6109d481610997565b0190565b6109ed9060208101905f8183039101526109be565b90565b156109f757565b6109ff6100d2565b62461bcd60e51b815280610a15600482016109d8565b0390fd5b60081c90565b60ff1690565b610a31610a3691610a19565b610a1f565b90565b610a439054610a25565b90565b634e487b7160e01b5f52603260045260245ffd5b5061010090565b90565b610a6d81610a5a565b821015610a8757610a7f600291610a61565b910201905f90565b610a46565b634e487b7160e01b5f525f60045260245ffd5b5f1b90565b90610ab560018060a01b0391610a9f565b9181191691161790565b90565b90610ad7610ad2610ade9261094b565b610abf565b8254610aa4565b9055565b634e487b7160e01b5f52604160045260245ffd5b634e487b7160e01b5f52602260045260245ffd5b9060016002830492168015610b2a575b6020831014610b2557565b610af6565b91607f1691610b1a565b5f5260205f2090565b601f602091010490565b1b90565b91906008610b66910291610b605f1984610b47565b92610b47565b9181191691161790565b610b84610b7f610b8992610454565b610920565b610454565b90565b90565b9190610ba5610ba0610bad93610b70565b610b8c565b908354610b4b565b9055565b5f90565b610bc791610bc1610bb1565b91610b8f565b565b5b818110610bd5575050565b80610be25f600193610bb5565b01610bca565b9190601f8111610bf8575b505050565b610c04610c2993610b34565b906020610c1084610b3d565b83019310610c31575b610c2290610b3d565b0190610bc9565b5f8080610bf3565b9150610c2281929050610c19565b1c90565b90610c53905f1990600802610c3f565b191690565b81610c6291610c43565b906002021790565b91610c759082610853565b9067ffffffffffffffff8211610d3457610c9982610c938554610b0a565b85610be8565b5f90601f8311600114610ccc57918091610cbb935f92610cc0575b5050610c58565b90555b565b90915001355f80610cb4565b601f19831691610cdb85610b34565b925f5b818110610d1c57509160029391856001969410610d02575b50505002019055610cbe565b610d12910135601f841690610c43565b90555f8080610cf6565b91936020600181928787013581550195019201610cde565b610ae2565b90610d449291610c6a565b565b90610d736001610d7993610d675f8201610d615f8701610857565b90610ac2565b0191602081019061080c565b91610d39565b565b9190610d8c57610d8a91610d46565b565b610a8c565b6fffffffffffffffffffffffffffffffff1690565b610db2610db791610864565b610d91565b90565b610dc49054610da6565b90565b634e487b7160e01b5f52601160045260245ffd5b610de49061056f565b6fffffffffffffffffffffffffffffffff8114610e015760010190565b610dc7565b90610e216fffffffffffffffffffffffffffffffff91610a9f565b9181191691161790565b610e3f610e3a610e449261056f565b610920565b61056f565b90565b90565b90610e5f610e5a610e6692610e2b565b610e47565b8254610e06565b9055565b50610e79906020810190610703565b90565b5f80fd5b5f80fd5b5f80fd5b9035600160200382360303811215610ec957016020813591019167ffffffffffffffff8211610ec4576001820236038313610ebf57565b610e80565b610e7c565b610e84565b90825f939282370152565b9190610ef381610eec81610ef89561034f565b8095610ece565b610363565b0190565b610f3891610f2a6040820192610f20610f175f830183610e6a565b5f85019061032b565b6020810190610e88565b916020818503910152610ed9565b90565b610f449061056f565b9052565b92916020610f64610f6c9360408701908782035f890152610efc565b940190610f3b565b565b610f8d610f88610f8283602081019061080c565b90610853565b613348565b33610faa610fa4610f9f5f8501610857565b61031f565b9161031f565b148015611075575b610fbb906108f7565b611011610fde610fd95f600101610fd35f8601610857565b90610957565b61096d565b610ff1610fec5f830161098a565b6109f0565b61100b83916110055f600180019201610a39565b90610a64565b90610d7b565b61102f61102761102261020c610dba565b610ddb565b61020c610e4a565b61103a61020c610dba565b7f5aab2c32b1e447db4dba1d2790fe8b863d4775042b10b92e00dab9d6b671b5b5916110706110676100d2565b92839283610f48565b0390a1565b50610fbb3361109461108e6110895f610888565b61031f565b9161031f565b149050610fb2565b5f7f6e6f7420746865206f776e657200000000000000000000000000000000000000910152565b6110d0600d602092610895565b6110d98161109c565b0190565b6110f29060208101905f8183039101526110c3565b90565b156110fc57565b6111046100d2565b62461bcd60e51b81528061111a600482016110dd565b0390fd5b9061114c916111473361114161113b6111365f610888565b61031f565b9161031f565b146110f5565b61147f565b565b151590565b5f7f616c726561647920657869737473000000000000000000000000000000000000910152565b611187600e602092610895565b61119081611153565b0190565b6111a99060208101905f81830391015261117a565b90565b156111b357565b6111bb6100d2565b62461bcd60e51b8152806111d160048201611194565b0390fd5b6111df9054610b0a565b90565b90565b6111f96111f46111fe926111e2565b610920565b610454565b90565b5f7f736c6f74206f6363757069656400000000000000000000000000000000000000910152565b611235600d602092610895565b61123e81611201565b0190565b6112579060208101905f818303910152611228565b90565b1561126157565b6112696100d2565b62461bcd60e51b81528061127f60048201611242565b0390fd5b9061128d90610363565b810190811067ffffffffffffffff8211176112a757604052565b610ae2565b906112bf6112b86100d2565b9283611283565b565b6112cb60406112ac565b90565b906112d89061114e565b9052565b906112e690610168565b9052565b6112f4905161114e565b90565b9061130360ff91610a9f565b9181191691161790565b6113169061114e565b90565b90565b9061133161132c6113389261130d565b611319565b82546112f7565b9055565b6113469051610168565b90565b60081b90565b9061135c61ff0091611349565b9181191691161790565b61137a61137561137f92610168565b610920565b610168565b90565b90565b9061139a6113956113a192611366565b611382565b825461134f565b9055565b906113cf60205f6113d5946113c78282016113c18488016112ea565b9061131c565b01920161133c565b90611385565b565b906113e1916113a5565b565b90565b6113f26113f791610864565b6113e3565b90565b61140490546113e6565b90565b906114135f1991610a9f565b9181191691161790565b9061143261142d61143992610b70565b610b8c565b8254611407565b9055565b61144690610168565b9052565b93929061147560409161147d9461146860608901925f8a019061143d565b8782036020890152610efc565b940190610f3b565b565b61149e61149961149384602081019061080c565b90610853565b613348565b6114d16114cc6114c65f6114c0816001016114ba838901610857565b90610957565b0161098a565b1561114e565b6111ac565b6115056114ed60016114e68180018590610a64565b50016111d5565b6114ff6114f95f6111e5565b91610454565b1461125a565b611548600161152b836115226115196112c1565b935f85016112ce565b602083016112dc565b6115435f60010161153d5f8701610857565b90610957565b6113d7565b6115608261155a600180018490610a64565b90610d7b565b61158661157b6115746102016001016113fa565b83906133d2565b61020160010161141d565b6115a461159c61159761020c610dba565b610ddb565b61020c610e4a565b906115b061020c610dba565b916115e77f952e65f049c574f487580ba41dcf6b0ea8350ef8abc8647a8a11dfaa7af6bad6936115de6100d2565b9384938461144a565b0390a1565b906115f69161111e565b565b611625906116203361161a61161461160f5f610888565b61031f565b9161031f565b146110f5565b6116a9565b565b5f7f6d6967726174696f6e20696e2070726f67726573730000000000000000000000910152565b61165b6015602092610895565b61166481611627565b0190565b61167d9060208101905f81830391015261164e565b90565b1561168757565b61168f6100d2565b62461bcd60e51b8152806116a560048201611668565b0390fd5b6116cb906116c66116c16116bb613401565b1561114e565b611680565b61174f565b565b5f7f6d61696e74656e616e636520696e2070726f6772657373000000000000000000910152565b6117016017602092610895565b61170a816116cd565b0190565b6117239060208101905f8183039101526116f4565b90565b1561172d57565b6117356100d2565b62461bcd60e51b81528061174b6004820161170e565b0390fd5b6117719061176c61176761176161342f565b1561114e565b611726565b611a66565b565b61177c81610454565b0361178357565b5f80fd5b3561179181611773565b90565b5f7f696e76616c6964206269746d61736b0000000000000000000000000000000000910152565b6117c8600f602092610895565b6117d181611794565b0190565b6117ea9060208101905f8183039101526117bb565b90565b156117f457565b6117fc6100d2565b62461bcd60e51b815280611812600482016117d5565b0390fd5b67ffffffffffffffff1690565b61182f61183491610864565b611816565b90565b6118419054611823565b90565b61184d906104f7565b67ffffffffffffffff81146118625760010190565b610dc7565b9061187a67ffffffffffffffff91610a9f565b9181191691161790565b61189861189361189d926104f7565b610920565b6104f7565b90565b90565b906118b86118b36118bf92611884565b6118a0565b8254611867565b9055565b90565b6118da6118d56118df926118c3565b610920565b6104f7565b90565b634e487b7160e01b5f52601260045260245ffd5b611902611908916104f7565b916104f7565b908115611913570690565b6118e2565b50600290565b90565b61192a81611918565b8210156119445761193c60029161191e565b910201905f90565b610a46565b356119538161016e565b90565b9061196b61196661197292611366565b611382565b82546112f7565b9055565b906119a1602060016119a7946119995f82016119935f8801611787565b9061141d565b019201611949565b90611956565b565b91906119ba576119b891611976565b565b610a8c565b6119c8906104f7565b9052565b905035906119d982611773565b565b506119ea9060208101906119cc565b90565b506119fc906020810190610182565b90565b906020611a2a611a3293611a21611a185f8301836119db565b5f860190610457565b828101906119ed565b910190610464565b565b606090611a5d611a649496959396611a5360808401985f8501906119bf565b60208301906119ff565b0190610f3b565b565b611a90611a8b611a775f8401611787565b611a856102016001016113fa565b90613464565b6117ed565b611aaf5f61020901611aa9611aa482611837565b611844565b906118a3565b611acd611ac5611ac0610207611837565b611844565b6102076118a3565b611b0181611afb610203611af5611ae5610207611837565b611aef60026118c6565b906118f6565b90611921565b906119a9565b611b1a611b0f5f8301611787565b60016102090161141d565b611b38611b30611b2b61020c610dba565b610ddb565b61020c610e4a565b611b455f61020901611837565b90611b5161020c610dba565b91611b887f490341fd8fc7a8294fbad1cc0db9f41ae0ac5aeb655ea31b46a475ec3a77749c93611b7f6100d2565b93849384611a34565b0390a1565b611b96906115f8565b565b5f7f6e6f206d61696e74656e616e6365000000000000000000000000000000000000910152565b611bcc600e602092610895565b611bd581611b98565b0190565b611bee9060208101905f818303910152611bbf565b90565b15611bf857565b611c006100d2565b62461bcd60e51b815280611c1660048201611bd9565b0390fd5b611c2a611c2561342f565b611bf1565b611c32611c71565b565b611c48611c43611c4d926111e2565b610920565b610314565b90565b611c5990611c34565b90565b9190611c6f905f60208501940190610f3b565b565b611c7e5f61020b01610888565b611c90611c8a3361031f565b9161031f565b148015611d1b575b611ca1906108f7565b611cb7611cad5f611c50565b5f61020b01610ac2565b611cd5611ccd611cc861020c610dba565b610ddb565b61020c610e4a565b611ce061020c610dba565b611d167f11943d6deda6f0591d72674788d272eb0209e18b8a3a021fa51cb3b5e9a2ab6191611d0d6100d2565b91829182611c5c565b0390a1565b50611ca133611d3a611d34611d2f5f610888565b61031f565b9161031f565b149050611c98565b611d4a611c1a565b565b611d7990611d7433611d6e611d68611d635f610888565b61031f565b9161031f565b146110f5565b611e78565b565b611d8481610511565b03611d8b57565b5f80fd5b35611d9981611d7b565b90565b90611da961ffff91610a9f565b9181191691161790565b611dc7611dc2611dcc92610511565b610920565b610511565b90565b90565b90611de7611de2611dee92611db3565b611dcf565b8254611d9c565b9055565b90611e045f80611e0a94019201611d8f565b90611dd2565b565b90611e1691611df2565b565b90503590611e2582611d7b565b565b50611e36906020810190611e18565b90565b905f611e4b611e539382810190611e27565b910190610518565b565b916020611e76929493611e6f60408201965f830190611e39565b0190610f3b565b565b611e8481610208611e0c565b611ea2611e9a611e9561020c610dba565b610ddb565b61020c610e4a565b611ead61020c610dba565b7fb24d8d9dcfbb6be13176c1c7bfb0e76445a9ba2a3553b413d8671446f103083091611ee3611eda6100d2565b92839283611e55565b0390a1565b611ef190611d4c565b565b611efe6101006112ac565b90565b5f90565b606090565b67ffffffffffffffff8111611f1f5760200290565b610ae2565b611f30611f3591611f0a565b6112ac565b90565b611f4260406112ac565b90565b5f90565b5f90565b611f55611f38565b9060208083611f62611f45565b815201611f6d611f49565b81525050565b611f7b611f4d565b90565b5f5b828110611f8c57505050565b602090611f97611f73565b8184015201611f80565b90611fbf611fae83611f24565b92611fb98491611f0a565b90611f7e565b565b611fcb6002611fa1565b90565b5f90565b611fdc60206112ac565b90565b5f90565b611feb611fd2565b90602082611ff7611fdf565b81525050565b612005611fe3565b90565b61201260406112ac565b90565b61201d612008565b906020808361202a611fce565b815201612035611f45565b81525050565b612043612015565b90565b61205060206112ac565b90565b61205b612046565b90602082612067611f01565b81525050565b612075612053565b90565b5f90565b612084611ef3565b9060208080808080808089612097611f01565b8152016120a2611f05565b8152016120ad611fc1565b8152016120b8611fce565b8152016120c3611ffd565b8152016120ce61203b565b8152016120d961206d565b8152016120e4612078565b81525050565b6120f261207c565b90565b90565b61210c612107612111926120f5565b610920565b610454565b90565b61212361212991939293610454565b92610454565b820180921161213457565b610dc7565b67ffffffffffffffff81116121515760208091020190565b610ae2565b9061216861216383612139565b6112ac565b918252565b61217760406112ac565b90565b606090565b61218761216d565b9060208083612194611f01565b81520161219f61217a565b81525050565b6121ad61217f565b90565b5f5b8281106121be57505050565b6020906121c96121a5565b81840152016121b2565b906121f86121e083612156565b926020806121ee8693612139565b92019103906121b0565b565b6122056101006112ac565b90565b906122129061031f565b9052565b52565b9061222390610454565b9052565b61223361223891610864565b610a1f565b90565b6122459054612227565b90565b9061227f6122766001612259611f38565b946122706122685f83016113fa565b5f8801612219565b0161223b565b602084016112dc565b565b61228a90612248565b90565b9061229782611918565b6122a081611f24565b926122ab849161191e565b5f915b8383106122bb5750505050565b600260206001926122cb85612281565b8152019201920191906122ae565b6122e29061228d565b90565b52565b906122f2906104f7565b9052565b61ffff1690565b61230961230e91610864565b6122f6565b90565b61231b90546122fd565b90565b9061232890610511565b9052565b9061234b6123435f61233c611fd2565b9401612311565b5f840161231e565b565b6123569061232c565b90565b52565b9061239361238a600161236d612008565b9461238461237c5f8301611837565b5f88016122e8565b016113fa565b60208401612219565b565b61239e9061235c565b90565b52565b906123c36123bb5f6123b4612046565b9401610888565b5f8401612208565b565b6123ce906123a4565b90565b52565b906123de9061056f565b9052565b6123eb90610454565b5f1981146123f95760010190565b610dc7565b61241261240d61241792610454565b610920565b610168565b90565b9061242482610338565b811015612435576020809102010190565b610a46565b905f929180549061245461244d83610b0a565b809461034f565b916001811690815f146124ab575060011461246f575b505050565b61247c9192939450610b34565b915f925b81841061249357505001905f808061246a565b60018160209295939554848601520191019290612480565b92949550505060ff19168252151560200201905f808061246a565b906124d09161243a565b90565b906124f36124ec926124e36100d2565b938480926124c6565b0383611283565b565b52565b9061252f612526600161250961216d565b946125206125185f8301610888565b5f8801612208565b016124d3565b602084016124f5565b565b61253a906124f8565b90565b6125456120ea565b50600161020101612555906113fa565b61255e9061348f565b6125675f610888565b816001612573906120f8565b61257c91612114565b612585906121d3565b610203612593610207611837565b6102086102099161020b936125a961020c610dba565b956125b26121fa565b975f8901906125c091612208565b60208801906125ce91612216565b6125d7906122d9565b60408701906125e5916122e5565b60608601906125f3916122e8565b6125fc9061234d565b608085019061260a91612359565b61261390612395565b60a0840190612621916123a1565b61262a906123c5565b60c0830190612638916123d1565b60e0820190612646916123d4565b600161020101612655906113fa565b925f612660906111e5565b5b8061267461266e86610454565b91610454565b116126d7576126cd906126908661268a836123fe565b906134a4565b6126d2576126c56126a5600180018390610a64565b5060208601516126b58492612531565b6126bf838361241a565b5261241a565b51505b6123e2565b612661565b6126c8565b509250905090565b5f7f6e6f206d6967726174696f6e0000000000000000000000000000000000000000910152565b612713600c602092610895565b61271c816126df565b0190565b6127359060208101905f818303910152612706565b90565b1561273f57565b6127476100d2565b62461bcd60e51b81528061275d60048201612720565b0390fd5b61277a90612775612770613401565b612738565b612910565b565b5f7f77726f6e67206d6967726174696f6e2069640000000000000000000000000000910152565b6127b06012602092610895565b6127b98161277c565b0190565b6127d29060208101905f8183039101526127a3565b90565b156127dc57565b6127e46100d2565b62461bcd60e51b8152806127fa600482016127bd565b0390fd5b61280860406112ac565b90565b906128416128385f61281b6127fe565b9461283261282a83830161098a565b8388016112ce565b01610a39565b602084016112dc565b565b61284c9061280b565b90565b5f7f6e6f742070756c6c696e67000000000000000000000000000000000000000000910152565b612883600b602092610895565b61288c8161284f565b0190565b6128a59060208101905f818303910152612876565b90565b156128af57565b6128b76100d2565b62461bcd60e51b8152806128cd60048201612890565b0390fd5b6128da9061031f565b9052565b60409061290761290e94969593966128fd60608401985f8501906119bf565b60208301906128d1565b0190610f3b565b565b6129389061293261292c6129275f61020901611837565b6104f7565b916104f7565b146127d5565b6129bd6129b261295461294f5f6001013390610957565b612843565b6129676129625f83016112ea565b6109f0565b61299261298d61297b6001610209016113fa565b6129876020850161133c565b906134e2565b6128a8565b6129ac60206129a56001610209016113fa565b920161133c565b90613521565b60016102090161141d565b6129db6129d36129ce61020c610dba565b610ddb565b61020c610e4a565b6129e96001610209016113fa565b6129fb6129f55f6111e5565b91610454565b145f14612a5857612a0f5f61020901611837565b33612a1b61020c610dba565b91612a527f01269879535f40ee8957e15e160bf1866c5e2728ff0cbc583d848821e2639b4e93612a496100d2565b938493846128de565b0390a15b565b612a655f61020901611837565b33612a7161020c610dba565b91612aa87faf5e90e72015f43138f66b4cd08bd1dfa2839030104f22a00af843fe847c6d1993612a9f6100d2565b938493846128de565b0390a1612a56565b612ab990612761565b565b612ae890612ae333612add612ad7612ad25f610888565b61031f565b9161031f565b146110f5565b612d89565b565b5f7f696e206b65797370616365000000000000000000000000000000000000000000910152565b612b1e600b602092610895565b612b2781612aea565b0190565b612b409060208101905f818303910152612b11565b90565b15612b4a57565b612b526100d2565b62461bcd60e51b815280612b6860048201612b2b565b0390fd5b5f80910155565b905f03612b8557612b8390612b6c565b565b610a8c565b90612b9d905f1990602003600802610c3f565b8154169055565b905f91612bbb612bb382610b34565b928354610c58565b905555565b919290602082105f14612c1957601f8411600114612be957612be3929350610c58565b90555b5b565b5090612c0f612c14936001612c06612c0085610b34565b92610b3d565b82019101610bc9565b612ba4565b612be6565b50612c508293612c2a600194610b34565b612c49612c3685610b3d565b820192601f861680612c5b575b50610b3d565b0190610bc9565b600202179055612be7565b612c6790888603612b8a565b5f612c43565b929091680100000000000000008211612ccd576020115f14612cbe57602081105f14612ca257612c9c91610c58565b90555b5b565b60019160ff1916612cb284610b34565b55600202019055612c9f565b60019150600202019055612ca0565b610ae2565b908154612cde81610b0a565b90818311612d07575b818310612cf5575b50505050565b612cfe93612bc0565b5f808080612cef565b612d1383838387612c6d565b612ce7565b5f612d2291612cd2565b565b905f03612d3657612d3490612d18565b565b610a8c565b5f6001612d4d92828082015501612d24565b565b905f03612d6157612d5f90612d3b565b565b610a8c565b916020612d87929493612d8060408201965f8301906128d1565b0190610f3b565b565b612e4e612e43612dc25f612da9612da4826001018790610957565b61096d565b612dbc612db783830161098a565b6109f0565b01610a39565b612dca613401565b5f14612ee057612df2612deb5f612de46102038290611921565b50016113fa565b82906134a4565b80612eb2575b612e0190612b43565b5b612e195f612e14816001018790610957565b612b73565b612e30612e2a600180018390610a64565b90612d4f565b612e3e6102016001016113fa565b613521565b61020160010161141d565b612e6c612e64612e5f61020c610dba565b610ddb565b61020c610e4a565b612e7761020c610dba565b7f6a1d7ddc82d57e783a3ae60737a6c1a4704fcf38d966561fea0af8564f2d895d91612ead612ea46100d2565b92839283612d66565b0390a1565b50612e01612ed9612ed25f612ecb610203600190611921565b50016113fa565b83906134a4565b9050612df8565b612f27612f22612f1b5f612f14610203612f0e612efe610207611837565b612f0860026118c6565b906118f6565b90611921565b50016113fa565b83906134a4565b612b43565b612e02565b612f3590612abb565b565b612f5b33612f55612f4f612f4a5f610888565b61031f565b9161031f565b146110f5565b612f63612f65565b565b612f75612f70613401565b612738565b612f7d612fbe565b565b612f88906104f7565b5f8114612f96576001900390565b610dc7565b916020612fbc929493612fb560408201965f8301906119bf565b0190610f3b565b565b612fdc612fd4612fcf610207611837565b612f7f565b6102076118a3565b612ff3612fe85f6111e5565b60016102090161141d565b61301161300961300461020c610dba565b610ddb565b61020c610e4a565b61301e5f61020901611837565b61302961020c610dba565b7ff73240422246f63ed633ef3ce0726b8ab8fb69d46c8a4e5ecb0b2922668674a19161305f6130566100d2565b92839283612f9b565b0390a1565b61306c612f37565b565b61309b906130963361309061308a6130855f610888565b61031f565b9161031f565b146110f5565b61309d565b565b6130a7815f610ac2565b6130c56130bd6130b861020c610dba565b610ddb565b61020c610e4a565b6130d061020c610dba565b7f476610ebc6647c15376100955efbf22ef2a0c3b923fc00b380b660c873ef20ac916131066130fd6100d2565b92839283612d66565b0390a1565b6131149061306e565b565b61312f61312a613124613401565b1561114e565b611680565b613137613139565b565b61315261314d61314761342f565b1561114e565b611726565b61315a61315c565b565b6131745f61316e816001013390610957565b0161098a565b80156131f7575b613184906108f7565b613192335f61020b01610ac2565b6131b06131a86131a361020c610dba565b610ddb565b61020c610e4a565b336131bc61020c610dba565b7fbc2748cf02f7a1291525e866efc76ab3b96d32d7afcbb26c53daec617b38b479916131f26131e96100d2565b92839283612d66565b0390a1565b506131843361321661321061320b5f610888565b61031f565b9161031f565b14905061317b565b613226613116565b565b5f7f656d707479206f70657261746f72206461746100000000000000000000000000910152565b61325c6013602092610895565b61326581613228565b0190565b61327e9060208101905f81830391015261324f565b90565b1561328857565b6132906100d2565b62461bcd60e51b8152806132a660048201613269565b0390fd5b6132be6132b96132c392610511565b610920565b610454565b90565b5f7f6f70657261746f72206461746120746f6f206c61726765000000000000000000910152565b6132fa6017602092610895565b613303816132c6565b0190565b61331c9060208101905f8183039101526132ed565b90565b1561332657565b61332e6100d2565b62461bcd60e51b81528061334460048201613307565b0390fd5b61338d906133688161336261335c5f6111e5565b91610454565b11613281565b61338661338061337b5f61020801612311565b6132aa565b91610454565b111561331f565b565b6133a361339e6133a892610168565b610920565b610454565b90565b6133ca906133c46133be6133cf94610454565b91610454565b90610b47565b610454565b90565b6133f9906133de610bb1565b50916133f46133ee60019261338f565b916120f8565b6133ab565b1790565b5f90565b6134096133fd565b506134186001610209016113fa565b61342a6134245f6111e5565b91610454565b141590565b6134376133fd565b506134455f61020b01610888565b61345f6134596134545f611c50565b61031f565b9161031f565b141590565b613478906134706133fd565b509119610454565b1661348b6134855f6111e5565b91610454565b1490565b6134a19061349b610bb1565b50613714565b90565b6134cb906134b06133fd565b50916134c66134c060019261338f565b916120f8565b6133ab565b166134de6134d85f6111e5565b91610454565b1490565b613509906134ee6133fd565b50916135046134fe60019261338f565b916120f8565b6133ab565b1661351c6135165f6111e5565b91610454565b141590565b61354b61355191613530610bb1565b509261354661354060019261338f565b916120f8565b6133ab565b19610454565b1690565b90565b61356c61356761357192613555565b610920565b610454565b90565b90565b61358b61358661359092613574565b610920565b610168565b90565b6135b2906135ac6135a66135b794610168565b91610454565b90610b47565b610454565b90565b6135d9906135d36135cd6135de94610454565b91610454565b90610c3f565b610454565b90565b90565b6135f86135f36135fd926135e1565b610920565b610454565b90565b90565b61361761361261361c92613600565b610920565b610168565b90565b90565b61363661363161363b9261361f565b610920565b610454565b90565b90565b61365561365061365a9261363e565b610920565b610168565b90565b90565b61367461366f6136799261365d565b610920565b610454565b90565b90565b61369361368e6136989261367c565b610920565b610168565b90565b90565b6136b26136ad6136b79261369b565b610920565b610454565b90565b90565b6136d16136cc6136d6926136ba565b610920565b610168565b90565b90565b6136f06136eb6136f5926136d9565b610920565b610454565b90565b61370c613707613711926118c3565b610920565b610168565b90565b61371c610bb1565b5061375c61374c826137466137406fffffffffffffffffffffffffffffffff613558565b91610454565b116138a9565b6137566007613577565b90613593565b61379d61378d61376d8484906135ba565b61378761378167ffffffffffffffff6135e4565b91610454565b116138a9565b6137976006613603565b90613593565b176137db6137cb6137af8484906135ba565b6137c56137bf63ffffffff613622565b91610454565b116138a9565b6137d56005613641565b90613593565b176138176138076137ed8484906135ba565b6138016137fb61ffff613660565b91610454565b116138a9565b613811600461367f565b90613593565b176138526138426138298484906135ba565b61383c61383660ff61369e565b91610454565b116138a9565b61384c60036136bd565b90613593565b1761388d61387d6138648484906135ba565b613877613871600f6136dc565b91610454565b116138a9565b61388760026136f8565b90613593565b17906d010102020202030303030303030360801b90821c1a1790565b6138b1610bb1565b5015159056fea264697066735822122015abc4566b5a4eece53e06dab0721de14be34963877d9977ca41a88371cca70b64736f6c634300081c0033","sourceMap":"993:7199:24:-:0;;;;;;;;;-1:-1:-1;993:7199:24;:::i;:::-;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;;;:::o;:::-;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;:::i;:::-;;;;:::o;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;:::o;:::-;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;:::i;:::-;;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;:::o;:::-;;;;;;;:::o;:::-;;;;:::o;:::-;;;:::o;:::-;;;;;;;:::o;:::-;;;;;;;;;;:::o;:::-;;;;;;;;:::o;:::-;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;;;;;;:::o;:::-;;;;:::o;:::-;;:::o;:::-;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;:::o;:::-;;;;;;;:::i;:::-;;;:::o;:::-;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;;;;:::o;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;;;:::i;:::-;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;;;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;:::o;:::-;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;:::o;:::-;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;:::o;:::-;;:::o;:::-;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;:::o;:::-;;;;;;;:::o;:::-;;;:::o;:::-;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;:::i;:::-;;;;;:::i;:::-;;;:::o;:::-;;;:::o;:::-;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;;;;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;:::o;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;:::i;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;;;;:::i;:::-;:::o;:::-;;:::i;:::-;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;;;;;;;;;:::o;:::-;;;;;;;;;;:::i;:::-;;;;:::i;:::-;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;:::o;5247:469::-;5351:20;;:13;:8;:13;;;;;:::i;:::-;:20;;:::i;:::-;;:::i;:::-;5390:10;:27;;5404:13;;:8;:13;;:::i;:::-;5390:27;:::i;:::-;;;:::i;:::-;;:50;;;;5247:469;5382:75;;;:::i;:::-;5596:41;5468:59;5491:36;:21;:13;:21;5513:13;;:8;:13;;:::i;:::-;5491:36;;:::i;:::-;5468:59;:::i;:::-;5537:40;5545:11;;:3;:11;;:::i;:::-;5537:40;:::i;:::-;5596:30;5629:8;5596:13;5616:9;;5596:19;:13;:19;5616:3;:9;;:::i;:::-;5596:30;;:::i;:::-;:41;;:::i;:::-;5647:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;5701:7;;;:::i;:::-;5671:38;;;;;:::i;:::-;;;;;;:::i;:::-;;;;5247:469::o;5390:50::-;5421:10;5382:75;5421:10;:19;;5435:5;;;:::i;:::-;5421:19;:::i;:::-;;;:::i;:::-;;5390:50;;;;993:7199;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;2121:94;;2207:1;2121:94;2152:45;2160:10;:19;;2174:5;;;:::i;:::-;2160:19;:::i;:::-;;;:::i;:::-;;2152:45;:::i;:::-;2207:1;:::i;:::-;2121:94::o;993:7199::-;;;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;:::i;:::-;;;;:::i;:::-;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;:::i;:::-;:::o;:::-;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;:::i;:::-;:::o;4649:592::-;4771:20;;:13;:8;:13;;;;;:::i;:::-;:20;;:::i;:::-;;:::i;:::-;4802:72;4810:45;4811:44;;:36;:13;;:21;4833:13;:8;;:13;;:::i;:::-;4811:36;;:::i;:::-;:44;;:::i;:::-;4810:45;;:::i;:::-;4802:72;:::i;:::-;4884:67;4892:36;:29;:24;:13;;:19;4912:3;4892:24;;:::i;:::-;;:29;:36;:::i;:::-;:41;;4932:1;4892:41;:::i;:::-;;;:::i;:::-;;4884:67;:::i;:::-;4970:78;5029:4;5009:39;5042:3;5009:39;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::i;:::-;4970:36;:21;:13;:21;4992:13;;:8;:13;;:::i;:::-;4970:36;;:::i;:::-;:78;:::i;:::-;5058:35;5085:8;5058:24;:19;:13;:19;5078:3;5058:24;;:::i;:::-;:35;;:::i;:::-;5103:55;5127:31;:21;;:13;:21;;:::i;:::-;5154:3;5127:31;;:::i;:::-;5103:21;:13;:21;:55;:::i;:::-;5169:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;5216:8;5226:7;;;:::i;:::-;5193:41;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;4649:592::o;:::-;;;;;:::i;:::-;:::o;2121:94::-;2207:1;2121:94;2152:45;2160:10;:19;;2174:5;;;:::i;:::-;2160:19;:::i;:::-;;;:::i;:::-;;2152:45;:::i;:::-;2207:1;:::i;:::-;2121:94::o;993:7199::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;2327:109;2428:1;2327:109;2360:58;2368:24;2369:23;;:::i;:::-;2368:24;;:::i;:::-;2360:58;:::i;:::-;2428:1;:::i;:::-;2327:109::o;993:7199::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;2554:115;2661:1;2554:115;2589:62;2597:26;2598:25;;:::i;:::-;2597:26;;:::i;:::-;2589:62;:::i;:::-;2661:1;:::i;:::-;2554:115::o;993:7199::-;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;:::o;:::-;;:::i;:::-;;;;:::o;:::-;;:::o;:::-;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;:::o;:::-;;:::i;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;;;;:::i;:::-;:::o;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;:::i;:::-;:::o;2675:480::-;2785:90;2793:62;:28;;:11;:28;;:::i;:::-;2833:21;;:13;:21;;:::i;:::-;2793:62;;:::i;:::-;2785:90;:::i;:::-;2890:14;:12;:9;:12;:14;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;2915:17;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;2942:44;2975:11;2942:30;:9;2952:19;:15;;;:::i;:::-;:19;2970:1;2952:19;:::i;:::-;;;:::i;:::-;2942:30;;:::i;:::-;:44;;:::i;:::-;2997:64;3033:28;;:11;:28;;:::i;:::-;2997:33;:9;:33;:64;:::i;:::-;3072:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;3113:12;;:9;:12;;:::i;:::-;3127:11;3140:7;;;:::i;:::-;3096:52;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;2675:480::o;:::-;;;;:::i;:::-;:::o;993:7199::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;2442:106;2478:52;2486:25;;:::i;:::-;2478:52;:::i;:::-;2540:1;;:::i;:::-;2442:106::o;993:7199::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;:::i;:::-;:::o;4392:251::-;4463:16;;:11;:16;;:::i;:::-;:30;;4483:10;4463:30;:::i;:::-;;;:::i;:::-;;:53;;;;4392:251;4455:78;;;:::i;:::-;4544:29;4563:10;4571:1;4563:10;:::i;:::-;4544:16;:11;:16;:29;:::i;:::-;4584:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;4628:7;;;:::i;:::-;4608:28;;;;;:::i;:::-;;;;;;:::i;:::-;;;;4392:251::o;4463:53::-;4497:10;4455:78;4497:10;:19;;4511:5;;;:::i;:::-;4497:19;:::i;:::-;;;:::i;:::-;;4463:53;;;;4392:251;;;:::i;:::-;:::o;2121:94::-;2207:1;2121:94;2152:45;2160:10;:19;;2174:5;;;:::i;:::-;2160:19;:::i;:::-;;;:::i;:::-;;2152:45;:::i;:::-;2207:1;:::i;:::-;2121:94::o;993:7199::-;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;:::i;:::-;:::o;:::-;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;:::o;6514:184::-;6598:22;6609:11;6598:22;;:::i;:::-;6630:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;6683:7;;;:::i;:::-;6654:37;;;;;:::i;:::-;;;;;;:::i;:::-;;;;6514:184::o;:::-;;;;:::i;:::-;:::o;993:7199::-;;;;:::i;:::-;;:::o;:::-;;;:::o;:::-;;;:::o;:::-;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;:::o;:::-;;;:::o;:::-;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::o;:::-;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;:::o;:::-;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;:::o;:::-;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::o;:::-;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::o;:::-;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::o;:::-;;;:::i;:::-;;:::o;:::-;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::o;:::-;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;:::i;:::-;;:::i;:::-;;;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;:::o;:::-;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::o;:::-;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;:::o;:::-;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;;;;:::o;:::-;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;:::i;:::-;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;:::i;:::-;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;:::i;:::-;;:::o;6880:845::-;6920:18;;:::i;:::-;6975:13;;:21;;;;;:::i;:::-;:32;;;:::i;:::-;7088:5;;;:::i;:::-;7145:14;7162:1;7145:18;;;:::i;:::-;;;;:::i;:::-;7126:38;;;:::i;:::-;7189:9;7229:15;;;:::i;:::-;7268:8;7301:9;7337:11;;7371:7;;;;:::i;:::-;7055:334;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;7431:13;:21;;;;;:::i;:::-;7480:1;;7468:13;;;:::i;:::-;7504:3;7483:1;:19;;7488:14;7483:19;:::i;:::-;;;:::i;:::-;;;;7504:3;7527:20;:34;:20;7552:8;7558:1;7552:8;:::i;:::-;7527:34;;:::i;:::-;7523:81;;7618:57;7653:22;:19;:13;:19;7673:1;7653:22;;:::i;:::-;;7618:29;:11;:29;;:57;7648:1;7618:57;;:::i;:::-;;;;;:::i;:::-;;;:::i;:::-;;;7468:13;7504:3;:::i;:::-;7468:13;;7523:81;7581:8;;7483:19;;;;;;7700:18;:::o;993:7199::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;2221:100;2313:1;2221:100;2255:48;2263:23;;:::i;:::-;2255:48;:::i;:::-;2313:1;:::i;:::-;2221:100::o;993:7199::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;:::i;:::-;:::o;3161:709::-;3231:49;3161:709;3239:18;;3245:12;;:9;:12;;:::i;:::-;3239:18;:::i;:::-;;;:::i;:::-;;3231:49;:::i;:::-;3513:93;3549:57;3291:63;3321:33;:21;:13;:21;3343:10;3321:33;;:::i;:::-;3291:63;:::i;:::-;3364:48;3372:19;;:11;:19;;:::i;:::-;3364:48;:::i;:::-;3422:80;3430:56;:33;;:9;:33;;:::i;:::-;3468:17;;:11;:17;;:::i;:::-;3430:56;;:::i;:::-;3422:80;:::i;:::-;3588:17;;3549:33;;:9;:33;;:::i;:::-;3588:11;:17;;:::i;:::-;3549:57;;:::i;:::-;3513:33;:9;:33;:93;:::i;:::-;3621:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;3644:33;;:9;:33;;:::i;:::-;:38;;3681:1;3644:38;:::i;:::-;;;:::i;:::-;;3640:224;;;;3722:12;;:9;:12;;:::i;:::-;3736:10;3748:7;;;:::i;:::-;3703:53;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;3640:224;3161:709::o;3640:224::-;3819:12;;:9;:12;;:::i;:::-;3833:10;3845:7;;;:::i;:::-;3792:61;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;3640:224;;3161:709;;;;:::i;:::-;:::o;2121:94::-;2207:1;2121:94;2152:45;2160:10;:19;;2174:5;;;:::i;:::-;2160:19;:::i;:::-;;;:::i;:::-;;2152:45;:::i;:::-;2207:1;:::i;:::-;2121:94::o;993:7199::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;;;:::o;:::-;;;;;;;;;:::i;:::-;:::o;:::-;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;:::o;:::-;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;:::o;:::-;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;-1:-1:-1;993:7199:24;;;;;;;;;;;;;;:::i;:::-;;;;;:::o;:::-;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;:::o;:::-;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;:::i;:::-;:::o;:::-;;:::i;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;:::i;:::-;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;:::o;5722:786::-;6366:55;6390:31;5945:13;;5804:65;5831:38;:13;;:21;5853:15;5831:38;;:::i;:::-;5804:65;:::i;:::-;5879:44;5887:15;:7;;:15;;:::i;:::-;5879:44;:::i;:::-;5945:13;;:::i;:::-;5973:23;;:::i;:::-;5969:281;;;;6032:38;:29;;:12;:9;6042:1;6032:12;;:::i;:::-;;:29;;:::i;:::-;6066:3;6032:38;;:::i;:::-;:80;;;5969:281;6024:104;;;:::i;:::-;5969:281;6268:46;;6275:38;:13;;:21;6297:15;6275:38;;:::i;:::-;6268:46;:::i;:::-;6324:32;6331:24;:19;:13;:19;6351:3;6331:24;;:::i;:::-;6324:32;;:::i;:::-;6390:21;;:13;:21;;:::i;:::-;:31;:::i;:::-;6366:21;:13;:21;:55;:::i;:::-;6432:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;6493:7;;;:::i;:::-;6456:45;;;;;:::i;:::-;;;;;;:::i;:::-;;;;5722:786::o;6032:80::-;6074:9;6024:104;6074:38;:29;;:12;:9;6084:1;6074:12;;:::i;:::-;;:29;;:::i;:::-;6108:3;6074:38;;:::i;:::-;6032:80;;;;5969:281;6159:80;6167:56;:47;;:30;:9;6177:19;:15;;;:::i;:::-;:19;6195:1;6177:19;:::i;:::-;;;:::i;:::-;6167:30;;:::i;:::-;;:47;;:::i;:::-;6219:3;6167:56;;:::i;:::-;6159:80;:::i;:::-;5969:281;;5722:786;;;;:::i;:::-;:::o;2121:94::-;2152:45;2160:10;:19;;2174:5;;;:::i;:::-;2160:19;:::i;:::-;;;:::i;:::-;;2152:45;:::i;:::-;2207:1;;:::i;:::-;2121:94::o;2221:100::-;2255:48;2263:23;;:::i;:::-;2255:48;:::i;:::-;2313:1;;:::i;:::-;2221:100::o;993:7199::-;;;;:::i;:::-;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;:::o;3876:213::-;3944:17;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;3971:37;;4007:1;3971:37;:::i;:::-;:33;:9;:33;:37;:::i;:::-;4019:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;4060:12;;:9;:12;;:::i;:::-;4074:7;;;:::i;:::-;4043:39;;;;;:::i;:::-;;;;;;:::i;:::-;;;;3876:213::o;:::-;;;:::i;:::-;:::o;2121:94::-;2207:1;2121:94;2152:45;2160:10;:19;;2174:5;;;:::i;:::-;2160:19;:::i;:::-;;;:::i;:::-;;2152:45;:::i;:::-;2207:1;:::i;:::-;2121:94::o;6704:170::-;6778:16;6786:8;6778:16;;:::i;:::-;6804:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;6859:7;;;:::i;:::-;6828:39;;;;;:::i;:::-;;;;;;:::i;:::-;;;;6704:170::o;:::-;;;;:::i;:::-;:::o;2327:109::-;2360:58;2368:24;2369:23;;:::i;:::-;2368:24;;:::i;:::-;2360:58;:::i;:::-;2428:1;;:::i;:::-;2327:109::o;2554:115::-;2589:62;2597:26;2598:25;;:::i;:::-;2597:26;;:::i;:::-;2589:62;:::i;:::-;2661:1;;:::i;:::-;2554:115::o;4095:291::-;4176:41;;:33;:13;;:21;4198:10;4176:33;;:::i;:::-;:41;;:::i;:::-;:64;;;;4095:291;4168:89;;;:::i;:::-;4276:29;4295:10;4276:16;:11;:16;:29;:::i;:::-;4316:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;4359:10;4371:7;;;:::i;:::-;4340:39;;;;;:::i;:::-;;;;;;:::i;:::-;;;;4095:291::o;4176:64::-;4221:10;4168:89;4221:10;:19;;4235:5;;;:::i;:::-;4221:19;:::i;:::-;;;:::i;:::-;;4176:64;;;;4095:291;;;:::i;:::-;:::o;993:7199::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;7731:205;7855:74;7731:205;7804:41;7812:5;:9;;7820:1;7812:9;:::i;:::-;;;:::i;:::-;;7804:41;:::i;:::-;7863:38;;7872:29;;:8;:29;;:::i;:::-;7863:38;:::i;:::-;;;:::i;:::-;;;7855:74;:::i;:::-;7731:205::o;993:7199::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;:::i;:::-;;:::o;8992:122::-;9092:15;8992:122;9055:7;;:::i;:::-;9082;9092:1;:15;9097:10;9092:1;9105;9097:10;:::i;:::-;9092:15;;:::i;:::-;;:::i;:::-;9082:25;9075:32;:::o;993:7199::-;;;:::o;7942:124::-;7998:4;;:::i;:::-;8021:9;:33;;:9;:33;;:::i;:::-;:38;;8058:1;8021:38;:::i;:::-;;;:::i;:::-;;;8014:45;:::o;8072:118::-;8130:4;;:::i;:::-;8153:11;:16;;:11;:16;;:::i;:::-;:30;;8173:10;8181:1;8173:10;:::i;:::-;8153:30;:::i;:::-;;;:::i;:::-;;;8146:37;:::o;9820:120::-;9922:6;9820:120;9892:4;;:::i;:::-;9915;9923:5;9922:6;;:::i;:::-;9915:13;:18;;9932:1;9915:18;:::i;:::-;;;:::i;:::-;;9908:25;:::o;9701:113::-;9785:18;9701:113;9759:7;;:::i;:::-;9795;9785:18;:::i;:::-;9778:25;:::o;9384:127::-;9482:15;9384:127;9446:4;;:::i;:::-;9471:7;9482:1;:15;9487:10;9482:1;9495;9487:10;:::i;:::-;9482:15;;:::i;:::-;;:::i;:::-;9471:27;9470:34;;9503:1;9470:34;:::i;:::-;;;:::i;:::-;;9463:41;:::o;9251:127::-;9349:15;9251:127;9313:4;;:::i;:::-;9338:7;9349:1;:15;9354:10;9349:1;9362;9354:10;:::i;:::-;9349:15;;:::i;:::-;;:::i;:::-;9338:27;9337:34;;9370:1;9337:34;:::i;:::-;;;:::i;:::-;;;9330:41;:::o;9120:125::-;9222:15;9220:18;9120:125;9183:7;;:::i;:::-;9210;9222:1;:15;9227:10;9222:1;9235;9227:10;:::i;:::-;9222:15;;:::i;:::-;;:::i;:::-;9220:18;;:::i;:::-;9210:28;9203:35;:::o;993:7199::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;26222:2393:21:-;26270:9;;:::i;:::-;26383:1;26367:60;:55;26383:1;:38;;26387:34;26383:38;:::i;:::-;;;:::i;:::-;;26367:55;:::i;:::-;:60;26426:1;26367:60;:::i;:::-;;;:::i;:::-;26508:51;:46;26525:6;:1;26530;26525:6;;:::i;:::-;26524:29;;26535:18;26524:29;:::i;:::-;;;:::i;:::-;;26508:46;:::i;:::-;:51;26558:1;26508:51;:::i;:::-;;;:::i;:::-;26503:56;26639:43;:38;26656:6;:1;26661;26656:6;;:::i;:::-;26655:21;;26666:10;26655:21;:::i;:::-;;;:::i;:::-;;26639:38;:::i;:::-;:43;26681:1;26639:43;:::i;:::-;;;:::i;:::-;26634:48;26762:39;:34;26779:6;:1;26784;26779:6;;:::i;:::-;26778:17;;26789:6;26778:17;:::i;:::-;;;:::i;:::-;;26762:34;:::i;:::-;:39;26800:1;26762:39;:::i;:::-;;;:::i;:::-;26757:44;26879:37;:32;26896:6;:1;26901;26896:6;;:::i;:::-;26895:15;;26906:4;26895:15;:::i;:::-;;;:::i;:::-;;26879:32;:::i;:::-;:37;26915:1;26879:37;:::i;:::-;;;:::i;:::-;26874:42;26993:36;:31;27010:6;:1;27015;27010:6;;:::i;:::-;27009:14;;27020:3;27009:14;:::i;:::-;;;:::i;:::-;;26993:31;:::i;:::-;:36;27028:1;26993:36;:::i;:::-;;;:::i;:::-;26988:41;28465:144;;;;;;;;;26222:2393;:::o;34795:145:22:-;34842:9;;:::i;:::-;34863:71;;;34795:145;:::o","linkReferences":{}},"methodIdentifiers":{"abortMigration()":"c130809a","addNodeOperator(uint8,(address,bytes))":"2b726062","completeMigration(uint64)":"9d44e717","finishMaintenance()":"53bfb584","getView()":"75418b9d","removeNodeOperator(address)":"c05665dd","startMaintenance()":"f5f2d9f1","startMigration((uint256,uint8))":"47011c5c","transferOwnership(address)":"f2fde38b","updateNodeOperator((address,bytes))":"26322217","updateSettings((uint16))":"65706f9c"},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.28+commit.7893614a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"components\":[{\"internalType\":\"uint16\",\"name\":\"maxOperatorDataBytes\",\"type\":\"uint16\"}],\"internalType\":\"struct Settings\",\"name\":\"initialSettings\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"struct NodeOperator[]\",\"name\":\"initialOperators\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"MaintenanceFinished\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"MaintenanceStarted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"MigrationAborted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"operatorAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"MigrationCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"operatorAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"MigrationDataPullCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"operatorsBitmask\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"replicationStrategy\",\"type\":\"uint8\"}],\"indexed\":false,\"internalType\":\"struct Keyspace\",\"name\":\"newKeyspace\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"MigrationStarted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"idx\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"struct NodeOperator\",\"name\":\"operator\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"NodeOperatorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"operatorAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"NodeOperatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"struct NodeOperator\",\"name\":\"operator\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"NodeOperatorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"cluserVersion\",\"type\":\"uint128\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint16\",\"name\":\"maxOperatorDataBytes\",\"type\":\"uint16\"}],\"indexed\":false,\"internalType\":\"struct Settings\",\"name\":\"newSettings\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"SettingsUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"abortMigration\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"idx\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"struct NodeOperator\",\"name\":\"operator\",\"type\":\"tuple\"}],\"name\":\"addNodeOperator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"}],\"name\":\"completeMigration\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"finishMaintenance\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getView\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"struct NodeOperator[]\",\"name\":\"nodeOperatorSlots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"operatorsBitmask\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"replicationStrategy\",\"type\":\"uint8\"}],\"internalType\":\"struct Keyspace[2]\",\"name\":\"keyspaces\",\"type\":\"tuple[2]\"},{\"internalType\":\"uint64\",\"name\":\"keyspaceVersion\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint16\",\"name\":\"maxOperatorDataBytes\",\"type\":\"uint16\"}],\"internalType\":\"struct Settings\",\"name\":\"settings\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"pullingOperatorsBitmask\",\"type\":\"uint256\"}],\"internalType\":\"struct Migration\",\"name\":\"migration\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"slot\",\"type\":\"address\"}],\"internalType\":\"struct Maintenance\",\"name\":\"maintenance\",\"type\":\"tuple\"},{\"internalType\":\"uint128\",\"name\":\"version\",\"type\":\"uint128\"}],\"internalType\":\"struct ClusterView\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operatorAddress\",\"type\":\"address\"}],\"name\":\"removeNodeOperator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startMaintenance\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"operatorsBitmask\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"replicationStrategy\",\"type\":\"uint8\"}],\"internalType\":\"struct Keyspace\",\"name\":\"newKeyspace\",\"type\":\"tuple\"}],\"name\":\"startMigration\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"struct NodeOperator\",\"name\":\"operator\",\"type\":\"tuple\"}],\"name\":\"updateNodeOperator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint16\",\"name\":\"maxOperatorDataBytes\",\"type\":\"uint16\"}],\"internalType\":\"struct Settings\",\"name\":\"newSettings\",\"type\":\"tuple\"}],\"name\":\"updateSettings\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/Cluster.sol\":\"Cluster\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[\":@openzeppelin-contracts-5.3.0/=dependencies/@openzeppelin-contracts-5.3.0/\",\":forge-std-1.9.7/=dependencies/forge-std-1.9.7/src/\",\":forge-std/=dependencies/forge-std/src/\",\":openzeppelin-contracts/=dependencies/@openzeppelin-contracts-5.3.0/\"],\"viaIR\":true},\"sources\":{\"dependencies/openzeppelin-contracts/utils/Panic.sol\":{\"keccak256\":\"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a\",\"dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG\"]},\"dependencies/openzeppelin-contracts/utils/math/Math.sol\":{\"keccak256\":\"0x1225214420c83ebcca88f2ae2b50f053aaa7df7bd684c3e878d334627f2edfc6\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6c5fab4970634f9ab9a620983dc1c8a30153981a0b1a521666e269d0a11399d3\",\"dweb:/ipfs/QmVRnBC575MESGkEHndjujtR7qub2FzU9RWy9eKLp4hPZB\"]},\"dependencies/openzeppelin-contracts/utils/math/SafeCast.sol\":{\"keccak256\":\"0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b1d578337048cad08c1c03041cca5978eff5428aa130c781b271ad9e5566e1f8\",\"dweb:/ipfs/QmPFKL2r9CBsMwmUqqdcFPfHZB2qcs9g1HDrPxzWSxomvy\"]},\"src/Cluster.sol\":{\"keccak256\":\"0x8ade3b168437cafe86f09cb2c71514eb497e9e25b9f9b836497e05942427217b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://1a4141701f07e7ccd86e1573762adfd8dd292eb286ce6a113d7baae6bbc9f087\",\"dweb:/ipfs/QmYGCqntKqzcfeCnDx667mgQn9vVYKXFokJvt8Kp2Lycxn\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.28+commit.7893614a"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"struct Settings","name":"initialSettings","type":"tuple","components":[{"internalType":"uint16","name":"maxOperatorDataBytes","type":"uint16"}]},{"internalType":"struct NodeOperator[]","name":"initialOperators","type":"tuple[]","components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}]}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"MaintenanceFinished","anonymous":false},{"inputs":[{"internalType":"address","name":"addr","type":"address","indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"MaintenanceStarted","anonymous":false},{"inputs":[{"internalType":"uint64","name":"id","type":"uint64","indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"MigrationAborted","anonymous":false},{"inputs":[{"internalType":"uint64","name":"id","type":"uint64","indexed":false},{"internalType":"address","name":"operatorAddress","type":"address","indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"MigrationCompleted","anonymous":false},{"inputs":[{"internalType":"uint64","name":"id","type":"uint64","indexed":false},{"internalType":"address","name":"operatorAddress","type":"address","indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"MigrationDataPullCompleted","anonymous":false},{"inputs":[{"internalType":"uint64","name":"id","type":"uint64","indexed":false},{"internalType":"struct Keyspace","name":"newKeyspace","type":"tuple","components":[{"internalType":"uint256","name":"operatorsBitmask","type":"uint256"},{"internalType":"uint8","name":"replicationStrategy","type":"uint8"}],"indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"MigrationStarted","anonymous":false},{"inputs":[{"internalType":"uint8","name":"idx","type":"uint8","indexed":false},{"internalType":"struct NodeOperator","name":"operator","type":"tuple","components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"NodeOperatorAdded","anonymous":false},{"inputs":[{"internalType":"address","name":"operatorAddress","type":"address","indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"NodeOperatorRemoved","anonymous":false},{"inputs":[{"internalType":"struct NodeOperator","name":"operator","type":"tuple","components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"NodeOperatorUpdated","anonymous":false},{"inputs":[{"internalType":"address","name":"newOwner","type":"address","indexed":false},{"internalType":"uint128","name":"cluserVersion","type":"uint128","indexed":false}],"type":"event","name":"OwnershipTransferred","anonymous":false},{"inputs":[{"internalType":"struct Settings","name":"newSettings","type":"tuple","components":[{"internalType":"uint16","name":"maxOperatorDataBytes","type":"uint16"}],"indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"SettingsUpdated","anonymous":false},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"abortMigration"},{"inputs":[{"internalType":"uint8","name":"idx","type":"uint8"},{"internalType":"struct NodeOperator","name":"operator","type":"tuple","components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}]}],"stateMutability":"nonpayable","type":"function","name":"addNodeOperator"},{"inputs":[{"internalType":"uint64","name":"id","type":"uint64"}],"stateMutability":"nonpayable","type":"function","name":"completeMigration"},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"finishMaintenance"},{"inputs":[],"stateMutability":"view","type":"function","name":"getView","outputs":[{"internalType":"struct ClusterView","name":"","type":"tuple","components":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"struct NodeOperator[]","name":"nodeOperatorSlots","type":"tuple[]","components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}]},{"internalType":"struct Keyspace[2]","name":"keyspaces","type":"tuple[2]","components":[{"internalType":"uint256","name":"operatorsBitmask","type":"uint256"},{"internalType":"uint8","name":"replicationStrategy","type":"uint8"}]},{"internalType":"uint64","name":"keyspaceVersion","type":"uint64"},{"internalType":"struct Settings","name":"settings","type":"tuple","components":[{"internalType":"uint16","name":"maxOperatorDataBytes","type":"uint16"}]},{"internalType":"struct Migration","name":"migration","type":"tuple","components":[{"internalType":"uint64","name":"id","type":"uint64"},{"internalType":"uint256","name":"pullingOperatorsBitmask","type":"uint256"}]},{"internalType":"struct Maintenance","name":"maintenance","type":"tuple","components":[{"internalType":"address","name":"slot","type":"address"}]},{"internalType":"uint128","name":"version","type":"uint128"}]}]},{"inputs":[{"internalType":"address","name":"operatorAddress","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"removeNodeOperator"},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"startMaintenance"},{"inputs":[{"internalType":"struct Keyspace","name":"newKeyspace","type":"tuple","components":[{"internalType":"uint256","name":"operatorsBitmask","type":"uint256"},{"internalType":"uint8","name":"replicationStrategy","type":"uint8"}]}],"stateMutability":"nonpayable","type":"function","name":"startMigration"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"transferOwnership"},{"inputs":[{"internalType":"struct NodeOperator","name":"operator","type":"tuple","components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}]}],"stateMutability":"nonpayable","type":"function","name":"updateNodeOperator"},{"inputs":[{"internalType":"struct Settings","name":"newSettings","type":"tuple","components":[{"internalType":"uint16","name":"maxOperatorDataBytes","type":"uint16"}]}],"stateMutability":"nonpayable","type":"function","name":"updateSettings"}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"remappings":["@openzeppelin-contracts-5.3.0/=dependencies/@openzeppelin-contracts-5.3.0/","forge-std-1.9.7/=dependencies/forge-std-1.9.7/src/","forge-std/=dependencies/forge-std/src/","openzeppelin-contracts/=dependencies/@openzeppelin-contracts-5.3.0/"],"optimizer":{"enabled":false,"runs":200},"metadata":{"bytecodeHash":"ipfs"},"compilationTarget":{"src/Cluster.sol":"Cluster"},"evmVersion":"cancun","libraries":{},"viaIR":true},"sources":{"dependencies/openzeppelin-contracts/utils/Panic.sol":{"keccak256":"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a","urls":["bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a","dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG"],"license":"MIT"},"dependencies/openzeppelin-contracts/utils/math/Math.sol":{"keccak256":"0x1225214420c83ebcca88f2ae2b50f053aaa7df7bd684c3e878d334627f2edfc6","urls":["bzz-raw://6c5fab4970634f9ab9a620983dc1c8a30153981a0b1a521666e269d0a11399d3","dweb:/ipfs/QmVRnBC575MESGkEHndjujtR7qub2FzU9RWy9eKLp4hPZB"],"license":"MIT"},"dependencies/openzeppelin-contracts/utils/math/SafeCast.sol":{"keccak256":"0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54","urls":["bzz-raw://b1d578337048cad08c1c03041cca5978eff5428aa130c781b271ad9e5566e1f8","dweb:/ipfs/QmPFKL2r9CBsMwmUqqdcFPfHZB2qcs9g1HDrPxzWSxomvy"],"license":"MIT"},"src/Cluster.sol":{"keccak256":"0x8ade3b168437cafe86f09cb2c71514eb497e9e25b9f9b836497e05942427217b","urls":["bzz-raw://1a4141701f07e7ccd86e1573762adfd8dd292eb286ce6a113d7baae6bbc9f087","dweb:/ipfs/QmYGCqntKqzcfeCnDx667mgQn9vVYKXFokJvt8Kp2Lycxn"],"license":"MIT"}},"version":1},"id":24} \ No newline at end of file +{"abi":[{"type":"constructor","inputs":[{"name":"initialSettings","type":"tuple","internalType":"struct Settings","components":[{"name":"maxOperatorDataBytes","type":"uint16","internalType":"uint16"}]},{"name":"initialOperators","type":"tuple[]","internalType":"struct NodeOperator[]","components":[{"name":"addr","type":"address","internalType":"address"},{"name":"data","type":"bytes","internalType":"bytes"}]}],"stateMutability":"nonpayable"},{"type":"function","name":"abortMigration","inputs":[{"name":"id","type":"uint64","internalType":"uint64"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"addNodeOperator","inputs":[{"name":"idx","type":"uint8","internalType":"uint8"},{"name":"operator","type":"tuple","internalType":"struct NodeOperator","components":[{"name":"addr","type":"address","internalType":"address"},{"name":"data","type":"bytes","internalType":"bytes"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"completeMigration","inputs":[{"name":"id","type":"uint64","internalType":"uint64"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"finishMaintenance","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"getView","inputs":[],"outputs":[{"name":"","type":"tuple","internalType":"struct ClusterView","components":[{"name":"owner","type":"address","internalType":"address"},{"name":"nodeOperatorSlots","type":"tuple[]","internalType":"struct NodeOperator[]","components":[{"name":"addr","type":"address","internalType":"address"},{"name":"data","type":"bytes","internalType":"bytes"}]},{"name":"keyspaces","type":"tuple[2]","internalType":"struct Keyspace[2]","components":[{"name":"operatorsBitmask","type":"uint256","internalType":"uint256"},{"name":"replicationStrategy","type":"uint8","internalType":"uint8"}]},{"name":"keyspaceVersion","type":"uint64","internalType":"uint64"},{"name":"settings","type":"tuple","internalType":"struct Settings","components":[{"name":"maxOperatorDataBytes","type":"uint16","internalType":"uint16"}]},{"name":"migration","type":"tuple","internalType":"struct Migration","components":[{"name":"id","type":"uint64","internalType":"uint64"},{"name":"pullingOperatorsBitmask","type":"uint256","internalType":"uint256"}]},{"name":"maintenance","type":"tuple","internalType":"struct Maintenance","components":[{"name":"slot","type":"address","internalType":"address"}]},{"name":"version","type":"uint128","internalType":"uint128"}]}],"stateMutability":"view"},{"type":"function","name":"removeNodeOperator","inputs":[{"name":"operatorAddress","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"startMaintenance","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"startMigration","inputs":[{"name":"newKeyspace","type":"tuple","internalType":"struct Keyspace","components":[{"name":"operatorsBitmask","type":"uint256","internalType":"uint256"},{"name":"replicationStrategy","type":"uint8","internalType":"uint8"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"transferOwnership","inputs":[{"name":"newOwner","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateNodeOperator","inputs":[{"name":"operator","type":"tuple","internalType":"struct NodeOperator","components":[{"name":"addr","type":"address","internalType":"address"},{"name":"data","type":"bytes","internalType":"bytes"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateSettings","inputs":[{"name":"newSettings","type":"tuple","internalType":"struct Settings","components":[{"name":"maxOperatorDataBytes","type":"uint16","internalType":"uint16"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"event","name":"MaintenanceFinished","inputs":[{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"MaintenanceStarted","inputs":[{"name":"addr","type":"address","indexed":false,"internalType":"address"},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"MigrationAborted","inputs":[{"name":"id","type":"uint64","indexed":false,"internalType":"uint64"},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"MigrationCompleted","inputs":[{"name":"id","type":"uint64","indexed":false,"internalType":"uint64"},{"name":"operatorAddress","type":"address","indexed":false,"internalType":"address"},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"MigrationDataPullCompleted","inputs":[{"name":"id","type":"uint64","indexed":false,"internalType":"uint64"},{"name":"operatorAddress","type":"address","indexed":false,"internalType":"address"},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"MigrationStarted","inputs":[{"name":"id","type":"uint64","indexed":false,"internalType":"uint64"},{"name":"newKeyspace","type":"tuple","indexed":false,"internalType":"struct Keyspace","components":[{"name":"operatorsBitmask","type":"uint256","internalType":"uint256"},{"name":"replicationStrategy","type":"uint8","internalType":"uint8"}]},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"NodeOperatorAdded","inputs":[{"name":"idx","type":"uint8","indexed":false,"internalType":"uint8"},{"name":"operator","type":"tuple","indexed":false,"internalType":"struct NodeOperator","components":[{"name":"addr","type":"address","internalType":"address"},{"name":"data","type":"bytes","internalType":"bytes"}]},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"NodeOperatorRemoved","inputs":[{"name":"operatorAddress","type":"address","indexed":false,"internalType":"address"},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"NodeOperatorUpdated","inputs":[{"name":"operator","type":"tuple","indexed":false,"internalType":"struct NodeOperator","components":[{"name":"addr","type":"address","internalType":"address"},{"name":"data","type":"bytes","internalType":"bytes"}]},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"name":"newOwner","type":"address","indexed":false,"internalType":"address"},{"name":"cluserVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"SettingsUpdated","inputs":[{"name":"newSettings","type":"tuple","indexed":false,"internalType":"struct Settings","components":[{"name":"maxOperatorDataBytes","type":"uint16","internalType":"uint16"}]},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false}],"bytecode":{"object":"0x6080604052346100305761001a61001461030f565b90610acf565b610022610035565b613a46610ed38239613a4690f35b61003b565b60405190565b5f80fd5b601f801991011690565b634e487b7160e01b5f52604160045260245ffd5b906100679061003f565b810190811060018060401b0382111761007f57604052565b610049565b90610097610090610035565b928361005d565b565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b61ffff1690565b6100b9816100a9565b036100c057565b5f80fd5b905051906100d1826100b0565b565b91906020838203126100fb576100f5906100ed6020610084565b935f016100c4565b5f830152565b6100a1565b5f80fd5b60018060401b03811161011a5760208091020190565b610049565b5f80fd5b60018060a01b031690565b61013790610123565b90565b6101438161012e565b0361014a57565b5f80fd5b9050519061015b8261013a565b565b5f80fd5b60018060401b03811161017d5761017960209161003f565b0190565b610049565b90825f9392825e0152565b909291926101a261019d82610161565b610084565b938185526020850190828401116101be576101bc92610182565b565b61015d565b9080601f830112156101e1578160206101de9351910161018d565b90565b610100565b919091604081840312610236576101fd6040610084565b9261020a815f840161014e565b5f850152602082015160018060401b0381116102315761022a92016101c3565b6020830152565b6100a5565b6100a1565b92919061024f61024a82610104565b610084565b93818552602080860192028101918383116102a45781905b838210610275575050505050565b815160018060401b03811161029f5760209161029487849387016101e6565b815201910190610267565b610100565b61011f565b9080601f830112156102c7578160206102c49351910161023b565b90565b610100565b91909160408184031261030a576102e5835f83016100d3565b92602082015160018060401b0381116103055761030292016102a9565b90565b61009d565b610099565b61032d6149198038038061032281610084565b9283398101906102cc565b9091565b5190565b90565b90565b90565b61035261034d61035792610338565b61033b565b610335565b90565b60209181520190565b5f7f746f6f206d616e79206f70657261746f72730000000000000000000000000000910152565b610397601260209261035a565b6103a081610363565b0190565b6103b99060208101905f81830391015261038a565b90565b156103c357565b6103cb610035565b62461bcd60e51b8152806103e1600482016103a4565b0390fd5b5f1b90565b906103fb60018060a01b03916103e5565b9181191691161790565b61041961041461041e92610123565b61033b565b610123565b90565b61042a90610405565b90565b61043690610421565b90565b90565b9061045161044c6104589261042d565b610439565b82546103ea565b9055565b634e487b7160e01b5f525f60045260245ffd5b61047990516100a9565b90565b9061048961ffff916103e5565b9181191691161790565b6104a76104a26104ac926100a9565b61033b565b6100a9565b90565b90565b906104c76104c26104ce92610493565b6104af565b825461047c565b9055565b906104e45f806104ea9401920161046f565b906104b2565b565b906104f6916104d2565b565b90565b61050f61050a610514926104f8565b61033b565b610335565b90565b60016105239101610335565b90565b634e487b7160e01b5f52603260045260245ffd5b9061054482610331565b811015610555576020809102010190565b610526565b5190565b610568905161012e565b90565b906105759061042d565b5f5260205260405f2090565b5f1c90565b60ff1690565b61059861059d91610581565b610586565b90565b6105aa905461058c565b90565b151590565b5f7f6475706c6963617465206f70657261746f720000000000000000000000000000910152565b6105e6601260209261035a565b6105ef816105b2565b0190565b6106089060208101905f8183039101526105d9565b90565b1561061257565b61061a610035565b62461bcd60e51b815280610630600482016105f3565b0390fd5b60ff1690565b61064e61064961065392610335565b61033b565b610634565b90565b6106606040610084565b90565b9061066d906105ad565b9052565b9061067b90610634565b9052565b61068990516105ad565b90565b9061069860ff916103e5565b9181191691161790565b6106ab906105ad565b90565b90565b906106c66106c16106cd926106a2565b6106ae565b825461068c565b9055565b6106db9051610634565b90565b60081b90565b906106f161ff00916106de565b9181191691161790565b61070f61070a61071492610634565b61033b565b610634565b90565b90565b9061072f61072a610736926106fb565b610717565b82546106e4565b9055565b9061076460205f61076a9461075c82820161075684880161067f565b906106b1565b0192016106d1565b9061071a565b565b906107769161073a565b565b5061010090565b90565b61078b81610778565b8210156107a55761079d60029161077f565b910201905f90565b610526565b5190565b634e487b7160e01b5f52602260045260245ffd5b90600160028304921680156107e2575b60208310146107dd57565b6107ae565b91607f16916107d2565b5f5260205f2090565b601f602091010490565b1b90565b9190600861081e9102916108185f19846107ff565b926107ff565b9181191691161790565b61083c61083761084192610335565b61033b565b610335565b90565b90565b919061085d61085861086593610828565b610844565b908354610803565b9055565b5f90565b61087f91610879610869565b91610847565b565b5b81811061088d575050565b8061089a5f60019361086d565b01610882565b9190601f81116108b0575b505050565b6108bc6108e1936107ec565b9060206108c8846107f5565b830193106108e9575b6108da906107f5565b0190610881565b5f80806108ab565b91506108da819290506108d1565b1c90565b9061090b905f19906008026108f7565b191690565b8161091a916108fb565b906002021790565b9061092c8161055a565b9060018060401b0382116109ea5761094e8261094885546107c2565b856108a0565b602090601f831160011461098257918091610971935f92610976575b5050610910565b90555b565b90915001515f8061096a565b601f19831691610991856107ec565b925f5b8181106109d2575091600293918560019694106109b8575b50505002019055610974565b6109c8910151601f8416906108fb565b90555f80806109ac565b91936020600181928787015181550195019201610994565b610049565b906109f991610922565b565b90610a2660206001610a2c94610a1e5f8201610a185f880161055e565b9061043c565b0192016107aa565b906109ef565b565b9190610a3f57610a3d916109fb565b565b61045c565b90610a505f19916103e5565b9181191691161790565b90610a6f610a6a610a7692610828565b610844565b8254610a44565b9055565b90565b610a89610a8e91610581565b610a7a565b90565b610a9b9054610a7d565b90565b50600290565b90565b610ab081610a9e565b821015610aca57610ac2600291610aa4565b910201905f90565b610526565b610b0c90610afa610adf84610331565b610af3610aed61010061033e565b91610335565b11156103bc565b610b04335f61043c565b6102086104ec565b610b155f6104fb565b5b80610b31610b2b610b2685610331565b610335565b91610335565b1015610c1c57610c1790610b5b610b566020610b4e86859061053a565b51015161055a565b610db4565b610b99610b94610b8e5f610b8881600101610b8283610b7b8b8a9061053a565b510161055e565b9061056b565b016105a0565b156105ad565b61060b565b610bef6001610bc7610baa8461063a565b610bbe610bb5610656565b935f8501610663565b60208301610671565b610bea5f600101610be45f610bdd89889061053a565b510161055e565b9061056b565b61076c565b610c12610bfd84839061053a565b51610c0c600180018490610782565b90610a2e565b610517565b610b16565b50610c39610c34610c2f610c4493610331565b61063a565b610e96565b610201600101610a5a565b610c6a610c55610201600101610a91565b5f610c636102038290610aa7565b5001610a5a565b565b5f7f656d707479206f70657261746f72206461746100000000000000000000000000910152565b610ca0601360209261035a565b610ca981610c6c565b0190565b610cc29060208101905f818303910152610c93565b90565b15610ccc57565b610cd4610035565b62461bcd60e51b815280610cea60048201610cad565b0390fd5b61ffff1690565b610d01610d0691610581565b610cee565b90565b610d139054610cf5565b90565b610d2a610d25610d2f926100a9565b61033b565b610335565b90565b5f7f6f70657261746f72206461746120746f6f206c61726765000000000000000000910152565b610d66601760209261035a565b610d6f81610d32565b0190565b610d889060208101905f818303910152610d59565b90565b15610d9257565b610d9a610035565b62461bcd60e51b815280610db060048201610d73565b0390fd5b610df990610dd481610dce610dc85f6104fb565b91610335565b11610cc5565b610df2610dec610de75f61020801610d09565b610d16565b91610335565b1115610d8b565b565b610e0f610e0a610e1492610634565b61033b565b610335565b90565b90565b610e2e610e29610e3392610e17565b61033b565b610335565b90565b610e5590610e4f610e49610e5a94610335565b91610335565b906107ff565b610335565b90565b634e487b7160e01b5f52601160045260245ffd5b610e80610e8691939293610335565b92610335565b8203918211610e9157565b610e5d565b610ebf610ecf91610ea5610869565b50610eba610eb4600192610dfb565b91610e1a565b610e36565b610ec96001610e1a565b90610e71565b9056fe60806040526004361015610013575b6107fc565b61001d5f356100cc565b806326322217146100c75780632b726062146100c257806347011c5c146100bd57806353bfb584146100b857806365706f9c146100b357806375418b9d146100ae5780639d44e717146100a9578063c05665dd146100a4578063e88e97491461009f578063f2fde38b1461009a5763f5f2d9f10361000e576107c9565b610796565b610763565b610730565b6106bc565b610646565b6102e1565b61027d565b61023b565b6101d6565b610135565b60e01c90565b60405190565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b908160409103126100f65790565b6100e4565b9060208282031261012b575f82013567ffffffffffffffff81116101265761012392016100e8565b90565b6100e0565b6100dc565b5f0190565b346101635761014d6101483660046100fb565b610f6e565b6101556100d2565b8061015f81610130565b0390f35b6100d8565b60ff1690565b61017781610168565b0361017e57565b5f80fd5b9050359061018f8261016e565b565b9190916040818403126101d1576101aa835f8301610182565b92602082013567ffffffffffffffff81116101cc576101c992016100e8565b90565b6100e0565b6100dc565b34610205576101ef6101e9366004610191565b906115ec565b6101f76100d2565b8061020181610130565b0390f35b6100d8565b908160409103126102185790565b6100e4565b9060408282031261023657610233915f0161020a565b90565b6100dc565b346102695761025361024e36600461021d565b611d3c565b61025b6100d2565b8061026581610130565b0390f35b6100d8565b5f91031261027857565b6100dc565b346102ab5761028d36600461026e565b610295611ef1565b61029d6100d2565b806102a781610130565b0390f35b6100d8565b908160209103126102be5790565b6100e4565b906020828203126102dc576102d9915f016102b0565b90565b6100dc565b3461030f576102f96102f43660046102c3565b612097565b6103016100d2565b8061030b81610130565b0390f35b6100d8565b60018060a01b031690565b61032890610314565b90565b6103349061031f565b9052565b5190565b60209181520190565b60200190565b5190565b60209181520190565b90825f9392825e0152565b601f801991011690565b61038c61039560209361039a936103838161034b565b9384809361034f565b95869101610358565b610363565b0190565b6103c991602060408201926103b95f8201515f85019061032b565b015190602081840391015261036d565b90565b906103d69161039e565b90565b60200190565b906103f36103ec83610338565b809261033c565b908161040460208302840194610345565b925f915b83831061041757505050505090565b90919293946020610439610433838560019503875289516103cc565b976103d9565b9301930191939290610408565b50600290565b905090565b90565b90565b61046090610454565b9052565b61046d90610168565b9052565b90602080610493936104895f8201515f860190610457565b0151910190610464565b565b906104a281604093610471565b0190565b60200190565b6104c86104c26104bb83610446565b809461044c565b91610451565b5f915b8383106104d85750505050565b6104ee6104e86001928451610495565b926104a6565b920191906104cb565b67ffffffffffffffff1690565b61050d906104f7565b9052565b61ffff1690565b61052190610511565b9052565b905f80610536930151910190610518565b565b9060208061055a936105505f8201515f860190610504565b0151910190610457565b565b905f8061056d93015191019061032b565b565b6fffffffffffffffffffffffffffffffff1690565b61058d9061056f565b9052565b9061062b9061016060e06105c561018084016105b35f8801515f87019061032b565b602087015185820360208701526103df565b946105d8604082015160408601906104ac565b6105ea606082015160c0860190610504565b6105fb608082015183860190610525565b61060e60a0820151610100860190610538565b61062160c082015161014086019061055c565b0151910190610584565b90565b6106439160208201915f818403910152610591565b90565b346106765761065636600461026e565b61067261066161266b565b6106696100d2565b9182918261062e565b0390f35b6100d8565b610684816104f7565b0361068b57565b5f80fd5b9050359061069c8261067b565b565b906020828203126106b7576106b4915f0161068f565b90565b6100dc565b346106ea576106d46106cf36600461069e565b612bde565b6106dc6100d2565b806106e681610130565b0390f35b6100d8565b6106f88161031f565b036106ff57565b5f80fd5b90503590610710826106ef565b565b9060208282031261072b57610728915f01610703565b90565b6100dc565b3461075e57610748610743366004610712565b61305a565b6107506100d2565b8061075a81610130565b0390f35b6100d8565b346107915761077b61077636600461069e565b6131bc565b6107836100d2565b8061078d81610130565b0390f35b6100d8565b346107c4576107ae6107a9366004610712565b613264565b6107b66100d2565b806107c081610130565b0390f35b6100d8565b346107f7576107d936600461026e565b6107e1613377565b6107e96100d2565b806107f381610130565b0390f35b6100d8565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b90359060016020038136030382121561084e570180359067ffffffffffffffff82116108495760200191600182023603831361084457565b610808565b610804565b610800565b5090565b35610861816106ef565b90565b5f1c90565b60018060a01b031690565b61088061088591610864565b610869565b90565b6108929054610874565b90565b60209181520190565b5f7f756e617574686f72697a65640000000000000000000000000000000000000000910152565b6108d2600c602092610895565b6108db8161089e565b0190565b6108f49060208101905f8183039101526108c5565b90565b156108fe57565b6109066100d2565b62461bcd60e51b81528061091c600482016108df565b0390fd5b90565b61093761093261093c92610314565b610920565b610314565b90565b61094890610923565b90565b6109549061093f565b90565b906109619061094b565b5f5260205260405f2090565b90565b60ff1690565b61098261098791610864565b610970565b90565b6109949054610976565b90565b5f7f756e6b6e6f776e206f70657261746f7200000000000000000000000000000000910152565b6109cb6010602092610895565b6109d481610997565b0190565b6109ed9060208101905f8183039101526109be565b90565b156109f757565b6109ff6100d2565b62461bcd60e51b815280610a15600482016109d8565b0390fd5b60081c90565b60ff1690565b610a31610a3691610a19565b610a1f565b90565b610a439054610a25565b90565b634e487b7160e01b5f52603260045260245ffd5b5061010090565b90565b610a6d81610a5a565b821015610a8757610a7f600291610a61565b910201905f90565b610a46565b634e487b7160e01b5f525f60045260245ffd5b5f1b90565b90610ab560018060a01b0391610a9f565b9181191691161790565b90565b90610ad7610ad2610ade9261094b565b610abf565b8254610aa4565b9055565b634e487b7160e01b5f52604160045260245ffd5b634e487b7160e01b5f52602260045260245ffd5b9060016002830492168015610b2a575b6020831014610b2557565b610af6565b91607f1691610b1a565b5f5260205f2090565b601f602091010490565b1b90565b91906008610b66910291610b605f1984610b47565b92610b47565b9181191691161790565b610b84610b7f610b8992610454565b610920565b610454565b90565b90565b9190610ba5610ba0610bad93610b70565b610b8c565b908354610b4b565b9055565b5f90565b610bc791610bc1610bb1565b91610b8f565b565b5b818110610bd5575050565b80610be25f600193610bb5565b01610bca565b9190601f8111610bf8575b505050565b610c04610c2993610b34565b906020610c1084610b3d565b83019310610c31575b610c2290610b3d565b0190610bc9565b5f8080610bf3565b9150610c2281929050610c19565b1c90565b90610c53905f1990600802610c3f565b191690565b81610c6291610c43565b906002021790565b91610c759082610853565b9067ffffffffffffffff8211610d3457610c9982610c938554610b0a565b85610be8565b5f90601f8311600114610ccc57918091610cbb935f92610cc0575b5050610c58565b90555b565b90915001355f80610cb4565b601f19831691610cdb85610b34565b925f5b818110610d1c57509160029391856001969410610d02575b50505002019055610cbe565b610d12910135601f841690610c43565b90555f8080610cf6565b91936020600181928787013581550195019201610cde565b610ae2565b90610d449291610c6a565b565b90610d736001610d7993610d675f8201610d615f8701610857565b90610ac2565b0191602081019061080c565b91610d39565b565b9190610d8c57610d8a91610d46565b565b610a8c565b6fffffffffffffffffffffffffffffffff1690565b610db2610db791610864565b610d91565b90565b610dc49054610da6565b90565b634e487b7160e01b5f52601160045260245ffd5b610de49061056f565b6fffffffffffffffffffffffffffffffff8114610e015760010190565b610dc7565b90610e216fffffffffffffffffffffffffffffffff91610a9f565b9181191691161790565b610e3f610e3a610e449261056f565b610920565b61056f565b90565b90565b90610e5f610e5a610e6692610e2b565b610e47565b8254610e06565b9055565b50610e79906020810190610703565b90565b5f80fd5b5f80fd5b5f80fd5b9035600160200382360303811215610ec957016020813591019167ffffffffffffffff8211610ec4576001820236038313610ebf57565b610e80565b610e7c565b610e84565b90825f939282370152565b9190610ef381610eec81610ef89561034f565b8095610ece565b610363565b0190565b610f3891610f2a6040820192610f20610f175f830183610e6a565b5f85019061032b565b6020810190610e88565b916020818503910152610ed9565b90565b610f449061056f565b9052565b92916020610f64610f6c9360408701908782035f890152610efc565b940190610f3b565b565b610f8d610f88610f8283602081019061080c565b90610853565b6134a1565b33610faa610fa4610f9f5f8501610857565b61031f565b9161031f565b148015611075575b610fbb906108f7565b611011610fde610fd95f600101610fd35f8601610857565b90610957565b61096d565b610ff1610fec5f830161098a565b6109f0565b61100b83916110055f600180019201610a39565b90610a64565b90610d7b565b61102f61102761102261020c610dba565b610ddb565b61020c610e4a565b61103a61020c610dba565b7f5aab2c32b1e447db4dba1d2790fe8b863d4775042b10b92e00dab9d6b671b5b5916110706110676100d2565b92839283610f48565b0390a1565b50610fbb3361109461108e6110895f610888565b61031f565b9161031f565b149050610fb2565b5f7f6e6f7420746865206f776e657200000000000000000000000000000000000000910152565b6110d0600d602092610895565b6110d98161109c565b0190565b6110f29060208101905f8183039101526110c3565b90565b156110fc57565b6111046100d2565b62461bcd60e51b81528061111a600482016110dd565b0390fd5b9061114c916111473361114161113b6111365f610888565b61031f565b9161031f565b146110f5565b61147f565b565b151590565b5f7f616c726561647920657869737473000000000000000000000000000000000000910152565b611187600e602092610895565b61119081611153565b0190565b6111a99060208101905f81830391015261117a565b90565b156111b357565b6111bb6100d2565b62461bcd60e51b8152806111d160048201611194565b0390fd5b6111df9054610b0a565b90565b90565b6111f96111f46111fe926111e2565b610920565b610454565b90565b5f7f736c6f74206f6363757069656400000000000000000000000000000000000000910152565b611235600d602092610895565b61123e81611201565b0190565b6112579060208101905f818303910152611228565b90565b1561126157565b6112696100d2565b62461bcd60e51b81528061127f60048201611242565b0390fd5b9061128d90610363565b810190811067ffffffffffffffff8211176112a757604052565b610ae2565b906112bf6112b86100d2565b9283611283565b565b6112cb60406112ac565b90565b906112d89061114e565b9052565b906112e690610168565b9052565b6112f4905161114e565b90565b9061130360ff91610a9f565b9181191691161790565b6113169061114e565b90565b90565b9061133161132c6113389261130d565b611319565b82546112f7565b9055565b6113469051610168565b90565b60081b90565b9061135c61ff0091611349565b9181191691161790565b61137a61137561137f92610168565b610920565b610168565b90565b90565b9061139a6113956113a192611366565b611382565b825461134f565b9055565b906113cf60205f6113d5946113c78282016113c18488016112ea565b9061131c565b01920161133c565b90611385565b565b906113e1916113a5565b565b90565b6113f26113f791610864565b6113e3565b90565b61140490546113e6565b90565b906114135f1991610a9f565b9181191691161790565b9061143261142d61143992610b70565b610b8c565b8254611407565b9055565b61144690610168565b9052565b93929061147560409161147d9461146860608901925f8a019061143d565b8782036020890152610efc565b940190610f3b565b565b61149e61149961149384602081019061080c565b90610853565b6134a1565b6114d16114cc6114c65f6114c0816001016114ba838901610857565b90610957565b0161098a565b1561114e565b6111ac565b6115056114ed60016114e68180018590610a64565b50016111d5565b6114ff6114f95f6111e5565b91610454565b1461125a565b611548600161152b836115226115196112c1565b935f85016112ce565b602083016112dc565b6115435f60010161153d5f8701610857565b90610957565b6113d7565b6115608261155a600180018490610a64565b90610d7b565b61158661157b6115746102016001016113fa565b839061352b565b61020160010161141d565b6115a461159c61159761020c610dba565b610ddb565b61020c610e4a565b906115b061020c610dba565b916115e77f952e65f049c574f487580ba41dcf6b0ea8350ef8abc8647a8a11dfaa7af6bad6936115de6100d2565b9384938461144a565b0390a1565b906115f69161111e565b565b611625906116203361161a61161461160f5f610888565b61031f565b9161031f565b146110f5565b6116a9565b565b5f7f6d6967726174696f6e20696e2070726f67726573730000000000000000000000910152565b61165b6015602092610895565b61166481611627565b0190565b61167d9060208101905f81830391015261164e565b90565b1561168757565b61168f6100d2565b62461bcd60e51b8152806116a560048201611668565b0390fd5b6116cb906116c66116c16116bb61355a565b1561114e565b611680565b61174f565b565b5f7f6d61696e74656e616e636520696e2070726f6772657373000000000000000000910152565b6117016017602092610895565b61170a816116cd565b0190565b6117239060208101905f8183039101526116f4565b90565b1561172d57565b6117356100d2565b62461bcd60e51b81528061174b6004820161170e565b0390fd5b6117719061176c611767611761613588565b1561114e565b611726565b611b76565b565b61177c81610454565b0361178357565b5f80fd5b3561179181611773565b90565b5f7f696e76616c6964206269746d61736b0000000000000000000000000000000000910152565b6117c8600f602092610895565b6117d181611794565b0190565b6117ea9060208101905f8183039101526117bb565b90565b156117f457565b6117fc6100d2565b62461bcd60e51b815280611812600482016117d5565b0390fd5b67ffffffffffffffff1690565b61182f61183491610864565b611816565b90565b6118419054611823565b90565b90565b61185b61185661186092611844565b610920565b6104f7565b90565b634e487b7160e01b5f52601260045260245ffd5b611883611889916104f7565b916104f7565b908115611894570690565b611863565b50600290565b90565b6118ab81611899565b8210156118c5576118bd60029161189f565b910201905f90565b610a46565b906118d490610454565b9052565b6118e46118e991610864565b610a1f565b90565b6118f690546118d8565b90565b61190360406112ac565b90565b9061193d61193460016119176118f9565b9461192e6119265f83016113fa565b5f88016118ca565b016118ec565b602084016112dc565b565b61194890611906565b90565b6119559051610454565b90565b356119628161016e565b90565b5f7f73616d65206b6579737061636500000000000000000000000000000000000000910152565b611999600d602092610895565b6119a281611965565b0190565b6119bb9060208101905f81830391015261198c565b90565b156119c557565b6119cd6100d2565b62461bcd60e51b8152806119e3600482016119a6565b0390fd5b6119f0906104f7565b67ffffffffffffffff8114611a055760010190565b610dc7565b90611a1d67ffffffffffffffff91610a9f565b9181191691161790565b611a3b611a36611a40926104f7565b610920565b6104f7565b90565b90565b90611a5b611a56611a6292611a27565b611a43565b8254611a0a565b9055565b90611a7b611a76611a8292611366565b611382565b82546112f7565b9055565b90611ab160206001611ab794611aa95f8201611aa35f8801611787565b9061141d565b019201611958565b90611a66565b565b9190611aca57611ac891611a86565b565b610a8c565b611ad8906104f7565b9052565b90503590611ae982611773565b565b50611afa906020810190611adc565b90565b50611b0c906020810190610182565b90565b906020611b3a611b4293611b31611b285f830183611aeb565b5f860190610457565b82810190611afd565b910190610464565b565b606090611b6d611b749496959396611b6360808401985f850190611acf565b6020830190611b0f565b0190610f3b565b565b611ba0611b9b611b875f8401611787565b611b956102016001016113fa565b906135bd565b6117ed565b611c0d611bd6611bd0610203611bca611bba610207611837565b611bc46002611847565b90611877565b906118a2565b5061193f565b611be15f820161194b565b611bfd611bf7611bf25f8701611787565b610454565b91610454565b1415908115611d0a575b506119be565b611c2c5f61020901611c26611c2182611837565b6119e7565b90611a46565b611c4a611c42611c3d610207611837565b6119e7565b610207611a46565b611c7e81611c78610203611c72611c62610207611837565b611c6c6002611847565b90611877565b906118a2565b90611ab9565b611c97611c8c5f8301611787565b60016102090161141d565b611cb5611cad611ca861020c610dba565b610ddb565b61020c610e4a565b611cc25f61020901611837565b90611cce61020c610dba565b91611d057f490341fd8fc7a8294fbad1cc0db9f41ae0ac5aeb655ea31b46a475ec3a77749c93611cfc6100d2565b93849384611b44565b0390a1565b611d17915060200161133c565b611d34611d2e611d2960208601611958565b610168565b91610168565b14155f611c07565b611d45906115f8565b565b5f7f6e6f206d61696e74656e616e6365000000000000000000000000000000000000910152565b611d7b600e602092610895565b611d8481611d47565b0190565b611d9d9060208101905f818303910152611d6e565b90565b15611da757565b611daf6100d2565b62461bcd60e51b815280611dc560048201611d88565b0390fd5b611dd9611dd4613588565b611da0565b611de1611e20565b565b611df7611df2611dfc926111e2565b610920565b610314565b90565b611e0890611de3565b90565b9190611e1e905f60208501940190610f3b565b565b611e2d5f61020b01610888565b611e3f611e393361031f565b9161031f565b148015611eca575b611e50906108f7565b611e66611e5c5f611dff565b5f61020b01610ac2565b611e84611e7c611e7761020c610dba565b610ddb565b61020c610e4a565b611e8f61020c610dba565b611ec57f11943d6deda6f0591d72674788d272eb0209e18b8a3a021fa51cb3b5e9a2ab6191611ebc6100d2565b91829182611e0b565b0390a1565b50611e5033611ee9611ee3611ede5f610888565b61031f565b9161031f565b149050611e47565b611ef9611dc9565b565b611f2890611f2333611f1d611f17611f125f610888565b61031f565b9161031f565b146110f5565b612027565b565b611f3381610511565b03611f3a57565b5f80fd5b35611f4881611f2a565b90565b90611f5861ffff91610a9f565b9181191691161790565b611f76611f71611f7b92610511565b610920565b610511565b90565b90565b90611f96611f91611f9d92611f62565b611f7e565b8254611f4b565b9055565b90611fb35f80611fb994019201611f3e565b90611f81565b565b90611fc591611fa1565b565b90503590611fd482611f2a565b565b50611fe5906020810190611fc7565b90565b905f611ffa6120029382810190611fd6565b910190610518565b565b91602061202592949361201e60408201965f830190611fe8565b0190610f3b565b565b61203381610208611fbb565b61205161204961204461020c610dba565b610ddb565b61020c610e4a565b61205c61020c610dba565b7fb24d8d9dcfbb6be13176c1c7bfb0e76445a9ba2a3553b413d8671446f1030830916120926120896100d2565b92839283612004565b0390a1565b6120a090611efb565b565b6120ad6101006112ac565b90565b5f90565b606090565b67ffffffffffffffff81116120ce5760200290565b610ae2565b6120df6120e4916120b9565b6112ac565b90565b5f90565b5f90565b6120f76118f9565b90602080836121046120e7565b81520161210f6120eb565b81525050565b61211d6120ef565b90565b5f5b82811061212e57505050565b602090612139612115565b8184015201612122565b90612161612150836120d3565b9261215b84916120b9565b90612120565b565b61216d6002612143565b90565b5f90565b61217e60206112ac565b90565b5f90565b61218d612174565b90602082612199612181565b81525050565b6121a7612185565b90565b6121b460406112ac565b90565b6121bf6121aa565b90602080836121cc612170565b8152016121d76120e7565b81525050565b6121e56121b7565b90565b6121f260206112ac565b90565b6121fd6121e8565b906020826122096120b0565b81525050565b6122176121f5565b90565b5f90565b6122266120a2565b90602080808080808080896122396120b0565b8152016122446120b4565b81520161224f612163565b81520161225a612170565b81520161226561219f565b8152016122706121dd565b81520161227b61220f565b81520161228661221a565b81525050565b61229461221e565b90565b90565b6122ae6122a96122b392612297565b610920565b610454565b90565b6122c56122cb91939293610454565b92610454565b82018092116122d657565b610dc7565b67ffffffffffffffff81116122f35760208091020190565b610ae2565b9061230a612305836122db565b6112ac565b918252565b61231960406112ac565b90565b606090565b61232961230f565b90602080836123366120b0565b81520161234161231c565b81525050565b61234f612321565b90565b5f5b82811061236057505050565b60209061236b612347565b8184015201612354565b9061239a612382836122f8565b9260208061239086936122db565b9201910390612352565b565b6123a76101006112ac565b90565b906123b49061031f565b9052565b52565b906123c582611899565b6123ce816120d3565b926123d9849161189f565b5f915b8383106123e95750505050565b600260206001926123f98561193f565b8152019201920191906123dc565b612410906123bb565b90565b52565b90612420906104f7565b9052565b61ffff1690565b61243761243c91610864565b612424565b90565b612449905461242b565b90565b9061245690610511565b9052565b906124796124715f61246a612174565b940161243f565b5f840161244c565b565b6124849061245a565b90565b52565b906124c16124b8600161249b6121aa565b946124b26124aa5f8301611837565b5f8801612416565b016113fa565b602084016118ca565b565b6124cc9061248a565b90565b52565b906124f16124e95f6124e26121e8565b9401610888565b5f84016123aa565b565b6124fc906124d2565b90565b52565b9061250c9061056f565b9052565b61251990610454565b5f1981146125275760010190565b610dc7565b61254061253b61254592610454565b610920565b610168565b90565b9061255282610338565b811015612563576020809102010190565b610a46565b905f929180549061258261257b83610b0a565b809461034f565b916001811690815f146125d9575060011461259d575b505050565b6125aa9192939450610b34565b915f925b8184106125c157505001905f8080612598565b600181602092959395548486015201910192906125ae565b92949550505060ff19168252151560200201905f8080612598565b906125fe91612568565b90565b9061262161261a926126116100d2565b938480926125f4565b0383611283565b565b52565b9061265d612654600161263761230f565b9461264e6126465f8301610888565b5f88016123aa565b01612601565b60208401612623565b565b61266890612626565b90565b61267361228c565b50600161020101612683906113fa565b61268c906135e8565b6126955f610888565b8160016126a19061229a565b6126aa916122b6565b6126b390612375565b6102036126c1610207611837565b6102086102099161020b936126d761020c610dba565b956126e061239c565b975f8901906126ee916123aa565b60208801906126fc916123b8565b61270590612407565b604087019061271391612413565b606086019061272191612416565b61272a9061247b565b608085019061273891612487565b612741906124c3565b60a084019061274f916124cf565b612758906124f3565b60c0830190612766916124ff565b60e082019061277491612502565b600161020101612783906113fa565b925f61278e906111e5565b5b806127a261279c86610454565b91610454565b11612805576127fb906127be866127b88361252c565b906135fd565b612800576127f36127d3600180018390610a64565b5060208601516127e3849261265f565b6127ed8383612548565b52612548565b51505b612510565b61278f565b6127f6565b509250905090565b5f7f6e6f206d6967726174696f6e0000000000000000000000000000000000000000910152565b612841600c602092610895565b61284a8161280d565b0190565b6128639060208101905f818303910152612834565b90565b1561286d57565b6128756100d2565b62461bcd60e51b81528061288b6004820161284e565b0390fd5b6128a8906128a361289e61355a565b612866565b612a3e565b565b5f7f77726f6e67206d6967726174696f6e2069640000000000000000000000000000910152565b6128de6012602092610895565b6128e7816128aa565b0190565b6129009060208101905f8183039101526128d1565b90565b1561290a57565b6129126100d2565b62461bcd60e51b815280612928600482016128eb565b0390fd5b61293660406112ac565b90565b9061296f6129665f61294961292c565b9461296061295883830161098a565b8388016112ce565b01610a39565b602084016112dc565b565b61297a90612939565b90565b5f7f6e6f742070756c6c696e67000000000000000000000000000000000000000000910152565b6129b1600b602092610895565b6129ba8161297d565b0190565b6129d39060208101905f8183039101526129a4565b90565b156129dd57565b6129e56100d2565b62461bcd60e51b8152806129fb600482016129be565b0390fd5b612a089061031f565b9052565b604090612a35612a3c9496959396612a2b60608401985f850190611acf565b60208301906129ff565b0190610f3b565b565b612a6690612a60612a5a612a555f61020901611837565b6104f7565b916104f7565b14612903565b612aeb612ae0612a82612a7d5f6001013390610957565b612971565b612a95612a905f83016112ea565b6109f0565b612ac0612abb612aa96001610209016113fa565b612ab56020850161133c565b9061363b565b6129d6565b612ada6020612ad36001610209016113fa565b920161133c565b9061367a565b60016102090161141d565b612b09612b01612afc61020c610dba565b610ddb565b61020c610e4a565b612b176001610209016113fa565b612b29612b235f6111e5565b91610454565b145f14612b8657612b3d5f61020901611837565b33612b4961020c610dba565b91612b807f01269879535f40ee8957e15e160bf1866c5e2728ff0cbc583d848821e2639b4e93612b776100d2565b93849384612a0c565b0390a15b565b612b935f61020901611837565b33612b9f61020c610dba565b91612bd67faf5e90e72015f43138f66b4cd08bd1dfa2839030104f22a00af843fe847c6d1993612bcd6100d2565b93849384612a0c565b0390a1612b84565b612be79061288f565b565b612c1690612c1133612c0b612c05612c005f610888565b61031f565b9161031f565b146110f5565b612eb7565b565b5f7f696e206b65797370616365000000000000000000000000000000000000000000910152565b612c4c600b602092610895565b612c5581612c18565b0190565b612c6e9060208101905f818303910152612c3f565b90565b15612c7857565b612c806100d2565b62461bcd60e51b815280612c9660048201612c59565b0390fd5b5f80910155565b905f03612cb357612cb190612c9a565b565b610a8c565b90612ccb905f1990602003600802610c3f565b8154169055565b905f91612ce9612ce182610b34565b928354610c58565b905555565b919290602082105f14612d4757601f8411600114612d1757612d11929350610c58565b90555b5b565b5090612d3d612d42936001612d34612d2e85610b34565b92610b3d565b82019101610bc9565b612cd2565b612d14565b50612d7e8293612d58600194610b34565b612d77612d6485610b3d565b820192601f861680612d89575b50610b3d565b0190610bc9565b600202179055612d15565b612d9590888603612cb8565b5f612d71565b929091680100000000000000008211612dfb576020115f14612dec57602081105f14612dd057612dca91610c58565b90555b5b565b60019160ff1916612de084610b34565b55600202019055612dcd565b60019150600202019055612dce565b610ae2565b908154612e0c81610b0a565b90818311612e35575b818310612e23575b50505050565b612e2c93612cee565b5f808080612e1d565b612e4183838387612d9b565b612e15565b5f612e5091612e00565b565b905f03612e6457612e6290612e46565b565b610a8c565b5f6001612e7b92828082015501612e52565b565b905f03612e8f57612e8d90612e69565b565b610a8c565b916020612eb5929493612eae60408201965f8301906129ff565b0190610f3b565b565b612f7c612f71612ef05f612ed7612ed2826001018790610957565b61096d565b612eea612ee583830161098a565b6109f0565b01610a39565b612ef861355a565b5f1461300e57612f20612f195f612f1261020382906118a2565b50016113fa565b82906135fd565b80612fe0575b612f2f90612c71565b5b612f475f612f42816001018790610957565b612ca1565b612f5e612f58600180018390610a64565b90612e7d565b612f6c6102016001016113fa565b61367a565b61020160010161141d565b612f9a612f92612f8d61020c610dba565b610ddb565b61020c610e4a565b612fa561020c610dba565b7f6a1d7ddc82d57e783a3ae60737a6c1a4704fcf38d966561fea0af8564f2d895d91612fdb612fd26100d2565b92839283612e94565b0390a1565b50612f2f6130076130005f612ff96102036001906118a2565b50016113fa565b83906135fd565b9050612f26565b6130556130506130495f61304261020361303c61302c610207611837565b6130366002611847565b90611877565b906118a2565b50016113fa565b83906135fd565b612c71565b612f30565b61306390612be9565b565b6130929061308d3361308761308161307c5f610888565b61031f565b9161031f565b146110f5565b613094565b565b6130ad906130a86130a361355a565b612866565b6130ee565b565b6130b8906104f7565b5f81146130c6576001900390565b610dc7565b9160206130ec9294936130e560408201965f830190611acf565b0190610f3b565b565b6131169061311061310a6131055f61020901611837565b6104f7565b916104f7565b14612903565b61313461312c613127610207611837565b6130af565b610207611a46565b61314b6131405f6111e5565b60016102090161141d565b61316961316161315c61020c610dba565b610ddb565b61020c610e4a565b6131765f61020901611837565b61318161020c610dba565b7ff73240422246f63ed633ef3ce0726b8ab8fb69d46c8a4e5ecb0b2922668674a1916131b76131ae6100d2565b928392836130cb565b0390a1565b6131c590613065565b565b6131f4906131ef336131e96131e36131de5f610888565b61031f565b9161031f565b146110f5565b6131f6565b565b613200815f610ac2565b61321e61321661321161020c610dba565b610ddb565b61020c610e4a565b61322961020c610dba565b7f476610ebc6647c15376100955efbf22ef2a0c3b923fc00b380b660c873ef20ac9161325f6132566100d2565b92839283612e94565b0390a1565b61326d906131c7565b565b61328861328361327d61355a565b1561114e565b611680565b613290613292565b565b6132ab6132a66132a0613588565b1561114e565b611726565b6132b36132b5565b565b6132cd5f6132c7816001013390610957565b0161098a565b8015613350575b6132dd906108f7565b6132eb335f61020b01610ac2565b6133096133016132fc61020c610dba565b610ddb565b61020c610e4a565b3361331561020c610dba565b7fbc2748cf02f7a1291525e866efc76ab3b96d32d7afcbb26c53daec617b38b4799161334b6133426100d2565b92839283612e94565b0390a1565b506132dd3361336f6133696133645f610888565b61031f565b9161031f565b1490506132d4565b61337f61326f565b565b5f7f656d707479206f70657261746f72206461746100000000000000000000000000910152565b6133b56013602092610895565b6133be81613381565b0190565b6133d79060208101905f8183039101526133a8565b90565b156133e157565b6133e96100d2565b62461bcd60e51b8152806133ff600482016133c2565b0390fd5b61341761341261341c92610511565b610920565b610454565b90565b5f7f6f70657261746f72206461746120746f6f206c61726765000000000000000000910152565b6134536017602092610895565b61345c8161341f565b0190565b6134759060208101905f818303910152613446565b90565b1561347f57565b6134876100d2565b62461bcd60e51b81528061349d60048201613460565b0390fd5b6134e6906134c1816134bb6134b55f6111e5565b91610454565b116133da565b6134df6134d96134d45f6102080161243f565b613403565b91610454565b1115613478565b565b6134fc6134f761350192610168565b610920565b610454565b90565b6135239061351d61351761352894610454565b91610454565b90610b47565b610454565b90565b61355290613537610bb1565b509161354d6135476001926134e8565b9161229a565b613504565b1790565b5f90565b613562613556565b506135716001610209016113fa565b61358361357d5f6111e5565b91610454565b141590565b613590613556565b5061359e5f61020b01610888565b6135b86135b26135ad5f611dff565b61031f565b9161031f565b141590565b6135d1906135c9613556565b509119610454565b166135e46135de5f6111e5565b91610454565b1490565b6135fa906135f4610bb1565b5061386d565b90565b61362490613609613556565b509161361f6136196001926134e8565b9161229a565b613504565b166136376136315f6111e5565b91610454565b1490565b61366290613647613556565b509161365d6136576001926134e8565b9161229a565b613504565b1661367561366f5f6111e5565b91610454565b141590565b6136a46136aa91613689610bb1565b509261369f6136996001926134e8565b9161229a565b613504565b19610454565b1690565b90565b6136c56136c06136ca926136ae565b610920565b610454565b90565b90565b6136e46136df6136e9926136cd565b610920565b610168565b90565b61370b906137056136ff61371094610168565b91610454565b90610b47565b610454565b90565b6137329061372c61372661373794610454565b91610454565b90610c3f565b610454565b90565b90565b61375161374c6137569261373a565b610920565b610454565b90565b90565b61377061376b61377592613759565b610920565b610168565b90565b90565b61378f61378a61379492613778565b610920565b610454565b90565b90565b6137ae6137a96137b392613797565b610920565b610168565b90565b90565b6137cd6137c86137d2926137b6565b610920565b610454565b90565b90565b6137ec6137e76137f1926137d5565b610920565b610168565b90565b90565b61380b613806613810926137f4565b610920565b610454565b90565b90565b61382a61382561382f92613813565b610920565b610168565b90565b90565b61384961384461384e92613832565b610920565b610454565b90565b61386561386061386a92611844565b610920565b610168565b90565b613875610bb1565b506138b56138a58261389f6138996fffffffffffffffffffffffffffffffff6136b1565b91610454565b11613a02565b6138af60076136d0565b906136ec565b6138f66138e66138c6848490613713565b6138e06138da67ffffffffffffffff61373d565b91610454565b11613a02565b6138f0600661375c565b906136ec565b17613934613924613908848490613713565b61391e61391863ffffffff61377b565b91610454565b11613a02565b61392e600561379a565b906136ec565b17613970613960613946848490613713565b61395a61395461ffff6137b9565b91610454565b11613a02565b61396a60046137d8565b906136ec565b176139ab61399b613982848490613713565b61399561398f60ff6137f7565b91610454565b11613a02565b6139a56003613816565b906136ec565b176139e66139d66139bd848490613713565b6139d06139ca600f613835565b91610454565b11613a02565b6139e06002613851565b906136ec565b17906d010102020202030303030303030360801b90821c1a1790565b613a0a610bb1565b5015159056fea2646970667358221220bc4a2db5c2380b433af49bee3a9ba8346459244bbf4bf330a5ad42faf155a8c364736f6c634300081c0033","sourceMap":"993:7551:24:-:0;;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;:::i;:::-;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;:::i;:::-;;;;;;;;;;:::o;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;:::o;:::-;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;:::o;:::-;;;:::o;:::-;;:::o;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;:::o;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;:::i;:::-;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;:::o;:::-;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;:::i;:::-;:::o;:::-;;;;:::o;:::-;;:::o;:::-;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;:::o;:::-;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;:::o;:::-;;;;;;;:::o;:::-;;;:::o;:::-;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;:::i;:::-;;;;;:::i;:::-;;;:::o;:::-;;;:::o;:::-;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;;;;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;:::o;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;:::i;:::-;;;;;;:::o;:::-;;;;;:::i;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;;;;:::i;:::-;:::o;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;:::o;:::-;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;:::o;:::-;;:::i;1315:800::-;1510:26;1315:800;1410:61;1418:23;:16;:23;:::i;:::-;:30;;1445:3;1418:30;:::i;:::-;;;:::i;:::-;;;1410:61;:::i;:::-;1482:18;1490:10;1482:18;;:::i;:::-;1510:26;;:::i;:::-;1568:13;1580:1;1568:13;:::i;:::-;1612:3;1583:1;:27;;1587:23;:16;:23;:::i;:::-;1583:27;:::i;:::-;;;:::i;:::-;;;;;1612:3;1656:16;:31;;:24;:19;:16;1673:1;1656:19;;:::i;:::-;;:24;;:31;:::i;:::-;;:::i;:::-;1702:87;1710:56;1711:55;;:47;:13;;:21;1733:24;:16;:19;:16;1750:1;1733:19;;:::i;:::-;;:24;;:::i;:::-;1711:47;;:::i;:::-;:55;;:::i;:::-;1710:56;;:::i;:::-;1702:87;:::i;:::-;1804:94;1874:4;1854:44;1887:8;1893:1;1887:8;:::i;:::-;1854:44;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::i;:::-;1804:47;:21;:13;:21;1826:24;;:19;:16;1843:1;1826:19;;:::i;:::-;;:24;;:::i;:::-;1804:47;;:::i;:::-;:94;:::i;:::-;1912:44;1937:19;:16;1954:1;1937:19;;:::i;:::-;;1912:22;:19;:13;:19;1932:1;1912:22;;:::i;:::-;:44;;:::i;:::-;1612:3;:::i;:::-;1568:13;;1583:27;;2001:44;2014:30;2020:23;1977:68;1583:27;2020:23;:::i;:::-;2014:30;:::i;:::-;2001:44;:::i;:::-;1977:21;:13;:21;:68;:::i;:::-;2055:53;2087:21;;:13;:21;;:::i;:::-;2055:29;:12;:9;2065:1;2055:12;;:::i;:::-;;:29;:53;:::i;:::-;1315:800::o;993:7551::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;8083:205;8207:74;8083:205;8156:41;8164:5;:9;;8172:1;8164:9;:::i;:::-;;;:::i;:::-;;8156:41;:::i;:::-;8215:38;;8224:29;;:8;:29;;:::i;:::-;8215:38;:::i;:::-;;;:::i;:::-;;;8207:74;:::i;:::-;8083:205::o;993:7551::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;:::o;:::-;;:::i;9237:101::-;9311:15;9310:21;9237:101;9283:7;;:::i;:::-;9311:1;:15;9316:10;9311:1;9324;9316:10;:::i;:::-;9311:15;;:::i;:::-;;:::i;:::-;9310:21;9330:1;9310:21;:::i;:::-;;;:::i;:::-;9303:28;:::o","linkReferences":{}},"deployedBytecode":{"object":"0x60806040526004361015610013575b6107fc565b61001d5f356100cc565b806326322217146100c75780632b726062146100c257806347011c5c146100bd57806353bfb584146100b857806365706f9c146100b357806375418b9d146100ae5780639d44e717146100a9578063c05665dd146100a4578063e88e97491461009f578063f2fde38b1461009a5763f5f2d9f10361000e576107c9565b610796565b610763565b610730565b6106bc565b610646565b6102e1565b61027d565b61023b565b6101d6565b610135565b60e01c90565b60405190565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b908160409103126100f65790565b6100e4565b9060208282031261012b575f82013567ffffffffffffffff81116101265761012392016100e8565b90565b6100e0565b6100dc565b5f0190565b346101635761014d6101483660046100fb565b610f6e565b6101556100d2565b8061015f81610130565b0390f35b6100d8565b60ff1690565b61017781610168565b0361017e57565b5f80fd5b9050359061018f8261016e565b565b9190916040818403126101d1576101aa835f8301610182565b92602082013567ffffffffffffffff81116101cc576101c992016100e8565b90565b6100e0565b6100dc565b34610205576101ef6101e9366004610191565b906115ec565b6101f76100d2565b8061020181610130565b0390f35b6100d8565b908160409103126102185790565b6100e4565b9060408282031261023657610233915f0161020a565b90565b6100dc565b346102695761025361024e36600461021d565b611d3c565b61025b6100d2565b8061026581610130565b0390f35b6100d8565b5f91031261027857565b6100dc565b346102ab5761028d36600461026e565b610295611ef1565b61029d6100d2565b806102a781610130565b0390f35b6100d8565b908160209103126102be5790565b6100e4565b906020828203126102dc576102d9915f016102b0565b90565b6100dc565b3461030f576102f96102f43660046102c3565b612097565b6103016100d2565b8061030b81610130565b0390f35b6100d8565b60018060a01b031690565b61032890610314565b90565b6103349061031f565b9052565b5190565b60209181520190565b60200190565b5190565b60209181520190565b90825f9392825e0152565b601f801991011690565b61038c61039560209361039a936103838161034b565b9384809361034f565b95869101610358565b610363565b0190565b6103c991602060408201926103b95f8201515f85019061032b565b015190602081840391015261036d565b90565b906103d69161039e565b90565b60200190565b906103f36103ec83610338565b809261033c565b908161040460208302840194610345565b925f915b83831061041757505050505090565b90919293946020610439610433838560019503875289516103cc565b976103d9565b9301930191939290610408565b50600290565b905090565b90565b90565b61046090610454565b9052565b61046d90610168565b9052565b90602080610493936104895f8201515f860190610457565b0151910190610464565b565b906104a281604093610471565b0190565b60200190565b6104c86104c26104bb83610446565b809461044c565b91610451565b5f915b8383106104d85750505050565b6104ee6104e86001928451610495565b926104a6565b920191906104cb565b67ffffffffffffffff1690565b61050d906104f7565b9052565b61ffff1690565b61052190610511565b9052565b905f80610536930151910190610518565b565b9060208061055a936105505f8201515f860190610504565b0151910190610457565b565b905f8061056d93015191019061032b565b565b6fffffffffffffffffffffffffffffffff1690565b61058d9061056f565b9052565b9061062b9061016060e06105c561018084016105b35f8801515f87019061032b565b602087015185820360208701526103df565b946105d8604082015160408601906104ac565b6105ea606082015160c0860190610504565b6105fb608082015183860190610525565b61060e60a0820151610100860190610538565b61062160c082015161014086019061055c565b0151910190610584565b90565b6106439160208201915f818403910152610591565b90565b346106765761065636600461026e565b61067261066161266b565b6106696100d2565b9182918261062e565b0390f35b6100d8565b610684816104f7565b0361068b57565b5f80fd5b9050359061069c8261067b565b565b906020828203126106b7576106b4915f0161068f565b90565b6100dc565b346106ea576106d46106cf36600461069e565b612bde565b6106dc6100d2565b806106e681610130565b0390f35b6100d8565b6106f88161031f565b036106ff57565b5f80fd5b90503590610710826106ef565b565b9060208282031261072b57610728915f01610703565b90565b6100dc565b3461075e57610748610743366004610712565b61305a565b6107506100d2565b8061075a81610130565b0390f35b6100d8565b346107915761077b61077636600461069e565b6131bc565b6107836100d2565b8061078d81610130565b0390f35b6100d8565b346107c4576107ae6107a9366004610712565b613264565b6107b66100d2565b806107c081610130565b0390f35b6100d8565b346107f7576107d936600461026e565b6107e1613377565b6107e96100d2565b806107f381610130565b0390f35b6100d8565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b90359060016020038136030382121561084e570180359067ffffffffffffffff82116108495760200191600182023603831361084457565b610808565b610804565b610800565b5090565b35610861816106ef565b90565b5f1c90565b60018060a01b031690565b61088061088591610864565b610869565b90565b6108929054610874565b90565b60209181520190565b5f7f756e617574686f72697a65640000000000000000000000000000000000000000910152565b6108d2600c602092610895565b6108db8161089e565b0190565b6108f49060208101905f8183039101526108c5565b90565b156108fe57565b6109066100d2565b62461bcd60e51b81528061091c600482016108df565b0390fd5b90565b61093761093261093c92610314565b610920565b610314565b90565b61094890610923565b90565b6109549061093f565b90565b906109619061094b565b5f5260205260405f2090565b90565b60ff1690565b61098261098791610864565b610970565b90565b6109949054610976565b90565b5f7f756e6b6e6f776e206f70657261746f7200000000000000000000000000000000910152565b6109cb6010602092610895565b6109d481610997565b0190565b6109ed9060208101905f8183039101526109be565b90565b156109f757565b6109ff6100d2565b62461bcd60e51b815280610a15600482016109d8565b0390fd5b60081c90565b60ff1690565b610a31610a3691610a19565b610a1f565b90565b610a439054610a25565b90565b634e487b7160e01b5f52603260045260245ffd5b5061010090565b90565b610a6d81610a5a565b821015610a8757610a7f600291610a61565b910201905f90565b610a46565b634e487b7160e01b5f525f60045260245ffd5b5f1b90565b90610ab560018060a01b0391610a9f565b9181191691161790565b90565b90610ad7610ad2610ade9261094b565b610abf565b8254610aa4565b9055565b634e487b7160e01b5f52604160045260245ffd5b634e487b7160e01b5f52602260045260245ffd5b9060016002830492168015610b2a575b6020831014610b2557565b610af6565b91607f1691610b1a565b5f5260205f2090565b601f602091010490565b1b90565b91906008610b66910291610b605f1984610b47565b92610b47565b9181191691161790565b610b84610b7f610b8992610454565b610920565b610454565b90565b90565b9190610ba5610ba0610bad93610b70565b610b8c565b908354610b4b565b9055565b5f90565b610bc791610bc1610bb1565b91610b8f565b565b5b818110610bd5575050565b80610be25f600193610bb5565b01610bca565b9190601f8111610bf8575b505050565b610c04610c2993610b34565b906020610c1084610b3d565b83019310610c31575b610c2290610b3d565b0190610bc9565b5f8080610bf3565b9150610c2281929050610c19565b1c90565b90610c53905f1990600802610c3f565b191690565b81610c6291610c43565b906002021790565b91610c759082610853565b9067ffffffffffffffff8211610d3457610c9982610c938554610b0a565b85610be8565b5f90601f8311600114610ccc57918091610cbb935f92610cc0575b5050610c58565b90555b565b90915001355f80610cb4565b601f19831691610cdb85610b34565b925f5b818110610d1c57509160029391856001969410610d02575b50505002019055610cbe565b610d12910135601f841690610c43565b90555f8080610cf6565b91936020600181928787013581550195019201610cde565b610ae2565b90610d449291610c6a565b565b90610d736001610d7993610d675f8201610d615f8701610857565b90610ac2565b0191602081019061080c565b91610d39565b565b9190610d8c57610d8a91610d46565b565b610a8c565b6fffffffffffffffffffffffffffffffff1690565b610db2610db791610864565b610d91565b90565b610dc49054610da6565b90565b634e487b7160e01b5f52601160045260245ffd5b610de49061056f565b6fffffffffffffffffffffffffffffffff8114610e015760010190565b610dc7565b90610e216fffffffffffffffffffffffffffffffff91610a9f565b9181191691161790565b610e3f610e3a610e449261056f565b610920565b61056f565b90565b90565b90610e5f610e5a610e6692610e2b565b610e47565b8254610e06565b9055565b50610e79906020810190610703565b90565b5f80fd5b5f80fd5b5f80fd5b9035600160200382360303811215610ec957016020813591019167ffffffffffffffff8211610ec4576001820236038313610ebf57565b610e80565b610e7c565b610e84565b90825f939282370152565b9190610ef381610eec81610ef89561034f565b8095610ece565b610363565b0190565b610f3891610f2a6040820192610f20610f175f830183610e6a565b5f85019061032b565b6020810190610e88565b916020818503910152610ed9565b90565b610f449061056f565b9052565b92916020610f64610f6c9360408701908782035f890152610efc565b940190610f3b565b565b610f8d610f88610f8283602081019061080c565b90610853565b6134a1565b33610faa610fa4610f9f5f8501610857565b61031f565b9161031f565b148015611075575b610fbb906108f7565b611011610fde610fd95f600101610fd35f8601610857565b90610957565b61096d565b610ff1610fec5f830161098a565b6109f0565b61100b83916110055f600180019201610a39565b90610a64565b90610d7b565b61102f61102761102261020c610dba565b610ddb565b61020c610e4a565b61103a61020c610dba565b7f5aab2c32b1e447db4dba1d2790fe8b863d4775042b10b92e00dab9d6b671b5b5916110706110676100d2565b92839283610f48565b0390a1565b50610fbb3361109461108e6110895f610888565b61031f565b9161031f565b149050610fb2565b5f7f6e6f7420746865206f776e657200000000000000000000000000000000000000910152565b6110d0600d602092610895565b6110d98161109c565b0190565b6110f29060208101905f8183039101526110c3565b90565b156110fc57565b6111046100d2565b62461bcd60e51b81528061111a600482016110dd565b0390fd5b9061114c916111473361114161113b6111365f610888565b61031f565b9161031f565b146110f5565b61147f565b565b151590565b5f7f616c726561647920657869737473000000000000000000000000000000000000910152565b611187600e602092610895565b61119081611153565b0190565b6111a99060208101905f81830391015261117a565b90565b156111b357565b6111bb6100d2565b62461bcd60e51b8152806111d160048201611194565b0390fd5b6111df9054610b0a565b90565b90565b6111f96111f46111fe926111e2565b610920565b610454565b90565b5f7f736c6f74206f6363757069656400000000000000000000000000000000000000910152565b611235600d602092610895565b61123e81611201565b0190565b6112579060208101905f818303910152611228565b90565b1561126157565b6112696100d2565b62461bcd60e51b81528061127f60048201611242565b0390fd5b9061128d90610363565b810190811067ffffffffffffffff8211176112a757604052565b610ae2565b906112bf6112b86100d2565b9283611283565b565b6112cb60406112ac565b90565b906112d89061114e565b9052565b906112e690610168565b9052565b6112f4905161114e565b90565b9061130360ff91610a9f565b9181191691161790565b6113169061114e565b90565b90565b9061133161132c6113389261130d565b611319565b82546112f7565b9055565b6113469051610168565b90565b60081b90565b9061135c61ff0091611349565b9181191691161790565b61137a61137561137f92610168565b610920565b610168565b90565b90565b9061139a6113956113a192611366565b611382565b825461134f565b9055565b906113cf60205f6113d5946113c78282016113c18488016112ea565b9061131c565b01920161133c565b90611385565b565b906113e1916113a5565b565b90565b6113f26113f791610864565b6113e3565b90565b61140490546113e6565b90565b906114135f1991610a9f565b9181191691161790565b9061143261142d61143992610b70565b610b8c565b8254611407565b9055565b61144690610168565b9052565b93929061147560409161147d9461146860608901925f8a019061143d565b8782036020890152610efc565b940190610f3b565b565b61149e61149961149384602081019061080c565b90610853565b6134a1565b6114d16114cc6114c65f6114c0816001016114ba838901610857565b90610957565b0161098a565b1561114e565b6111ac565b6115056114ed60016114e68180018590610a64565b50016111d5565b6114ff6114f95f6111e5565b91610454565b1461125a565b611548600161152b836115226115196112c1565b935f85016112ce565b602083016112dc565b6115435f60010161153d5f8701610857565b90610957565b6113d7565b6115608261155a600180018490610a64565b90610d7b565b61158661157b6115746102016001016113fa565b839061352b565b61020160010161141d565b6115a461159c61159761020c610dba565b610ddb565b61020c610e4a565b906115b061020c610dba565b916115e77f952e65f049c574f487580ba41dcf6b0ea8350ef8abc8647a8a11dfaa7af6bad6936115de6100d2565b9384938461144a565b0390a1565b906115f69161111e565b565b611625906116203361161a61161461160f5f610888565b61031f565b9161031f565b146110f5565b6116a9565b565b5f7f6d6967726174696f6e20696e2070726f67726573730000000000000000000000910152565b61165b6015602092610895565b61166481611627565b0190565b61167d9060208101905f81830391015261164e565b90565b1561168757565b61168f6100d2565b62461bcd60e51b8152806116a560048201611668565b0390fd5b6116cb906116c66116c16116bb61355a565b1561114e565b611680565b61174f565b565b5f7f6d61696e74656e616e636520696e2070726f6772657373000000000000000000910152565b6117016017602092610895565b61170a816116cd565b0190565b6117239060208101905f8183039101526116f4565b90565b1561172d57565b6117356100d2565b62461bcd60e51b81528061174b6004820161170e565b0390fd5b6117719061176c611767611761613588565b1561114e565b611726565b611b76565b565b61177c81610454565b0361178357565b5f80fd5b3561179181611773565b90565b5f7f696e76616c6964206269746d61736b0000000000000000000000000000000000910152565b6117c8600f602092610895565b6117d181611794565b0190565b6117ea9060208101905f8183039101526117bb565b90565b156117f457565b6117fc6100d2565b62461bcd60e51b815280611812600482016117d5565b0390fd5b67ffffffffffffffff1690565b61182f61183491610864565b611816565b90565b6118419054611823565b90565b90565b61185b61185661186092611844565b610920565b6104f7565b90565b634e487b7160e01b5f52601260045260245ffd5b611883611889916104f7565b916104f7565b908115611894570690565b611863565b50600290565b90565b6118ab81611899565b8210156118c5576118bd60029161189f565b910201905f90565b610a46565b906118d490610454565b9052565b6118e46118e991610864565b610a1f565b90565b6118f690546118d8565b90565b61190360406112ac565b90565b9061193d61193460016119176118f9565b9461192e6119265f83016113fa565b5f88016118ca565b016118ec565b602084016112dc565b565b61194890611906565b90565b6119559051610454565b90565b356119628161016e565b90565b5f7f73616d65206b6579737061636500000000000000000000000000000000000000910152565b611999600d602092610895565b6119a281611965565b0190565b6119bb9060208101905f81830391015261198c565b90565b156119c557565b6119cd6100d2565b62461bcd60e51b8152806119e3600482016119a6565b0390fd5b6119f0906104f7565b67ffffffffffffffff8114611a055760010190565b610dc7565b90611a1d67ffffffffffffffff91610a9f565b9181191691161790565b611a3b611a36611a40926104f7565b610920565b6104f7565b90565b90565b90611a5b611a56611a6292611a27565b611a43565b8254611a0a565b9055565b90611a7b611a76611a8292611366565b611382565b82546112f7565b9055565b90611ab160206001611ab794611aa95f8201611aa35f8801611787565b9061141d565b019201611958565b90611a66565b565b9190611aca57611ac891611a86565b565b610a8c565b611ad8906104f7565b9052565b90503590611ae982611773565b565b50611afa906020810190611adc565b90565b50611b0c906020810190610182565b90565b906020611b3a611b4293611b31611b285f830183611aeb565b5f860190610457565b82810190611afd565b910190610464565b565b606090611b6d611b749496959396611b6360808401985f850190611acf565b6020830190611b0f565b0190610f3b565b565b611ba0611b9b611b875f8401611787565b611b956102016001016113fa565b906135bd565b6117ed565b611c0d611bd6611bd0610203611bca611bba610207611837565b611bc46002611847565b90611877565b906118a2565b5061193f565b611be15f820161194b565b611bfd611bf7611bf25f8701611787565b610454565b91610454565b1415908115611d0a575b506119be565b611c2c5f61020901611c26611c2182611837565b6119e7565b90611a46565b611c4a611c42611c3d610207611837565b6119e7565b610207611a46565b611c7e81611c78610203611c72611c62610207611837565b611c6c6002611847565b90611877565b906118a2565b90611ab9565b611c97611c8c5f8301611787565b60016102090161141d565b611cb5611cad611ca861020c610dba565b610ddb565b61020c610e4a565b611cc25f61020901611837565b90611cce61020c610dba565b91611d057f490341fd8fc7a8294fbad1cc0db9f41ae0ac5aeb655ea31b46a475ec3a77749c93611cfc6100d2565b93849384611b44565b0390a1565b611d17915060200161133c565b611d34611d2e611d2960208601611958565b610168565b91610168565b14155f611c07565b611d45906115f8565b565b5f7f6e6f206d61696e74656e616e6365000000000000000000000000000000000000910152565b611d7b600e602092610895565b611d8481611d47565b0190565b611d9d9060208101905f818303910152611d6e565b90565b15611da757565b611daf6100d2565b62461bcd60e51b815280611dc560048201611d88565b0390fd5b611dd9611dd4613588565b611da0565b611de1611e20565b565b611df7611df2611dfc926111e2565b610920565b610314565b90565b611e0890611de3565b90565b9190611e1e905f60208501940190610f3b565b565b611e2d5f61020b01610888565b611e3f611e393361031f565b9161031f565b148015611eca575b611e50906108f7565b611e66611e5c5f611dff565b5f61020b01610ac2565b611e84611e7c611e7761020c610dba565b610ddb565b61020c610e4a565b611e8f61020c610dba565b611ec57f11943d6deda6f0591d72674788d272eb0209e18b8a3a021fa51cb3b5e9a2ab6191611ebc6100d2565b91829182611e0b565b0390a1565b50611e5033611ee9611ee3611ede5f610888565b61031f565b9161031f565b149050611e47565b611ef9611dc9565b565b611f2890611f2333611f1d611f17611f125f610888565b61031f565b9161031f565b146110f5565b612027565b565b611f3381610511565b03611f3a57565b5f80fd5b35611f4881611f2a565b90565b90611f5861ffff91610a9f565b9181191691161790565b611f76611f71611f7b92610511565b610920565b610511565b90565b90565b90611f96611f91611f9d92611f62565b611f7e565b8254611f4b565b9055565b90611fb35f80611fb994019201611f3e565b90611f81565b565b90611fc591611fa1565b565b90503590611fd482611f2a565b565b50611fe5906020810190611fc7565b90565b905f611ffa6120029382810190611fd6565b910190610518565b565b91602061202592949361201e60408201965f830190611fe8565b0190610f3b565b565b61203381610208611fbb565b61205161204961204461020c610dba565b610ddb565b61020c610e4a565b61205c61020c610dba565b7fb24d8d9dcfbb6be13176c1c7bfb0e76445a9ba2a3553b413d8671446f1030830916120926120896100d2565b92839283612004565b0390a1565b6120a090611efb565b565b6120ad6101006112ac565b90565b5f90565b606090565b67ffffffffffffffff81116120ce5760200290565b610ae2565b6120df6120e4916120b9565b6112ac565b90565b5f90565b5f90565b6120f76118f9565b90602080836121046120e7565b81520161210f6120eb565b81525050565b61211d6120ef565b90565b5f5b82811061212e57505050565b602090612139612115565b8184015201612122565b90612161612150836120d3565b9261215b84916120b9565b90612120565b565b61216d6002612143565b90565b5f90565b61217e60206112ac565b90565b5f90565b61218d612174565b90602082612199612181565b81525050565b6121a7612185565b90565b6121b460406112ac565b90565b6121bf6121aa565b90602080836121cc612170565b8152016121d76120e7565b81525050565b6121e56121b7565b90565b6121f260206112ac565b90565b6121fd6121e8565b906020826122096120b0565b81525050565b6122176121f5565b90565b5f90565b6122266120a2565b90602080808080808080896122396120b0565b8152016122446120b4565b81520161224f612163565b81520161225a612170565b81520161226561219f565b8152016122706121dd565b81520161227b61220f565b81520161228661221a565b81525050565b61229461221e565b90565b90565b6122ae6122a96122b392612297565b610920565b610454565b90565b6122c56122cb91939293610454565b92610454565b82018092116122d657565b610dc7565b67ffffffffffffffff81116122f35760208091020190565b610ae2565b9061230a612305836122db565b6112ac565b918252565b61231960406112ac565b90565b606090565b61232961230f565b90602080836123366120b0565b81520161234161231c565b81525050565b61234f612321565b90565b5f5b82811061236057505050565b60209061236b612347565b8184015201612354565b9061239a612382836122f8565b9260208061239086936122db565b9201910390612352565b565b6123a76101006112ac565b90565b906123b49061031f565b9052565b52565b906123c582611899565b6123ce816120d3565b926123d9849161189f565b5f915b8383106123e95750505050565b600260206001926123f98561193f565b8152019201920191906123dc565b612410906123bb565b90565b52565b90612420906104f7565b9052565b61ffff1690565b61243761243c91610864565b612424565b90565b612449905461242b565b90565b9061245690610511565b9052565b906124796124715f61246a612174565b940161243f565b5f840161244c565b565b6124849061245a565b90565b52565b906124c16124b8600161249b6121aa565b946124b26124aa5f8301611837565b5f8801612416565b016113fa565b602084016118ca565b565b6124cc9061248a565b90565b52565b906124f16124e95f6124e26121e8565b9401610888565b5f84016123aa565b565b6124fc906124d2565b90565b52565b9061250c9061056f565b9052565b61251990610454565b5f1981146125275760010190565b610dc7565b61254061253b61254592610454565b610920565b610168565b90565b9061255282610338565b811015612563576020809102010190565b610a46565b905f929180549061258261257b83610b0a565b809461034f565b916001811690815f146125d9575060011461259d575b505050565b6125aa9192939450610b34565b915f925b8184106125c157505001905f8080612598565b600181602092959395548486015201910192906125ae565b92949550505060ff19168252151560200201905f8080612598565b906125fe91612568565b90565b9061262161261a926126116100d2565b938480926125f4565b0383611283565b565b52565b9061265d612654600161263761230f565b9461264e6126465f8301610888565b5f88016123aa565b01612601565b60208401612623565b565b61266890612626565b90565b61267361228c565b50600161020101612683906113fa565b61268c906135e8565b6126955f610888565b8160016126a19061229a565b6126aa916122b6565b6126b390612375565b6102036126c1610207611837565b6102086102099161020b936126d761020c610dba565b956126e061239c565b975f8901906126ee916123aa565b60208801906126fc916123b8565b61270590612407565b604087019061271391612413565b606086019061272191612416565b61272a9061247b565b608085019061273891612487565b612741906124c3565b60a084019061274f916124cf565b612758906124f3565b60c0830190612766916124ff565b60e082019061277491612502565b600161020101612783906113fa565b925f61278e906111e5565b5b806127a261279c86610454565b91610454565b11612805576127fb906127be866127b88361252c565b906135fd565b612800576127f36127d3600180018390610a64565b5060208601516127e3849261265f565b6127ed8383612548565b52612548565b51505b612510565b61278f565b6127f6565b509250905090565b5f7f6e6f206d6967726174696f6e0000000000000000000000000000000000000000910152565b612841600c602092610895565b61284a8161280d565b0190565b6128639060208101905f818303910152612834565b90565b1561286d57565b6128756100d2565b62461bcd60e51b81528061288b6004820161284e565b0390fd5b6128a8906128a361289e61355a565b612866565b612a3e565b565b5f7f77726f6e67206d6967726174696f6e2069640000000000000000000000000000910152565b6128de6012602092610895565b6128e7816128aa565b0190565b6129009060208101905f8183039101526128d1565b90565b1561290a57565b6129126100d2565b62461bcd60e51b815280612928600482016128eb565b0390fd5b61293660406112ac565b90565b9061296f6129665f61294961292c565b9461296061295883830161098a565b8388016112ce565b01610a39565b602084016112dc565b565b61297a90612939565b90565b5f7f6e6f742070756c6c696e67000000000000000000000000000000000000000000910152565b6129b1600b602092610895565b6129ba8161297d565b0190565b6129d39060208101905f8183039101526129a4565b90565b156129dd57565b6129e56100d2565b62461bcd60e51b8152806129fb600482016129be565b0390fd5b612a089061031f565b9052565b604090612a35612a3c9496959396612a2b60608401985f850190611acf565b60208301906129ff565b0190610f3b565b565b612a6690612a60612a5a612a555f61020901611837565b6104f7565b916104f7565b14612903565b612aeb612ae0612a82612a7d5f6001013390610957565b612971565b612a95612a905f83016112ea565b6109f0565b612ac0612abb612aa96001610209016113fa565b612ab56020850161133c565b9061363b565b6129d6565b612ada6020612ad36001610209016113fa565b920161133c565b9061367a565b60016102090161141d565b612b09612b01612afc61020c610dba565b610ddb565b61020c610e4a565b612b176001610209016113fa565b612b29612b235f6111e5565b91610454565b145f14612b8657612b3d5f61020901611837565b33612b4961020c610dba565b91612b807f01269879535f40ee8957e15e160bf1866c5e2728ff0cbc583d848821e2639b4e93612b776100d2565b93849384612a0c565b0390a15b565b612b935f61020901611837565b33612b9f61020c610dba565b91612bd67faf5e90e72015f43138f66b4cd08bd1dfa2839030104f22a00af843fe847c6d1993612bcd6100d2565b93849384612a0c565b0390a1612b84565b612be79061288f565b565b612c1690612c1133612c0b612c05612c005f610888565b61031f565b9161031f565b146110f5565b612eb7565b565b5f7f696e206b65797370616365000000000000000000000000000000000000000000910152565b612c4c600b602092610895565b612c5581612c18565b0190565b612c6e9060208101905f818303910152612c3f565b90565b15612c7857565b612c806100d2565b62461bcd60e51b815280612c9660048201612c59565b0390fd5b5f80910155565b905f03612cb357612cb190612c9a565b565b610a8c565b90612ccb905f1990602003600802610c3f565b8154169055565b905f91612ce9612ce182610b34565b928354610c58565b905555565b919290602082105f14612d4757601f8411600114612d1757612d11929350610c58565b90555b5b565b5090612d3d612d42936001612d34612d2e85610b34565b92610b3d565b82019101610bc9565b612cd2565b612d14565b50612d7e8293612d58600194610b34565b612d77612d6485610b3d565b820192601f861680612d89575b50610b3d565b0190610bc9565b600202179055612d15565b612d9590888603612cb8565b5f612d71565b929091680100000000000000008211612dfb576020115f14612dec57602081105f14612dd057612dca91610c58565b90555b5b565b60019160ff1916612de084610b34565b55600202019055612dcd565b60019150600202019055612dce565b610ae2565b908154612e0c81610b0a565b90818311612e35575b818310612e23575b50505050565b612e2c93612cee565b5f808080612e1d565b612e4183838387612d9b565b612e15565b5f612e5091612e00565b565b905f03612e6457612e6290612e46565b565b610a8c565b5f6001612e7b92828082015501612e52565b565b905f03612e8f57612e8d90612e69565b565b610a8c565b916020612eb5929493612eae60408201965f8301906129ff565b0190610f3b565b565b612f7c612f71612ef05f612ed7612ed2826001018790610957565b61096d565b612eea612ee583830161098a565b6109f0565b01610a39565b612ef861355a565b5f1461300e57612f20612f195f612f1261020382906118a2565b50016113fa565b82906135fd565b80612fe0575b612f2f90612c71565b5b612f475f612f42816001018790610957565b612ca1565b612f5e612f58600180018390610a64565b90612e7d565b612f6c6102016001016113fa565b61367a565b61020160010161141d565b612f9a612f92612f8d61020c610dba565b610ddb565b61020c610e4a565b612fa561020c610dba565b7f6a1d7ddc82d57e783a3ae60737a6c1a4704fcf38d966561fea0af8564f2d895d91612fdb612fd26100d2565b92839283612e94565b0390a1565b50612f2f6130076130005f612ff96102036001906118a2565b50016113fa565b83906135fd565b9050612f26565b6130556130506130495f61304261020361303c61302c610207611837565b6130366002611847565b90611877565b906118a2565b50016113fa565b83906135fd565b612c71565b612f30565b61306390612be9565b565b6130929061308d3361308761308161307c5f610888565b61031f565b9161031f565b146110f5565b613094565b565b6130ad906130a86130a361355a565b612866565b6130ee565b565b6130b8906104f7565b5f81146130c6576001900390565b610dc7565b9160206130ec9294936130e560408201965f830190611acf565b0190610f3b565b565b6131169061311061310a6131055f61020901611837565b6104f7565b916104f7565b14612903565b61313461312c613127610207611837565b6130af565b610207611a46565b61314b6131405f6111e5565b60016102090161141d565b61316961316161315c61020c610dba565b610ddb565b61020c610e4a565b6131765f61020901611837565b61318161020c610dba565b7ff73240422246f63ed633ef3ce0726b8ab8fb69d46c8a4e5ecb0b2922668674a1916131b76131ae6100d2565b928392836130cb565b0390a1565b6131c590613065565b565b6131f4906131ef336131e96131e36131de5f610888565b61031f565b9161031f565b146110f5565b6131f6565b565b613200815f610ac2565b61321e61321661321161020c610dba565b610ddb565b61020c610e4a565b61322961020c610dba565b7f476610ebc6647c15376100955efbf22ef2a0c3b923fc00b380b660c873ef20ac9161325f6132566100d2565b92839283612e94565b0390a1565b61326d906131c7565b565b61328861328361327d61355a565b1561114e565b611680565b613290613292565b565b6132ab6132a66132a0613588565b1561114e565b611726565b6132b36132b5565b565b6132cd5f6132c7816001013390610957565b0161098a565b8015613350575b6132dd906108f7565b6132eb335f61020b01610ac2565b6133096133016132fc61020c610dba565b610ddb565b61020c610e4a565b3361331561020c610dba565b7fbc2748cf02f7a1291525e866efc76ab3b96d32d7afcbb26c53daec617b38b4799161334b6133426100d2565b92839283612e94565b0390a1565b506132dd3361336f6133696133645f610888565b61031f565b9161031f565b1490506132d4565b61337f61326f565b565b5f7f656d707479206f70657261746f72206461746100000000000000000000000000910152565b6133b56013602092610895565b6133be81613381565b0190565b6133d79060208101905f8183039101526133a8565b90565b156133e157565b6133e96100d2565b62461bcd60e51b8152806133ff600482016133c2565b0390fd5b61341761341261341c92610511565b610920565b610454565b90565b5f7f6f70657261746f72206461746120746f6f206c61726765000000000000000000910152565b6134536017602092610895565b61345c8161341f565b0190565b6134759060208101905f818303910152613446565b90565b1561347f57565b6134876100d2565b62461bcd60e51b81528061349d60048201613460565b0390fd5b6134e6906134c1816134bb6134b55f6111e5565b91610454565b116133da565b6134df6134d96134d45f6102080161243f565b613403565b91610454565b1115613478565b565b6134fc6134f761350192610168565b610920565b610454565b90565b6135239061351d61351761352894610454565b91610454565b90610b47565b610454565b90565b61355290613537610bb1565b509161354d6135476001926134e8565b9161229a565b613504565b1790565b5f90565b613562613556565b506135716001610209016113fa565b61358361357d5f6111e5565b91610454565b141590565b613590613556565b5061359e5f61020b01610888565b6135b86135b26135ad5f611dff565b61031f565b9161031f565b141590565b6135d1906135c9613556565b509119610454565b166135e46135de5f6111e5565b91610454565b1490565b6135fa906135f4610bb1565b5061386d565b90565b61362490613609613556565b509161361f6136196001926134e8565b9161229a565b613504565b166136376136315f6111e5565b91610454565b1490565b61366290613647613556565b509161365d6136576001926134e8565b9161229a565b613504565b1661367561366f5f6111e5565b91610454565b141590565b6136a46136aa91613689610bb1565b509261369f6136996001926134e8565b9161229a565b613504565b19610454565b1690565b90565b6136c56136c06136ca926136ae565b610920565b610454565b90565b90565b6136e46136df6136e9926136cd565b610920565b610168565b90565b61370b906137056136ff61371094610168565b91610454565b90610b47565b610454565b90565b6137329061372c61372661373794610454565b91610454565b90610c3f565b610454565b90565b90565b61375161374c6137569261373a565b610920565b610454565b90565b90565b61377061376b61377592613759565b610920565b610168565b90565b90565b61378f61378a61379492613778565b610920565b610454565b90565b90565b6137ae6137a96137b392613797565b610920565b610168565b90565b90565b6137cd6137c86137d2926137b6565b610920565b610454565b90565b90565b6137ec6137e76137f1926137d5565b610920565b610168565b90565b90565b61380b613806613810926137f4565b610920565b610454565b90565b90565b61382a61382561382f92613813565b610920565b610168565b90565b90565b61384961384461384e92613832565b610920565b610454565b90565b61386561386061386a92611844565b610920565b610168565b90565b613875610bb1565b506138b56138a58261389f6138996fffffffffffffffffffffffffffffffff6136b1565b91610454565b11613a02565b6138af60076136d0565b906136ec565b6138f66138e66138c6848490613713565b6138e06138da67ffffffffffffffff61373d565b91610454565b11613a02565b6138f0600661375c565b906136ec565b17613934613924613908848490613713565b61391e61391863ffffffff61377b565b91610454565b11613a02565b61392e600561379a565b906136ec565b17613970613960613946848490613713565b61395a61395461ffff6137b9565b91610454565b11613a02565b61396a60046137d8565b906136ec565b176139ab61399b613982848490613713565b61399561398f60ff6137f7565b91610454565b11613a02565b6139a56003613816565b906136ec565b176139e66139d66139bd848490613713565b6139d06139ca600f613835565b91610454565b11613a02565b6139e06002613851565b906136ec565b17906d010102020202030303030303030360801b90821c1a1790565b613a0a610bb1565b5015159056fea2646970667358221220bc4a2db5c2380b433af49bee3a9ba8346459244bbf4bf330a5ad42faf155a8c364736f6c634300081c0033","sourceMap":"993:7551:24:-:0;;;;;;;;;-1:-1:-1;993:7551:24;:::i;:::-;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;;;:::o;:::-;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;:::i;:::-;;;;:::o;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;:::o;:::-;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;:::i;:::-;;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;:::o;:::-;;;;;;;:::o;:::-;;;;:::o;:::-;;;:::o;:::-;;;;;;;:::o;:::-;;;;;;;;;;:::o;:::-;;;;;;;;:::o;:::-;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;;;;;;:::o;:::-;;;;:::o;:::-;;:::o;:::-;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;:::o;:::-;;;;;;;:::i;:::-;;;:::o;:::-;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;;;;:::o;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;;;:::i;:::-;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;;;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;:::o;:::-;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;:::o;:::-;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;:::o;:::-;;:::o;:::-;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;:::o;:::-;;;;;;;:::o;:::-;;;:::o;:::-;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;:::i;:::-;;;;;:::i;:::-;;;:::o;:::-;;;:::o;:::-;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;;;;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;:::o;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;:::i;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;;;;:::i;:::-;:::o;:::-;;:::i;:::-;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;;;;;;;;;:::o;:::-;;;;;;;;;;:::i;:::-;;;;:::i;:::-;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;:::o;5599:469::-;5703:20;;:13;:8;:13;;;;;:::i;:::-;:20;;:::i;:::-;;:::i;:::-;5742:10;:27;;5756:13;;:8;:13;;:::i;:::-;5742:27;:::i;:::-;;;:::i;:::-;;:50;;;;5599:469;5734:75;;;:::i;:::-;5948:41;5820:59;5843:36;:21;:13;:21;5865:13;;:8;:13;;:::i;:::-;5843:36;;:::i;:::-;5820:59;:::i;:::-;5889:40;5897:11;;:3;:11;;:::i;:::-;5889:40;:::i;:::-;5948:30;5981:8;5948:13;5968:9;;5948:19;:13;:19;5968:3;:9;;:::i;:::-;5948:30;;:::i;:::-;:41;;:::i;:::-;5999:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;6053:7;;;:::i;:::-;6023:38;;;;;:::i;:::-;;;;;;:::i;:::-;;;;5599:469::o;5742:50::-;5773:10;5734:75;5773:10;:19;;5787:5;;;:::i;:::-;5773:19;:::i;:::-;;;:::i;:::-;;5742:50;;;;993:7551;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;2121:94;;2207:1;2121:94;2152:45;2160:10;:19;;2174:5;;;:::i;:::-;2160:19;:::i;:::-;;;:::i;:::-;;2152:45;:::i;:::-;2207:1;:::i;:::-;2121:94::o;993:7551::-;;;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;:::i;:::-;;;;:::i;:::-;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;:::i;:::-;:::o;:::-;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;:::i;:::-;:::o;5001:592::-;5123:20;;:13;:8;:13;;;;;:::i;:::-;:20;;:::i;:::-;;:::i;:::-;5154:72;5162:45;5163:44;;:36;:13;;:21;5185:13;:8;;:13;;:::i;:::-;5163:36;;:::i;:::-;:44;;:::i;:::-;5162:45;;:::i;:::-;5154:72;:::i;:::-;5236:67;5244:36;:29;:24;:13;;:19;5264:3;5244:24;;:::i;:::-;;:29;:36;:::i;:::-;:41;;5284:1;5244:41;:::i;:::-;;;:::i;:::-;;5236:67;:::i;:::-;5322:78;5381:4;5361:39;5394:3;5361:39;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::i;:::-;5322:36;:21;:13;:21;5344:13;;:8;:13;;:::i;:::-;5322:36;;:::i;:::-;:78;:::i;:::-;5410:35;5437:8;5410:24;:19;:13;:19;5430:3;5410:24;;:::i;:::-;:35;;:::i;:::-;5455:55;5479:31;:21;;:13;:21;;:::i;:::-;5506:3;5479:31;;:::i;:::-;5455:21;:13;:21;:55;:::i;:::-;5521:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;5568:8;5578:7;;;:::i;:::-;5545:41;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;5001:592::o;:::-;;;;;:::i;:::-;:::o;2121:94::-;2207:1;2121:94;2152:45;2160:10;:19;;2174:5;;;:::i;:::-;2160:19;:::i;:::-;;;:::i;:::-;;2152:45;:::i;:::-;2207:1;:::i;:::-;2121:94::o;993:7551::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;2327:109;2428:1;2327:109;2360:58;2368:24;2369:23;;:::i;:::-;2368:24;;:::i;:::-;2360:58;:::i;:::-;2428:1;:::i;:::-;2327:109::o;993:7551::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;2554:115;2661:1;2554:115;2589:62;2597:26;2598:25;;:::i;:::-;2597:26;;:::i;:::-;2589:62;:::i;:::-;2661:1;:::i;:::-;2554:115::o;993:7551::-;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;:::o;:::-;;:::i;:::-;;;;:::o;:::-;;:::o;:::-;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;:::o;:::-;;:::i;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;;;;:::i;:::-;:::o;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;:::i;:::-;:::o;2675:763::-;2785:90;2793:62;:28;;:11;:28;;:::i;:::-;2833:21;;:13;:21;;:::i;:::-;2793:62;;:::i;:::-;2785:90;:::i;:::-;2956:202;2886:60;2916:30;:9;2926:19;:15;;;:::i;:::-;:19;2944:1;2926:19;:::i;:::-;;;:::i;:::-;2916:30;;:::i;:::-;;2886:60;:::i;:::-;2977:28;;:11;:28;;:::i;:::-;:60;;3009:28;;:11;:28;;:::i;:::-;2977:60;:::i;:::-;;;:::i;:::-;;;:142;;;;;2675:763;2956:202;;:::i;:::-;3173:14;:12;:9;:12;:14;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;3198:17;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;3225:44;3258:11;3225:30;:9;3235:19;:15;;;:::i;:::-;:19;3253:1;3235:19;:::i;:::-;;;:::i;:::-;3225:30;;:::i;:::-;:44;;:::i;:::-;3280:64;3316:28;;:11;:28;;:::i;:::-;3280:33;:9;:33;:64;:::i;:::-;3355:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;3396:12;;:9;:12;;:::i;:::-;3410:11;3423:7;;;:::i;:::-;3379:52;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;2675:763::o;2977:142::-;3053:31;:11;;:31;;;:::i;:::-;:66;;3088:31;;:11;:31;;:::i;:::-;3053:66;:::i;:::-;;;:::i;:::-;;;2977:142;;;2675:763;;;;:::i;:::-;:::o;993:7551::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;2442:106;2478:52;2486:25;;:::i;:::-;2478:52;:::i;:::-;2540:1;;:::i;:::-;2442:106::o;993:7551::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;:::i;:::-;:::o;4744:251::-;4815:16;;:11;:16;;:::i;:::-;:30;;4835:10;4815:30;:::i;:::-;;;:::i;:::-;;:53;;;;4744:251;4807:78;;;:::i;:::-;4896:29;4915:10;4923:1;4915:10;:::i;:::-;4896:16;:11;:16;:29;:::i;:::-;4936:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;4980:7;;;:::i;:::-;4960:28;;;;;:::i;:::-;;;;;;:::i;:::-;;;;4744:251::o;4815:53::-;4849:10;4807:78;4849:10;:19;;4863:5;;;:::i;:::-;4849:19;:::i;:::-;;;:::i;:::-;;4815:53;;;;4744:251;;;:::i;:::-;:::o;2121:94::-;2207:1;2121:94;2152:45;2160:10;:19;;2174:5;;;:::i;:::-;2160:19;:::i;:::-;;;:::i;:::-;;2152:45;:::i;:::-;2207:1;:::i;:::-;2121:94::o;993:7551::-;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;:::i;:::-;:::o;:::-;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;:::o;6866:184::-;6950:22;6961:11;6950:22;;:::i;:::-;6982:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;7035:7;;;:::i;:::-;7006:37;;;;;:::i;:::-;;;;;;:::i;:::-;;;;6866:184::o;:::-;;;;:::i;:::-;:::o;993:7551::-;;;;:::i;:::-;;:::o;:::-;;;:::o;:::-;;;:::o;:::-;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;:::o;:::-;;;:::o;:::-;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::o;:::-;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;:::o;:::-;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;:::o;:::-;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::o;:::-;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::o;:::-;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::o;:::-;;;:::i;:::-;;:::o;:::-;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::o;:::-;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;:::i;:::-;;:::i;:::-;;;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;:::o;:::-;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::o;:::-;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;:::o;:::-;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;:::o;:::-;;;;;:::i;:::-;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;;;;:::o;:::-;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;:::i;:::-;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;:::i;:::-;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;:::i;:::-;;:::o;7232:845::-;7272:18;;:::i;:::-;7327:13;;:21;;;;;:::i;:::-;:32;;;:::i;:::-;7440:5;;;:::i;:::-;7497:14;7514:1;7497:18;;;:::i;:::-;;;;:::i;:::-;7478:38;;;:::i;:::-;7541:9;7581:15;;;:::i;:::-;7620:8;7653:9;7689:11;;7723:7;;;;:::i;:::-;7407:334;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;7783:13;:21;;;;;:::i;:::-;7832:1;;7820:13;;;:::i;:::-;7856:3;7835:1;:19;;7840:14;7835:19;:::i;:::-;;;:::i;:::-;;;;7856:3;7879:20;:34;:20;7904:8;7910:1;7904:8;:::i;:::-;7879:34;;:::i;:::-;7875:81;;7970:57;8005:22;:19;:13;:19;8025:1;8005:22;;:::i;:::-;;7970:29;:11;:29;;:57;8000:1;7970:57;;:::i;:::-;;;;;:::i;:::-;;;:::i;:::-;;;7820:13;7856:3;:::i;:::-;7820:13;;7875:81;7933:8;;7835:19;;;;;;8052:18;:::o;993:7551::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;2221:100;2313:1;2221:100;2255:48;2263:23;;:::i;:::-;2255:48;:::i;:::-;2313:1;:::i;:::-;2221:100::o;993:7551::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;:::i;:::-;:::o;3444:709::-;3514:49;3444:709;3522:18;;3528:12;;:9;:12;;:::i;:::-;3522:18;:::i;:::-;;;:::i;:::-;;3514:49;:::i;:::-;3796:93;3832:57;3574:63;3604:33;:21;:13;:21;3626:10;3604:33;;:::i;:::-;3574:63;:::i;:::-;3647:48;3655:19;;:11;:19;;:::i;:::-;3647:48;:::i;:::-;3705:80;3713:56;:33;;:9;:33;;:::i;:::-;3751:17;;:11;:17;;:::i;:::-;3713:56;;:::i;:::-;3705:80;:::i;:::-;3871:17;;3832:33;;:9;:33;;:::i;:::-;3871:11;:17;;:::i;:::-;3832:57;;:::i;:::-;3796:33;:9;:33;:93;:::i;:::-;3904:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;3927:33;;:9;:33;;:::i;:::-;:38;;3964:1;3927:38;:::i;:::-;;;:::i;:::-;;3923:224;;;;4005:12;;:9;:12;;:::i;:::-;4019:10;4031:7;;;:::i;:::-;3986:53;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;3923:224;3444:709::o;3923:224::-;4102:12;;:9;:12;;:::i;:::-;4116:10;4128:7;;;:::i;:::-;4075:61;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;3923:224;;3444:709;;;;:::i;:::-;:::o;2121:94::-;2207:1;2121:94;2152:45;2160:10;:19;;2174:5;;;:::i;:::-;2160:19;:::i;:::-;;;:::i;:::-;;2152:45;:::i;:::-;2207:1;:::i;:::-;2121:94::o;993:7551::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;;;:::o;:::-;;;;;;;;;:::i;:::-;:::o;:::-;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;:::o;:::-;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;:::o;:::-;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;-1:-1:-1;993:7551:24;;;;;;;;;;;;;;:::i;:::-;;;;;:::o;:::-;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;:::o;:::-;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;:::i;:::-;:::o;:::-;;:::i;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;:::i;:::-;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;:::o;6074:786::-;6718:55;6742:31;6297:13;;6156:65;6183:38;:13;;:21;6205:15;6183:38;;:::i;:::-;6156:65;:::i;:::-;6231:44;6239:15;:7;;:15;;:::i;:::-;6231:44;:::i;:::-;6297:13;;:::i;:::-;6325:23;;:::i;:::-;6321:281;;;;6384:38;:29;;:12;:9;6394:1;6384:12;;:::i;:::-;;:29;;:::i;:::-;6418:3;6384:38;;:::i;:::-;:80;;;6321:281;6376:104;;;:::i;:::-;6321:281;6620:46;;6627:38;:13;;:21;6649:15;6627:38;;:::i;:::-;6620:46;:::i;:::-;6676:32;6683:24;:19;:13;:19;6703:3;6683:24;;:::i;:::-;6676:32;;:::i;:::-;6742:21;;:13;:21;;:::i;:::-;:31;:::i;:::-;6718:21;:13;:21;:55;:::i;:::-;6784:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;6845:7;;;:::i;:::-;6808:45;;;;;:::i;:::-;;;;;;:::i;:::-;;;;6074:786::o;6384:80::-;6426:9;6376:104;6426:38;:29;;:12;:9;6436:1;6426:12;;:::i;:::-;;:29;;:::i;:::-;6460:3;6426:38;;:::i;:::-;6384:80;;;;6321:281;6511:80;6519:56;:47;;:30;:9;6529:19;:15;;;:::i;:::-;:19;6547:1;6529:19;:::i;:::-;;;:::i;:::-;6519:30;;:::i;:::-;;:47;;:::i;:::-;6571:3;6519:56;;:::i;:::-;6511:80;:::i;:::-;6321:281;;6074:786;;;;:::i;:::-;:::o;2121:94::-;2207:1;2121:94;2152:45;2160:10;:19;;2174:5;;;:::i;:::-;2160:19;:::i;:::-;;;:::i;:::-;;2152:45;:::i;:::-;2207:1;:::i;:::-;2121:94::o;2221:100::-;2313:1;2221:100;2255:48;2263:23;;:::i;:::-;2255:48;:::i;:::-;2313:1;:::i;:::-;2221:100::o;993:7551::-;;;;:::i;:::-;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;:::o;4159:282::-;4236:49;4159:282;4244:18;;4250:12;;:9;:12;;:::i;:::-;4244:18;:::i;:::-;;;:::i;:::-;;4236:49;:::i;:::-;4296:17;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;4323:37;;4359:1;4323:37;:::i;:::-;:33;:9;:33;:37;:::i;:::-;4371:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;4412:12;;:9;:12;;:::i;:::-;4426:7;;;:::i;:::-;4395:39;;;;;:::i;:::-;;;;;;:::i;:::-;;;;4159:282::o;:::-;;;;:::i;:::-;:::o;2121:94::-;2207:1;2121:94;2152:45;2160:10;:19;;2174:5;;;:::i;:::-;2160:19;:::i;:::-;;;:::i;:::-;;2152:45;:::i;:::-;2207:1;:::i;:::-;2121:94::o;7056:170::-;7130:16;7138:8;7130:16;;:::i;:::-;7156:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;7211:7;;;:::i;:::-;7180:39;;;;;:::i;:::-;;;;;;:::i;:::-;;;;7056:170::o;:::-;;;;:::i;:::-;:::o;2327:109::-;2360:58;2368:24;2369:23;;:::i;:::-;2368:24;;:::i;:::-;2360:58;:::i;:::-;2428:1;;:::i;:::-;2327:109::o;2554:115::-;2589:62;2597:26;2598:25;;:::i;:::-;2597:26;;:::i;:::-;2589:62;:::i;:::-;2661:1;;:::i;:::-;2554:115::o;4447:291::-;4528:41;;:33;:13;;:21;4550:10;4528:33;;:::i;:::-;:41;;:::i;:::-;:64;;;;4447:291;4520:89;;;:::i;:::-;4628:29;4647:10;4628:16;:11;:16;:29;:::i;:::-;4668:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;4711:10;4723:7;;;:::i;:::-;4692:39;;;;;:::i;:::-;;;;;;:::i;:::-;;;;4447:291::o;4528:64::-;4573:10;4520:89;4573:10;:19;;4587:5;;;:::i;:::-;4573:19;:::i;:::-;;;:::i;:::-;;4528:64;;;;4447:291;;;:::i;:::-;:::o;993:7551::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;8083:205;8207:74;8083:205;8156:41;8164:5;:9;;8172:1;8164:9;:::i;:::-;;;:::i;:::-;;8156:41;:::i;:::-;8215:38;;8224:29;;:8;:29;;:::i;:::-;8215:38;:::i;:::-;;;:::i;:::-;;;8207:74;:::i;:::-;8083:205::o;993:7551::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;:::i;:::-;;:::o;9344:122::-;9444:15;9344:122;9407:7;;:::i;:::-;9434;9444:1;:15;9449:10;9444:1;9457;9449:10;:::i;:::-;9444:15;;:::i;:::-;;:::i;:::-;9434:25;9427:32;:::o;993:7551::-;;;:::o;8294:124::-;8350:4;;:::i;:::-;8373:9;:33;;:9;:33;;:::i;:::-;:38;;8410:1;8373:38;:::i;:::-;;;:::i;:::-;;;8366:45;:::o;8424:118::-;8482:4;;:::i;:::-;8505:11;:16;;:11;:16;;:::i;:::-;:30;;8525:10;8533:1;8525:10;:::i;:::-;8505:30;:::i;:::-;;;:::i;:::-;;;8498:37;:::o;10172:120::-;10274:6;10172:120;10244:4;;:::i;:::-;10267;10275:5;10274:6;;:::i;:::-;10267:13;:18;;10284:1;10267:18;:::i;:::-;;;:::i;:::-;;10260:25;:::o;10053:113::-;10137:18;10053:113;10111:7;;:::i;:::-;10147;10137:18;:::i;:::-;10130:25;:::o;9736:127::-;9834:15;9736:127;9798:4;;:::i;:::-;9823:7;9834:1;:15;9839:10;9834:1;9847;9839:10;:::i;:::-;9834:15;;:::i;:::-;;:::i;:::-;9823:27;9822:34;;9855:1;9822:34;:::i;:::-;;;:::i;:::-;;9815:41;:::o;9603:127::-;9701:15;9603:127;9665:4;;:::i;:::-;9690:7;9701:1;:15;9706:10;9701:1;9714;9706:10;:::i;:::-;9701:15;;:::i;:::-;;:::i;:::-;9690:27;9689:34;;9722:1;9689:34;:::i;:::-;;;:::i;:::-;;;9682:41;:::o;9472:125::-;9574:15;9572:18;9472:125;9535:7;;:::i;:::-;9562;9574:1;:15;9579:10;9574:1;9587;9579:10;:::i;:::-;9574:15;;:::i;:::-;;:::i;:::-;9572:18;;:::i;:::-;9562:28;9555:35;:::o;993:7551::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;26222:2393:21:-;26270:9;;:::i;:::-;26383:1;26367:60;:55;26383:1;:38;;26387:34;26383:38;:::i;:::-;;;:::i;:::-;;26367:55;:::i;:::-;:60;26426:1;26367:60;:::i;:::-;;;:::i;:::-;26508:51;:46;26525:6;:1;26530;26525:6;;:::i;:::-;26524:29;;26535:18;26524:29;:::i;:::-;;;:::i;:::-;;26508:46;:::i;:::-;:51;26558:1;26508:51;:::i;:::-;;;:::i;:::-;26503:56;26639:43;:38;26656:6;:1;26661;26656:6;;:::i;:::-;26655:21;;26666:10;26655:21;:::i;:::-;;;:::i;:::-;;26639:38;:::i;:::-;:43;26681:1;26639:43;:::i;:::-;;;:::i;:::-;26634:48;26762:39;:34;26779:6;:1;26784;26779:6;;:::i;:::-;26778:17;;26789:6;26778:17;:::i;:::-;;;:::i;:::-;;26762:34;:::i;:::-;:39;26800:1;26762:39;:::i;:::-;;;:::i;:::-;26757:44;26879:37;:32;26896:6;:1;26901;26896:6;;:::i;:::-;26895:15;;26906:4;26895:15;:::i;:::-;;;:::i;:::-;;26879:32;:::i;:::-;:37;26915:1;26879:37;:::i;:::-;;;:::i;:::-;26874:42;26993:36;:31;27010:6;:1;27015;27010:6;;:::i;:::-;27009:14;;27020:3;27009:14;:::i;:::-;;;:::i;:::-;;26993:31;:::i;:::-;:36;27028:1;26993:36;:::i;:::-;;;:::i;:::-;26988:41;28465:144;;;;;;;;;26222:2393;:::o;34795:145:22:-;34842:9;;:::i;:::-;34863:71;;;34795:145;:::o","linkReferences":{}},"methodIdentifiers":{"abortMigration(uint64)":"e88e9749","addNodeOperator(uint8,(address,bytes))":"2b726062","completeMigration(uint64)":"9d44e717","finishMaintenance()":"53bfb584","getView()":"75418b9d","removeNodeOperator(address)":"c05665dd","startMaintenance()":"f5f2d9f1","startMigration((uint256,uint8))":"47011c5c","transferOwnership(address)":"f2fde38b","updateNodeOperator((address,bytes))":"26322217","updateSettings((uint16))":"65706f9c"},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.28+commit.7893614a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"components\":[{\"internalType\":\"uint16\",\"name\":\"maxOperatorDataBytes\",\"type\":\"uint16\"}],\"internalType\":\"struct Settings\",\"name\":\"initialSettings\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"struct NodeOperator[]\",\"name\":\"initialOperators\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"MaintenanceFinished\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"MaintenanceStarted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"MigrationAborted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"operatorAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"MigrationCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"operatorAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"MigrationDataPullCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"operatorsBitmask\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"replicationStrategy\",\"type\":\"uint8\"}],\"indexed\":false,\"internalType\":\"struct Keyspace\",\"name\":\"newKeyspace\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"MigrationStarted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"idx\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"struct NodeOperator\",\"name\":\"operator\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"NodeOperatorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"operatorAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"NodeOperatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"struct NodeOperator\",\"name\":\"operator\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"NodeOperatorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"cluserVersion\",\"type\":\"uint128\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint16\",\"name\":\"maxOperatorDataBytes\",\"type\":\"uint16\"}],\"indexed\":false,\"internalType\":\"struct Settings\",\"name\":\"newSettings\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"SettingsUpdated\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"}],\"name\":\"abortMigration\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"idx\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"struct NodeOperator\",\"name\":\"operator\",\"type\":\"tuple\"}],\"name\":\"addNodeOperator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"}],\"name\":\"completeMigration\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"finishMaintenance\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getView\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"struct NodeOperator[]\",\"name\":\"nodeOperatorSlots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"operatorsBitmask\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"replicationStrategy\",\"type\":\"uint8\"}],\"internalType\":\"struct Keyspace[2]\",\"name\":\"keyspaces\",\"type\":\"tuple[2]\"},{\"internalType\":\"uint64\",\"name\":\"keyspaceVersion\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint16\",\"name\":\"maxOperatorDataBytes\",\"type\":\"uint16\"}],\"internalType\":\"struct Settings\",\"name\":\"settings\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"pullingOperatorsBitmask\",\"type\":\"uint256\"}],\"internalType\":\"struct Migration\",\"name\":\"migration\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"slot\",\"type\":\"address\"}],\"internalType\":\"struct Maintenance\",\"name\":\"maintenance\",\"type\":\"tuple\"},{\"internalType\":\"uint128\",\"name\":\"version\",\"type\":\"uint128\"}],\"internalType\":\"struct ClusterView\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operatorAddress\",\"type\":\"address\"}],\"name\":\"removeNodeOperator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startMaintenance\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"operatorsBitmask\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"replicationStrategy\",\"type\":\"uint8\"}],\"internalType\":\"struct Keyspace\",\"name\":\"newKeyspace\",\"type\":\"tuple\"}],\"name\":\"startMigration\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"struct NodeOperator\",\"name\":\"operator\",\"type\":\"tuple\"}],\"name\":\"updateNodeOperator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint16\",\"name\":\"maxOperatorDataBytes\",\"type\":\"uint16\"}],\"internalType\":\"struct Settings\",\"name\":\"newSettings\",\"type\":\"tuple\"}],\"name\":\"updateSettings\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/Cluster.sol\":\"Cluster\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[\":@openzeppelin-contracts-5.3.0/=dependencies/@openzeppelin-contracts-5.3.0/\",\":forge-std-1.9.7/=dependencies/forge-std-1.9.7/src/\",\":forge-std/=dependencies/forge-std/src/\",\":openzeppelin-contracts/=dependencies/@openzeppelin-contracts-5.3.0/\"],\"viaIR\":true},\"sources\":{\"dependencies/openzeppelin-contracts/utils/Panic.sol\":{\"keccak256\":\"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a\",\"dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG\"]},\"dependencies/openzeppelin-contracts/utils/math/Math.sol\":{\"keccak256\":\"0x1225214420c83ebcca88f2ae2b50f053aaa7df7bd684c3e878d334627f2edfc6\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6c5fab4970634f9ab9a620983dc1c8a30153981a0b1a521666e269d0a11399d3\",\"dweb:/ipfs/QmVRnBC575MESGkEHndjujtR7qub2FzU9RWy9eKLp4hPZB\"]},\"dependencies/openzeppelin-contracts/utils/math/SafeCast.sol\":{\"keccak256\":\"0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b1d578337048cad08c1c03041cca5978eff5428aa130c781b271ad9e5566e1f8\",\"dweb:/ipfs/QmPFKL2r9CBsMwmUqqdcFPfHZB2qcs9g1HDrPxzWSxomvy\"]},\"src/Cluster.sol\":{\"keccak256\":\"0xc78e6f85b957de947ea15d06612efc306c2cd979f8f08d37e4484a65880ffb48\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c14a8b6856276888d44ba5368193e7b0ca9cd898d3cdc90d272edc32aef830be\",\"dweb:/ipfs/QmQkuwMCYXcuv1g68FsC7ZrpAdCKQS7KmHQZwRUftXKJVa\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.28+commit.7893614a"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"struct Settings","name":"initialSettings","type":"tuple","components":[{"internalType":"uint16","name":"maxOperatorDataBytes","type":"uint16"}]},{"internalType":"struct NodeOperator[]","name":"initialOperators","type":"tuple[]","components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}]}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"MaintenanceFinished","anonymous":false},{"inputs":[{"internalType":"address","name":"addr","type":"address","indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"MaintenanceStarted","anonymous":false},{"inputs":[{"internalType":"uint64","name":"id","type":"uint64","indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"MigrationAborted","anonymous":false},{"inputs":[{"internalType":"uint64","name":"id","type":"uint64","indexed":false},{"internalType":"address","name":"operatorAddress","type":"address","indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"MigrationCompleted","anonymous":false},{"inputs":[{"internalType":"uint64","name":"id","type":"uint64","indexed":false},{"internalType":"address","name":"operatorAddress","type":"address","indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"MigrationDataPullCompleted","anonymous":false},{"inputs":[{"internalType":"uint64","name":"id","type":"uint64","indexed":false},{"internalType":"struct Keyspace","name":"newKeyspace","type":"tuple","components":[{"internalType":"uint256","name":"operatorsBitmask","type":"uint256"},{"internalType":"uint8","name":"replicationStrategy","type":"uint8"}],"indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"MigrationStarted","anonymous":false},{"inputs":[{"internalType":"uint8","name":"idx","type":"uint8","indexed":false},{"internalType":"struct NodeOperator","name":"operator","type":"tuple","components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"NodeOperatorAdded","anonymous":false},{"inputs":[{"internalType":"address","name":"operatorAddress","type":"address","indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"NodeOperatorRemoved","anonymous":false},{"inputs":[{"internalType":"struct NodeOperator","name":"operator","type":"tuple","components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"NodeOperatorUpdated","anonymous":false},{"inputs":[{"internalType":"address","name":"newOwner","type":"address","indexed":false},{"internalType":"uint128","name":"cluserVersion","type":"uint128","indexed":false}],"type":"event","name":"OwnershipTransferred","anonymous":false},{"inputs":[{"internalType":"struct Settings","name":"newSettings","type":"tuple","components":[{"internalType":"uint16","name":"maxOperatorDataBytes","type":"uint16"}],"indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"SettingsUpdated","anonymous":false},{"inputs":[{"internalType":"uint64","name":"id","type":"uint64"}],"stateMutability":"nonpayable","type":"function","name":"abortMigration"},{"inputs":[{"internalType":"uint8","name":"idx","type":"uint8"},{"internalType":"struct NodeOperator","name":"operator","type":"tuple","components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}]}],"stateMutability":"nonpayable","type":"function","name":"addNodeOperator"},{"inputs":[{"internalType":"uint64","name":"id","type":"uint64"}],"stateMutability":"nonpayable","type":"function","name":"completeMigration"},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"finishMaintenance"},{"inputs":[],"stateMutability":"view","type":"function","name":"getView","outputs":[{"internalType":"struct ClusterView","name":"","type":"tuple","components":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"struct NodeOperator[]","name":"nodeOperatorSlots","type":"tuple[]","components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}]},{"internalType":"struct Keyspace[2]","name":"keyspaces","type":"tuple[2]","components":[{"internalType":"uint256","name":"operatorsBitmask","type":"uint256"},{"internalType":"uint8","name":"replicationStrategy","type":"uint8"}]},{"internalType":"uint64","name":"keyspaceVersion","type":"uint64"},{"internalType":"struct Settings","name":"settings","type":"tuple","components":[{"internalType":"uint16","name":"maxOperatorDataBytes","type":"uint16"}]},{"internalType":"struct Migration","name":"migration","type":"tuple","components":[{"internalType":"uint64","name":"id","type":"uint64"},{"internalType":"uint256","name":"pullingOperatorsBitmask","type":"uint256"}]},{"internalType":"struct Maintenance","name":"maintenance","type":"tuple","components":[{"internalType":"address","name":"slot","type":"address"}]},{"internalType":"uint128","name":"version","type":"uint128"}]}]},{"inputs":[{"internalType":"address","name":"operatorAddress","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"removeNodeOperator"},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"startMaintenance"},{"inputs":[{"internalType":"struct Keyspace","name":"newKeyspace","type":"tuple","components":[{"internalType":"uint256","name":"operatorsBitmask","type":"uint256"},{"internalType":"uint8","name":"replicationStrategy","type":"uint8"}]}],"stateMutability":"nonpayable","type":"function","name":"startMigration"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"transferOwnership"},{"inputs":[{"internalType":"struct NodeOperator","name":"operator","type":"tuple","components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}]}],"stateMutability":"nonpayable","type":"function","name":"updateNodeOperator"},{"inputs":[{"internalType":"struct Settings","name":"newSettings","type":"tuple","components":[{"internalType":"uint16","name":"maxOperatorDataBytes","type":"uint16"}]}],"stateMutability":"nonpayable","type":"function","name":"updateSettings"}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"remappings":["@openzeppelin-contracts-5.3.0/=dependencies/@openzeppelin-contracts-5.3.0/","forge-std-1.9.7/=dependencies/forge-std-1.9.7/src/","forge-std/=dependencies/forge-std/src/","openzeppelin-contracts/=dependencies/@openzeppelin-contracts-5.3.0/"],"optimizer":{"enabled":false,"runs":200},"metadata":{"bytecodeHash":"ipfs"},"compilationTarget":{"src/Cluster.sol":"Cluster"},"evmVersion":"cancun","libraries":{},"viaIR":true},"sources":{"dependencies/openzeppelin-contracts/utils/Panic.sol":{"keccak256":"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a","urls":["bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a","dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG"],"license":"MIT"},"dependencies/openzeppelin-contracts/utils/math/Math.sol":{"keccak256":"0x1225214420c83ebcca88f2ae2b50f053aaa7df7bd684c3e878d334627f2edfc6","urls":["bzz-raw://6c5fab4970634f9ab9a620983dc1c8a30153981a0b1a521666e269d0a11399d3","dweb:/ipfs/QmVRnBC575MESGkEHndjujtR7qub2FzU9RWy9eKLp4hPZB"],"license":"MIT"},"dependencies/openzeppelin-contracts/utils/math/SafeCast.sol":{"keccak256":"0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54","urls":["bzz-raw://b1d578337048cad08c1c03041cca5978eff5428aa130c781b271ad9e5566e1f8","dweb:/ipfs/QmPFKL2r9CBsMwmUqqdcFPfHZB2qcs9g1HDrPxzWSxomvy"],"license":"MIT"},"src/Cluster.sol":{"keccak256":"0xc78e6f85b957de947ea15d06612efc306c2cd979f8f08d37e4484a65880ffb48","urls":["bzz-raw://c14a8b6856276888d44ba5368193e7b0ca9cd898d3cdc90d272edc32aef830be","dweb:/ipfs/QmQkuwMCYXcuv1g68FsC7ZrpAdCKQS7KmHQZwRUftXKJVa"],"license":"MIT"}},"version":1},"id":24} \ No newline at end of file diff --git a/contracts/src/Cluster.sol b/contracts/src/Cluster.sol index 27ea715e..d2cd7263 100644 --- a/contracts/src/Cluster.sol +++ b/contracts/src/Cluster.sol @@ -86,6 +86,13 @@ contract Cluster { function startMigration(Keyspace calldata newKeyspace) external onlyOwner noMigration noMaintenance { require(newKeyspace.operatorsBitmask.isSubsetOf(nodeOperators.bitmask), "invalid bitmask"); + + Keyspace memory oldKeyspace = keyspaces[keyspaceVersion % 2]; + require( + oldKeyspace.operatorsBitmask != newKeyspace.operatorsBitmask + || oldKeyspace.replicationStrategy != newKeyspace.replicationStrategy, + "same keyspace" + ); migration.id++; @@ -115,7 +122,9 @@ contract Cluster { } } - function abortMigration() external onlyOwner hasMigration { + function abortMigration(uint64 id) external onlyOwner hasMigration { + require(id == migration.id, "wrong migration id"); + keyspaceVersion--; migration.pullingOperatorsBitmask = 0; diff --git a/contracts/test/Suite.sol b/contracts/test/Suite.sol index acff02e0..5047257b 100644 --- a/contracts/test/Suite.sol +++ b/contracts/test/Suite.sol @@ -379,28 +379,28 @@ contract ClusterTest is Test { function test_anyoneCanNotAbortMigration() public { startMigration(OWNER, newKeyspace("01111")); expectRevert("not the owner"); - abortMigration(ANYONE); + abortMigration(ANYONE, 1); } function test_operatorCanNotAbortMigration() public { startMigration(OWNER, newKeyspace("01111")); expectRevert("not the owner"); - abortMigration(OPERATOR); + abortMigration(OPERATOR, 1); } function test_ownerCanAbortMigration() public { startMigration(OWNER, newKeyspace("01111")); - abortMigration(OWNER); + abortMigration(OWNER, 1); } function test_canNotAbortNonExistentMigration() public { expectRevert("no migration"); - abortMigration(OWNER); + abortMigration(OWNER, 1); } function test_abortMigrationBumpsVersion() public { startMigration(OWNER, newKeyspace("01111")); - abortMigration(OWNER); + abortMigration(OWNER, 1); assertVersion(2); } @@ -408,13 +408,13 @@ contract ClusterTest is Test { assertKeyspaceVersion(0); startMigration(OWNER, newKeyspace("01111")); assertKeyspaceVersion(1); - abortMigration(OWNER); + abortMigration(OWNER, 1); assertKeyspaceVersion(0); } function test_abortMigrationClearsPullingOperators() public { startMigration(OWNER, newKeyspace("01111")); - abortMigration(OWNER); + abortMigration(OWNER, 1); assertMigration(1, "00000"); } @@ -422,7 +422,7 @@ contract ClusterTest is Test { startMigration(OWNER, newKeyspace("01111")); vm.expectEmit(); emit MigrationAborted(1, 2); - abortMigration(OWNER); + abortMigration(OWNER, 1); } // startMaintenance @@ -615,7 +615,7 @@ contract ClusterTest is Test { completeMigration(i + 1, 3); } } - abortMigration(OWNER); + abortMigration(OWNER, 3); transferOwnership(OWNER, NEW_OWNER); updateSettings(NEW_OWNER, Settings({ maxOperatorDataBytes: 1024 })); @@ -711,9 +711,9 @@ contract ClusterTest is Test { updateClusterView(); } - function abortMigration(uint256 caller) internal { + function abortMigration(uint256 caller, uint64 id) internal { setCaller(caller); - cluster.abortMigration(); + cluster.abortMigration(id); updateClusterView(); } diff --git a/crates/cluster/Cargo.toml b/crates/cluster/Cargo.toml index c9efe68c..06fd10d2 100644 --- a/crates/cluster/Cargo.toml +++ b/crates/cluster/Cargo.toml @@ -7,9 +7,10 @@ edition = "2021" workspace = true [dependencies] -derive_more = { workspace = true, features = ["try_from"] } +derive_more = { workspace = true, features = ["try_from", "into"] } libp2p = { workspace = true } itertools = { workspace = true } +futures = { workspace = true } sharding = { path = "../sharding" } @@ -23,6 +24,7 @@ tracing = "0.1" serde = { version = "1", features = ["derive"] } postcard = { version = "1.0", default-features = false, features = ["alloc"] } +xxhash-rust = { version = "0.8", features = ["xxh3", "const_xxh3"] } fpe = "0.6" aes = "0.8" diff --git a/crates/cluster/src/client.rs b/crates/cluster/src/client.rs index ddd98898..891c0fef 100644 --- a/crates/cluster/src/client.rs +++ b/crates/cluster/src/client.rs @@ -6,7 +6,7 @@ use { }; /// On-chain data of a [`Client`]. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct Data { /// [`PeerId`] of the [`Client`]. Used for authentication. pub peer_id: PeerId, diff --git a/crates/cluster/src/keyspace.rs b/crates/cluster/src/keyspace.rs index 507ff0a8..1b9f53cb 100644 --- a/crates/cluster/src/keyspace.rs +++ b/crates/cluster/src/keyspace.rs @@ -1,82 +1,103 @@ use { - crate::{ - node_operator::{self, NodeOperators}, - VersionedNodeOperator, - }, - arc_swap::ArcSwap, + crate::node_operator::{self}, derive_more::TryFrom, sharding::ShardId, - std::sync::Arc, - tap::TapOptional, + std::collections::HashSet, + xxhash_rust::xxh3::Xxh3Builder, }; -const REPLICATION_FACTOR: usize = 5; +/// Maximum number of [`node_operator`]s within a [`Keyspace`]. +pub const MAX_OPERATORS: usize = 256; -/// [`Keyspace`] version. -pub type Version = u64; +/// Number of [`node_operator`]s within a [`ReplicaSet`]. +pub const REPLICATION_FACTOR: usize = 5; + +/// Continuous space of `u64` keys. +/// +/// [`Keyspace`] is being split into a set of equally sized [`Shards`], +/// and each [`Shard`] is being assigned to a set of [`node_operator`]s. +pub struct Keyspace { + operators: HashSet, + shards: S, + replication_strategy: ReplicationStrategy, -/// Strategy of replicating data within a [`Keyspace`] across a set of -/// [`node::Operator`]s. + version: u64, +} + +/// All [`Shard`]s within a [`Keyspace`]. +pub struct Shards(sharding::Keyspace); + +/// A single [`Shard`] within a [`Keyspace`]. +#[derive(Clone, Copy, Debug)] +pub struct Shard { + replica_set: [node_operator::Idx; REPLICATION_FACTOR], +} + +/// Strategy of distributing [`Shard`]s to [`node_operator`]s. #[repr(u8)] -#[derive(Clone, Copy, Debug, Default, TryFrom)] +#[derive(Clone, Copy, Debug, Default, TryFrom, Eq, PartialEq)] #[try_from(repr)] pub enum ReplicationStrategy { - /// Keys are being uniformly distributed across [`node::Operator`]s. + /// [`Shard`]s are being uniformly distributed across [`node_operator`]s. #[default] UniformDistribution = 0, } -// impl ReplicationStrategy { -// pub(super) fn try_from(repr: u8) -> Option { -// match repr { -// 0 => Some(Self::UniformDistribution), -// _ => None, -// } -// } -// } - -/// Continuous space of `u64` keys, where each key is assigned to a set of -/// [`node::Operator`]s. -pub struct Keyspace { - operators: NodeOperators, - sharding: sharding::Keyspace, - replication_strategy: ReplicationStrategy, +/// Set of [`node_operator`]s assigned to a [`Shard`]. +pub type ReplicaSet = [T; REPLICATION_FACTOR]; - version: u64, -} +/// [`Keyspace`] version. +pub type Version = u64; impl Keyspace { /// Creates a new [`Keyspace`]. - /// - /// It's highly CPU intensive to construct a new [`Keyspace`] (order of - /// seconds), so the task is being [spawned](tokio::task::spawn_blocking) - /// to the [`tokio`] threadpool. - /// - /// May return `None` if the [`tokio`] task gets canceled for some reason. - pub(super) async fn new( - operators: NodeOperators, + pub fn new( + operators: HashSet, replication_strategy: ReplicationStrategy, version: u64, - ) -> Self { - todo!() + ) -> Result { + if operators.len() < REPLICATION_FACTOR { + return Err(CreationError::TooFewOperators(operators.len())); + } + + if operators.len() > MAX_OPERATORS { + return Err(CreationError::TooManyOperators(operators.len())); + } + + Ok(Keyspace { + operators, + shards: (), + replication_strategy, + version, + }) } - /// Required number of [`NodeOperator`]s a data should be replicated to. - pub fn replication_factor(&self) -> usize { - REPLICATION_FACTOR + pub(crate) async fn calculate_shards(self) -> Keyspace + where + Self: sealed::Calculate, + { + sealed::Calculate::::calculate_shards(self).await } +} - /// Returns the set of [`NodeOperator`]s the data under the specified key - /// should be replicated to. - pub fn replicas(&self, key: u64) -> impl Iterator + '_ { - self.sharding - .shard_replicas(ShardId::from_key(key)) - .iter() - .filter_map(|&idx| { - self.operators - .get_by_idx(idx) - .tap_none(|| tracing::warn!("Missing node operator {idx}")) - }) +impl Keyspace { + /// Returns the [`Shard`] that contains the specified key. + pub fn shard(&self, key: u64) -> Shard { + Shard { + replica_set: *self.shards.0.shard_replicas(ShardId::from_key(key)), + } + } +} + +impl Keyspace { + /// Returns an [`Iterator`] over [`node_operator`]s of this [`Keyspace`]. + pub fn operators(&self) -> impl Iterator + '_ { + self.operators.iter().copied() + } + + /// Returns [`ReplicationStrategy`] of this [`Keyspace`]. + pub fn replication_strategy(&self) -> ReplicationStrategy { + self.replication_strategy } /// Returns [`Version`] of this [`Keyspace`]. @@ -84,23 +105,86 @@ impl Keyspace { self.version } - /// Get [`NodeOperators`] of this [`Keyspace`]. - pub(super) fn operators(&self) -> &NodeOperators { - &self.operators + pub(super) fn contains_operator(&self, idx: node_operator::Idx) -> bool { + self.operators.contains(&idx) + } + + pub(super) fn require_diff(&self, other: &Keyspace) -> Result<(), SameKeyspaceError> { + if self.operators == other.operators + && self.replication_strategy == other.replication_strategy + { + return Err(SameKeyspaceError); + } + + Ok(()) } +} - /// Returns a mutable reference to [`NodeOperator`] data. - pub(super) fn operator_data_mut( - &mut self, - id: &node_operator::Id, - ) -> Option<&mut node_operator::VersionedData> { - self.operators.get_data_mut(id) +impl Shard { + /// Returns [`ReplicaSet`] assigned to this [`Shard`]. + pub fn replica_set(&self) -> ReplicaSet { + self.replica_set } } -struct Snapshot {} +#[derive(Debug, thiserror::Error)] +pub enum CreationError { + #[error("Too few operators within a Keyspace: {_0} < {REPLICATION_FACTOR}")] + TooFewOperators(usize), -pub struct Replica { - idx: node_operator::Idx, - node_operator: Arc, + #[error("Too many operators within a Keyspace: {_0} > {MAX_OPERATORS}")] + TooManyOperators(usize), +} + +#[derive(Debug, thiserror::Error)] +#[error("The new Keyspace doesn't differ from the old one")] +pub struct SameKeyspaceError; + +pub(crate) mod sealed { + #[allow(unused_imports)] + use super::*; + + /// Trait to make `Keyspace<()>` and `Keyspace` polymorphic. + pub trait Calculate { + /// Calculates [`Shards`] of a [`Keyspace`]. + /// + /// It's highly CPU intensive task (order of seconds), so the task is + /// being [spawned](tokio::task::spawn_blocking) to the + /// [`tokio`] threadpool. + async fn calculate_shards(self) -> Keyspace; + } +} + +impl sealed::Calculate for Keyspace { + async fn calculate_shards(self) -> Keyspace { + let operators = self.operators.clone(); + let res = tokio::task::spawn_blocking(move || { + sharding::Keyspace::new(operators.into_iter(), &Xxh3Builder::default(), || { + sharding::DefaultReplicationStrategy + }) + }) + .await + .unwrap(); // we don't expect the task to panic + + match res { + Ok(sharding) => Keyspace { + operators: self.operators, + shards: Shards(sharding), + replication_strategy: ReplicationStrategy::UniformDistribution, + version: self.version, + }, + + // we checked this in the `Keyspace` constructor + Err(sharding::Error::InvalidNodesCount(_)) => unreachable!(), + + // impossible with the default replication strategy + Err(sharding::Error::IncompleteReplicaSet) => unreachable!(), + } + } +} + +impl sealed::Calculate<()> for Keyspace { + async fn calculate_shards(self) -> Keyspace { + self + } } diff --git a/crates/cluster/src/lib.rs b/crates/cluster/src/lib.rs index db642509..d613f2e8 100644 --- a/crates/cluster/src/lib.rs +++ b/crates/cluster/src/lib.rs @@ -2,16 +2,15 @@ use { arc_swap::ArcSwap, itertools::Itertools, smart_contract::evm, - std::{ - collections::{HashMap, HashSet}, - future::Future, - sync::Arc, - }, + std::{collections::HashSet, sync::Arc}, }; pub mod smart_contract; pub use smart_contract::SmartContract; +pub mod view; +pub use view::View; + pub mod settings; pub use settings::Settings; @@ -25,7 +24,12 @@ pub mod node; pub use node::{Node, NodeRef}; pub mod node_operator; -pub use node_operator::{NodeOperator, SerializedNodeOperator, VersionedNodeOperator}; +pub use node_operator::{ + NodeOperator, + NodeOperators, + SerializedNodeOperator, + VersionedNodeOperator, +}; pub mod keyspace; pub use keyspace::Keyspace; @@ -37,7 +41,10 @@ pub mod maintenance; pub use maintenance::Maintenance; /// Maximum number of [`NodeOperator`]s within a WCN [`Cluster`]. -pub const MAX_OPERATORS: usize = 256; +pub const MAX_OPERATORS: usize = keyspace::MAX_OPERATORS; + +/// Minimum number fo [`NodeOperator`]s within a WCN [`Cluster`]. +pub const MIN_OPERATORS: usize = keyspace::REPLICATION_FACTOR; /// WCN cluster. /// @@ -45,9 +52,9 @@ pub const MAX_OPERATORS: usize = 256; /// /// Performs preliminary invariant validation before calling the actual /// [`SmartContract`] methods. -pub struct Cluster { +pub struct Cluster { smart_contract: SC, - view: ArcSwap>, + view: ArcSwap>>, } /// Version of a WCN [`Cluster`]. @@ -102,65 +109,74 @@ impl Cluster { initial_settings: Settings, initial_operators: Vec, ) -> Result { - if initial_operators - .iter() - .map(VersionedNodeOperator::id) - .dedup() - .count() - != initial_operators.len() - { - return Err(DeploymentError::OperatorIdDuplicate); - } + let operators: Vec<_> = initial_operators + .into_iter() + .map(|op| { + let op = op.serialize()?; + op.data().validate(&initial_settings)?; + Ok::<_, DeploymentError>(op) + }) + .try_collect()?; - if initial_operators.len() > MAX_OPERATORS { - return Err(DeploymentError::TooManyOperators); - } + let operators = NodeOperators::new(operators.into_iter().map(Some))?; - let contract = SC::deploy(signer, rpc_url, initial_settings, initial_operators).await?; + let contract = SC::deploy(signer, rpc_url, initial_settings, operators).await?; - let view = contract.cluster_view().await?; + let view = contract.cluster_view().await?.deserialize()?; Ok(Self { smart_contract: contract, view: ArcSwap::new(Arc::new(Arc::new(view))), }) } +} - /// Prepares a new [`migration::Plan`] and calls - /// [`SmartContract::start_migration`] using the prepared plan. - pub async fn start_migration( - &self, - remove: Vec, - add: Vec, - ) -> Result<(), StartMigrationError> { - let plan = self.using_view(move |view| { - view.ownership.validate_signer(&self.smart_contract)?; - - if view.migration().is_some() { - return Err(StartMigrationError::MigrationInProgress); - } +impl Cluster { + /// Builds a new [`Keyspace`] using the provided [`migration::Plan`] and + /// calls [`SmartContract::start_migration`]. + pub async fn start_migration(&self, plan: migration::Plan) -> Result<(), StartMigrationError> { + let new_keyspace = self.using_view(move |view| { + view.ownership().require_owner(&self.smart_contract)?; + view.require_no_migration()?; + view.require_no_maintenance()?; + + let operators = view.node_operators(); + let keyspace = view.keyspace(); + + let mut new_operators: HashSet<_> = view.node_operators().occupied_indexes().collect(); + + for id in plan.remove { + let idx = operators.require_idx(&id)?; - if view.maintenance().is_some() { - return Err(StartMigrationError::MaintenanceInProgress); + if !keyspace.contains_operator(idx) { + return Err(StartMigrationError::NotInKeyspace(id)); + } + + new_operators.remove(&idx); } - let add = add - .into_iter() - .map(|operator| { - let operator = operator.serialize()?; + for id in plan.add { + let idx = operators.require_idx(&id)?; + + if keyspace.contains_operator(idx) { + return Err(StartMigrationError::AlreadyInKeyspace(id)); + } - operator - .data() - .validate_size(view.settings.max_node_operator_data_bytes)?; + new_operators.insert(idx); + } - Ok::<_, StartMigrationError>(operator) - }) - .try_collect()?; + let new_keyspace = Keyspace::new( + new_operators, + plan.replication_strategy, + keyspace.version() + 1, + )?; - migration::Plan::new(view, remove, add).map_err(Into::into) + keyspace.require_diff(&new_keyspace)?; + + Ok(new_keyspace) })?; - self.smart_contract.start_migration(plan).await?; + self.smart_contract.start_migration(new_keyspace).await?; Ok(()) } @@ -170,48 +186,30 @@ impl Cluster { &self, id: migration::Id, ) -> Result<(), CompleteMigrationError> { - let signer = self.smart_contract.signer(); - - let operator_idx = self.using_view(|view| { - let migration = view - .migration() - .ok_or(CompleteMigrationError::NoMigration)?; - - if migration.id() != id { - return Err(CompleteMigrationError::WrongMigrationId); - } - - let operator_idx = migration - .keyspace() - .operators() - .get_idx(&signer) - .ok_or(CompleteMigrationError::NotOperator)?; + self.using_view(|view| { + let operator_idx = view + .node_operators() + .require_idx(self.smart_contract.signer())?; - if !migration.is_pulling(&signer) { - return Err(CompleteMigrationError::NotPulling); - } + view.require_migration()? + .require_id(id)? + .require_pulling(operator_idx)?; - Ok(operator_idx) + Ok::<_, CompleteMigrationError>(()) })?; - self.smart_contract - .complete_migration(id, operator_idx) - .await - .map_err(Into::into) + self.smart_contract.complete_migration(id).await?; + + Ok(()) } /// Calls [`SmartContract::abort_migration`]. pub async fn abort_migration(&self, id: migration::Id) -> Result<(), AbortMigrationError> { self.using_view(|view| { - view.ownership.validate_signer(&self.smart_contract)?; + view.ownership().require_owner(&self.smart_contract)?; + view.require_migration()?.require_id(id)?; - let migration = view.migration().ok_or(AbortMigrationError::NoMigration)?; - - if migration.id() != id { - return Err(AbortMigrationError::WrongMigrationId); - } - - Ok(()) + Ok::<_, AbortMigrationError>(()) })?; self.smart_contract @@ -222,35 +220,33 @@ impl Cluster { /// Calls [`SmartContract::start_maintenance`]. pub async fn start_maintenance(&self) -> Result<(), StartMaintenanceError> { - let operator_idx = self.using_view(move |view| { - if view.migration().is_some() { - return Err(StartMaintenanceError::MigrationInProgress); - } + let signer = self.smart_contract.signer(); - if view.maintenance().is_some() { - return Err(StartMaintenanceError::MaintenanceInProgress); + self.using_view(move |view| { + if !(view.node_operators().contains(signer) || view.ownership().is_owner(signer)) { + return Err(StartMaintenanceError::Unauthorized); } - view.keyspace() - .operators() - .get_idx(&self.smart_contract.signer()) - .ok_or(StartMaintenanceError::NotOperator) + view.require_no_migration()?; + view.require_no_maintenance()?; + + Ok::<_, StartMaintenanceError>(()) })?; - self.smart_contract.start_maintenance(operator_idx).await?; + self.smart_contract.start_maintenance().await?; Ok(()) } /// Calls [`SmartContract::finish_maintenance`]. - pub async fn finish_maintenance(&self) -> Result<(), CompleteMaintenanceError> { + pub async fn finish_maintenance(&self) -> Result<(), FinishMaintenanceError> { + let signer = self.smart_contract.signer(); + self.using_view(|view| { - let maintenance = view - .maintenance() - .ok_or(CompleteMaintenanceError::NoMaintenance)?; + let maintenance = view.require_maintenance()?; - if maintenance.operator() != &self.smart_contract.signer() { - return Err(CompleteMaintenanceError::WrongOperator); + if !(signer == maintenance.slot() || view.ownership().is_owner(signer)) { + return Err(FinishMaintenanceError::Unauthorized); } Ok(()) @@ -261,29 +257,80 @@ impl Cluster { Ok(()) } + /// Calls [`SmartContract::add_node_operator`]. + pub async fn add_node_operator( + &self, + idx: node_operator::Idx, + operator: NodeOperator, + ) -> Result<(), AddNodeOperatorError> { + let operator = self.using_view(|view| { + view.ownership().require_owner(&self.smart_contract)?; + view.node_operators().require_not_exists(operator.id())?; + view.node_operators().require_free_slot(idx)?; + + let operator = operator.serialize()?; + operator.data().validate(view.settings())?; + + Ok::<_, AddNodeOperatorError>(operator) + })?; + + self.smart_contract.add_node_operator(idx, operator).await?; + + Ok(()) + } + /// Calls [`SmartContract::update_node_operator`]. pub async fn update_node_operator( &self, operator: NodeOperator, ) -> Result<(), UpdateNodeOperatorError> { - let (idx, data) = self.using_view(|view| { - let idx = view - .operator_idx(operator.id()) - .ok_or(UpdateNodeOperatorError::UnknownOperator)?; + let signer = self.smart_contract.signer(); - let data = data.serialize()?; + let operator = self.using_view(|view| { + if !(signer == operator.id() || view.ownership().is_owner(signer)) { + return Err(UpdateNodeOperatorError::Unauthorized); + } - data.validate_size(view.settings.max_node_operator_data_bytes)?; - Ok::<_, UpdateNodeOperatorError>((idx, data)) + let _idx = view.node_operators().require_idx(operator.id())?; + + let operator = operator.serialize()?; + operator.data().validate(view.settings())?; + + Ok::<_, UpdateNodeOperatorError>(operator) })?; - self.smart_contract - .update_node_operator(id, idx, data) - .await - .map_err(Into::into) + self.smart_contract.update_node_operator(operator).await?; + + Ok(()) } - fn using_view(&self, f: impl FnOnce(&View) -> T) -> T { + /// Calls [`SmartContract::remove_node_operator`]. + pub async fn remove_node_operator( + &self, + id: node_operator::Id, + ) -> Result<(), RemoveNodeOperatorError> { + self.using_view(|view| { + let idx = view.node_operators().require_idx(&id)?; + + if view.keyspace().contains_operator(idx) { + return Err(RemoveNodeOperatorError::InKeyspace); + } + + if let Some(keyspace) = view.migration().map(Migration::keyspace) { + if keyspace.contains_operator(idx) { + return Err(RemoveNodeOperatorError::InKeyspace); + } + } + + Ok::<_, RemoveNodeOperatorError>(()) + })?; + + self.smart_contract.remove_node_operator(id).await?; + + Ok(()) + } + + fn using_view(&self, f: impl FnOnce(&View) -> T) -> T { f(&self.view.load()) } } @@ -291,11 +338,17 @@ impl Cluster { /// [`Cluster::deploy`] error. #[derive(Debug, thiserror::Error)] pub enum DeploymentError { - #[error("Too many initial operators provided, should be <= {MAX_OPERATORS}")] - TooManyOperators, + #[error(transparent)] + NodeOperatorSlotMapCreation(#[from] node_operator::SlotMapCreationError), + + #[error(transparent)] + DataSerialization(#[from] node_operator::DataSerializationError), + + #[error(transparent)] + DataDeserialization(#[from] node_operator::DataDeserializationError), - #[error("Initial operator list contains duplicates")] - OperatorIdDuplicate, + #[error(transparent)] + DataTooLarge(#[from] node_operator::DataTooLargeError), #[error("Smart-contract: {0}")] SmartContract(#[from] smart_contract::Error), @@ -307,20 +360,26 @@ pub enum StartMigrationError { #[error(transparent)] NotOwner(#[from] ownership::NotOwnerError), - #[error("Another migration in progress")] - MigrationInProgress, + #[error(transparent)] + MigrationInProgress(#[from] migration::InProgressError), + + #[error(transparent)] + MaintenanceInProgress(#[from] maintenance::InProgressError), - #[error("Maintenance in progress")] - MaintenanceInProgress, + #[error(transparent)] + UnknownOperator(#[from] node_operator::NotFoundError), - #[error("Data serialization: {0}")] - DataSerialization(#[from] node_operator::DataSerializationError), + #[error("NodeOperator(id: {_0}) is not in the Keyspace")] + NotInKeyspace(node_operator::Id), + + #[error("NodeOperator(id: {_0}) is already in the Keyspace")] + AlreadyInKeyspace(node_operator::Id), #[error(transparent)] - NodeOperatorDataTooLarge(#[from] node_operator::DataTooLargeError), + KeyspaceCreation(#[from] keyspace::CreationError), - #[error("Plan: {0}")] - Plan(#[from] migration::PlanError), + #[error(transparent)] + SameKeyspace(#[from] keyspace::SameKeyspaceError), #[error("Smart-contract: {0}")] SmartContract(#[from] smart_contract::Error), @@ -329,17 +388,17 @@ pub enum StartMigrationError { /// [`Cluster::complete_migration`] error. #[derive(Debug, thiserror::Error)] pub enum CompleteMigrationError { - #[error("No migration is currently in progress")] - NoMigration, + #[error(transparent)] + UnknownOperator(#[from] node_operator::NotFoundError), - #[error("Provided migration id doesn't match the actual one")] - WrongMigrationId, + #[error(transparent)] + NoMigration(#[from] migration::NotFoundError), - #[error("Signer is not a node operator")] - NotOperator, + #[error(transparent)] + WrongMigrationId(#[from] migration::WrongIdError), - #[error("Signer has already completed the data pull")] - NotPulling, + #[error(transparent)] + OperatorNotPulling(#[from] migration::OperatorNotPullingError), #[error("Smart-contract: {0}")] SmartContract(#[from] smart_contract::Error), @@ -351,11 +410,11 @@ pub enum AbortMigrationError { #[error(transparent)] NotOwner(#[from] ownership::NotOwnerError), - #[error("No migration is currently in progress")] - NoMigration, + #[error(transparent)] + NoMigration(#[from] migration::NotFoundError), - #[error("Provided migration id doesn't match the actual one")] - WrongMigrationId, + #[error(transparent)] + WrongMigrationId(#[from] migration::WrongIdError), #[error("Smart-contract: {0}")] SmartContract(#[from] smart_contract::Error), @@ -364,40 +423,49 @@ pub enum AbortMigrationError { /// [`Cluster::start_maintenance`] error. #[derive(Debug, thiserror::Error)] pub enum StartMaintenanceError { - #[error("Migration in progress")] - MigrationInProgress, + #[error("Signer should either be a node operator or the owner")] + Unauthorized, - #[error("Another maintenance in progress")] - MaintenanceInProgress, + #[error(transparent)] + MigrationInProgress(#[from] migration::InProgressError), - #[error("Signer is not a node operator")] - NotOperator, + #[error(transparent)] + MaintenanceInProgress(#[from] maintenance::InProgressError), #[error("Smart-contract: {0}")] SmartContract(#[from] smart_contract::Error), } -/// [`Cluster::complete_maintenance`] error. +/// [`Cluster::finish_maintenance`] error. #[derive(Debug, thiserror::Error)] -pub enum CompleteMaintenanceError { - #[error("No maintenance is currently in progress")] - NoMaintenance, +pub enum FinishMaintenanceError { + #[error(transparent)] + NoMaintenance(#[from] maintenance::NotFoundError), - #[error("Signer is not under maintenance")] - WrongOperator, + #[error("Signer should either be a node operator that started the maintenance or the owner")] + Unauthorized, #[error("Smart-contract: {0}")] SmartContract(#[from] smart_contract::Error), } -/// [`Cluster::abort_maintenance`] error. +/// [`Cluster::add_node_operator`] error. #[derive(Debug, thiserror::Error)] -pub enum AbortMaintenanceError { +pub enum AddNodeOperatorError { #[error(transparent)] NotOwner(#[from] ownership::NotOwnerError), - #[error("No maintenance is currently in progress")] - NoMaintenance, + #[error(transparent)] + AlreadyExists(#[from] node_operator::AlreadyExistsError), + + #[error(transparent)] + SlotOccupied(#[from] node_operator::SlotOccupiedError), + + #[error(transparent)] + DataSerialization(#[from] node_operator::DataSerializationError), + + #[error(transparent)] + DataTooLarge(#[from] node_operator::DataTooLargeError), #[error("Smart-contract: {0}")] SmartContract(#[from] smart_contract::Error), @@ -406,10 +474,13 @@ pub enum AbortMaintenanceError { /// [`Cluster::update_node_operator`] error. #[derive(Debug, thiserror::Error)] pub enum UpdateNodeOperatorError { - #[error("Provided node operator is not a member of this cluster")] - UnknownOperator, + #[error("Signer should either be the NodeOperator being updated or the owner")] + Unauthorized, - #[error("Data serialization: {0}")] + #[error(transparent)] + NotFoundError(#[from] node_operator::NotFoundError), + + #[error(transparent)] DataSerialization(#[from] node_operator::DataSerializationError), #[error(transparent)] @@ -419,6 +490,22 @@ pub enum UpdateNodeOperatorError { SmartContract(#[from] smart_contract::Error), } +/// [`Cluster::remove_node_operator`] error. +#[derive(Debug, thiserror::Error)] +pub enum RemoveNodeOperatorError { + #[error(transparent)] + NotOwner(#[from] ownership::NotOwnerError), + + #[error(transparent)] + NotFoundError(#[from] node_operator::NotFoundError), + + #[error("Node operator is still within a Keyspace")] + InKeyspace, + + #[error("Smart-contract: {0}")] + SmartContract(#[from] smart_contract::Error), +} + impl Event { fn cluster_version(&self) -> Version { match self { @@ -436,151 +523,3 @@ impl Event { } } } - -/// Read-only view of a WCN cluster. -pub struct View { - node_operators: HashMap>, - - ownership: Ownership, - settings: Settings, - - keyspace: Keyspace, - migration: Option, - maintenance: Option, - - cluster_version: Version, -} - -impl View { - fn no_migration(&self) -> Result<(), LogicalError> { - if let Some(migration) = self.migration() { - return Err(LogicalError::MigrationInProgress(migration.id())); - } - - Ok(()) - } - - fn no_maintenance(&self) -> Result<(), LogicalError> { - if self.maintenance().is_some() { - return Err(LogicalError::MaintenanceInProgress); - } - - Ok(()) - } - - fn has_migration(&mut self) -> Result<&mut Migration, LogicalError> { - self.migration.as_mut().ok_or(LogicalError::NoMigration) - } - - fn has_maintenance(&mut self) -> Result<&mut Maintenance, LogicalError> { - self.maintenance.as_mut().ok_or(LogicalError::NoMaintenance) - } - - /// Applies the provided [`Event`] to this [`View`]. - pub async fn apply_event(mut self, event: Event) -> Result { - let new_version = event.cluster_version(); - - if new_version != self.cluster_version + 1 { - return Err(ApplyEventError::ClusterVersionMismatch { - current: self.cluster_version, - event: new_version, - }); - } - - match event { - Event::MigrationStarted(evt) => evt.apply(&mut self).await, - Event::MigrationDataPullCompleted(evt) => evt.apply(&mut self), - Event::MigrationCompleted(evt) => evt.apply(&mut self), - Event::MigrationAborted(evt) => evt.apply(&mut self), - Event::MaintenanceStarted(evt) => evt.apply(&mut self), - Event::MaintenanceFinished(evt) => evt.apply(&mut self), - Event::NodeOperatorAdded(evt) => evt.apply(&mut self), - Event::NodeOperatorUpdated(evt) => evt.apply(&mut self), - Event::NodeOperatorRemoved(evt) => evt.apply(&mut self), - Event::SettingsUpdated(evt) => evt.apply(&mut self), - Event::OwnershipTransferred(evt) => evt.apply(&mut self), - }?; - - self.cluster_version = new_version; - - Ok(self) - } - - /// Returns the primary [`Keyspace`] of this WCN cluster. - pub fn keyspace(&self) -> &Keyspace { - &self.keyspace - } - - /// Returns the ongoing data [`Migration`] of this WCN cluster. - pub fn migration(&self) -> Option<&Migration> { - self.migration.as_ref() - } - - /// Returns the ongoing [`Maintenance`] of this WCN cluster. - pub fn maintenance(&self) -> Option<&Maintenance> { - self.maintenance.as_ref() - } - - /// Indicates whether the [`NodeOperator`] is a member of the [`Cluster`]. - pub fn is_member(&self, id: &node_operator::Id) -> bool { - self.operator_idx(id).is_some() - } - - fn operator_idx(&self, id: &node_operator::Id) -> Option { - self.keyspace.operators().get_idx(&id).or_else(|| { - self.migration - .as_ref() - .and_then(|migration| migration.keyspace().operators().get_idx(&id)) - }) - } -} - -/// Error of [`View::apply_event`] -#[derive(Debug, thiserror::Error)] -pub enum ApplyEventError { - /// [`Version`] inside the [`Event`] wasn't monotonic. - #[error("Cluster version mismatch (current: {current}, event: {event})")] - ClusterVersionMismatch { current: Version, event: Version }, - - /// [`LogicalError`] observed while applying an [`Event`]. - #[error("Logic: {0}")] - Logic(#[from] LogicalError), -} - -/// Logical error caused by a race condition or by an incorrect implementation -/// of the [`SmartContract`] -#[derive(Debug, thiserror::Error)] -pub enum LogicalError { - #[error("Migration(id: {0}) is in progress, but it shouldn't be")] - MigrationInProgress(migration::Id), - - #[error("Maintenance is in progress, but it shouldn't be")] - MaintenanceInProgress, - - #[error("No migration, but there should be")] - NoMigration, - - #[error("No maintenance, but there should be")] - NoMaintenance, - - #[error("Migration ID mismatch (event: {event}, local: {event})")] - MigrationIdMismatch { - event: migration::Id, - local: migration::Id, - }, - - #[error("Node operator (id: {0}) is not currently pulling the data")] - NodeOperatorNotPulling(node_operator::Id), - - #[error("There are still pulling operators remaining, but ther shouldn't be")] - PullingOperatorsRemaining, - - #[error("Node operator (id: {0}) is not within the cluster, but should be")] - UnknownOperator(node_operator::Id), - - #[error("Settings unchanged, but they should have changed")] - SettingsUnchanged, - - #[error("Owner unchanged, but it should have changed")] - OwnerUnchanged, -} diff --git a/crates/cluster/src/maintenance.rs b/crates/cluster/src/maintenance.rs index 26915085..67f80ff1 100644 --- a/crates/cluster/src/maintenance.rs +++ b/crates/cluster/src/maintenance.rs @@ -1,18 +1,21 @@ -use crate::{node, node_operator, LogicalError, Version as ClusterVersion, View as ClusterView}; +use crate::{node_operator, Version as ClusterVersion}; /// Maintenance process within a WCN cluster. /// /// Only a single [`node_operator`] at a time is allowed to be under /// maintenance. pub struct Maintenance { - operator_id: node_operator::Id, + slot: node_operator::Id, } impl Maintenance { - /// Returns [`node_operator::Id`] of the node operator currently under - /// [`Maintenance`]. - pub fn operator(&self) -> &node_operator::Id { - &self.operator_id + pub fn new(slot: node_operator::Id) -> Self { + Self { slot } + } + + /// Returns [`node_operator::Id`] that occupies the [`Maintenance`] slot. + pub fn slot(&self) -> &node_operator::Id { + &self.slot } } @@ -25,30 +28,16 @@ pub struct Started { pub cluster_version: ClusterVersion, } -impl Started { - pub(super) fn apply(self, view: &mut ClusterView) -> Result<(), LogicalError> { - view.no_migration()?; - view.no_maintenance()?; - - view.maintenance = Some(Maintenance { - operator_id: self.operator_id, - }); - - Ok(()) - } -} - /// [`Maintenance`] has been finished. pub struct Finished { /// Updated [`ClusterVersion`]. pub cluster_version: ClusterVersion, } -impl Finished { - pub(super) fn apply(self, view: &mut ClusterView) -> Result<(), LogicalError> { - view.has_maintenance()?; - view.maintenance = None; +#[derive(Debug, thiserror::Error)] +#[error("Maintenance(slot: {_0}) in progress")] +pub struct InProgressError(pub node_operator::Id); - Ok(()) - } -} +#[derive(Debug, thiserror::Error)] +#[error("No maintenance")] +pub struct NotFoundError; diff --git a/crates/cluster/src/migration.rs b/crates/cluster/src/migration.rs index 6ff02c0a..3bcf3103 100644 --- a/crates/cluster/src/migration.rs +++ b/crates/cluster/src/migration.rs @@ -3,13 +3,8 @@ use { keyspace::{self, ReplicationStrategy}, node_operator, Keyspace, - LogicalError, - SerializedNodeOperator, Version as ClusterVersion, - VersionedNodeOperator, - View as ClusterView, }, - itertools::Itertools, std::collections::HashSet, }; @@ -17,38 +12,35 @@ use { pub type Id = u64; /// Data migration process within a WCN cluster. -pub struct Migration { +pub struct Migration { id: Id, - keyspace: Keyspace, - pulling_operators: HashSet, + keyspace: Keyspace, + pulling_operators: HashSet, } -impl Migration { - /// Creates a new [`Migration`]. - pub(super) async fn new(id: Id, old_keyspace: &Keyspace, plan: Plan) -> Self { - let mut operators = old_keyspace.operators().clone(); - for (idx, slot) in plan.slots { - operators.set(idx, slot); - } +/// [`Migration`] plan. +pub struct Plan { + /// Set of [`node_operator`]s to remove from the current [`Keyspace`]. + pub remove: HashSet, - let new_keyspace = Keyspace::new( - operators, - plan.replication_strategy, - old_keyspace.version() + 1, - ) - .await; + /// Set of [`node_operator`]s to add to the current [`Keyspace`]. + pub add: HashSet, - let pulling_operators = new_keyspace - .operators() - .slots() - .iter() - .filter_map(|slot| slot.as_ref().map(|operator| *operator.id())) - .collect(); + /// New [`ReplicationStrategy`] to use. + pub replication_strategy: ReplicationStrategy, +} +impl Migration { + /// Creates a new [`Migration`]. + pub(super) fn new( + id: Id, + keyspace: Keyspace, + pulling_operators: impl IntoIterator, + ) -> Self { Self { id, - keyspace: new_keyspace, - pulling_operators, + keyspace, + pulling_operators: pulling_operators.into_iter().collect(), } } @@ -58,103 +50,73 @@ impl Migration { } /// Returns the new [`Keyspace`] this [`Migration`] is migrating to. - pub fn keyspace(&self) -> &Keyspace { + pub fn keyspace(&self) -> &Keyspace { &self.keyspace } - /// Mutable version of [`Migration::keyspace`]. - pub fn keyspace_mut(&mut self) -> &mut Keyspace { - &mut self.keyspace + // /// Mutable version of [`Migration::keyspace`]. + // pub fn keyspace_mut(&mut self) -> &mut Keyspace { + // &mut self.keyspace + // } + + pub(super) fn into_keyspace(self) -> Keyspace { + self.keyspace } /// Indicates whether the specified [`node_operator`] is still in process of /// pulling the data. - pub fn is_pulling(&self, id: &node_operator::Id) -> bool { - self.pulling_operators.contains(&id) + pub fn is_pulling(&self, idx: node_operator::Idx) -> bool { + self.pulling_operators.contains(&idx) } -} -/// [`Plan`] that is not yet published on-chain. -pub type NewPlan = Plan; - -/// [`Migration`] plan. -pub struct Plan { - slots: Vec<(node_operator::Idx, Option)>, - replication_strategy: ReplicationStrategy, -} + pub(crate) fn pulling_operators_count(&self) -> usize { + self.pulling_operators.len() + } -impl Plan { - /// Creates a new migration [`Plan`]. - pub(super) fn new( - cluster_view: &ClusterView, - remove: Vec, - add: Vec, - ) -> Result { - let slot_count = remove - .iter() - .chain(add.iter().map(VersionedNodeOperator::id)) - .dedup() - .count(); - - if slot_count != remove.len() + add.len() { - return Err(PlanError::DuplicateIds); - } + pub(crate) fn complete_pull(&mut self, idx: node_operator::Idx) { + self.pulling_operators.remove(&idx); + } - if cluster_view.migration.is_some() { - return Err(PlanError::MigrationInProgress); + pub(crate) fn require_id(&self, id: Id) -> Result<&Migration, WrongIdError> { + if id != self.id { + return Err(WrongIdError(id, self.id)); } - let mut slots = Vec::with_capacity(slot_count); - let operators = cluster_view.keyspace.operators(); + Ok(self) + } - for id in remove { - operators - .get_idx(&id) - .map(|idx| slots.push((idx, None))) - .ok_or_else(|| PlanError::UnknownOperator(id))?; + pub(crate) fn require_pulling( + &self, + idx: node_operator::Idx, + ) -> Result<&Migration, OperatorNotPullingError> { + if !self.is_pulling(idx) { + return Err(OperatorNotPullingError(idx)); } - let add = &mut add.into_iter(); - - // First populate the slots that were cleared just now. - for (id, slot) in add.zip(slots.iter_mut()) { - slot.1 = Some(id); - } + Ok(self) + } - for item in add.zip_longest(operators.freeSlots()) { - match item.left_and_right() { - (Some(_), None) => return Err(PlanError::TooManyOperators), - (None, _) => break, - (Some(operator), _) if operators.contains(operator.id()) => { - return Err(PlanError::OperatorAlreadyExists(*operator.id())) - } - (Some(id), Some(idx)) => slots.push((idx, Some(id))), - }; + pub(crate) fn require_pulling_count( + &self, + expected: usize, + ) -> Result<&Migration, WrongPullingOperatorsCountError> { + let count = self.pulling_operators.len(); + if count != expected { + return Err(WrongPullingOperatorsCountError(expected, count)); } - Ok(NewPlan { - slots, - replication_strategy: keyspace::ReplicationStrategy::default(), - }) + Ok(self) } } -#[derive(Debug, thiserror::Error)] -pub enum PlanError { - #[error("Another migration is already in progress")] - MigrationInProgress, - - #[error("Duplicate operator IDs provided")] - DuplicateIds, - - #[error("Unknown operator: {0}")] - UnknownOperator(node_operator::Id), - - #[error("Operator already exists: {0}")] - OperatorAlreadyExists(node_operator::Id), - - #[error("Too many operators")] - TooManyOperators, +impl Migration { + pub(crate) async fn calculate_keyspace_shards(self) -> Migration { + Migration { + id: self.id, + keyspace: self.keyspace.calculate_shards().await, + pulling_operators: self.pulling_operators, + } + } } /// [`Migration`] has started. @@ -162,24 +124,13 @@ pub struct Started { /// [`Id`] of the [`Migration`] being started. pub migration_id: Id, - /// Migration [`Plan`] being used. - pub plan: Plan, + /// New [`Keyspace`] to migrate to. + pub new_keyspace: Keyspace, /// Updated [`ClusterVersion`]. pub cluster_version: ClusterVersion, } -impl Started { - pub(super) async fn apply(self, view: &mut ClusterView) -> Result<(), LogicalError> { - view.no_migration()?; - view.no_maintenance()?; - - view.migration = Some(Migration::new(self.migration_id, &view.keyspace, self.plan).await); - - Ok(()) - } -} - /// [`NodeOperator`](crate::NodeOperator) has completed the data pull. pub struct DataPullCompleted { /// [`Id`] of the [`Migration`]. @@ -192,18 +143,6 @@ pub struct DataPullCompleted { pub cluster_version: ClusterVersion, } -impl DataPullCompleted { - pub(super) fn apply(self, view: &mut ClusterView) -> Result<(), LogicalError> { - let migration = view.has_migration()?.with_correct_id(self.migration_id)?; - - if !migration.pulling_operators.remove(&self.operator_id) { - return Err(LogicalError::NodeOperatorNotPulling(self.operator_id)); - } - - Ok(()) - } -} - /// [`Migration`] has been completed. pub struct Completed { /// [`Id`] of the completed [`Migration`]. @@ -216,24 +155,6 @@ pub struct Completed { pub cluster_version: ClusterVersion, } -impl Completed { - pub(super) fn apply(self, view: &mut ClusterView) -> Result<(), LogicalError> { - let migration = view.has_migration()?.with_correct_id(self.migration_id)?; - - if !migration.pulling_operators.remove(&self.operator_id) { - return Err(LogicalError::NodeOperatorNotPulling(self.operator_id)); - } - - if !migration.pulling_operators.is_empty() { - return Err(LogicalError::PullingOperatorsRemaining); - } - - view.keyspace = view.migration.take().unwrap().keyspace; - - Ok(()) - } -} - /// [`Migration`] has been aborted. pub struct Aborted { /// [`Id`] of the [`Migration`]. @@ -243,23 +164,22 @@ pub struct Aborted { pub cluster_version: ClusterVersion, } -impl Aborted { - pub(super) fn apply(self, view: &mut ClusterView) -> Result<(), LogicalError> { - view.has_migration()?.with_correct_id(self.migration_id)?; - view.migration = None; +#[derive(Debug, thiserror::Error)] +#[error("Migration(id: {_0}) in progress")] +pub struct InProgressError(pub Id); - Ok(()) - } -} +#[derive(Debug, thiserror::Error)] +#[error("No migration")] +pub struct NotFoundError; -impl Migration { - fn with_correct_id(&mut self, id: Id) -> Result<&mut Self, LogicalError> { - if id != self.id { - return Err(LogicalError::MigrationIdMismatch { - event: id, - local: self.id, - }); - } - Ok(self) - } -} +#[derive(Debug, thiserror::Error)] +#[error("Wrong migration ID: {_0} != {_1}")] +pub struct WrongIdError(pub Id, pub Id); + +#[derive(Debug, thiserror::Error)] +#[error("NodeOperator(idx: {_0}) is not currently pulling data")] +pub struct OperatorNotPullingError(pub node_operator::Idx); + +#[derive(Debug, thiserror::Error)] +#[error("Wrong pulling operators count: {_0} != {_1}")] +pub struct WrongPullingOperatorsCountError(pub usize, pub usize); diff --git a/crates/cluster/src/node.rs b/crates/cluster/src/node.rs index 820f5526..ee7a00c4 100644 --- a/crates/cluster/src/node.rs +++ b/crates/cluster/src/node.rs @@ -10,7 +10,7 @@ use { /// /// The IP address is currently being encrypted using a format-preserving /// encryption algorithm. -#[derive(Debug)] +#[derive(Debug, Clone, Copy)] pub struct Data { /// [`PeerId`] of the [`Node`]. /// diff --git a/crates/cluster/src/node_operator.rs b/crates/cluster/src/node_operator.rs index a27d6c70..76386073 100644 --- a/crates/cluster/src/node_operator.rs +++ b/crates/cluster/src/node_operator.rs @@ -1,23 +1,15 @@ //! Entity operating a set of nodes within a WCN cluster. use { - crate::{ - client, - node, - smart_contract, - LogicalError, - Node, - Version as ClusterVersion, - View as ClusterView, - }, - arc_swap::ArcSwap, - derive_more::From, + crate::{self as cluster, client, node, smart_contract, Version as ClusterVersion}, + derive_more::derive::{From, Into}, + itertools::Itertools as _, serde::{Deserialize, Serialize}, - std::{collections::HashMap, ops::Sub, sync::Arc}, + std::collections::HashMap, }; /// Globally unique identifier of a [`NodeOperator`]; -pub type Id = smart_contract::PublicKey; +pub type Id = smart_contract::AccountAddress; /// Locally unique identifier of a [`NodeOperator`] within a WCN cluster. /// @@ -64,11 +56,8 @@ pub struct Data { } /// [`NodeOperator`] [`Data`] serialized for on-chain storage. -#[derive(Debug)] -pub struct SerializedData(Vec); - -/// [`NodeOperator`] [`Data`] that can be shared and modified across threads. -pub struct SharedData(Arc>); +#[derive(Debug, Into)] +pub struct SerializedData(pub(crate) Vec); /// Entity operating a set of [`Node`]s within a WCN cluster. #[derive(Clone, Debug)] @@ -83,12 +72,9 @@ pub type SerializedNodeOperator = NodeOperator; /// [`NodeOperator`] with [`VersionedData`]. pub type VersionedNodeOperator = NodeOperator; -/// [`NodeOperator`] with [`SharedData`]. -pub type SharedNodeOperator = NodeOperator; - impl NodeOperator { - /// Creates a [`NewNodeOperator`]. - pub fn new(id: Id, data: Data) -> NodeOperator { + /// Creates a [`NodeOperator`]. + pub fn new(id: Id, data: D) -> NodeOperator { NodeOperator { id, data } } @@ -101,10 +87,19 @@ impl NodeOperator { pub fn data(&self) -> &D { &self.data } + + /// Converts this [`NodeOperator`] into the inner `data`. + pub fn into_data(self) -> D { + self.data + } } /// Event of a new [`NodeOperator`] being added to a WCN cluster. pub struct Added { + /// [`Idx`] in the [`NodeOperators`] slot map the [`NodeOperator`] is being + /// placed to. + pub idx: Idx, + /// [`NodeOperator`] being added. pub operator: VersionedNodeOperator, @@ -112,12 +107,6 @@ pub struct Added { pub cluster_version: ClusterVersion, } -impl Added { - pub(super) fn apply(self, view: &mut ClusterView) -> Result<(), LogicalError> { - todo!() - } -} - /// Event of a [`NodeOperator`] being updated. pub struct Updated { /// Updated [`NodeOperator`]. @@ -127,33 +116,6 @@ pub struct Updated { pub cluster_version: ClusterVersion, } -impl Updated { - pub(super) fn apply(self, view: &mut ClusterView) -> Result<(), LogicalError> { - let mut applied = false; - - if let Some(migration) = &mut view.migration { - if let Some(data) = migration - .keyspace_mut() - .operator_data_mut(self.operator.id()) - { - *data = self.operator.data.clone(); - applied = true; - } - } - - if let Some(data) = view.keyspace.operator_data_mut(self.operator.id()) { - *data = self.operator.data; - applied = true; - } - - if !applied { - return Err(LogicalError::UnknownOperator(self.operator.id)); - } - - Ok(()) - } -} - /// Event of a [`NodeOperator`] being removed from a WCN cluster. pub struct Removed { /// [`Id`] of the [`NodeOperator`] being removed. @@ -163,15 +125,9 @@ pub struct Removed { pub cluster_version: ClusterVersion, } -impl Removed { - pub(super) fn apply(self, view: &mut ClusterView) -> Result<(), LogicalError> { - todo!() - } -} - impl NodeOperator { pub(super) fn serialize(self) -> Result { - Ok(VersionedNodeOperator { + Ok(NodeOperator { id: self.id, data: self.data.serialize()?, }) @@ -215,10 +171,12 @@ enum VersionedDataInner { V0(DataV0), } -impl VersionedNodeOperator { - fn deserialize(id: Id, data_bytes: &[u8]) -> Result { +impl SerializedNodeOperator { + fn deserialize(self) -> Result { use DataDeserializationError as Error; + let data_bytes = self.data.0; + if data_bytes.is_empty() { return Err(DataDeserializationError::EmptyBuffer); } @@ -232,7 +190,7 @@ impl VersionedNodeOperator { } .map_err(Error::from_postcard)?; - Ok(Self { id, data }) + Ok(NodeOperator { id: self.id, data }) } } @@ -276,11 +234,11 @@ impl DataDeserializationError { } impl SerializedData { - /// Validates that [`SerializedData`] size doesn't exceed the provided - /// `limit`. - pub(super) fn validate_size(&self, limit: u16) -> Result<(), DataTooLargeError> { + /// Validates that [`SerializedData`] size doesn't exceed + /// [`cluster::Settings::max_node_operator_data_bytes`]. + pub(super) fn validate(&self, settings: &cluster::Settings) -> Result<(), DataTooLargeError> { let value = self.0.len(); - let limit = limit as usize; + let limit = settings.max_node_operator_data_bytes as usize; if value > limit { return Err(DataTooLargeError { value, limit }); @@ -300,15 +258,44 @@ pub struct DataTooLargeError { /// Slot map of [`NodeOperator`]s. #[derive(Debug, Clone)] -pub(super) struct NodeOperators { +pub struct NodeOperators { id_to_idx: HashMap, // TODO: assert length - slots: Vec>, + slots: Vec>>, } -impl NodeOperators { - pub(super) fn set(&mut self, idx: Idx, slot: Option) { +impl NodeOperators { + pub(super) fn new( + slots: impl IntoIterator>>, + ) -> Result { + let slots: Vec<_> = slots.into_iter().collect(); + + if slots.len() > cluster::MAX_OPERATORS { + return Err(SlotMapCreationError::TooManyOperatorSlots(slots.len())); + } + + let mut this = Self { + id_to_idx: HashMap::with_capacity(slots.len()), + slots: Vec::with_capacity(slots.len()), + }; + + for (idx, slot) in slots.iter().enumerate() { + if let Some(operator) = &slot { + if this.id_to_idx.insert(*operator.id(), idx as u8).is_some() { + return Err(SlotMapCreationError::OperatorDuplicate(*operator.id())); + }; + } + } + + Ok(this) + } + + pub(super) fn into_slots(self) -> Vec>> { + self.slots + } + + pub(super) fn set(&mut self, idx: Idx, slot: Option>) { if let Some(id) = self.get_by_idx(idx).map(|op| op.id) { self.id_to_idx.remove(&id); } @@ -336,27 +323,33 @@ impl NodeOperators { /// Returns whether this map contains the [`NodeOperator`] with the provided /// [`Id`]. pub(super) fn contains(&self, id: &Id) -> bool { - self.get(id).is_some() + self.get_idx(id).is_some() + } + + /// Returns whether this map contains the [`NodeOperator`] with the provided + /// [`Idx`]. + pub(super) fn contains_idx(&self, idx: Idx) -> bool { + self.get_by_idx(idx).is_some() } /// Gets an [`NodeOperator`] by [`Id`]. - pub(super) fn get(&self, id: &Id) -> Option<&VersionedNodeOperator> { + pub(super) fn get(&self, id: &Id) -> Option<&NodeOperator> { self.get_by_idx(self.get_idx(id)?) } /// Gets a mutable reference to a [`NodeOperator`] [`Data`]. - pub(super) fn get_data_mut(&mut self, id: &Id) -> Option<&mut VersionedData> { + pub(super) fn get_data_mut(&mut self, id: &Id) -> Option<&mut Data> { self.get_by_idx_mut(self.get_idx(id)?) .map(|operator| &mut operator.data) } /// Gets an [`NodeOperator`] by [`Idx`]. - pub(super) fn get_by_idx(&self, idx: Idx) -> Option<&VersionedNodeOperator> { + pub(super) fn get_by_idx(&self, idx: Idx) -> Option<&NodeOperator> { self.slots.get(idx as usize)?.as_ref() } /// Mutable version of [`NodeOperators::get_by_idx`]. - fn get_by_idx_mut(&mut self, idx: Idx) -> Option<&mut VersionedNodeOperator> { + fn get_by_idx_mut(&mut self, idx: Idx) -> Option<&mut NodeOperator> { self.slots.get_mut(idx as usize)?.as_mut() } @@ -365,15 +358,67 @@ impl NodeOperators { self.id_to_idx.get(id).copied() } - /// Returns the list of [`NodeOperator`] slots. - pub(super) fn slots(&self) -> &[Option] { - &self.slots - } - - pub(super) fn freeSlots(&self) -> impl Iterator + '_ { + pub(super) fn occupied_indexes(&self) -> impl Iterator + '_ { self.slots .iter() .enumerate() - .filter_map(|(idx, slot)| slot.is_none().then_some(idx.try_into().unwrap())) + .filter_map(|(idx, slot)| slot.is_some().then_some(idx as u8)) } + + pub(super) fn require_idx(&self, id: &Id) -> Result { + self.get_idx(id).ok_or_else(|| NotFoundError(*id)) + } + + pub(super) fn require_not_exists(&self, id: &Id) -> Result<&Self, AlreadyExistsError> { + if self.contains(id) { + return Err(AlreadyExistsError(*id)); + } + + Ok(self) + } + + pub(super) fn require_free_slot(&self, idx: Idx) -> Result<&Self, SlotOccupiedError> { + if self.contains_idx(idx) { + return Err(SlotOccupiedError(idx)); + } + + Ok(self) + } +} + +impl NodeOperators { + pub(super) fn deserialize(self) -> Result { + Ok(NodeOperators { + id_to_idx: self.id_to_idx, + slots: self + .slots + .into_iter() + .map(|slot| slot.map(SerializedNodeOperator::deserialize).transpose()) + .try_collect()?, + }) + } +} + +#[derive(Debug, thiserror::Error)] +pub enum SlotMapCreationError { + #[error("Too many operator slots: {_0} > {}", cluster::MAX_OPERATORS)] + TooManyOperatorSlots(usize), + + #[error("Too few operators: {_0} < {}", cluster::MIN_OPERATORS)] + TooFewOperators(usize), + + #[error("Duplicate NodeOperator(id: {_0})")] + OperatorDuplicate(Id), } + +#[derive(Debug, thiserror::Error)] +#[error("Node operator (id: {0}) is not a member of this cluster")] +pub struct NotFoundError(pub Id); + +#[derive(Debug, thiserror::Error)] +#[error("Node operator (id: {0}) is already a member of the cluster")] +pub struct AlreadyExistsError(pub Id); + +#[derive(Debug, thiserror::Error)] +#[error("Slot {_0} in NodeOperators slot map is already occupied")] +pub struct SlotOccupiedError(pub Idx); diff --git a/crates/cluster/src/ownership.rs b/crates/cluster/src/ownership.rs index a0329f47..89d7fb35 100644 --- a/crates/cluster/src/ownership.rs +++ b/crates/cluster/src/ownership.rs @@ -1,55 +1,49 @@ //! Ownership of a WCN cluster. -use crate::{ - smart_contract, - LogicalError, - SmartContract, - Version as ClusterVersion, - View as ClusterView, -}; +use crate::{smart_contract, SmartContract, Version as ClusterVersion}; /// Ownership of a WCN cluster. /// /// Cluster has a single owner, and some [`smart_contract`] methods are /// resticted to be executed only by the owner. pub struct Ownership { - owner: smart_contract::PublicKey, + owner: smart_contract::AccountAddress, } impl Ownership { - pub(super) fn validate_signer( + pub(super) fn new(owner: smart_contract::AccountAddress) -> Self { + Self { owner } + } + + pub(super) fn is_owner(&self, address: &smart_contract::AccountAddress) -> bool { + address == &self.owner + } + + pub(super) fn require_owner( &self, smart_contract: &impl SmartContract, ) -> Result<(), NotOwnerError> { - if self.owner != smart_contract.signer() { + if !self.is_owner(smart_contract.signer()) { return Err(NotOwnerError); } Ok(()) } + + pub(super) fn transfer(&mut self, new_owner: smart_contract::AccountAddress) { + self.owner = new_owner; + } } /// Event of [`Ownership`] being transferred. pub struct Transferred { /// New owner of the WCN cluster. - pub new_owner: smart_contract::PublicKey, + pub new_owner: smart_contract::AccountAddress, /// Update [`ClusterVersion`]. pub cluster_version: ClusterVersion, } -impl Transferred { - pub(super) fn apply(self, view: &mut ClusterView) -> Result<(), LogicalError> { - if view.ownership.owner == self.new_owner { - return Err(LogicalError::OwnerUnchanged); - } - - view.ownership.owner = self.new_owner; - - Ok(()) - } -} - #[derive(Debug, thiserror::Error)] #[error("Smart-contract signer is not the owner")] pub struct NotOwnerError; diff --git a/crates/cluster/src/settings.rs b/crates/cluster/src/settings.rs index 117f6221..440031e8 100644 --- a/crates/cluster/src/settings.rs +++ b/crates/cluster/src/settings.rs @@ -1,5 +1,5 @@ //! WCN cluster settings. -use crate::{LogicalError, Version as ClusterVersion, View as ClusterView}; +use crate::Version as ClusterVersion; /// WCN cluster settings. #[derive(Clone, Debug, Eq, PartialEq)] @@ -16,15 +16,3 @@ pub struct Updated { /// Updated [`ClusterVersion`]. pub cluster_version: ClusterVersion, } - -impl Updated { - pub(super) fn apply(self, view: &mut ClusterView) -> Result<(), LogicalError> { - if view.settings == self.settings { - return Err(LogicalError::SettingsUnchanged); - } - - view.settings = self.settings; - - Ok(()) - } -} diff --git a/crates/cluster/src/smart_contract/evm.rs b/crates/cluster/src/smart_contract/evm.rs index 0ef5e371..ff45d7b2 100644 --- a/crates/cluster/src/smart_contract/evm.rs +++ b/crates/cluster/src/smart_contract/evm.rs @@ -1,7 +1,28 @@ +//! EVM implementation of [`SmartContract`](super::SmartContract). + use { - super::{PublicKey, Result, RpcUrl, Signer}, - crate::{node, node_operator, NodeOperator, Settings}, - alloy::{providers::DynProvider, sol, sol_types::SolConstructor}, + super::{AccountAddress, ConnectError, Error, Result, RpcUrl, Signer, SignerInner}, + crate::{ + self as cluster, + migration, + node_operator, + smart_contract, + Keyspace, + Maintenance, + Migration, + NodeOperator, + NodeOperators, + Ownership, + SerializedNodeOperator, + Settings, + }, + alloy::{ + contract::{CallBuilder, CallDecoder}, + network::EthereumWallet, + primitives::Uint, + providers::{DynProvider, Provider, ProviderBuilder}, + }, + std::{collections::HashSet, time::Duration}, }; mod bindings { @@ -12,107 +33,338 @@ mod bindings { ); } +type AlloyContract = bindings::Cluster::ClusterInstance; + +type U256 = Uint<256, 4>; + +/// EVM implementation of [`SmartContract`](super::SmartContract). #[derive(Clone)] -pub struct SmartContract(bindings::Cluster::ClusterInstance); +pub struct SmartContract { + signer_addr: S, + alloy: AlloyContract, +} + +/// EVM implementation of +/// [`ReadOnlySmartContract`](super::ReadOnlySmartContract). +pub type SmartContractRO = SmartContract<()>; pub(crate) type Address = alloy::primitives::Address; impl super::SmartContract for SmartContract { - type ReadOnly = Self; + type ReadOnly = SmartContractRO; async fn deploy( signer: Signer, rpc_url: RpcUrl, initial_settings: Settings, - initial_operators: Vec, + initial_operators: NodeOperators, ) -> Result { - todo!() - - // let initial_settings = bindings::Cluster::Settings { - // maxOperatorDataBytes: 4096, - // }; + let signer_addr = signer.address(); - // let initial_operators = initial_operators.into_iter().map(|key| - // key.0).collect(); + bindings::Cluster::deploy( + new_provier(signer, rpc_url), + initial_settings.into(), + initial_operators + .into_slots() + .into_iter() + .filter_map(|op| op.map(Into::into)) + .collect(), + ) + .await + .map(|alloy| Self { signer_addr, alloy }) + .map_err(Into::into) + } - // let smart_contract = bindings::Cluster::deploy( - // self.alloy_provider.clone(), - // initial_settings, - // initial_operators, - // ) - // .await?; + async fn connect( + address: smart_contract::Address, + signer: Signer, + rpc_url: RpcUrl, + ) -> Result { + let signer_addr = signer.address(); - // Ok(Manager { - // smart_contract, - // alloy_provider: self.alloy_provider, - // }) + connect(address, new_provier(signer, rpc_url)) + .await + .map(|alloy| Self { signer_addr, alloy }) } - async fn connect(signer: Signer, rpc_url: RpcUrl) -> super::Result { - // let wallet: EthereumWallet = match signer.inner { - // SignerInner::PrivateKey(key) => key.into(), - // }; + async fn connect_ro( + address: smart_contract::Address, + rpc_url: RpcUrl, + ) -> Result { + let signer_addr = (); + + connect(address, new_ro_provier(rpc_url)) + .await + .map(|alloy| Self::ReadOnly { signer_addr, alloy }) + } - // let provider = ProviderBuilder::new().wallet(wallet).on_http(rpc_url.0); + fn signer(&self) -> &AccountAddress { + &self.signer_addr + } - // Self { - // smart_contract: (), - // alloy_provider: DynProvider::new(provider), - // } + async fn start_migration(&self, new_keyspace: Keyspace) -> Result<()> { + check_receipt(self.alloy.startMigration(new_keyspace.into())).await + } - todo!() + async fn complete_migration(&self, id: migration::Id) -> Result<()> { + check_receipt(self.alloy.completeMigration(id)).await } - async fn connect_ro(rpc_url: RpcUrl) -> Result { - todo!() + async fn abort_migration(&self, id: migration::Id) -> Result<()> { + check_receipt(self.alloy.abortMigration(id)).await } - fn signer(&self) -> PublicKey { - todo!() + async fn start_maintenance(&self) -> Result<()> { + check_receipt(self.alloy.startMaintenance()).await } - async fn start_migration(&self, plan: crate::migration::Plan) -> Result<()> { - todo!() + async fn finish_maintenance(&self) -> Result<()> { + check_receipt(self.alloy.finishMaintenance()).await } - async fn complete_migration( + async fn add_node_operator( &self, - id: crate::migration::Id, - operator_idx: node_operator::Idx, - ) -> super::Result<()> { - todo!() + idx: node_operator::Idx, + operator: SerializedNodeOperator, + ) -> Result<()> { + check_receipt(self.alloy.addNodeOperator(idx, operator.into())).await } - async fn abort_migration(&self, id: crate::migration::Id) -> Result<()> { - todo!() + async fn update_node_operator(&self, operator: SerializedNodeOperator) -> super::Result<()> { + check_receipt(self.alloy.updateNodeOperator(operator.into())).await } - async fn start_maintenance(&self, operator_idx: node_operator::Idx) -> Result<()> { - todo!() + async fn remove_node_operator(&self, id: node_operator::Id) -> Result<()> { + check_receipt(self.alloy.removeNodeOperator(id.0)).await } - async fn finish_maintenance(&self) -> Result<()> { - todo!() + async fn update_settings(&self, new_settings: Settings) -> Result<()> { + check_receipt(self.alloy.updateSettings(new_settings.into())).await } - async fn update_node_operator( - &self, - id: node_operator::Id, - idx: node_operator::Idx, - data: node_operator::SerializedData, - ) -> super::Result<()> { - todo!() + async fn transfer_ownership(&self, new_owner: AccountAddress) -> Result<()> { + check_receipt(self.alloy.transferOwnership(new_owner.0)).await + } +} + +async fn check_receipt(call: CallBuilder<&DynProvider, D>) -> Result<(), Error> +where + D: CallDecoder, +{ + let receipt = call + .send() + .await? + .with_timeout(Some(Duration::from_secs(30))) + .get_receipt() + .await?; + + if !receipt.status() { + return Err(Error::Revert(format!("{}", receipt.transaction_hash))); + } + + Ok(()) +} + +impl super::ReadOnlySmartContract for SmartContract { + async fn cluster_view(&self) -> Result> { + self.alloy.getView().call().await?.try_into() + } +} + +async fn connect( + address: smart_contract::Address, + provider: DynProvider, +) -> Result { + let code = provider + .get_code_at(address.0) + .await + .map_err(|err| ConnectError::Other(err.to_string()))?; + + if code.is_empty() { + return Err(ConnectError::UnknownContract); + } + + if code != bindings::Cluster::BYTECODE { + return Err(ConnectError::WrongContract); + } + + Ok(bindings::Cluster::new(address.0, provider)) +} + +fn new_provier(signer: Signer, rpc_url: RpcUrl) -> DynProvider { + let wallet: EthereumWallet = match signer.inner { + SignerInner::PrivateKey(key) => key.into(), + }; + + let provider = ProviderBuilder::new() + .wallet(wallet) + .connect_http(rpc_url.0); + + DynProvider::new(provider) +} + +fn new_ro_provier(rpc_url: RpcUrl) -> DynProvider { + let provider = ProviderBuilder::new().connect_http(rpc_url.0); + DynProvider::new(provider) +} + +impl From for Error { + fn from(err: alloy::contract::Error) -> Self { + Self::Other(format!("{err:?}")) } } -impl super::ReadOnlySmartContract for SmartContract { - async fn cluster_view(&self) -> super::Result { - std::todo!() - // let view = self.inner.getView().call().await?._0; +impl From for Error { + fn from(err: alloy::providers::PendingTransactionError) -> Self { + Self::Other(format!("{err:?}")) + } +} + +impl From for bindings::Cluster::NodeOperator { + fn from(op: SerializedNodeOperator) -> Self { + let addr = op.id().0; + let data: Vec = op.into_data().into(); + + Self { + addr, + data: data.into(), + } + } +} + +impl From for SerializedNodeOperator { + fn from(op: bindings::Cluster::NodeOperator) -> Self { + NodeOperator::new( + smart_contract::AccountAddress(op.addr), + node_operator::SerializedData(op.data.into()), + ) + } +} + +impl From for bindings::Cluster::Settings { + fn from(settings: Settings) -> Self { + Self { + maxOperatorDataBytes: settings.max_node_operator_data_bytes, + } + } +} + +impl From for Settings { + fn from(settings: bindings::Cluster::Settings) -> Self { + Self { + max_node_operator_data_bytes: settings.maxOperatorDataBytes, + } + } +} + +impl From for bindings::Cluster::Keyspace { + fn from(keyspace: Keyspace) -> Self { + let mut operators_bitmask = U256::ZERO; + + for idx in keyspace.operators() { + operators_bitmask.set_bit(idx as usize, true); + } + + Self { + operatorsBitmask: operators_bitmask, + replicationStrategy: keyspace.replication_strategy() as u8, + } + } +} + +impl Keyspace { + fn try_from_alloy(keyspace: &bindings::Cluster::Keyspace, version: u64) -> Result { + let mut operators = HashSet::new(); + + // TODO: do less iterations + for idx in 0..256 { + if keyspace.operatorsBitmask.bit(idx) { + operators.insert(idx as u8); + } + } + + let replication_strategy = keyspace + .replicationStrategy + .try_into() + .map_err(|err| Error::Other(format!("Invalid ReplicationStrategy: {err:?}")))?; + + Self::new(operators, replication_strategy, version) + .map_err(|err| Error::Other(format!("Invalid Kespace: {err:?}"))) + } +} + +impl Migration { + fn from_alloy(migration: bindings::Cluster::Migration, keyspace: Keyspace) -> Self { + let mut pulling_operators = HashSet::new(); + + // TODO: do less iterations + for idx in 0..256 { + if migration.pullingOperatorsBitmask.bit(idx) { + pulling_operators.insert(idx as u8); + } + } + + Self::new(migration.id, keyspace, pulling_operators) + } +} + +impl From for Option { + fn from(maintenance: bindings::Cluster::Maintenance) -> Self { + if maintenance.slot.is_zero() { + None + } else { + Some(Maintenance::new(maintenance.slot.into())) + } + } +} + +impl TryFrom for cluster::View<(), node_operator::SerializedData> { + type Error = Error; + + fn try_from(view: bindings::Cluster::ClusterView) -> Result { + let node_operators = + NodeOperators::new(view.nodeOperatorSlots.into_iter().map(|operator| { + if operator.addr.is_zero() { + None + } else { + Some(operator.into()) + } + })) + .map_err(|err| Error::Other(format!("Invalid NodeOperators: {err:?}")))?; + + // assert array length + let _: &[_; 2] = &view.keyspaces; + + let try_keyspace = + |version| Keyspace::try_from_alloy(&view.keyspaces[version as usize % 2], version); + + let (keyspace, migration) = if view.migration.pullingOperatorsBitmask == U256::ZERO { + // migration not in progress + + (try_keyspace(view.keyspaceVersion)?, None) + } else { + // migration in progress + + let prev_keyspace_version = view + .keyspaceVersion + .checked_sub(1) + .ok_or_else(|| Error::Other(format!("Invalid keyspace::Version")))?; + + let keyspace = try_keyspace(prev_keyspace_version)?; + let migration_keyspace = try_keyspace(view.keyspaceVersion)?; + let migration = Migration::from_alloy(view.migration, migration_keyspace); + + (keyspace, Some(migration)) + }; - // Ok(ClusterView { - // keyspace: - // Keyspace::new(view.keyspace.replicationStrategy.try_into().unwrap()), - // }) + Ok(Self { + node_operators, + ownership: Ownership::new(view.owner.into()), + settings: view.settings.into(), + keyspace, + migration, + maintenance: view.maintenance.into(), + cluster_version: view.version, + }) } } diff --git a/crates/cluster/src/smart_contract/mod.rs b/crates/cluster/src/smart_contract/mod.rs index df72b925..2b3fa219 100644 --- a/crates/cluster/src/smart_contract/mod.rs +++ b/crates/cluster/src/smart_contract/mod.rs @@ -1,21 +1,24 @@ +//! Smart-contract managing the state of a WCN cluster. + pub mod evm; use { crate::{ + self as cluster, migration, node_operator, - NodeOperator, + Keyspace, + NodeOperators, SerializedNodeOperator, Settings, - View as ClusterView, }, - alloy::{signers::local::PrivateKeySigner, transports::http::reqwest}, - derive_more::derive::Display, + alloy::{network::TxSigner as _, signers::local::PrivateKeySigner, transports::http::reqwest}, + derive_more::derive::{Display, From}, serde::{Deserialize, Serialize}, std::str::FromStr, }; -/// Handle to a smart-contract managing the state of a WCN cluster. +/// Smart-contract managing the state of a WCN cluster. /// /// Logic invariants documented on the methods of this trait MUST be /// implemented inside the on-chain implementation of the smart-contract itself. @@ -27,18 +30,22 @@ pub trait SmartContract: ReadOnlySmartContract { signer: Signer, rpc_url: RpcUrl, initial_settings: Settings, - initial_operators: Vec, + initial_operators: NodeOperators, ) -> Result; /// Connects to an existing smart-contract. - async fn connect(signer: Signer, rpc_url: RpcUrl) -> Result; + async fn connect( + address: Address, + signer: Signer, + rpc_url: RpcUrl, + ) -> Result; /// Connects to an existing smart-contract in read-only mode. - async fn connect_ro(rpc_url: RpcUrl) -> Result; + async fn connect_ro(address: Address, rpc_url: RpcUrl) -> Result; - /// Returns the [`PublicKey`] of the [`Signer`] which is currently being - /// used for this [`SmartContract`] handle. - fn signer(&self) -> PublicKey; + /// Returns the [`AccountAddress`] of the [`Signer`] which is currently + /// being used for signing transactions of [`SmartContract`] instance. + fn signer(&self) -> &AccountAddress; /// Starts a new data [`migration`] process using the provided /// [`migration::Plan`]. @@ -50,7 +57,7 @@ pub trait SmartContract: ReadOnlySmartContract { /// [`SmartContract`] /// /// The implementation MUST emit [`migration::Started`] event on success. - async fn start_migration(&self, plan: migration::NewPlan) -> Result<()>; + async fn start_migration(&self, new_keyspace: Keyspace) -> Result<()>; /// Marks that the [`signer`](SmartContract::signer) has completed the data /// pull required for completion of the current [`migration`]. @@ -69,11 +76,7 @@ pub trait SmartContract: ReadOnlySmartContract { /// /// The implementation MAY be idempotent. In case of an idempotent /// execution the event MUST not be emitted. - async fn complete_migration( - &self, - id: migration::Id, - operator_idx: node_operator::Idx, - ) -> Result<()>; + async fn complete_migration(&self, id: migration::Id) -> Result<()>; /// Aborts the ongoing data [`migration`] process restoring the WCN cluster /// to the original state it had before the migration had started. @@ -96,7 +99,7 @@ pub trait SmartContract: ReadOnlySmartContract { /// provided [`node::OperatorIdx`] /// /// The implementation MUST emit [`maintenance::Started`] event on success. - async fn start_maintenance(&self, operator_idx: node_operator::Idx) -> Result<()>; + async fn start_maintenance(&self) -> Result<()>; /// Completes the ongoing [`maintenance`] process. /// @@ -109,7 +112,11 @@ pub trait SmartContract: ReadOnlySmartContract { /// success. async fn finish_maintenance(&self) -> Result<()>; - async fn add_node_operator(&self, operator: SerializedNodeOperator) -> Result<()>; + async fn add_node_operator( + &self, + idx: node_operator::Idx, + operator: SerializedNodeOperator, + ) -> Result<()>; /// Updates on-chain data of a [`node::Operator`]. /// @@ -118,28 +125,49 @@ pub trait SmartContract: ReadOnlySmartContract { /// provided [`node::OperatorIdx`] /// /// The implementation MUST emit [`node::OperatorUpdated`] event on success. - async fn update_node_operator( - &self, - operator: SerializedNodeOperator, - id: node_operator::Id, - idx: node_operator::Idx, - data: node_operator::SerializedData, - ) -> Result<()>; + async fn update_node_operator(&self, operator: SerializedNodeOperator) -> Result<()>; - async fn remove_node_operator(&self, operator_id: node_operator::Id) -> Result<()>; + async fn remove_node_operator(&self, id: node_operator::Id) -> Result<()>; + + async fn update_settings(&self, new_settings: Settings) -> Result<()>; + + async fn transfer_ownership(&self, new_owner: AccountAddress) -> Result<()>; } /// Read-only handle to a smart-contract managing the state of a WCN cluster. pub trait ReadOnlySmartContract: Sized + Send + Sync + 'static { /// Returns the current [`ClusterView`]. - async fn cluster_view(&self) -> Result; + async fn cluster_view(&self) -> Result>; } -// impl From for Error { -// fn from(err: alloy::contract::Error) -> Self { -// Self(format!("{err:?}")) -// } -// } +/// [`SmartContract`] address. +#[derive(Clone, Copy, Debug, Display, From, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub struct Address(evm::Address); + +/// Account address on the chain hosting WCN cluster [`SmartContract`]. +#[derive(Clone, Copy, Debug, Display, From, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub struct AccountAddress(evm::Address); + +/// Transaction signer. +pub struct Signer { + inner: SignerInner, +} + +/// RPC provider URL. +pub struct RpcUrl(reqwest::Url); + +/// Error of [`SmartContract::connect`] and [`SmartContract::connect_ro`]. +#[derive(Debug, thiserror::Error)] +pub enum ConnectError { + #[error("Smart-contract with the provided address doesn't exist")] + UnknownContract, + + #[error("Smart-contract with the provided address is not a WCN cluster")] + WrongContract, + + #[error("Other: {0}")] + Other(String), +} /// [`SmartContract`] error. #[derive(Debug, thiserror::Error)] @@ -156,33 +184,24 @@ pub enum Error { #[error("{0}")] pub struct ReadError(String); +/// [`SmartContract`] result. pub type Result = std::result::Result; +/// [`ReadOnlySmartContract`] result. pub type ReadResult = std::result::Result; -#[derive(Clone, Copy, Debug, Display, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub struct PublicKey(evm::Address); - -impl FromStr for PublicKey { - type Err = InvalidPublicKey; - - fn from_str(s: &str) -> Result { - alloy::primitives::Address::from_str(s) - .map(PublicKey) - .map_err(|err| InvalidPublicKey(err.to_string())) - } -} - -pub struct Signer { - inner: SignerInner, -} - impl Signer { - pub fn try_from_private_key(hex: &str) -> Result { + pub fn try_from_private_key(hex: &str) -> Result { PrivateKeySigner::from_str(hex) .map(SignerInner::PrivateKey) .map(|inner| Self { inner }) - .map_err(|err| InvalidPrivateKey(err.to_string())) + .map_err(|err| InvalidPrivateKeyError(err.to_string())) + } + + pub fn address(&self) -> AccountAddress { + match &self.inner { + SignerInner::PrivateKey(key) => AccountAddress(key.address()), + } } } @@ -190,48 +209,48 @@ enum SignerInner { PrivateKey(PrivateKeySigner), } -pub struct RpcUrl(reqwest::Url); +#[derive(Debug, thiserror::Error)] +#[error("Invalid RPC URL: {0:?}")] +pub struct InvalidRpcUrlError(String); + +#[derive(Debug, thiserror::Error)] +#[error("Invalid private key: {0:?}")] +pub struct InvalidPrivateKeyError(String); + +#[derive(Debug, thiserror::Error)] +#[error("Invalid account address: {0:?}")] +pub struct InvalidAccountAddressError(String); + +#[derive(Debug, thiserror::Error)] +#[error("Invalid smart-contract address: {0:?}")] +pub struct InvalidAddressError(String); impl FromStr for RpcUrl { - type Err = InvalidRpcUrl; + type Err = InvalidRpcUrlError; fn from_str(s: &str) -> Result { reqwest::Url::from_str(s) .map(Self) - .map_err(|err| InvalidRpcUrl(err.to_string())) + .map_err(|err| InvalidRpcUrlError(err.to_string())) } } -#[derive(Debug, thiserror::Error)] -#[error("Invalid RPC URL: {0:?}")] -pub struct InvalidRpcUrl(String); +impl FromStr for AccountAddress { + type Err = InvalidAccountAddressError; -#[derive(Debug, thiserror::Error)] -#[error("Invalid private key: {0:?}")] -pub struct InvalidPrivateKey(String); + fn from_str(s: &str) -> Result { + alloy::primitives::Address::from_str(s) + .map(AccountAddress) + .map_err(|err| InvalidAccountAddressError(err.to_string())) + } +} -#[derive(Debug, thiserror::Error)] -#[error("Invalid public key: {0:?}")] -pub struct InvalidPublicKey(String); - -// impl TryFrom for Keyspace { -// type Error = Error; - -// fn try_from(view: bindings::Cluster::KeyspaceView) -> Result { -// let replication_strategy = view -// .replicationStrategy -// .try_into() -// .map_err(|err| Error(format!("Invalid ReplicationStrategy: -// {err}")))?; - -// Ok(Keyspace::new(replication_strategy)) -// } -// } - -// #[cfg(test)] -// mod test { -// #[test] -// fn address_to_from_public_key_conversion() { -// todo!() -// } -// } +impl FromStr for Address { + type Err = InvalidAddressError; + + fn from_str(s: &str) -> Result { + alloy::primitives::Address::from_str(s) + .map(Address) + .map_err(|err| InvalidAddressError(err.to_string())) + } +} diff --git a/crates/cluster/src/view.rs b/crates/cluster/src/view.rs new file mode 100644 index 00000000..3b0cafd4 --- /dev/null +++ b/crates/cluster/src/view.rs @@ -0,0 +1,325 @@ +//! Read-only view of a WCN cluster. + +use { + crate::{ + self as cluster, + keyspace, + maintenance, + migration, + node_operator::{self, NodeOperators}, + ownership, + settings, + Event, + Keyspace, + Maintenance, + Migration, + Ownership, + Settings, + }, + futures::future::OptionFuture, +}; + +/// Read-only view of a WCN cluster. +pub struct View { + pub(crate) node_operators: NodeOperators, + + pub(crate) ownership: Ownership, + pub(crate) settings: Settings, + + pub(crate) keyspace: Keyspace, + pub(crate) migration: Option>, + pub(crate) maintenance: Option, + + pub(crate) cluster_version: cluster::Version, +} + +impl View { + /// Returns [`Ownership`] of the WCN cluster. + pub fn ownership(&self) -> &Ownership { + &self.ownership + } + + /// Returns [`Settings`] of the WCN cluster. + pub fn settings(&self) -> &Settings { + &self.settings + } + + /// Returns the primary [`Keyspace`] of the WCN cluster. + pub fn keyspace(&self) -> &Keyspace { + &self.keyspace + } + + /// Returns the ongoing [`Migration`] of the WCN cluster. + pub fn migration(&self) -> Option<&Migration> { + self.migration.as_ref() + } + + /// Returns the ongoing [`Maintenance`] of the WCN cluster. + pub fn maintenance(&self) -> Option<&Maintenance> { + self.maintenance.as_ref() + } + + /// Returns [`NodeOperators`] of the WCN cluster. + pub fn node_operators(&self) -> &NodeOperators { + &self.node_operators + } + + pub(super) fn require_no_migration(&self) -> Result<(), migration::InProgressError> { + if let Some(migration) = self.migration() { + return Err(migration::InProgressError(migration.id())); + } + + Ok(()) + } + + pub(super) fn require_no_maintenance(&self) -> Result<(), maintenance::InProgressError> { + if let Some(maintenance) = self.maintenance() { + return Err(maintenance::InProgressError(*maintenance.slot())); + } + + Ok(()) + } + + pub(super) fn require_migration(&self) -> Result<&Migration, migration::NotFoundError> { + self.migration.as_ref().ok_or(migration::NotFoundError) + } + + pub(super) fn require_maintenance(&self) -> Result<&Maintenance, maintenance::NotFoundError> { + self.maintenance.as_ref().ok_or(maintenance::NotFoundError) + } + + /// Applies the provided [`Event`] to this [`View`]. + pub async fn apply_event(mut self, event: Event) -> Result + where + Keyspace: keyspace::sealed::Calculate, + { + let new_version = event.cluster_version(); + + if new_version != self.cluster_version + 1 { + return Err(Error::ClusterVersionNotMonotonic( + self.cluster_version, + new_version, + )); + } + + match event { + Event::MigrationStarted(evt) => evt.apply(&mut self).await, + Event::MigrationDataPullCompleted(evt) => evt.apply(&mut self), + Event::MigrationCompleted(evt) => evt.apply(&mut self), + Event::MigrationAborted(evt) => evt.apply(&mut self), + Event::MaintenanceStarted(evt) => evt.apply(&mut self), + Event::MaintenanceFinished(evt) => evt.apply(&mut self), + Event::NodeOperatorAdded(evt) => evt.apply(&mut self), + Event::NodeOperatorUpdated(evt) => evt.apply(&mut self), + Event::NodeOperatorRemoved(evt) => evt.apply(&mut self), + Event::SettingsUpdated(evt) => evt.apply(&mut self), + Event::OwnershipTransferred(evt) => evt.apply(&mut self), + }?; + + self.cluster_version = new_version; + + Ok(self) + } +} + +impl View { + pub(super) async fn calculate_keyspace_shards(self) -> View { + let (keyspace, migration) = tokio::join!( + self.keyspace.calculate_shards(), + OptionFuture::from(self.migration.map(Migration::calculate_keyspace_shards)) + ); + + View { + node_operators: self.node_operators, + ownership: self.ownership, + settings: self.settings, + keyspace, + migration, + maintenance: self.maintenance, + cluster_version: self.cluster_version, + } + } +} + +impl View { + pub(super) fn deserialize( + self, + ) -> Result, node_operator::DataDeserializationError> { + Ok(View { + node_operators: self.node_operators.deserialize()?, + ownership: self.ownership, + settings: self.settings, + keyspace: self.keyspace, + migration: self.migration, + maintenance: self.maintenance, + cluster_version: self.cluster_version, + }) + } +} + +impl migration::Started { + async fn apply(self, view: &mut View) -> Result<()> + where + Keyspace: keyspace::sealed::Calculate, + { + view.require_no_migration()?; + view.require_no_maintenance()?; + view.keyspace().require_diff(&self.new_keyspace)?; + + view.migration = Some(Migration::new( + self.migration_id, + self.new_keyspace.calculate_shards().await, + view.node_operators.occupied_indexes(), + )); + + Ok(()) + } +} + +impl migration::DataPullCompleted { + pub(super) fn apply(self, view: &mut View) -> Result<()> { + let idx = view.node_operators.require_idx(&self.operator_id)?; + view.require_migration()? + .require_id(self.migration_id)? + .require_pulling(idx)?; + + if let Some(migration) = view.migration.as_mut() { + migration.complete_pull(idx); + } + + Ok(()) + } +} + +impl migration::Completed { + pub(super) fn apply(self, view: &mut View) -> Result<()> { + let idx = view.node_operators.require_idx(&self.operator_id)?; + view.require_migration()? + .require_id(self.migration_id)? + .require_pulling(idx)? + .require_pulling_count(1)?; + + view.keyspace = view.migration.take().unwrap().into_keyspace(); + + Ok(()) + } +} + +impl migration::Aborted { + pub(super) fn apply(self, view: &mut View) -> Result<()> { + view.require_migration()?.require_id(self.migration_id)?; + view.migration = None; + + Ok(()) + } +} + +impl maintenance::Started { + pub(super) fn apply(self, view: &mut View) -> Result<()> { + view.require_no_migration()?; + view.require_no_maintenance()?; + + view.maintenance = Some(Maintenance::new(self.operator_id)); + + Ok(()) + } +} + +impl maintenance::Finished { + pub(super) fn apply(self, view: &mut View) -> Result<()> { + view.require_maintenance()?; + view.maintenance = None; + + Ok(()) + } +} + +impl node_operator::Added { + pub(super) fn apply(self, view: &mut View) -> Result<()> { + view.node_operators() + .require_not_exists(self.operator.id())? + .require_free_slot(self.idx)?; + + view.node_operators.set(self.idx, Some(self.operator)); + + Ok(()) + } +} + +impl node_operator::Updated { + pub(super) fn apply(self, view: &mut View) -> Result<()> { + let idx = view.node_operators.require_idx(self.operator.id())?; + view.node_operators.set(idx, Some(self.operator)); + + Ok(()) + } +} + +impl node_operator::Removed { + pub(super) fn apply(self, view: &mut View) -> Result<()> { + let idx = view.node_operators.require_idx(&self.id)?; + view.node_operators.set(idx, None); + + Ok(()) + } +} + +impl settings::Updated { + pub(super) fn apply(self, view: &mut View) -> Result<()> { + view.settings = self.settings; + + Ok(()) + } +} + +impl ownership::Transferred { + pub(super) fn apply(self, view: &mut View) -> Result<()> { + view.ownership.transfer(self.new_owner); + + Ok(()) + } +} + +/// Error of [`View::apply_event`] caused by a race condition or by an incorrect +/// implementation of the [`SmartContract`](crate::SmartContract). +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("Cluster version change wasn't monotonic: {_0} -> {_1}")] + ClusterVersionNotMonotonic(cluster::Version, cluster::Version), + + #[error(transparent)] + MigrationInProgress(#[from] migration::InProgressError), + + #[error(transparent)] + MaintenanceInProgress(#[from] maintenance::InProgressError), + + #[error(transparent)] + NoMigration(#[from] migration::NotFoundError), + + #[error(transparent)] + NoMaintenance(#[from] maintenance::NotFoundError), + + #[error(transparent)] + WrongMigrationId(#[from] migration::WrongIdError), + + #[error(transparent)] + SameKeyspace(#[from] keyspace::SameKeyspaceError), + + #[error(transparent)] + NotPulling(#[from] migration::OperatorNotPullingError), + + #[error(transparent)] + WrongPullingOperatorsCount(#[from] migration::WrongPullingOperatorsCountError), + + #[error(transparent)] + OperatorNotFound(#[from] node_operator::NotFoundError), + + #[error(transparent)] + OperatorAlreadyExists(#[from] node_operator::AlreadyExistsError), + + #[error(transparent)] + OperatorSlotOccupied(#[from] node_operator::SlotOccupiedError), +} + +/// Result of [`View::apply_event`]. +pub type Result = std::result::Result; From a790e9e49890f45db42dbd73e2a9e4e69a4d90d2 Mon Sep 17 00:00:00 2001 From: Github Bot Date: Wed, 4 Jun 2025 21:29:58 +0000 Subject: [PATCH 31/79] Bump VERSION to 250604.0 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index acfd827a..6df5e56f 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -250602.0 +250604.0 From 0f3de1385016dfc240b36c285fffd6ead0f3d6cd Mon Sep 17 00:00:00 2001 From: Darksome Date: Thu, 5 Jun 2025 10:56:06 +0000 Subject: [PATCH 32/79] WIP --- Cargo.lock | 1 + crates/cluster/Cargo.toml | 1 + crates/cluster/src/lib.rs | 30 +++++++++++- crates/cluster/src/node_operator.rs | 19 +++++++- crates/cluster/src/smart_contract/evm.rs | 8 ++-- crates/cluster/tests/integration.rs | 60 +++++++++++++++++------- 6 files changed, 96 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8997b81e..de6aaf3f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1681,6 +1681,7 @@ dependencies = [ "derive_more 1.0.0", "fpe", "futures", + "hex", "itertools 0.12.1", "libp2p", "postcard", diff --git a/crates/cluster/Cargo.toml b/crates/cluster/Cargo.toml index 06fd10d2..f4a7cbfa 100644 --- a/crates/cluster/Cargo.toml +++ b/crates/cluster/Cargo.toml @@ -34,3 +34,4 @@ arc-swap = "1.7" [dev-dependencies] alloy = { version = "1.0", default-features = false, features = ["provider-anvil-node"] } tokio = { version = "1", default-features = false } +hex = "0.4" diff --git a/crates/cluster/src/lib.rs b/crates/cluster/src/lib.rs index d613f2e8..9b90c1e3 100644 --- a/crates/cluster/src/lib.rs +++ b/crates/cluster/src/lib.rs @@ -18,7 +18,7 @@ pub mod ownership; pub use ownership::Ownership; pub mod client; -pub use client::{Client, ClientRef}; +pub use client::Client; pub mod node; pub use node::{Node, NodeRef}; @@ -129,6 +129,21 @@ impl Cluster { view: ArcSwap::new(Arc::new(Arc::new(view))), }) } + + /// Connects to an existing WCN [`Cluster`]. + pub async fn connect( + smart_contract_address: smart_contract::Address, + signer: smart_contract::Signer, + rpc_url: smart_contract::RpcUrl, + ) -> Result { + let contract = SC::connect(smart_contract_address, signer, rpc_url).await?; + let view = contract.cluster_view().await?.deserialize()?; + + Ok(Self { + smart_contract: contract, + view: ArcSwap::new(Arc::new(Arc::new(view))), + }) + } } impl Cluster { @@ -354,6 +369,19 @@ pub enum DeploymentError { SmartContract(#[from] smart_contract::Error), } +/// [`Cluster::connect`] error. +#[derive(Debug, thiserror::Error)] +pub enum ConnectError { + #[error(transparent)] + SmartContract(#[from] smart_contract::ConnectError), + + #[error(transparent)] + GetClusterView(#[from] smart_contract::Error), + + #[error(transparent)] + DataDeserialization(#[from] node_operator::DataDeserializationError), +} + /// [`Cluster::start_migration`] error. #[derive(Debug, thiserror::Error)] pub enum StartMigrationError { diff --git a/crates/cluster/src/node_operator.rs b/crates/cluster/src/node_operator.rs index 76386073..1a7ed8c3 100644 --- a/crates/cluster/src/node_operator.rs +++ b/crates/cluster/src/node_operator.rs @@ -1,7 +1,7 @@ //! Entity operating a set of nodes within a WCN cluster. use { - crate::{self as cluster, client, node, smart_contract, Version as ClusterVersion}, + crate::{self as cluster, client, node, smart_contract, NodeRef, Version as ClusterVersion}, derive_more::derive::{From, Into}, itertools::Itertools as _, serde::{Deserialize, Serialize}, @@ -149,7 +149,7 @@ impl Data { let size = postcard::experimental::serialized_size(&data).map_err(Error::from_postcard)?; // reserve first byte for versioning - let mut buf = Vec::with_capacity(size + 1); + let mut buf = vec![0; size + 1]; buf[0] = 0; // current schema version postcard::to_slice(&data, &mut buf[1..]).map_err(Error::from_postcard)?; Ok(SerializedData(buf)) @@ -194,6 +194,21 @@ impl SerializedNodeOperator { } } +impl VersionedNodeOperator { + /// Returns [`Name`] of this [`NodeOperator`]. + pub fn name(&self) -> &Name { + match &self.data.0 { + VersionedDataInner::V0(data) => &data.name, + } + } + + // pub fn nodes(&self) -> impl Iterator> { + // match &self.data.0 { + // VersionedDataInner::V0(data) => &data.nodes, + // } + // } +} + // NOTE: The on-chain serialization is non self-describing! Every change to // the schema should be handled by creating a new version. #[derive(Debug, Clone, Deserialize, Serialize)] diff --git a/crates/cluster/src/smart_contract/evm.rs b/crates/cluster/src/smart_contract/evm.rs index ff45d7b2..e6e30b71 100644 --- a/crates/cluster/src/smart_contract/evm.rs +++ b/crates/cluster/src/smart_contract/evm.rs @@ -28,6 +28,7 @@ use { mod bindings { alloy::sol!( #[sol(rpc)] + #[derive(Debug)] Cluster, "../../contracts/out/Cluster.sol/Cluster.json", ); @@ -198,6 +199,7 @@ fn new_provier(signer: Signer, rpc_url: RpcUrl) -> DynProvider { let provider = ProviderBuilder::new() .wallet(wallet) + // .with_chain_id(10) .connect_http(rpc_url.0); DynProvider::new(provider) @@ -289,7 +291,7 @@ impl Keyspace { .map_err(|err| Error::Other(format!("Invalid ReplicationStrategy: {err:?}")))?; Self::new(operators, replication_strategy, version) - .map_err(|err| Error::Other(format!("Invalid Kespace: {err:?}"))) + .map_err(|err| Error::Other(format!("Invalid Keyspace: {err:?}"))) } } @@ -339,11 +341,11 @@ impl TryFrom for cluster::View<(), node_operator |version| Keyspace::try_from_alloy(&view.keyspaces[version as usize % 2], version); let (keyspace, migration) = if view.migration.pullingOperatorsBitmask == U256::ZERO { - // migration not in progress + // migration is not in progress (try_keyspace(view.keyspaceVersion)?, None) } else { - // migration in progress + // migration is in progress let prev_keyspace_version = view .keyspaceVersion diff --git a/crates/cluster/tests/integration.rs b/crates/cluster/tests/integration.rs index da733164..9b3189fd 100644 --- a/crates/cluster/tests/integration.rs +++ b/crates/cluster/tests/integration.rs @@ -1,31 +1,57 @@ use { alloy::providers::ProviderBuilder, - cluster::contract::{ - self, - Cluster::{NodeOperatorView, Settings}, + cluster::{ + node, + node_operator, + smart_contract::{self, evm, RpcUrl, Signer}, + Cluster, + NodeOperator, + Settings, }, + libp2p::PeerId, + std::net::SocketAddrV4, }; #[tokio::test] async fn test_suite() { - let provider = ProviderBuilder::new().on_anvil_with_wallet(); - let settings = Settings { - minOperators: 5, - minNodes: 1, + max_node_operator_data_bytes: 4096, }; - let contract = contract::Cluster::deploy(&provider, settings).await?; + let signer = + Signer::try_from_private_key(&std::env::var("SIGNER_PRIVATE_KEY").unwrap()).unwrap(); + + let rpc_url = "https://mainnet.optimism.io".parse().unwrap(); + + let operators = (1..=5).map(|n| test_node_operator(n)).collect(); + + let contract = Cluster::::deploy(signer, rpc_url, settings, operators) + .await + .unwrap(); + + // let contract_address = "0xcefa8836c9cd102c3b118b7681cf09d839cb324e" + // .parse() + // .unwrap(); + + // let contract = Cluster::::connect(contract_address, + // signer, rpc_url) .await + // .unwrap(); +} + +fn test_node_operator(n: u8) -> NodeOperator { + let data = node_operator::Data { + name: node_operator::Name::new(format!("Operator{n}")).unwrap(), + nodes: vec![node::Data { + peer_id: PeerId::random(), + addr: SocketAddrV4::new([127, 0, 0, 1].into(), 40000 + n as u16), + }], + clients: vec![], + }; - // // 2. Use Anvil's first default private key - // let wallet: LocalWallet = - // "0x59c6995e998f97a5a0044976f51e2bc4a26b19f3c6d8ff2b67d46e2b4103b3b3" - // .parse::()? - // .with_chain_id(31337); + let mut private_key: [u8; 32] = Default::default(); + private_key[0] = n; - // let client = Arc::new(provider.with_signer(wallet)); + let signer = Signer::try_from_private_key(&format!("0x{}", hex::encode(&private_key))).unwrap(); - // // 3. Deploy Counter contract - // let deployer = Counter::deploy(client.clone(), ())?; // No constructor - // args let contract = deployer.send().await?; + NodeOperator::new(signer.address(), data) } From 1aa1f32f67a51c6d62bf5ca8a05955703b91c9c4 Mon Sep 17 00:00:00 2001 From: Github Bot Date: Thu, 5 Jun 2025 10:56:52 +0000 Subject: [PATCH 33/79] Bump VERSION to 250605.0 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 6df5e56f..3f784cea 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -250604.0 +250605.0 From 508630c58404004f427a59c194f0cec239754138 Mon Sep 17 00:00:00 2001 From: Darksome Date: Thu, 5 Jun 2025 11:32:04 +0000 Subject: [PATCH 34/79] fix constructor bug --- crates/cluster/src/node_operator.rs | 9 +++------ crates/cluster/src/smart_contract/evm.rs | 23 +++++++++++------------ crates/cluster/tests/integration.rs | 14 +++++++++++--- 3 files changed, 25 insertions(+), 21 deletions(-) diff --git a/crates/cluster/src/node_operator.rs b/crates/cluster/src/node_operator.rs index 1a7ed8c3..2dc5c488 100644 --- a/crates/cluster/src/node_operator.rs +++ b/crates/cluster/src/node_operator.rs @@ -290,20 +290,17 @@ impl NodeOperators { return Err(SlotMapCreationError::TooManyOperatorSlots(slots.len())); } - let mut this = Self { - id_to_idx: HashMap::with_capacity(slots.len()), - slots: Vec::with_capacity(slots.len()), - }; + let mut id_to_idx = HashMap::with_capacity(slots.len()); for (idx, slot) in slots.iter().enumerate() { if let Some(operator) = &slot { - if this.id_to_idx.insert(*operator.id(), idx as u8).is_some() { + if id_to_idx.insert(*operator.id(), idx as u8).is_some() { return Err(SlotMapCreationError::OperatorDuplicate(*operator.id())); }; } } - Ok(this) + Ok(Self { id_to_idx, slots }) } pub(super) fn into_slots(self) -> Vec>> { diff --git a/crates/cluster/src/smart_contract/evm.rs b/crates/cluster/src/smart_contract/evm.rs index e6e30b71..f31aaa5c 100644 --- a/crates/cluster/src/smart_contract/evm.rs +++ b/crates/cluster/src/smart_contract/evm.rs @@ -62,18 +62,17 @@ impl super::SmartContract for SmartContract { ) -> Result { let signer_addr = signer.address(); - bindings::Cluster::deploy( - new_provier(signer, rpc_url), - initial_settings.into(), - initial_operators - .into_slots() - .into_iter() - .filter_map(|op| op.map(Into::into)) - .collect(), - ) - .await - .map(|alloy| Self { signer_addr, alloy }) - .map_err(Into::into) + let settings = initial_settings.into(); + let operators = initial_operators + .into_slots() + .into_iter() + .filter_map(|op| op.map(Into::into)) + .collect(); + + bindings::Cluster::deploy(new_provier(signer, rpc_url), settings, operators) + .await + .map(|alloy| Self { signer_addr, alloy }) + .map_err(Into::into) } async fn connect( diff --git a/crates/cluster/tests/integration.rs b/crates/cluster/tests/integration.rs index 9b3189fd..9272a00a 100644 --- a/crates/cluster/tests/integration.rs +++ b/crates/cluster/tests/integration.rs @@ -18,10 +18,18 @@ async fn test_suite() { max_node_operator_data_bytes: 4096, }; - let signer = - Signer::try_from_private_key(&std::env::var("SIGNER_PRIVATE_KEY").unwrap()).unwrap(); + // let signer = + // Signer::try_from_private_key(&std::env::var("SIGNER_PRIVATE_KEY"). + // unwrap()).unwrap(); - let rpc_url = "https://mainnet.optimism.io".parse().unwrap(); + let signer = Signer::try_from_private_key( + "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", + ) + .unwrap(); + + // let rpc_url = "https://mainnet.optimism.io".parse().unwrap(); + + let rpc_url = "http://127.0.0.1:8545".parse().unwrap(); let operators = (1..=5).map(|n| test_node_operator(n)).collect(); From 51b3440df4f07b3090431dc789169e23f81ed46d Mon Sep 17 00:00:00 2001 From: Darksome Date: Thu, 5 Jun 2025 13:26:19 +0000 Subject: [PATCH 35/79] move things around --- crates/cluster/src/client.rs | 62 ++--- crates/cluster/src/lib.rs | 28 ++- crates/cluster/src/node.rs | 74 ++---- crates/cluster/src/node_operator.rs | 282 ++++------------------- crates/cluster/src/node_operators.rs | 178 ++++++++++++++ crates/cluster/src/smart_contract/evm.rs | 26 +-- crates/cluster/src/smart_contract/mod.rs | 14 +- crates/cluster/src/view.rs | 26 ++- 8 files changed, 302 insertions(+), 388 deletions(-) create mode 100644 crates/cluster/src/node_operators.rs diff --git a/crates/cluster/src/client.rs b/crates/cluster/src/client.rs index 891c0fef..200939a7 100644 --- a/crates/cluster/src/client.rs +++ b/crates/cluster/src/client.rs @@ -5,66 +5,32 @@ use { serde::{Deserialize, Serialize}, }; -/// On-chain data of a [`Client`]. +/// Client of a WCN cluster. #[derive(Debug, Clone)] -pub struct Data { +pub struct Client { /// [`PeerId`] of the [`Client`]. Used for authentication. pub peer_id: PeerId, } -/// Client of a WCN cluster. -#[derive(Debug)] -pub struct Client { - data: VersionedData, -} - -impl Client { - /// Returns [`PeerId`] of this [`Client`]. - pub fn peer_id(&self) -> &PeerId { - match &self.data { - VersionedData::V0(data) => &data.peer_id, - } - } -} - -/// Borrowed [`Client`]. -#[derive(Debug)] -pub struct ClientRef<'a> { - data: VersionedDataRef<'a>, -} - -impl<'a> ClientRef<'a> { - /// Converts this [`ClientRef`] into an owned [`Client`]. - pub fn to_owned(self) -> Client { - Client { - data: match self.data { - VersionedDataRef::V0(data) => VersionedData::V0(*data), - }, - } - } -} - -#[derive(Clone, Copy, Debug)] -enum VersionedData { - V0(DataV0), -} - -#[derive(Debug)] -enum VersionedDataRef<'a> { - V0(&'a DataV0), -} - // NOTE: The on-chain serialization is non self-describing! Every change to // the schema should be handled by creating a new version. #[derive(Clone, Copy, Debug, Serialize, Deserialize)] -pub(crate) struct DataV0 { +pub(crate) struct V0 { pub peer_id: PeerId, } -impl From for DataV0 { - fn from(data: Data) -> Self { +impl From for V0 { + fn from(client: Client) -> Self { + Self { + peer_id: client.peer_id, + } + } +} + +impl From for Client { + fn from(client: V0) -> Self { Self { - peer_id: data.peer_id, + peer_id: client.peer_id, } } } diff --git a/crates/cluster/src/lib.rs b/crates/cluster/src/lib.rs index 9b90c1e3..50b5b5e7 100644 --- a/crates/cluster/src/lib.rs +++ b/crates/cluster/src/lib.rs @@ -21,15 +21,13 @@ pub mod client; pub use client::Client; pub mod node; -pub use node::{Node, NodeRef}; +pub use node::Node; pub mod node_operator; -pub use node_operator::{ - NodeOperator, - NodeOperators, - SerializedNodeOperator, - VersionedNodeOperator, -}; +pub use node_operator::NodeOperator; + +pub mod node_operators; +pub use node_operators::NodeOperators; pub mod keyspace; pub use keyspace::Keyspace; @@ -113,7 +111,7 @@ impl Cluster { .into_iter() .map(|op| { let op = op.serialize()?; - op.data().validate(&initial_settings)?; + op.data.validate(&initial_settings)?; Ok::<_, DeploymentError>(op) }) .try_collect()?; @@ -280,11 +278,11 @@ impl Cluster { ) -> Result<(), AddNodeOperatorError> { let operator = self.using_view(|view| { view.ownership().require_owner(&self.smart_contract)?; - view.node_operators().require_not_exists(operator.id())?; + view.node_operators().require_not_exists(&operator.id)?; view.node_operators().require_free_slot(idx)?; let operator = operator.serialize()?; - operator.data().validate(view.settings())?; + operator.data.validate(view.settings())?; Ok::<_, AddNodeOperatorError>(operator) })?; @@ -302,14 +300,14 @@ impl Cluster { let signer = self.smart_contract.signer(); let operator = self.using_view(|view| { - if !(signer == operator.id() || view.ownership().is_owner(signer)) { + if !(signer == &operator.id || view.ownership().is_owner(signer)) { return Err(UpdateNodeOperatorError::Unauthorized); } - let _idx = view.node_operators().require_idx(operator.id())?; + let _idx = view.node_operators().require_idx(&operator.id)?; let operator = operator.serialize()?; - operator.data().validate(view.settings())?; + operator.data.validate(view.settings())?; Ok::<_, UpdateNodeOperatorError>(operator) })?; @@ -354,7 +352,7 @@ impl Cluster { #[derive(Debug, thiserror::Error)] pub enum DeploymentError { #[error(transparent)] - NodeOperatorSlotMapCreation(#[from] node_operator::SlotMapCreationError), + NodeOperatorsCreation(#[from] node_operators::CreationError), #[error(transparent)] DataSerialization(#[from] node_operator::DataSerializationError), @@ -487,7 +485,7 @@ pub enum AddNodeOperatorError { AlreadyExists(#[from] node_operator::AlreadyExistsError), #[error(transparent)] - SlotOccupied(#[from] node_operator::SlotOccupiedError), + SlotOccupied(#[from] node_operators::SlotOccupiedError), #[error(transparent)] DataSerialization(#[from] node_operator::DataSerializationError), diff --git a/crates/cluster/src/node.rs b/crates/cluster/src/node.rs index ee7a00c4..74807af7 100644 --- a/crates/cluster/src/node.rs +++ b/crates/cluster/src/node.rs @@ -6,12 +6,12 @@ use { std::net::SocketAddrV4, }; -/// On-chain data of a [`Node`]. +/// Node within a WCN cluster. /// /// The IP address is currently being encrypted using a format-preserving /// encryption algorithm. #[derive(Debug, Clone, Copy)] -pub struct Data { +pub struct Node { /// [`PeerId`] of the [`Node`]. /// /// Used for authentication. Multiple nodes managed by the same @@ -22,67 +22,22 @@ pub struct Data { pub addr: SocketAddrV4, } -/// Node within a WCN cluster. -#[derive(Debug)] -pub struct Node { - data: VersionedData, -} - impl Node { - /// Returns [`PeerId`] of this [`Node`]. - pub fn peer_id(&self) -> &PeerId { - match &self.data { - VersionedData::V0(data) => &data.peer_id, - } + pub(super) fn encrypt(&mut self) { + // TODO } - /// Returns [`SocketAddrV4`] of this [`Node`]. - pub fn addr(&self) -> SocketAddrV4 { - match self.data { - VersionedData::V0(data) => data.addr, - } - } - - pub(super) fn encrypt(&mut self) {} - pub(super) fn decrypt(&mut self) { + // TODO // FF1::new(key, radix); - // let fpe_ff = FF1::::new(&[0; 32], 256).unwrap(); } } -/// Borrowed [`Node`]. -#[derive(Debug)] -pub struct NodeRef<'a> { - data: VersionedDataRef<'a>, -} - -impl<'a> NodeRef<'a> { - /// Converts this [`NodeRef`] into an owned [`Node`]. - pub fn to_owned(self) -> Node { - Node { - data: match self.data { - VersionedDataRef::V0(data) => VersionedData::V0(*data), - }, - } - } -} - -#[derive(Clone, Copy, Debug)] -enum VersionedData { - V0(DataV0), -} - -#[derive(Debug)] -enum VersionedDataRef<'a> { - V0(&'a DataV0), -} - // NOTE: The on-chain serialization is non self-describing! Every change to // the schema should be handled by creating a new version. #[derive(Clone, Copy, Debug, Serialize, Deserialize)] -pub(crate) struct DataV0 { +pub(crate) struct V0 { /// [`PeerId`] of this [`Node`]. /// /// Used for authentication. Multiple nodes managed by the same @@ -93,11 +48,20 @@ pub(crate) struct DataV0 { pub addr: SocketAddrV4, } -impl From for DataV0 { - fn from(data: Data) -> Self { +impl From for V0 { + fn from(node: Node) -> Self { + Self { + peer_id: node.peer_id, + addr: node.addr, + } + } +} + +impl From for Node { + fn from(node: V0) -> Self { Self { - peer_id: data.peer_id, - addr: data.addr, + peer_id: node.peer_id, + addr: node.addr, } } } diff --git a/crates/cluster/src/node_operator.rs b/crates/cluster/src/node_operator.rs index 2dc5c488..59b36e54 100644 --- a/crates/cluster/src/node_operator.rs +++ b/crates/cluster/src/node_operator.rs @@ -1,11 +1,17 @@ //! Entity operating a set of nodes within a WCN cluster. use { - crate::{self as cluster, client, node, smart_contract, NodeRef, Version as ClusterVersion}, - derive_more::derive::{From, Into}, - itertools::Itertools as _, + crate::{ + self as cluster, + client, + node, + smart_contract, + Client, + Node, + Version as ClusterVersion, + }, + derive_more::derive::Into, serde::{Deserialize, Serialize}, - std::collections::HashMap, }; /// Globally unique identifier of a [`NodeOperator`]; @@ -47,51 +53,29 @@ pub struct Data { /// Name of the [`NodeOperator`]. pub name: Name, - /// List of [`node`]s of the [`NodeOperator`]. - pub nodes: Vec, + /// List of [`Node`]s of the [`NodeOperator`]. + pub nodes: Vec, - /// List of [`client`]s authorized to use the WCN cluster on behalf of the + /// List of [`Client`]s authorized to use the WCN cluster on behalf of the /// [`NodeOperator`]. - pub clients: Vec, + pub clients: Vec, } /// [`NodeOperator`] [`Data`] serialized for on-chain storage. #[derive(Debug, Into)] pub struct SerializedData(pub(crate) Vec); +/// [`NodeOperator`] with [`SerializedData`]. +pub type Serialized = NodeOperator; + /// Entity operating a set of [`Node`]s within a WCN cluster. #[derive(Clone, Debug)] pub struct NodeOperator { - id: Id, - data: D, -} - -/// [`NodeOperator`] with [`SerializedData`]. -pub type SerializedNodeOperator = NodeOperator; - -/// [`NodeOperator`] with [`VersionedData`]. -pub type VersionedNodeOperator = NodeOperator; - -impl NodeOperator { - /// Creates a [`NodeOperator`]. - pub fn new(id: Id, data: D) -> NodeOperator { - NodeOperator { id, data } - } - - /// Returns [`Id`] of this [`NodeOperator`]. - pub fn id(&self) -> &Id { - &self.id - } - - /// Returns data of this [`NodeOperator`]. - pub fn data(&self) -> &D { - &self.data - } + /// ID of this [`NodeOperator`]. + pub id: Id, - /// Converts this [`NodeOperator`] into the inner `data`. - pub fn into_data(self) -> D { - self.data - } + /// On-chain data of this [`NodeOperator`]. + pub data: D, } /// Event of a new [`NodeOperator`] being added to a WCN cluster. @@ -101,7 +85,7 @@ pub struct Added { pub idx: Idx, /// [`NodeOperator`] being added. - pub operator: VersionedNodeOperator, + pub operator: NodeOperator, /// Updated [`ClusterVersion`]. pub cluster_version: ClusterVersion, @@ -110,7 +94,7 @@ pub struct Added { /// Event of a [`NodeOperator`] being updated. pub struct Updated { /// Updated [`NodeOperator`]. - pub operator: VersionedNodeOperator, + pub operator: NodeOperator, /// Updated [`ClusterVersion`]. pub cluster_version: ClusterVersion, @@ -126,7 +110,7 @@ pub struct Removed { } impl NodeOperator { - pub(super) fn serialize(self) -> Result { + pub(super) fn serialize(self) -> Result, DataSerializationError> { Ok(NodeOperator { id: self.id, data: self.data.serialize()?, @@ -156,23 +140,8 @@ impl Data { } } -/// Backwards-compatible [`NodeOperator`] [`Data`] supporting multiple versions. -#[derive(Debug, Clone, From)] -pub struct VersionedData(VersionedDataInner); - -impl VersionedData { - fn v0(data: DataV0) -> Self { - Self(VersionedDataInner::V0(data)) - } -} - -#[derive(Debug, Clone)] -enum VersionedDataInner { - V0(DataV0), -} - -impl SerializedNodeOperator { - fn deserialize(self) -> Result { +impl NodeOperator { + pub(super) fn deserialize(self) -> Result { use DataDeserializationError as Error; let data_bytes = self.data.0; @@ -185,7 +154,7 @@ impl SerializedNodeOperator { let bytes = &data_bytes[1..]; let data = match schema_version { - 0 => postcard::from_bytes(bytes).map(VersionedData::v0), + 0 => postcard::from_bytes::(bytes).map(Into::into), ver => return Err(Error::UnknownSchemaVersion(ver)), } .map_err(Error::from_postcard)?; @@ -194,28 +163,33 @@ impl SerializedNodeOperator { } } -impl VersionedNodeOperator { - /// Returns [`Name`] of this [`NodeOperator`]. - pub fn name(&self) -> &Name { - match &self.data.0 { - VersionedDataInner::V0(data) => &data.name, - } - } - - // pub fn nodes(&self) -> impl Iterator> { - // match &self.data.0 { - // VersionedDataInner::V0(data) => &data.nodes, - // } - // } -} - // NOTE: The on-chain serialization is non self-describing! Every change to // the schema should be handled by creating a new version. #[derive(Debug, Clone, Deserialize, Serialize)] struct DataV0 { name: Name, - nodes: Vec, - clients: Vec, + nodes: Vec, + clients: Vec, +} + +impl From for DataV0 { + fn from(data: Data) -> Self { + Self { + name: data.name, + nodes: data.nodes.into_iter().map(Into::into).collect(), + clients: data.clients.into_iter().map(Into::into).collect(), + } + } +} + +impl From for Data { + fn from(data: DataV0) -> Self { + Self { + name: data.name, + nodes: data.nodes.into_iter().map(Into::into).collect(), + clients: data.clients.into_iter().map(Into::into).collect(), + } + } } #[derive(Debug, thiserror::Error)] @@ -271,166 +245,10 @@ pub struct DataTooLargeError { limit: usize, } -/// Slot map of [`NodeOperator`]s. -#[derive(Debug, Clone)] -pub struct NodeOperators { - id_to_idx: HashMap, - - // TODO: assert length - slots: Vec>>, -} - -impl NodeOperators { - pub(super) fn new( - slots: impl IntoIterator>>, - ) -> Result { - let slots: Vec<_> = slots.into_iter().collect(); - - if slots.len() > cluster::MAX_OPERATORS { - return Err(SlotMapCreationError::TooManyOperatorSlots(slots.len())); - } - - let mut id_to_idx = HashMap::with_capacity(slots.len()); - - for (idx, slot) in slots.iter().enumerate() { - if let Some(operator) = &slot { - if id_to_idx.insert(*operator.id(), idx as u8).is_some() { - return Err(SlotMapCreationError::OperatorDuplicate(*operator.id())); - }; - } - } - - Ok(Self { id_to_idx, slots }) - } - - pub(super) fn into_slots(self) -> Vec>> { - self.slots - } - - pub(super) fn set(&mut self, idx: Idx, slot: Option>) { - if let Some(id) = self.get_by_idx(idx).map(|op| op.id) { - self.id_to_idx.remove(&id); - } - - if self.slots.len() >= idx as usize { - self.expand(idx); - } - - if let Some(operator) = &slot { - self.id_to_idx.insert(operator.id, idx); - } - - self.slots[idx as usize] = slot; - } - - fn expand(&mut self, idx: Idx) { - let desired_len = (idx as usize) + 1; - let slots_to_add = desired_len.checked_sub(self.slots.len()); - - for _ in 0..slots_to_add.unwrap_or_default() { - self.slots.push(None); - } - } - - /// Returns whether this map contains the [`NodeOperator`] with the provided - /// [`Id`]. - pub(super) fn contains(&self, id: &Id) -> bool { - self.get_idx(id).is_some() - } - - /// Returns whether this map contains the [`NodeOperator`] with the provided - /// [`Idx`]. - pub(super) fn contains_idx(&self, idx: Idx) -> bool { - self.get_by_idx(idx).is_some() - } - - /// Gets an [`NodeOperator`] by [`Id`]. - pub(super) fn get(&self, id: &Id) -> Option<&NodeOperator> { - self.get_by_idx(self.get_idx(id)?) - } - - /// Gets a mutable reference to a [`NodeOperator`] [`Data`]. - pub(super) fn get_data_mut(&mut self, id: &Id) -> Option<&mut Data> { - self.get_by_idx_mut(self.get_idx(id)?) - .map(|operator| &mut operator.data) - } - - /// Gets an [`NodeOperator`] by [`Idx`]. - pub(super) fn get_by_idx(&self, idx: Idx) -> Option<&NodeOperator> { - self.slots.get(idx as usize)?.as_ref() - } - - /// Mutable version of [`NodeOperators::get_by_idx`]. - fn get_by_idx_mut(&mut self, idx: Idx) -> Option<&mut NodeOperator> { - self.slots.get_mut(idx as usize)?.as_mut() - } - - /// Gets an [`Idx`] by [`Id`]. - pub(super) fn get_idx(&self, id: &Id) -> Option { - self.id_to_idx.get(id).copied() - } - - pub(super) fn occupied_indexes(&self) -> impl Iterator + '_ { - self.slots - .iter() - .enumerate() - .filter_map(|(idx, slot)| slot.is_some().then_some(idx as u8)) - } - - pub(super) fn require_idx(&self, id: &Id) -> Result { - self.get_idx(id).ok_or_else(|| NotFoundError(*id)) - } - - pub(super) fn require_not_exists(&self, id: &Id) -> Result<&Self, AlreadyExistsError> { - if self.contains(id) { - return Err(AlreadyExistsError(*id)); - } - - Ok(self) - } - - pub(super) fn require_free_slot(&self, idx: Idx) -> Result<&Self, SlotOccupiedError> { - if self.contains_idx(idx) { - return Err(SlotOccupiedError(idx)); - } - - Ok(self) - } -} - -impl NodeOperators { - pub(super) fn deserialize(self) -> Result { - Ok(NodeOperators { - id_to_idx: self.id_to_idx, - slots: self - .slots - .into_iter() - .map(|slot| slot.map(SerializedNodeOperator::deserialize).transpose()) - .try_collect()?, - }) - } -} - -#[derive(Debug, thiserror::Error)] -pub enum SlotMapCreationError { - #[error("Too many operator slots: {_0} > {}", cluster::MAX_OPERATORS)] - TooManyOperatorSlots(usize), - - #[error("Too few operators: {_0} < {}", cluster::MIN_OPERATORS)] - TooFewOperators(usize), - - #[error("Duplicate NodeOperator(id: {_0})")] - OperatorDuplicate(Id), -} - #[derive(Debug, thiserror::Error)] -#[error("Node operator (id: {0}) is not a member of this cluster")] +#[error("Node operator (id: {0}) is not a member of the cluster")] pub struct NotFoundError(pub Id); #[derive(Debug, thiserror::Error)] #[error("Node operator (id: {0}) is already a member of the cluster")] pub struct AlreadyExistsError(pub Id); - -#[derive(Debug, thiserror::Error)] -#[error("Slot {_0} in NodeOperators slot map is already occupied")] -pub struct SlotOccupiedError(pub Idx); diff --git a/crates/cluster/src/node_operators.rs b/crates/cluster/src/node_operators.rs new file mode 100644 index 00000000..33684328 --- /dev/null +++ b/crates/cluster/src/node_operators.rs @@ -0,0 +1,178 @@ +//! Slot map of [`NodeOperator`]s. + +use { + crate::{self as cluster, node_operator, NodeOperator}, + itertools::Itertools as _, + std::collections::HashMap, +}; + +/// Slot map of [`NodeOperator`]s. +#[derive(Debug, Clone)] +pub struct NodeOperators { + id_to_idx: HashMap, + + // TODO: assert length + slots: Vec>>, +} + +/// [`NodeOperators`] with [`node_operator::SerializedData`]. +pub type Serialized = NodeOperators; + +impl NodeOperators { + pub(super) fn new( + slots: impl IntoIterator>>, + ) -> Result { + let slots: Vec<_> = slots.into_iter().collect(); + + if slots.len() > cluster::MAX_OPERATORS { + return Err(CreationError::TooManyOperatorSlots(slots.len())); + } + + let mut id_to_idx = HashMap::with_capacity(slots.len()); + + for (idx, slot) in slots.iter().enumerate() { + if let Some(operator) = &slot { + if id_to_idx.insert(operator.id, idx as u8).is_some() { + return Err(CreationError::OperatorDuplicate(operator.id)); + }; + } + } + + Ok(Self { id_to_idx, slots }) + } + + pub(super) fn into_slots(self) -> Vec>> { + self.slots + } + + pub(super) fn set(&mut self, idx: node_operator::Idx, slot: Option>) { + if let Some(id) = self.get_by_idx(idx).map(|op| op.id) { + self.id_to_idx.remove(&id); + } + + if self.slots.len() >= idx as usize { + self.expand(idx); + } + + if let Some(operator) = &slot { + self.id_to_idx.insert(operator.id, idx); + } + + self.slots[idx as usize] = slot; + } + + fn expand(&mut self, idx: node_operator::Idx) { + let desired_len = (idx as usize) + 1; + let slots_to_add = desired_len.checked_sub(self.slots.len()); + + for _ in 0..slots_to_add.unwrap_or_default() { + self.slots.push(None); + } + } + + /// Returns whether this map contains the [`NodeOperator`] with the provided + /// [`Id`]. + pub(super) fn contains(&self, id: &node_operator::Id) -> bool { + self.get_idx(id).is_some() + } + + /// Returns whether this map contains the [`NodeOperator`] with the provided + /// [`Idx`]. + pub(super) fn contains_idx(&self, idx: node_operator::Idx) -> bool { + self.get_by_idx(idx).is_some() + } + + /// Gets an [`NodeOperator`] by [`Id`]. + pub(super) fn get(&self, id: &node_operator::Id) -> Option<&NodeOperator> { + self.get_by_idx(self.get_idx(id)?) + } + + /// Gets a mutable reference to a [`NodeOperator`] [`Data`]. + pub(super) fn get_data_mut(&mut self, id: &node_operator::Id) -> Option<&mut Data> { + self.get_by_idx_mut(self.get_idx(id)?) + .map(|operator| &mut operator.data) + } + + /// Gets an [`NodeOperator`] by [`Idx`]. + pub(super) fn get_by_idx(&self, idx: node_operator::Idx) -> Option<&NodeOperator> { + self.slots.get(idx as usize)?.as_ref() + } + + /// Mutable version of [`NodeOperators::get_by_idx`]. + fn get_by_idx_mut(&mut self, idx: node_operator::Idx) -> Option<&mut NodeOperator> { + self.slots.get_mut(idx as usize)?.as_mut() + } + + /// Gets an [`Idx`] by [`Id`]. + pub(super) fn get_idx(&self, id: &node_operator::Id) -> Option { + self.id_to_idx.get(id).copied() + } + + pub(super) fn occupied_indexes(&self) -> impl Iterator + '_ { + self.slots + .iter() + .enumerate() + .filter_map(|(idx, slot)| slot.is_some().then_some(idx as u8)) + } + + pub(super) fn require_idx( + &self, + id: &node_operator::Id, + ) -> Result { + self.get_idx(id) + .ok_or_else(|| node_operator::NotFoundError(*id)) + } + + pub(super) fn require_not_exists( + &self, + id: &node_operator::Id, + ) -> Result<&Self, node_operator::AlreadyExistsError> { + if self.contains(id) { + return Err(node_operator::AlreadyExistsError(*id)); + } + + Ok(self) + } + + pub(super) fn require_free_slot( + &self, + idx: node_operator::Idx, + ) -> Result<&Self, SlotOccupiedError> { + if self.contains_idx(idx) { + return Err(SlotOccupiedError(idx)); + } + + Ok(self) + } +} + +impl Serialized { + pub(super) fn deserialize( + self, + ) -> Result { + Ok(NodeOperators { + id_to_idx: self.id_to_idx, + slots: self + .slots + .into_iter() + .map(|slot| slot.map(NodeOperator::deserialize).transpose()) + .try_collect()?, + }) + } +} + +#[derive(Debug, thiserror::Error)] +pub enum CreationError { + #[error("Too many operator slots: {_0} > {}", cluster::MAX_OPERATORS)] + TooManyOperatorSlots(usize), + + #[error("Too few operators: {_0} < {}", cluster::MIN_OPERATORS)] + TooFewOperators(usize), + + #[error("Duplicate NodeOperator(id: {_0})")] + OperatorDuplicate(node_operator::Id), +} + +#[derive(Debug, thiserror::Error)] +#[error("Slot {_0} in NodeOperators slot map is already occupied")] +pub struct SlotOccupiedError(pub node_operator::Idx); diff --git a/crates/cluster/src/smart_contract/evm.rs b/crates/cluster/src/smart_contract/evm.rs index f31aaa5c..66c4076c 100644 --- a/crates/cluster/src/smart_contract/evm.rs +++ b/crates/cluster/src/smart_contract/evm.rs @@ -13,7 +13,6 @@ use { NodeOperator, NodeOperators, Ownership, - SerializedNodeOperator, Settings, }, alloy::{ @@ -125,12 +124,12 @@ impl super::SmartContract for SmartContract { async fn add_node_operator( &self, idx: node_operator::Idx, - operator: SerializedNodeOperator, + operator: NodeOperator, ) -> Result<()> { check_receipt(self.alloy.addNodeOperator(idx, operator.into())).await } - async fn update_node_operator(&self, operator: SerializedNodeOperator) -> super::Result<()> { + async fn update_node_operator(&self, operator: node_operator::Serialized) -> super::Result<()> { check_receipt(self.alloy.updateNodeOperator(operator.into())).await } @@ -221,24 +220,21 @@ impl From for Error { } } -impl From for bindings::Cluster::NodeOperator { - fn from(op: SerializedNodeOperator) -> Self { - let addr = op.id().0; - let data: Vec = op.into_data().into(); - +impl From for bindings::Cluster::NodeOperator { + fn from(op: node_operator::Serialized) -> Self { Self { - addr, - data: data.into(), + addr: op.id.0, + data: op.data.0.into(), } } } -impl From for SerializedNodeOperator { +impl From for node_operator::Serialized { fn from(op: bindings::Cluster::NodeOperator) -> Self { - NodeOperator::new( - smart_contract::AccountAddress(op.addr), - node_operator::SerializedData(op.data.into()), - ) + NodeOperator { + id: smart_contract::AccountAddress(op.addr), + data: node_operator::SerializedData(op.data.into()), + } } } diff --git a/crates/cluster/src/smart_contract/mod.rs b/crates/cluster/src/smart_contract/mod.rs index 2b3fa219..09ef2aab 100644 --- a/crates/cluster/src/smart_contract/mod.rs +++ b/crates/cluster/src/smart_contract/mod.rs @@ -3,15 +3,7 @@ pub mod evm; use { - crate::{ - self as cluster, - migration, - node_operator, - Keyspace, - NodeOperators, - SerializedNodeOperator, - Settings, - }, + crate::{self as cluster, migration, node_operator, Keyspace, NodeOperators, Settings}, alloy::{network::TxSigner as _, signers::local::PrivateKeySigner, transports::http::reqwest}, derive_more::derive::{Display, From}, serde::{Deserialize, Serialize}, @@ -115,7 +107,7 @@ pub trait SmartContract: ReadOnlySmartContract { async fn add_node_operator( &self, idx: node_operator::Idx, - operator: SerializedNodeOperator, + operator: node_operator::Serialized, ) -> Result<()>; /// Updates on-chain data of a [`node::Operator`]. @@ -125,7 +117,7 @@ pub trait SmartContract: ReadOnlySmartContract { /// provided [`node::OperatorIdx`] /// /// The implementation MUST emit [`node::OperatorUpdated`] event on success. - async fn update_node_operator(&self, operator: SerializedNodeOperator) -> Result<()>; + async fn update_node_operator(&self, operator: node_operator::Serialized) -> Result<()>; async fn remove_node_operator(&self, id: node_operator::Id) -> Result<()>; diff --git a/crates/cluster/src/view.rs b/crates/cluster/src/view.rs index 3b0cafd4..1b3bcba1 100644 --- a/crates/cluster/src/view.rs +++ b/crates/cluster/src/view.rs @@ -6,13 +6,15 @@ use { keyspace, maintenance, migration, - node_operator::{self, NodeOperators}, + node_operator, + node_operators, ownership, settings, Event, Keyspace, Maintenance, Migration, + NodeOperators, Ownership, Settings, }, @@ -20,17 +22,17 @@ use { }; /// Read-only view of a WCN cluster. -pub struct View { - pub(crate) node_operators: NodeOperators, +pub struct View { + pub(super) node_operators: NodeOperators, - pub(crate) ownership: Ownership, - pub(crate) settings: Settings, + pub(super) ownership: Ownership, + pub(super) settings: Settings, - pub(crate) keyspace: Keyspace, - pub(crate) migration: Option>, - pub(crate) maintenance: Option, + pub(super) keyspace: Keyspace, + pub(super) migration: Option>, + pub(super) maintenance: Option, - pub(crate) cluster_version: cluster::Version, + pub(super) cluster_version: cluster::Version, } impl View { @@ -237,7 +239,7 @@ impl maintenance::Finished { impl node_operator::Added { pub(super) fn apply(self, view: &mut View) -> Result<()> { view.node_operators() - .require_not_exists(self.operator.id())? + .require_not_exists(&self.operator.id)? .require_free_slot(self.idx)?; view.node_operators.set(self.idx, Some(self.operator)); @@ -248,7 +250,7 @@ impl node_operator::Added { impl node_operator::Updated { pub(super) fn apply(self, view: &mut View) -> Result<()> { - let idx = view.node_operators.require_idx(self.operator.id())?; + let idx = view.node_operators.require_idx(&self.operator.id)?; view.node_operators.set(idx, Some(self.operator)); Ok(()) @@ -318,7 +320,7 @@ pub enum Error { OperatorAlreadyExists(#[from] node_operator::AlreadyExistsError), #[error(transparent)] - OperatorSlotOccupied(#[from] node_operator::SlotOccupiedError), + OperatorSlotOccupied(#[from] node_operators::SlotOccupiedError), } /// Result of [`View::apply_event`]. From 5bfd6d48e98652376adcc51c2d24e0e7a218d36c Mon Sep 17 00:00:00 2001 From: Darksome Date: Thu, 5 Jun 2025 13:28:14 +0000 Subject: [PATCH 36/79] fix tests --- crates/cluster/tests/integration.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/crates/cluster/tests/integration.rs b/crates/cluster/tests/integration.rs index 9272a00a..49078be5 100644 --- a/crates/cluster/tests/integration.rs +++ b/crates/cluster/tests/integration.rs @@ -1,10 +1,9 @@ use { - alloy::providers::ProviderBuilder, cluster::{ - node, node_operator, - smart_contract::{self, evm, RpcUrl, Signer}, + smart_contract::{evm, Signer}, Cluster, + Node, NodeOperator, Settings, }, @@ -49,7 +48,7 @@ async fn test_suite() { fn test_node_operator(n: u8) -> NodeOperator { let data = node_operator::Data { name: node_operator::Name::new(format!("Operator{n}")).unwrap(), - nodes: vec![node::Data { + nodes: vec![Node { peer_id: PeerId::random(), addr: SocketAddrV4::new([127, 0, 0, 1].into(), 40000 + n as u16), }], @@ -61,5 +60,8 @@ fn test_node_operator(n: u8) -> NodeOperator { let signer = Signer::try_from_private_key(&format!("0x{}", hex::encode(&private_key))).unwrap(); - NodeOperator::new(signer.address(), data) + NodeOperator { + id: signer.address(), + data, + } } From ed1df7598729f2465e2e31993e753fc15668b45c Mon Sep 17 00:00:00 2001 From: Darksome Date: Fri, 6 Jun 2025 10:41:18 +0000 Subject: [PATCH 37/79] integration tests --- Cargo.lock | 340 +++++++++++++++--- Cargo.toml | 6 +- contracts/out/Cluster.sol/Bitmask.json | 2 +- contracts/out/Cluster.sol/Cluster.json | 2 +- contracts/src/Cluster.sol | 4 +- contracts/test/Suite.sol | 2 +- crates/cluster/Cargo.toml | 13 +- crates/cluster/src/keyspace.rs | 12 +- crates/cluster/src/lib.rs | 243 ++++++++++--- crates/cluster/src/maintenance.rs | 3 + crates/cluster/src/migration.rs | 24 +- crates/cluster/src/node.rs | 13 +- crates/cluster/src/node_operator.rs | 30 +- crates/cluster/src/node_operators.rs | 13 +- crates/cluster/src/ownership.rs | 4 +- crates/cluster/src/settings.rs | 1 + crates/cluster/src/smart_contract/evm.rs | 435 ++++++++++++++++++----- crates/cluster/src/smart_contract/mod.rs | 176 +++++---- crates/cluster/src/task.rs | 117 ++++++ crates/cluster/src/view.rs | 35 +- crates/cluster/tests/integration.rs | 138 +++++-- flake.lock | 12 +- 22 files changed, 1277 insertions(+), 348 deletions(-) create mode 100644 crates/cluster/src/task.rs diff --git a/Cargo.lock b/Cargo.lock index de6aaf3f..ecec469a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -110,6 +110,7 @@ dependencies = [ "alloy-network", "alloy-node-bindings", "alloy-provider", + "alloy-pubsub", "alloy-rpc-client", "alloy-rpc-types", "alloy-serde", @@ -117,6 +118,7 @@ dependencies = [ "alloy-signer-local", "alloy-transport", "alloy-transport-http", + "alloy-transport-ws", ] [[package]] @@ -181,6 +183,7 @@ dependencies = [ "alloy-network-primitives", "alloy-primitives", "alloy-provider", + "alloy-pubsub", "alloy-rpc-types-eth", "alloy-sol-types", "alloy-transport", @@ -426,6 +429,7 @@ dependencies = [ "alloy-network-primitives", "alloy-node-bindings", "alloy-primitives", + "alloy-pubsub", "alloy-rpc-client", "alloy-rpc-types-anvil", "alloy-rpc-types-eth", @@ -433,6 +437,7 @@ dependencies = [ "alloy-sol-types", "alloy-transport", "alloy-transport-http", + "alloy-transport-ws", "async-stream", "async-trait", "auto_impl", @@ -453,6 +458,27 @@ dependencies = [ "wasmtimer", ] +[[package]] +name = "alloy-pubsub" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8550f7306e0230fc835eb2ff4af0a96362db4b6fc3f25767d161e0ad0ac765bf" +dependencies = [ + "alloy-json-rpc", + "alloy-primitives", + "alloy-transport", + "bimap", + "futures", + "parking_lot", + "serde", + "serde_json", + "tokio", + "tokio-stream", + "tower 0.5.2", + "tracing", + "wasmtimer", +] + [[package]] name = "alloy-rlp" version = "0.3.11" @@ -483,8 +509,10 @@ checksum = "859ec46fb132175969a0101bdd2fe9ecd413c40feeb0383e98710a4a089cee77" dependencies = [ "alloy-json-rpc", "alloy-primitives", + "alloy-pubsub", "alloy-transport", "alloy-transport-http", + "alloy-transport-ws", "async-stream", "futures", "pin-project", @@ -709,6 +737,24 @@ dependencies = [ "url", ] +[[package]] +name = "alloy-transport-ws" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0c6f9b37cd8d44aab959613966cc9d4d7a9b429c575cec43b3e5b46ea109a79" +dependencies = [ + "alloy-pubsub", + "alloy-transport", + "futures", + "http 1.1.0", + "rustls", + "serde_json", + "tokio", + "tokio-tungstenite", + "tracing", + "ws_stream_wasm", +] + [[package]] name = "alloy-trie" version = "0.8.1" @@ -993,6 +1039,18 @@ dependencies = [ "syn 2.0.101", ] +[[package]] +name = "async-channel" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + [[package]] name = "async-stream" version = "0.3.5" @@ -1026,6 +1084,17 @@ dependencies = [ "syn 2.0.101", ] +[[package]] +name = "async_io_stream" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d7b9decdf35d8908a7e3ef02f64c5e9b1695e230154c0e8de3969142d9b94c" +dependencies = [ + "futures", + "pharos", + "rustc_version 0.4.0", +] + [[package]] name = "asynchronous-codec" version = "0.7.0" @@ -1225,6 +1294,12 @@ dependencies = [ "console", ] +[[package]] +name = "bimap" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "230c5f1ca6a325a32553f8640d31ac9b49f2411e901e427570154868b46da4f7" + [[package]] name = "bindgen" version = "0.65.1" @@ -1413,9 +1488,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.6.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" dependencies = [ "serde", ] @@ -1678,6 +1753,8 @@ dependencies = [ "alloy", "anyhow", "arc-swap", + "backoff", + "derivative", "derive_more 1.0.0", "fpe", "futures", @@ -1690,7 +1767,9 @@ dependencies = [ "tap", "thiserror 1.0.64", "tokio", + "tokio-stream", "tracing", + "tracing-subscriber", "xxhash-rust", ] @@ -1730,6 +1809,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "config" version = "0.14.0" @@ -2516,6 +2604,27 @@ dependencies = [ "version_check", ] +[[package]] +name = "event-listener" +version = "5.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3492acde4c3fc54c845eaab3eed8bd00c7a7d881f78bfc801e43a93dec1331ae" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" +dependencies = [ + "event-listener", + "pin-project-lite", +] + [[package]] name = "eyre" version = "0.6.12" @@ -2785,17 +2894,6 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" -[[package]] -name = "futures-ticker" -version = "0.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9763058047f713632a52e916cc7f6a4b3fc6e9fc1ff8c5b1dc49e5a89041682e" -dependencies = [ - "futures", - "futures-timer", - "instant", -] - [[package]] name = "futures-timer" version = "3.0.3" @@ -3488,6 +3586,15 @@ dependencies = [ "serde", ] +[[package]] +name = "hashlink" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af" +dependencies = [ + "hashbrown 0.14.3", +] + [[package]] name = "heck" version = "0.3.3" @@ -4070,9 +4177,9 @@ checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" [[package]] name = "libp2p" -version = "0.54.1" +version = "0.55.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbbe80f9c7e00526cd6b838075b9c171919404a4732cb2fa8ece0a093223bfc4" +checksum = "b72dc443ddd0254cb49a794ed6b6728400ee446a0f7ab4a07d0209ee98de20e9" dependencies = [ "bytes", "either", @@ -4081,7 +4188,7 @@ dependencies = [ "getrandom 0.2.15", "libp2p-allow-block-list", "libp2p-connection-limits", - "libp2p-core", + "libp2p-core 0.43.0", "libp2p-gossipsub", "libp2p-identity", "libp2p-kad", @@ -4089,31 +4196,29 @@ dependencies = [ "multiaddr", "pin-project", "rw-stream-sink", - "thiserror 1.0.64", + "thiserror 2.0.12", ] [[package]] name = "libp2p-allow-block-list" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1027ccf8d70320ed77e984f273bc8ce952f623762cb9bf2d126df73caef8041" +checksum = "38944b7cb981cc93f2f0fb411ff82d0e983bd226fbcc8d559639a3a73236568b" dependencies = [ - "libp2p-core", + "libp2p-core 0.43.0", "libp2p-identity", "libp2p-swarm", - "void", ] [[package]] name = "libp2p-connection-limits" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d003540ee8baef0d254f7b6bfd79bac3ddf774662ca0abf69186d517ef82ad8" +checksum = "efe9323175a17caa8a2ed4feaf8a548eeef5e0b72d03840a0eab4bcb0210ce1c" dependencies = [ - "libp2p-core", + "libp2p-core 0.43.0", "libp2p-identity", "libp2p-swarm", - "void", ] [[package]] @@ -4136,7 +4241,6 @@ dependencies = [ "quick-protobuf", "rand 0.8.5", "rw-stream-sink", - "serde", "smallvec", "thiserror 1.0.64", "tracing", @@ -4145,12 +4249,39 @@ dependencies = [ "web-time", ] +[[package]] +name = "libp2p-core" +version = "0.43.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "193c75710ba43f7504ad8f58a62ca0615b1d7e572cb0f1780bc607252c39e9ef" +dependencies = [ + "either", + "fnv", + "futures", + "futures-timer", + "libp2p-identity", + "multiaddr", + "multihash", + "multistream-select", + "once_cell", + "parking_lot", + "pin-project", + "quick-protobuf", + "rand 0.8.5", + "rw-stream-sink", + "thiserror 2.0.12", + "tracing", + "unsigned-varint 0.8.0", + "web-time", +] + [[package]] name = "libp2p-gossipsub" -version = "0.47.0" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4e830fdf24ac8c444c12415903174d506e1e077fbe3875c404a78c5935a8543" +checksum = "d558548fa3b5a8e9b66392f785921e363c57c05dcadfda4db0d41ae82d313e4a" dependencies = [ + "async-channel", "asynchronous-codec", "base64 0.22.1", "byteorder", @@ -4158,10 +4289,11 @@ dependencies = [ "either", "fnv", "futures", - "futures-ticker", + "futures-timer", "getrandom 0.2.15", + "hashlink", "hex_fmt", - "libp2p-core", + "libp2p-core 0.43.0", "libp2p-identity", "libp2p-swarm", "prometheus-client", @@ -4171,17 +4303,15 @@ dependencies = [ "regex", "serde", "sha2", - "smallvec", "tracing", - "void", "web-time", ] [[package]] name = "libp2p-identity" -version = "0.2.9" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cca1eb2bc1fd29f099f3daaab7effd01e1a54b7c577d0ed082521034d912e8" +checksum = "fbb68ea10844211a59ce46230909fd0ea040e8a192454d4cc2ee0d53e12280eb" dependencies = [ "bs58", "ed25519-dalek", @@ -4191,18 +4321,17 @@ dependencies = [ "rand 0.8.5", "serde", "sha2", - "thiserror 1.0.64", + "thiserror 2.0.12", "tracing", "zeroize", ] [[package]] name = "libp2p-kad" -version = "0.46.2" +version = "0.47.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced237d0bd84bbebb7c2cad4c073160dacb4fe40534963c32ed6d4c6bb7702a3" +checksum = "2bab0466a27ebe955bcbc27328fae5429c5b48c915fd6174931414149802ec23" dependencies = [ - "arrayvec", "asynchronous-codec", "bytes", "either", @@ -4210,7 +4339,7 @@ dependencies = [ "futures", "futures-bounded", "futures-timer", - "libp2p-core", + "libp2p-core 0.43.0", "libp2p-identity", "libp2p-swarm", "quick-protobuf", @@ -4219,24 +4348,23 @@ dependencies = [ "serde", "sha2", "smallvec", - "thiserror 1.0.64", + "thiserror 2.0.12", "tracing", - "uint", - "void", + "uint 0.10.0", "web-time", ] [[package]] name = "libp2p-swarm" -version = "0.45.1" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7dd6741793d2c1fb2088f67f82cf07261f25272ebe3c0b0c311e0c6b50e851a" +checksum = "803399b4b6f68adb85e63ab573ac568154b193e9a640f03e0f2890eabbcb37f8" dependencies = [ "either", "fnv", "futures", "futures-timer", - "libp2p-core", + "libp2p-core 0.43.0", "libp2p-identity", "lru 0.12.3", "multistream-select", @@ -4244,7 +4372,6 @@ dependencies = [ "rand 0.8.5", "smallvec", "tracing", - "void", "web-time", ] @@ -4256,7 +4383,7 @@ checksum = "47b23dddc2b9c355f73c1e36eb0c3ae86f7dc964a3715f0731cfad352db4d847" dependencies = [ "futures", "futures-rustls", - "libp2p-core", + "libp2p-core 0.42.0", "libp2p-identity", "rcgen", "ring 0.17.8", @@ -4901,6 +5028,12 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + [[package]] name = "parking_lot" version = "0.12.3" @@ -4978,6 +5111,16 @@ dependencies = [ "ucd-trie", ] +[[package]] +name = "pharos" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9567389417feee6ce15dd6527a8a1ecac205ef62c2932bcf3d9f6fc5b78b414" +dependencies = [ + "futures", + "rustc_version 0.4.0", +] + [[package]] name = "phi-accrual-failure-detector" version = "0.1.0" @@ -5126,7 +5269,7 @@ checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" dependencies = [ "fixed-hash", "impl-codec", - "uint", + "uint 0.9.5", ] [[package]] @@ -6183,6 +6326,12 @@ dependencies = [ "pest", ] +[[package]] +name = "send_wrapper" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" + [[package]] name = "serde" version = "1.0.202" @@ -6295,6 +6444,17 @@ dependencies = [ "serde", ] +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + [[package]] name = "sha1_smol" version = "1.0.0" @@ -6958,6 +7118,22 @@ dependencies = [ "tokio-util", ] +[[package]] +name = "tokio-tungstenite" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a9daff607c6d2bf6c16fd681ccb7eecc83e4e2cdc1ca067ffaadfca5de7f084" +dependencies = [ + "futures-util", + "log", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tungstenite", + "webpki-roots", +] + [[package]] name = "tokio-util" version = "0.7.10" @@ -7064,9 +7240,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "log", "pin-project-lite", @@ -7088,9 +7264,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", @@ -7099,9 +7275,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.32" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", "valuable", @@ -7187,6 +7363,25 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "tungstenite" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4793cb5e56680ecbb1d843515b23b6de9a75eb04b66643e256a396d43be33c13" +dependencies = [ + "bytes", + "data-encoding", + "http 1.1.0", + "httparse", + "log", + "rand 0.9.1", + "rustls", + "rustls-pki-types", + "sha1", + "thiserror 2.0.12", + "utf-8", +] + [[package]] name = "typenum" version = "1.17.0" @@ -7211,6 +7406,18 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "uint" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "909988d098b2f738727b161a106cfc7cab00c539c2687a8836f8e565976fb53e" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + [[package]] name = "unarray" version = "0.1.4" @@ -7303,6 +7510,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + [[package]] name = "utf8-width" version = "0.1.7" @@ -8197,6 +8410,25 @@ dependencies = [ "bitflags 2.6.0", ] +[[package]] +name = "ws_stream_wasm" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7999f5f4217fe3818726b66257a4475f71e74ffd190776ad053fa159e50737f5" +dependencies = [ + "async_io_stream", + "futures", + "js-sys", + "log", + "pharos", + "rustc_version 0.4.0", + "send_wrapper", + "thiserror 1.0.64", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + [[package]] name = "wyz" version = "0.5.1" diff --git a/Cargo.toml b/Cargo.toml index 1b757253..ae2fcead 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,7 @@ derive_more = { version = "1.0.0", features = [ "try_into", "deref", ] } +derivative = "2" core = { package = "wcn_core", path = "crates/core" } auth = { package = "wcn_auth", path = "crates/auth" } domain = { package = "wcn_domain", path = "crates/domain" } @@ -46,11 +47,14 @@ wcn_rpc = { path = "crates/rpc" } relay_rocks = { path = "crates/rocks" } metrics = "0.23" time = "0.3" -libp2p = { version = "0.54", default-features = false, features = ["serde"] } +libp2p = { version = "0.55", default-features = false, features = ["serde"] } tokio-serde = { git = "https://github.com/xDarksome/tokio-serde.git", rev = "6df9ff9" } tokio-serde-postcard = { git = "https://github.com/xDarksome/tokio-serde-postcard.git", rev = "5e1b77a" } itertools = "0.12" futures = "0.3" +backoff = { version = "0.4", features = ["tokio"] } +tracing = "0.1" +tokio-stream = "0.1" [workspace.lints.clippy] all = { level = "deny", priority = -1 } diff --git a/contracts/out/Cluster.sol/Bitmask.json b/contracts/out/Cluster.sol/Bitmask.json index 05c72c42..49c292ba 100644 --- a/contracts/out/Cluster.sol/Bitmask.json +++ b/contracts/out/Cluster.sol/Bitmask.json @@ -1 +1 @@ -{"abi":[],"bytecode":{"object":"0x608060405234601d57600e6021565b603e602c823930815050603e90f35b6027565b60405190565b5f80fdfe60806040525f80fdfea26469706673582212202e5c85f91ed6f87a0d6666b0c5006389206e839cbaa1af000488b75c0e4c9fca64736f6c634300081c0033","sourceMap":"9215:1079:24:-:0;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;","linkReferences":{}},"deployedBytecode":{"object":"0x60806040525f80fdfea26469706673582212202e5c85f91ed6f87a0d6666b0c5006389206e839cbaa1af000488b75c0e4c9fca64736f6c634300081c0033","sourceMap":"9215:1079:24:-:0;;;;;","linkReferences":{}},"methodIdentifiers":{},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.28+commit.7893614a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/Cluster.sol\":\"Bitmask\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[\":@openzeppelin-contracts-5.3.0/=dependencies/@openzeppelin-contracts-5.3.0/\",\":forge-std-1.9.7/=dependencies/forge-std-1.9.7/src/\",\":forge-std/=dependencies/forge-std/src/\",\":openzeppelin-contracts/=dependencies/@openzeppelin-contracts-5.3.0/\"],\"viaIR\":true},\"sources\":{\"dependencies/openzeppelin-contracts/utils/Panic.sol\":{\"keccak256\":\"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a\",\"dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG\"]},\"dependencies/openzeppelin-contracts/utils/math/Math.sol\":{\"keccak256\":\"0x1225214420c83ebcca88f2ae2b50f053aaa7df7bd684c3e878d334627f2edfc6\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6c5fab4970634f9ab9a620983dc1c8a30153981a0b1a521666e269d0a11399d3\",\"dweb:/ipfs/QmVRnBC575MESGkEHndjujtR7qub2FzU9RWy9eKLp4hPZB\"]},\"dependencies/openzeppelin-contracts/utils/math/SafeCast.sol\":{\"keccak256\":\"0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b1d578337048cad08c1c03041cca5978eff5428aa130c781b271ad9e5566e1f8\",\"dweb:/ipfs/QmPFKL2r9CBsMwmUqqdcFPfHZB2qcs9g1HDrPxzWSxomvy\"]},\"src/Cluster.sol\":{\"keccak256\":\"0xc78e6f85b957de947ea15d06612efc306c2cd979f8f08d37e4484a65880ffb48\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c14a8b6856276888d44ba5368193e7b0ca9cd898d3cdc90d272edc32aef830be\",\"dweb:/ipfs/QmQkuwMCYXcuv1g68FsC7ZrpAdCKQS7KmHQZwRUftXKJVa\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.28+commit.7893614a"},"language":"Solidity","output":{"abi":[],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"remappings":["@openzeppelin-contracts-5.3.0/=dependencies/@openzeppelin-contracts-5.3.0/","forge-std-1.9.7/=dependencies/forge-std-1.9.7/src/","forge-std/=dependencies/forge-std/src/","openzeppelin-contracts/=dependencies/@openzeppelin-contracts-5.3.0/"],"optimizer":{"enabled":false,"runs":200},"metadata":{"bytecodeHash":"ipfs"},"compilationTarget":{"src/Cluster.sol":"Bitmask"},"evmVersion":"cancun","libraries":{},"viaIR":true},"sources":{"dependencies/openzeppelin-contracts/utils/Panic.sol":{"keccak256":"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a","urls":["bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a","dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG"],"license":"MIT"},"dependencies/openzeppelin-contracts/utils/math/Math.sol":{"keccak256":"0x1225214420c83ebcca88f2ae2b50f053aaa7df7bd684c3e878d334627f2edfc6","urls":["bzz-raw://6c5fab4970634f9ab9a620983dc1c8a30153981a0b1a521666e269d0a11399d3","dweb:/ipfs/QmVRnBC575MESGkEHndjujtR7qub2FzU9RWy9eKLp4hPZB"],"license":"MIT"},"dependencies/openzeppelin-contracts/utils/math/SafeCast.sol":{"keccak256":"0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54","urls":["bzz-raw://b1d578337048cad08c1c03041cca5978eff5428aa130c781b271ad9e5566e1f8","dweb:/ipfs/QmPFKL2r9CBsMwmUqqdcFPfHZB2qcs9g1HDrPxzWSxomvy"],"license":"MIT"},"src/Cluster.sol":{"keccak256":"0xc78e6f85b957de947ea15d06612efc306c2cd979f8f08d37e4484a65880ffb48","urls":["bzz-raw://c14a8b6856276888d44ba5368193e7b0ca9cd898d3cdc90d272edc32aef830be","dweb:/ipfs/QmQkuwMCYXcuv1g68FsC7ZrpAdCKQS7KmHQZwRUftXKJVa"],"license":"MIT"}},"version":1},"id":24} \ No newline at end of file +{"abi":[],"bytecode":{"object":"0x608060405234601d57600e6021565b603e602c823930815050603e90f35b6027565b60405190565b5f80fdfe60806040525f80fdfea26469706673582212204aa32359976a200130b15990eea5f63a381b6d2388088cc5e76b3b7d8e36e1a264736f6c634300081c0033","sourceMap":"9259:1079:24:-:0;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;","linkReferences":{}},"deployedBytecode":{"object":"0x60806040525f80fdfea26469706673582212204aa32359976a200130b15990eea5f63a381b6d2388088cc5e76b3b7d8e36e1a264736f6c634300081c0033","sourceMap":"9259:1079:24:-:0;;;;;","linkReferences":{}},"methodIdentifiers":{},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.28+commit.7893614a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/Cluster.sol\":\"Bitmask\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[\":@openzeppelin-contracts-5.3.0/=dependencies/@openzeppelin-contracts-5.3.0/\",\":forge-std-1.9.7/=dependencies/forge-std-1.9.7/src/\",\":forge-std/=dependencies/forge-std/src/\",\":openzeppelin-contracts/=dependencies/@openzeppelin-contracts-5.3.0/\"],\"viaIR\":true},\"sources\":{\"dependencies/openzeppelin-contracts/utils/Panic.sol\":{\"keccak256\":\"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a\",\"dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG\"]},\"dependencies/openzeppelin-contracts/utils/math/Math.sol\":{\"keccak256\":\"0x1225214420c83ebcca88f2ae2b50f053aaa7df7bd684c3e878d334627f2edfc6\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6c5fab4970634f9ab9a620983dc1c8a30153981a0b1a521666e269d0a11399d3\",\"dweb:/ipfs/QmVRnBC575MESGkEHndjujtR7qub2FzU9RWy9eKLp4hPZB\"]},\"dependencies/openzeppelin-contracts/utils/math/SafeCast.sol\":{\"keccak256\":\"0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b1d578337048cad08c1c03041cca5978eff5428aa130c781b271ad9e5566e1f8\",\"dweb:/ipfs/QmPFKL2r9CBsMwmUqqdcFPfHZB2qcs9g1HDrPxzWSxomvy\"]},\"src/Cluster.sol\":{\"keccak256\":\"0xac5b938cdbe809da30fdf59bd2492c6aa341ff7ea88f152be3543202b7485a44\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://d5a43c1a46e45e9b06a441c5f0bd6cd2cba55c7a2aa2ffe605c2b51bd1823b89\",\"dweb:/ipfs/QmcSR9umgpQyM4YtDCrBC7nhSQD1UuTdUqEUCwCohB58Fy\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.28+commit.7893614a"},"language":"Solidity","output":{"abi":[],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"remappings":["@openzeppelin-contracts-5.3.0/=dependencies/@openzeppelin-contracts-5.3.0/","forge-std-1.9.7/=dependencies/forge-std-1.9.7/src/","forge-std/=dependencies/forge-std/src/","openzeppelin-contracts/=dependencies/@openzeppelin-contracts-5.3.0/"],"optimizer":{"enabled":false,"runs":200},"metadata":{"bytecodeHash":"ipfs"},"compilationTarget":{"src/Cluster.sol":"Bitmask"},"evmVersion":"cancun","libraries":{},"viaIR":true},"sources":{"dependencies/openzeppelin-contracts/utils/Panic.sol":{"keccak256":"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a","urls":["bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a","dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG"],"license":"MIT"},"dependencies/openzeppelin-contracts/utils/math/Math.sol":{"keccak256":"0x1225214420c83ebcca88f2ae2b50f053aaa7df7bd684c3e878d334627f2edfc6","urls":["bzz-raw://6c5fab4970634f9ab9a620983dc1c8a30153981a0b1a521666e269d0a11399d3","dweb:/ipfs/QmVRnBC575MESGkEHndjujtR7qub2FzU9RWy9eKLp4hPZB"],"license":"MIT"},"dependencies/openzeppelin-contracts/utils/math/SafeCast.sol":{"keccak256":"0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54","urls":["bzz-raw://b1d578337048cad08c1c03041cca5978eff5428aa130c781b271ad9e5566e1f8","dweb:/ipfs/QmPFKL2r9CBsMwmUqqdcFPfHZB2qcs9g1HDrPxzWSxomvy"],"license":"MIT"},"src/Cluster.sol":{"keccak256":"0xac5b938cdbe809da30fdf59bd2492c6aa341ff7ea88f152be3543202b7485a44","urls":["bzz-raw://d5a43c1a46e45e9b06a441c5f0bd6cd2cba55c7a2aa2ffe605c2b51bd1823b89","dweb:/ipfs/QmcSR9umgpQyM4YtDCrBC7nhSQD1UuTdUqEUCwCohB58Fy"],"license":"MIT"}},"version":1},"id":24} \ No newline at end of file diff --git a/contracts/out/Cluster.sol/Cluster.json b/contracts/out/Cluster.sol/Cluster.json index f63c6618..c1004319 100644 --- a/contracts/out/Cluster.sol/Cluster.json +++ b/contracts/out/Cluster.sol/Cluster.json @@ -1 +1 @@ -{"abi":[{"type":"constructor","inputs":[{"name":"initialSettings","type":"tuple","internalType":"struct Settings","components":[{"name":"maxOperatorDataBytes","type":"uint16","internalType":"uint16"}]},{"name":"initialOperators","type":"tuple[]","internalType":"struct NodeOperator[]","components":[{"name":"addr","type":"address","internalType":"address"},{"name":"data","type":"bytes","internalType":"bytes"}]}],"stateMutability":"nonpayable"},{"type":"function","name":"abortMigration","inputs":[{"name":"id","type":"uint64","internalType":"uint64"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"addNodeOperator","inputs":[{"name":"idx","type":"uint8","internalType":"uint8"},{"name":"operator","type":"tuple","internalType":"struct NodeOperator","components":[{"name":"addr","type":"address","internalType":"address"},{"name":"data","type":"bytes","internalType":"bytes"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"completeMigration","inputs":[{"name":"id","type":"uint64","internalType":"uint64"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"finishMaintenance","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"getView","inputs":[],"outputs":[{"name":"","type":"tuple","internalType":"struct ClusterView","components":[{"name":"owner","type":"address","internalType":"address"},{"name":"nodeOperatorSlots","type":"tuple[]","internalType":"struct NodeOperator[]","components":[{"name":"addr","type":"address","internalType":"address"},{"name":"data","type":"bytes","internalType":"bytes"}]},{"name":"keyspaces","type":"tuple[2]","internalType":"struct Keyspace[2]","components":[{"name":"operatorsBitmask","type":"uint256","internalType":"uint256"},{"name":"replicationStrategy","type":"uint8","internalType":"uint8"}]},{"name":"keyspaceVersion","type":"uint64","internalType":"uint64"},{"name":"settings","type":"tuple","internalType":"struct Settings","components":[{"name":"maxOperatorDataBytes","type":"uint16","internalType":"uint16"}]},{"name":"migration","type":"tuple","internalType":"struct Migration","components":[{"name":"id","type":"uint64","internalType":"uint64"},{"name":"pullingOperatorsBitmask","type":"uint256","internalType":"uint256"}]},{"name":"maintenance","type":"tuple","internalType":"struct Maintenance","components":[{"name":"slot","type":"address","internalType":"address"}]},{"name":"version","type":"uint128","internalType":"uint128"}]}],"stateMutability":"view"},{"type":"function","name":"removeNodeOperator","inputs":[{"name":"operatorAddress","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"startMaintenance","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"startMigration","inputs":[{"name":"newKeyspace","type":"tuple","internalType":"struct Keyspace","components":[{"name":"operatorsBitmask","type":"uint256","internalType":"uint256"},{"name":"replicationStrategy","type":"uint8","internalType":"uint8"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"transferOwnership","inputs":[{"name":"newOwner","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateNodeOperator","inputs":[{"name":"operator","type":"tuple","internalType":"struct NodeOperator","components":[{"name":"addr","type":"address","internalType":"address"},{"name":"data","type":"bytes","internalType":"bytes"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateSettings","inputs":[{"name":"newSettings","type":"tuple","internalType":"struct Settings","components":[{"name":"maxOperatorDataBytes","type":"uint16","internalType":"uint16"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"event","name":"MaintenanceFinished","inputs":[{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"MaintenanceStarted","inputs":[{"name":"addr","type":"address","indexed":false,"internalType":"address"},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"MigrationAborted","inputs":[{"name":"id","type":"uint64","indexed":false,"internalType":"uint64"},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"MigrationCompleted","inputs":[{"name":"id","type":"uint64","indexed":false,"internalType":"uint64"},{"name":"operatorAddress","type":"address","indexed":false,"internalType":"address"},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"MigrationDataPullCompleted","inputs":[{"name":"id","type":"uint64","indexed":false,"internalType":"uint64"},{"name":"operatorAddress","type":"address","indexed":false,"internalType":"address"},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"MigrationStarted","inputs":[{"name":"id","type":"uint64","indexed":false,"internalType":"uint64"},{"name":"newKeyspace","type":"tuple","indexed":false,"internalType":"struct Keyspace","components":[{"name":"operatorsBitmask","type":"uint256","internalType":"uint256"},{"name":"replicationStrategy","type":"uint8","internalType":"uint8"}]},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"NodeOperatorAdded","inputs":[{"name":"idx","type":"uint8","indexed":false,"internalType":"uint8"},{"name":"operator","type":"tuple","indexed":false,"internalType":"struct NodeOperator","components":[{"name":"addr","type":"address","internalType":"address"},{"name":"data","type":"bytes","internalType":"bytes"}]},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"NodeOperatorRemoved","inputs":[{"name":"operatorAddress","type":"address","indexed":false,"internalType":"address"},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"NodeOperatorUpdated","inputs":[{"name":"operator","type":"tuple","indexed":false,"internalType":"struct NodeOperator","components":[{"name":"addr","type":"address","internalType":"address"},{"name":"data","type":"bytes","internalType":"bytes"}]},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"name":"newOwner","type":"address","indexed":false,"internalType":"address"},{"name":"cluserVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"SettingsUpdated","inputs":[{"name":"newSettings","type":"tuple","indexed":false,"internalType":"struct Settings","components":[{"name":"maxOperatorDataBytes","type":"uint16","internalType":"uint16"}]},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false}],"bytecode":{"object":"0x6080604052346100305761001a61001461030f565b90610acf565b610022610035565b613a46610ed38239613a4690f35b61003b565b60405190565b5f80fd5b601f801991011690565b634e487b7160e01b5f52604160045260245ffd5b906100679061003f565b810190811060018060401b0382111761007f57604052565b610049565b90610097610090610035565b928361005d565b565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b61ffff1690565b6100b9816100a9565b036100c057565b5f80fd5b905051906100d1826100b0565b565b91906020838203126100fb576100f5906100ed6020610084565b935f016100c4565b5f830152565b6100a1565b5f80fd5b60018060401b03811161011a5760208091020190565b610049565b5f80fd5b60018060a01b031690565b61013790610123565b90565b6101438161012e565b0361014a57565b5f80fd5b9050519061015b8261013a565b565b5f80fd5b60018060401b03811161017d5761017960209161003f565b0190565b610049565b90825f9392825e0152565b909291926101a261019d82610161565b610084565b938185526020850190828401116101be576101bc92610182565b565b61015d565b9080601f830112156101e1578160206101de9351910161018d565b90565b610100565b919091604081840312610236576101fd6040610084565b9261020a815f840161014e565b5f850152602082015160018060401b0381116102315761022a92016101c3565b6020830152565b6100a5565b6100a1565b92919061024f61024a82610104565b610084565b93818552602080860192028101918383116102a45781905b838210610275575050505050565b815160018060401b03811161029f5760209161029487849387016101e6565b815201910190610267565b610100565b61011f565b9080601f830112156102c7578160206102c49351910161023b565b90565b610100565b91909160408184031261030a576102e5835f83016100d3565b92602082015160018060401b0381116103055761030292016102a9565b90565b61009d565b610099565b61032d6149198038038061032281610084565b9283398101906102cc565b9091565b5190565b90565b90565b90565b61035261034d61035792610338565b61033b565b610335565b90565b60209181520190565b5f7f746f6f206d616e79206f70657261746f72730000000000000000000000000000910152565b610397601260209261035a565b6103a081610363565b0190565b6103b99060208101905f81830391015261038a565b90565b156103c357565b6103cb610035565b62461bcd60e51b8152806103e1600482016103a4565b0390fd5b5f1b90565b906103fb60018060a01b03916103e5565b9181191691161790565b61041961041461041e92610123565b61033b565b610123565b90565b61042a90610405565b90565b61043690610421565b90565b90565b9061045161044c6104589261042d565b610439565b82546103ea565b9055565b634e487b7160e01b5f525f60045260245ffd5b61047990516100a9565b90565b9061048961ffff916103e5565b9181191691161790565b6104a76104a26104ac926100a9565b61033b565b6100a9565b90565b90565b906104c76104c26104ce92610493565b6104af565b825461047c565b9055565b906104e45f806104ea9401920161046f565b906104b2565b565b906104f6916104d2565b565b90565b61050f61050a610514926104f8565b61033b565b610335565b90565b60016105239101610335565b90565b634e487b7160e01b5f52603260045260245ffd5b9061054482610331565b811015610555576020809102010190565b610526565b5190565b610568905161012e565b90565b906105759061042d565b5f5260205260405f2090565b5f1c90565b60ff1690565b61059861059d91610581565b610586565b90565b6105aa905461058c565b90565b151590565b5f7f6475706c6963617465206f70657261746f720000000000000000000000000000910152565b6105e6601260209261035a565b6105ef816105b2565b0190565b6106089060208101905f8183039101526105d9565b90565b1561061257565b61061a610035565b62461bcd60e51b815280610630600482016105f3565b0390fd5b60ff1690565b61064e61064961065392610335565b61033b565b610634565b90565b6106606040610084565b90565b9061066d906105ad565b9052565b9061067b90610634565b9052565b61068990516105ad565b90565b9061069860ff916103e5565b9181191691161790565b6106ab906105ad565b90565b90565b906106c66106c16106cd926106a2565b6106ae565b825461068c565b9055565b6106db9051610634565b90565b60081b90565b906106f161ff00916106de565b9181191691161790565b61070f61070a61071492610634565b61033b565b610634565b90565b90565b9061072f61072a610736926106fb565b610717565b82546106e4565b9055565b9061076460205f61076a9461075c82820161075684880161067f565b906106b1565b0192016106d1565b9061071a565b565b906107769161073a565b565b5061010090565b90565b61078b81610778565b8210156107a55761079d60029161077f565b910201905f90565b610526565b5190565b634e487b7160e01b5f52602260045260245ffd5b90600160028304921680156107e2575b60208310146107dd57565b6107ae565b91607f16916107d2565b5f5260205f2090565b601f602091010490565b1b90565b9190600861081e9102916108185f19846107ff565b926107ff565b9181191691161790565b61083c61083761084192610335565b61033b565b610335565b90565b90565b919061085d61085861086593610828565b610844565b908354610803565b9055565b5f90565b61087f91610879610869565b91610847565b565b5b81811061088d575050565b8061089a5f60019361086d565b01610882565b9190601f81116108b0575b505050565b6108bc6108e1936107ec565b9060206108c8846107f5565b830193106108e9575b6108da906107f5565b0190610881565b5f80806108ab565b91506108da819290506108d1565b1c90565b9061090b905f19906008026108f7565b191690565b8161091a916108fb565b906002021790565b9061092c8161055a565b9060018060401b0382116109ea5761094e8261094885546107c2565b856108a0565b602090601f831160011461098257918091610971935f92610976575b5050610910565b90555b565b90915001515f8061096a565b601f19831691610991856107ec565b925f5b8181106109d2575091600293918560019694106109b8575b50505002019055610974565b6109c8910151601f8416906108fb565b90555f80806109ac565b91936020600181928787015181550195019201610994565b610049565b906109f991610922565b565b90610a2660206001610a2c94610a1e5f8201610a185f880161055e565b9061043c565b0192016107aa565b906109ef565b565b9190610a3f57610a3d916109fb565b565b61045c565b90610a505f19916103e5565b9181191691161790565b90610a6f610a6a610a7692610828565b610844565b8254610a44565b9055565b90565b610a89610a8e91610581565b610a7a565b90565b610a9b9054610a7d565b90565b50600290565b90565b610ab081610a9e565b821015610aca57610ac2600291610aa4565b910201905f90565b610526565b610b0c90610afa610adf84610331565b610af3610aed61010061033e565b91610335565b11156103bc565b610b04335f61043c565b6102086104ec565b610b155f6104fb565b5b80610b31610b2b610b2685610331565b610335565b91610335565b1015610c1c57610c1790610b5b610b566020610b4e86859061053a565b51015161055a565b610db4565b610b99610b94610b8e5f610b8881600101610b8283610b7b8b8a9061053a565b510161055e565b9061056b565b016105a0565b156105ad565b61060b565b610bef6001610bc7610baa8461063a565b610bbe610bb5610656565b935f8501610663565b60208301610671565b610bea5f600101610be45f610bdd89889061053a565b510161055e565b9061056b565b61076c565b610c12610bfd84839061053a565b51610c0c600180018490610782565b90610a2e565b610517565b610b16565b50610c39610c34610c2f610c4493610331565b61063a565b610e96565b610201600101610a5a565b610c6a610c55610201600101610a91565b5f610c636102038290610aa7565b5001610a5a565b565b5f7f656d707479206f70657261746f72206461746100000000000000000000000000910152565b610ca0601360209261035a565b610ca981610c6c565b0190565b610cc29060208101905f818303910152610c93565b90565b15610ccc57565b610cd4610035565b62461bcd60e51b815280610cea60048201610cad565b0390fd5b61ffff1690565b610d01610d0691610581565b610cee565b90565b610d139054610cf5565b90565b610d2a610d25610d2f926100a9565b61033b565b610335565b90565b5f7f6f70657261746f72206461746120746f6f206c61726765000000000000000000910152565b610d66601760209261035a565b610d6f81610d32565b0190565b610d889060208101905f818303910152610d59565b90565b15610d9257565b610d9a610035565b62461bcd60e51b815280610db060048201610d73565b0390fd5b610df990610dd481610dce610dc85f6104fb565b91610335565b11610cc5565b610df2610dec610de75f61020801610d09565b610d16565b91610335565b1115610d8b565b565b610e0f610e0a610e1492610634565b61033b565b610335565b90565b90565b610e2e610e29610e3392610e17565b61033b565b610335565b90565b610e5590610e4f610e49610e5a94610335565b91610335565b906107ff565b610335565b90565b634e487b7160e01b5f52601160045260245ffd5b610e80610e8691939293610335565b92610335565b8203918211610e9157565b610e5d565b610ebf610ecf91610ea5610869565b50610eba610eb4600192610dfb565b91610e1a565b610e36565b610ec96001610e1a565b90610e71565b9056fe60806040526004361015610013575b6107fc565b61001d5f356100cc565b806326322217146100c75780632b726062146100c257806347011c5c146100bd57806353bfb584146100b857806365706f9c146100b357806375418b9d146100ae5780639d44e717146100a9578063c05665dd146100a4578063e88e97491461009f578063f2fde38b1461009a5763f5f2d9f10361000e576107c9565b610796565b610763565b610730565b6106bc565b610646565b6102e1565b61027d565b61023b565b6101d6565b610135565b60e01c90565b60405190565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b908160409103126100f65790565b6100e4565b9060208282031261012b575f82013567ffffffffffffffff81116101265761012392016100e8565b90565b6100e0565b6100dc565b5f0190565b346101635761014d6101483660046100fb565b610f6e565b6101556100d2565b8061015f81610130565b0390f35b6100d8565b60ff1690565b61017781610168565b0361017e57565b5f80fd5b9050359061018f8261016e565b565b9190916040818403126101d1576101aa835f8301610182565b92602082013567ffffffffffffffff81116101cc576101c992016100e8565b90565b6100e0565b6100dc565b34610205576101ef6101e9366004610191565b906115ec565b6101f76100d2565b8061020181610130565b0390f35b6100d8565b908160409103126102185790565b6100e4565b9060408282031261023657610233915f0161020a565b90565b6100dc565b346102695761025361024e36600461021d565b611d3c565b61025b6100d2565b8061026581610130565b0390f35b6100d8565b5f91031261027857565b6100dc565b346102ab5761028d36600461026e565b610295611ef1565b61029d6100d2565b806102a781610130565b0390f35b6100d8565b908160209103126102be5790565b6100e4565b906020828203126102dc576102d9915f016102b0565b90565b6100dc565b3461030f576102f96102f43660046102c3565b612097565b6103016100d2565b8061030b81610130565b0390f35b6100d8565b60018060a01b031690565b61032890610314565b90565b6103349061031f565b9052565b5190565b60209181520190565b60200190565b5190565b60209181520190565b90825f9392825e0152565b601f801991011690565b61038c61039560209361039a936103838161034b565b9384809361034f565b95869101610358565b610363565b0190565b6103c991602060408201926103b95f8201515f85019061032b565b015190602081840391015261036d565b90565b906103d69161039e565b90565b60200190565b906103f36103ec83610338565b809261033c565b908161040460208302840194610345565b925f915b83831061041757505050505090565b90919293946020610439610433838560019503875289516103cc565b976103d9565b9301930191939290610408565b50600290565b905090565b90565b90565b61046090610454565b9052565b61046d90610168565b9052565b90602080610493936104895f8201515f860190610457565b0151910190610464565b565b906104a281604093610471565b0190565b60200190565b6104c86104c26104bb83610446565b809461044c565b91610451565b5f915b8383106104d85750505050565b6104ee6104e86001928451610495565b926104a6565b920191906104cb565b67ffffffffffffffff1690565b61050d906104f7565b9052565b61ffff1690565b61052190610511565b9052565b905f80610536930151910190610518565b565b9060208061055a936105505f8201515f860190610504565b0151910190610457565b565b905f8061056d93015191019061032b565b565b6fffffffffffffffffffffffffffffffff1690565b61058d9061056f565b9052565b9061062b9061016060e06105c561018084016105b35f8801515f87019061032b565b602087015185820360208701526103df565b946105d8604082015160408601906104ac565b6105ea606082015160c0860190610504565b6105fb608082015183860190610525565b61060e60a0820151610100860190610538565b61062160c082015161014086019061055c565b0151910190610584565b90565b6106439160208201915f818403910152610591565b90565b346106765761065636600461026e565b61067261066161266b565b6106696100d2565b9182918261062e565b0390f35b6100d8565b610684816104f7565b0361068b57565b5f80fd5b9050359061069c8261067b565b565b906020828203126106b7576106b4915f0161068f565b90565b6100dc565b346106ea576106d46106cf36600461069e565b612bde565b6106dc6100d2565b806106e681610130565b0390f35b6100d8565b6106f88161031f565b036106ff57565b5f80fd5b90503590610710826106ef565b565b9060208282031261072b57610728915f01610703565b90565b6100dc565b3461075e57610748610743366004610712565b61305a565b6107506100d2565b8061075a81610130565b0390f35b6100d8565b346107915761077b61077636600461069e565b6131bc565b6107836100d2565b8061078d81610130565b0390f35b6100d8565b346107c4576107ae6107a9366004610712565b613264565b6107b66100d2565b806107c081610130565b0390f35b6100d8565b346107f7576107d936600461026e565b6107e1613377565b6107e96100d2565b806107f381610130565b0390f35b6100d8565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b90359060016020038136030382121561084e570180359067ffffffffffffffff82116108495760200191600182023603831361084457565b610808565b610804565b610800565b5090565b35610861816106ef565b90565b5f1c90565b60018060a01b031690565b61088061088591610864565b610869565b90565b6108929054610874565b90565b60209181520190565b5f7f756e617574686f72697a65640000000000000000000000000000000000000000910152565b6108d2600c602092610895565b6108db8161089e565b0190565b6108f49060208101905f8183039101526108c5565b90565b156108fe57565b6109066100d2565b62461bcd60e51b81528061091c600482016108df565b0390fd5b90565b61093761093261093c92610314565b610920565b610314565b90565b61094890610923565b90565b6109549061093f565b90565b906109619061094b565b5f5260205260405f2090565b90565b60ff1690565b61098261098791610864565b610970565b90565b6109949054610976565b90565b5f7f756e6b6e6f776e206f70657261746f7200000000000000000000000000000000910152565b6109cb6010602092610895565b6109d481610997565b0190565b6109ed9060208101905f8183039101526109be565b90565b156109f757565b6109ff6100d2565b62461bcd60e51b815280610a15600482016109d8565b0390fd5b60081c90565b60ff1690565b610a31610a3691610a19565b610a1f565b90565b610a439054610a25565b90565b634e487b7160e01b5f52603260045260245ffd5b5061010090565b90565b610a6d81610a5a565b821015610a8757610a7f600291610a61565b910201905f90565b610a46565b634e487b7160e01b5f525f60045260245ffd5b5f1b90565b90610ab560018060a01b0391610a9f565b9181191691161790565b90565b90610ad7610ad2610ade9261094b565b610abf565b8254610aa4565b9055565b634e487b7160e01b5f52604160045260245ffd5b634e487b7160e01b5f52602260045260245ffd5b9060016002830492168015610b2a575b6020831014610b2557565b610af6565b91607f1691610b1a565b5f5260205f2090565b601f602091010490565b1b90565b91906008610b66910291610b605f1984610b47565b92610b47565b9181191691161790565b610b84610b7f610b8992610454565b610920565b610454565b90565b90565b9190610ba5610ba0610bad93610b70565b610b8c565b908354610b4b565b9055565b5f90565b610bc791610bc1610bb1565b91610b8f565b565b5b818110610bd5575050565b80610be25f600193610bb5565b01610bca565b9190601f8111610bf8575b505050565b610c04610c2993610b34565b906020610c1084610b3d565b83019310610c31575b610c2290610b3d565b0190610bc9565b5f8080610bf3565b9150610c2281929050610c19565b1c90565b90610c53905f1990600802610c3f565b191690565b81610c6291610c43565b906002021790565b91610c759082610853565b9067ffffffffffffffff8211610d3457610c9982610c938554610b0a565b85610be8565b5f90601f8311600114610ccc57918091610cbb935f92610cc0575b5050610c58565b90555b565b90915001355f80610cb4565b601f19831691610cdb85610b34565b925f5b818110610d1c57509160029391856001969410610d02575b50505002019055610cbe565b610d12910135601f841690610c43565b90555f8080610cf6565b91936020600181928787013581550195019201610cde565b610ae2565b90610d449291610c6a565b565b90610d736001610d7993610d675f8201610d615f8701610857565b90610ac2565b0191602081019061080c565b91610d39565b565b9190610d8c57610d8a91610d46565b565b610a8c565b6fffffffffffffffffffffffffffffffff1690565b610db2610db791610864565b610d91565b90565b610dc49054610da6565b90565b634e487b7160e01b5f52601160045260245ffd5b610de49061056f565b6fffffffffffffffffffffffffffffffff8114610e015760010190565b610dc7565b90610e216fffffffffffffffffffffffffffffffff91610a9f565b9181191691161790565b610e3f610e3a610e449261056f565b610920565b61056f565b90565b90565b90610e5f610e5a610e6692610e2b565b610e47565b8254610e06565b9055565b50610e79906020810190610703565b90565b5f80fd5b5f80fd5b5f80fd5b9035600160200382360303811215610ec957016020813591019167ffffffffffffffff8211610ec4576001820236038313610ebf57565b610e80565b610e7c565b610e84565b90825f939282370152565b9190610ef381610eec81610ef89561034f565b8095610ece565b610363565b0190565b610f3891610f2a6040820192610f20610f175f830183610e6a565b5f85019061032b565b6020810190610e88565b916020818503910152610ed9565b90565b610f449061056f565b9052565b92916020610f64610f6c9360408701908782035f890152610efc565b940190610f3b565b565b610f8d610f88610f8283602081019061080c565b90610853565b6134a1565b33610faa610fa4610f9f5f8501610857565b61031f565b9161031f565b148015611075575b610fbb906108f7565b611011610fde610fd95f600101610fd35f8601610857565b90610957565b61096d565b610ff1610fec5f830161098a565b6109f0565b61100b83916110055f600180019201610a39565b90610a64565b90610d7b565b61102f61102761102261020c610dba565b610ddb565b61020c610e4a565b61103a61020c610dba565b7f5aab2c32b1e447db4dba1d2790fe8b863d4775042b10b92e00dab9d6b671b5b5916110706110676100d2565b92839283610f48565b0390a1565b50610fbb3361109461108e6110895f610888565b61031f565b9161031f565b149050610fb2565b5f7f6e6f7420746865206f776e657200000000000000000000000000000000000000910152565b6110d0600d602092610895565b6110d98161109c565b0190565b6110f29060208101905f8183039101526110c3565b90565b156110fc57565b6111046100d2565b62461bcd60e51b81528061111a600482016110dd565b0390fd5b9061114c916111473361114161113b6111365f610888565b61031f565b9161031f565b146110f5565b61147f565b565b151590565b5f7f616c726561647920657869737473000000000000000000000000000000000000910152565b611187600e602092610895565b61119081611153565b0190565b6111a99060208101905f81830391015261117a565b90565b156111b357565b6111bb6100d2565b62461bcd60e51b8152806111d160048201611194565b0390fd5b6111df9054610b0a565b90565b90565b6111f96111f46111fe926111e2565b610920565b610454565b90565b5f7f736c6f74206f6363757069656400000000000000000000000000000000000000910152565b611235600d602092610895565b61123e81611201565b0190565b6112579060208101905f818303910152611228565b90565b1561126157565b6112696100d2565b62461bcd60e51b81528061127f60048201611242565b0390fd5b9061128d90610363565b810190811067ffffffffffffffff8211176112a757604052565b610ae2565b906112bf6112b86100d2565b9283611283565b565b6112cb60406112ac565b90565b906112d89061114e565b9052565b906112e690610168565b9052565b6112f4905161114e565b90565b9061130360ff91610a9f565b9181191691161790565b6113169061114e565b90565b90565b9061133161132c6113389261130d565b611319565b82546112f7565b9055565b6113469051610168565b90565b60081b90565b9061135c61ff0091611349565b9181191691161790565b61137a61137561137f92610168565b610920565b610168565b90565b90565b9061139a6113956113a192611366565b611382565b825461134f565b9055565b906113cf60205f6113d5946113c78282016113c18488016112ea565b9061131c565b01920161133c565b90611385565b565b906113e1916113a5565b565b90565b6113f26113f791610864565b6113e3565b90565b61140490546113e6565b90565b906114135f1991610a9f565b9181191691161790565b9061143261142d61143992610b70565b610b8c565b8254611407565b9055565b61144690610168565b9052565b93929061147560409161147d9461146860608901925f8a019061143d565b8782036020890152610efc565b940190610f3b565b565b61149e61149961149384602081019061080c565b90610853565b6134a1565b6114d16114cc6114c65f6114c0816001016114ba838901610857565b90610957565b0161098a565b1561114e565b6111ac565b6115056114ed60016114e68180018590610a64565b50016111d5565b6114ff6114f95f6111e5565b91610454565b1461125a565b611548600161152b836115226115196112c1565b935f85016112ce565b602083016112dc565b6115435f60010161153d5f8701610857565b90610957565b6113d7565b6115608261155a600180018490610a64565b90610d7b565b61158661157b6115746102016001016113fa565b839061352b565b61020160010161141d565b6115a461159c61159761020c610dba565b610ddb565b61020c610e4a565b906115b061020c610dba565b916115e77f952e65f049c574f487580ba41dcf6b0ea8350ef8abc8647a8a11dfaa7af6bad6936115de6100d2565b9384938461144a565b0390a1565b906115f69161111e565b565b611625906116203361161a61161461160f5f610888565b61031f565b9161031f565b146110f5565b6116a9565b565b5f7f6d6967726174696f6e20696e2070726f67726573730000000000000000000000910152565b61165b6015602092610895565b61166481611627565b0190565b61167d9060208101905f81830391015261164e565b90565b1561168757565b61168f6100d2565b62461bcd60e51b8152806116a560048201611668565b0390fd5b6116cb906116c66116c16116bb61355a565b1561114e565b611680565b61174f565b565b5f7f6d61696e74656e616e636520696e2070726f6772657373000000000000000000910152565b6117016017602092610895565b61170a816116cd565b0190565b6117239060208101905f8183039101526116f4565b90565b1561172d57565b6117356100d2565b62461bcd60e51b81528061174b6004820161170e565b0390fd5b6117719061176c611767611761613588565b1561114e565b611726565b611b76565b565b61177c81610454565b0361178357565b5f80fd5b3561179181611773565b90565b5f7f696e76616c6964206269746d61736b0000000000000000000000000000000000910152565b6117c8600f602092610895565b6117d181611794565b0190565b6117ea9060208101905f8183039101526117bb565b90565b156117f457565b6117fc6100d2565b62461bcd60e51b815280611812600482016117d5565b0390fd5b67ffffffffffffffff1690565b61182f61183491610864565b611816565b90565b6118419054611823565b90565b90565b61185b61185661186092611844565b610920565b6104f7565b90565b634e487b7160e01b5f52601260045260245ffd5b611883611889916104f7565b916104f7565b908115611894570690565b611863565b50600290565b90565b6118ab81611899565b8210156118c5576118bd60029161189f565b910201905f90565b610a46565b906118d490610454565b9052565b6118e46118e991610864565b610a1f565b90565b6118f690546118d8565b90565b61190360406112ac565b90565b9061193d61193460016119176118f9565b9461192e6119265f83016113fa565b5f88016118ca565b016118ec565b602084016112dc565b565b61194890611906565b90565b6119559051610454565b90565b356119628161016e565b90565b5f7f73616d65206b6579737061636500000000000000000000000000000000000000910152565b611999600d602092610895565b6119a281611965565b0190565b6119bb9060208101905f81830391015261198c565b90565b156119c557565b6119cd6100d2565b62461bcd60e51b8152806119e3600482016119a6565b0390fd5b6119f0906104f7565b67ffffffffffffffff8114611a055760010190565b610dc7565b90611a1d67ffffffffffffffff91610a9f565b9181191691161790565b611a3b611a36611a40926104f7565b610920565b6104f7565b90565b90565b90611a5b611a56611a6292611a27565b611a43565b8254611a0a565b9055565b90611a7b611a76611a8292611366565b611382565b82546112f7565b9055565b90611ab160206001611ab794611aa95f8201611aa35f8801611787565b9061141d565b019201611958565b90611a66565b565b9190611aca57611ac891611a86565b565b610a8c565b611ad8906104f7565b9052565b90503590611ae982611773565b565b50611afa906020810190611adc565b90565b50611b0c906020810190610182565b90565b906020611b3a611b4293611b31611b285f830183611aeb565b5f860190610457565b82810190611afd565b910190610464565b565b606090611b6d611b749496959396611b6360808401985f850190611acf565b6020830190611b0f565b0190610f3b565b565b611ba0611b9b611b875f8401611787565b611b956102016001016113fa565b906135bd565b6117ed565b611c0d611bd6611bd0610203611bca611bba610207611837565b611bc46002611847565b90611877565b906118a2565b5061193f565b611be15f820161194b565b611bfd611bf7611bf25f8701611787565b610454565b91610454565b1415908115611d0a575b506119be565b611c2c5f61020901611c26611c2182611837565b6119e7565b90611a46565b611c4a611c42611c3d610207611837565b6119e7565b610207611a46565b611c7e81611c78610203611c72611c62610207611837565b611c6c6002611847565b90611877565b906118a2565b90611ab9565b611c97611c8c5f8301611787565b60016102090161141d565b611cb5611cad611ca861020c610dba565b610ddb565b61020c610e4a565b611cc25f61020901611837565b90611cce61020c610dba565b91611d057f490341fd8fc7a8294fbad1cc0db9f41ae0ac5aeb655ea31b46a475ec3a77749c93611cfc6100d2565b93849384611b44565b0390a1565b611d17915060200161133c565b611d34611d2e611d2960208601611958565b610168565b91610168565b14155f611c07565b611d45906115f8565b565b5f7f6e6f206d61696e74656e616e6365000000000000000000000000000000000000910152565b611d7b600e602092610895565b611d8481611d47565b0190565b611d9d9060208101905f818303910152611d6e565b90565b15611da757565b611daf6100d2565b62461bcd60e51b815280611dc560048201611d88565b0390fd5b611dd9611dd4613588565b611da0565b611de1611e20565b565b611df7611df2611dfc926111e2565b610920565b610314565b90565b611e0890611de3565b90565b9190611e1e905f60208501940190610f3b565b565b611e2d5f61020b01610888565b611e3f611e393361031f565b9161031f565b148015611eca575b611e50906108f7565b611e66611e5c5f611dff565b5f61020b01610ac2565b611e84611e7c611e7761020c610dba565b610ddb565b61020c610e4a565b611e8f61020c610dba565b611ec57f11943d6deda6f0591d72674788d272eb0209e18b8a3a021fa51cb3b5e9a2ab6191611ebc6100d2565b91829182611e0b565b0390a1565b50611e5033611ee9611ee3611ede5f610888565b61031f565b9161031f565b149050611e47565b611ef9611dc9565b565b611f2890611f2333611f1d611f17611f125f610888565b61031f565b9161031f565b146110f5565b612027565b565b611f3381610511565b03611f3a57565b5f80fd5b35611f4881611f2a565b90565b90611f5861ffff91610a9f565b9181191691161790565b611f76611f71611f7b92610511565b610920565b610511565b90565b90565b90611f96611f91611f9d92611f62565b611f7e565b8254611f4b565b9055565b90611fb35f80611fb994019201611f3e565b90611f81565b565b90611fc591611fa1565b565b90503590611fd482611f2a565b565b50611fe5906020810190611fc7565b90565b905f611ffa6120029382810190611fd6565b910190610518565b565b91602061202592949361201e60408201965f830190611fe8565b0190610f3b565b565b61203381610208611fbb565b61205161204961204461020c610dba565b610ddb565b61020c610e4a565b61205c61020c610dba565b7fb24d8d9dcfbb6be13176c1c7bfb0e76445a9ba2a3553b413d8671446f1030830916120926120896100d2565b92839283612004565b0390a1565b6120a090611efb565b565b6120ad6101006112ac565b90565b5f90565b606090565b67ffffffffffffffff81116120ce5760200290565b610ae2565b6120df6120e4916120b9565b6112ac565b90565b5f90565b5f90565b6120f76118f9565b90602080836121046120e7565b81520161210f6120eb565b81525050565b61211d6120ef565b90565b5f5b82811061212e57505050565b602090612139612115565b8184015201612122565b90612161612150836120d3565b9261215b84916120b9565b90612120565b565b61216d6002612143565b90565b5f90565b61217e60206112ac565b90565b5f90565b61218d612174565b90602082612199612181565b81525050565b6121a7612185565b90565b6121b460406112ac565b90565b6121bf6121aa565b90602080836121cc612170565b8152016121d76120e7565b81525050565b6121e56121b7565b90565b6121f260206112ac565b90565b6121fd6121e8565b906020826122096120b0565b81525050565b6122176121f5565b90565b5f90565b6122266120a2565b90602080808080808080896122396120b0565b8152016122446120b4565b81520161224f612163565b81520161225a612170565b81520161226561219f565b8152016122706121dd565b81520161227b61220f565b81520161228661221a565b81525050565b61229461221e565b90565b90565b6122ae6122a96122b392612297565b610920565b610454565b90565b6122c56122cb91939293610454565b92610454565b82018092116122d657565b610dc7565b67ffffffffffffffff81116122f35760208091020190565b610ae2565b9061230a612305836122db565b6112ac565b918252565b61231960406112ac565b90565b606090565b61232961230f565b90602080836123366120b0565b81520161234161231c565b81525050565b61234f612321565b90565b5f5b82811061236057505050565b60209061236b612347565b8184015201612354565b9061239a612382836122f8565b9260208061239086936122db565b9201910390612352565b565b6123a76101006112ac565b90565b906123b49061031f565b9052565b52565b906123c582611899565b6123ce816120d3565b926123d9849161189f565b5f915b8383106123e95750505050565b600260206001926123f98561193f565b8152019201920191906123dc565b612410906123bb565b90565b52565b90612420906104f7565b9052565b61ffff1690565b61243761243c91610864565b612424565b90565b612449905461242b565b90565b9061245690610511565b9052565b906124796124715f61246a612174565b940161243f565b5f840161244c565b565b6124849061245a565b90565b52565b906124c16124b8600161249b6121aa565b946124b26124aa5f8301611837565b5f8801612416565b016113fa565b602084016118ca565b565b6124cc9061248a565b90565b52565b906124f16124e95f6124e26121e8565b9401610888565b5f84016123aa565b565b6124fc906124d2565b90565b52565b9061250c9061056f565b9052565b61251990610454565b5f1981146125275760010190565b610dc7565b61254061253b61254592610454565b610920565b610168565b90565b9061255282610338565b811015612563576020809102010190565b610a46565b905f929180549061258261257b83610b0a565b809461034f565b916001811690815f146125d9575060011461259d575b505050565b6125aa9192939450610b34565b915f925b8184106125c157505001905f8080612598565b600181602092959395548486015201910192906125ae565b92949550505060ff19168252151560200201905f8080612598565b906125fe91612568565b90565b9061262161261a926126116100d2565b938480926125f4565b0383611283565b565b52565b9061265d612654600161263761230f565b9461264e6126465f8301610888565b5f88016123aa565b01612601565b60208401612623565b565b61266890612626565b90565b61267361228c565b50600161020101612683906113fa565b61268c906135e8565b6126955f610888565b8160016126a19061229a565b6126aa916122b6565b6126b390612375565b6102036126c1610207611837565b6102086102099161020b936126d761020c610dba565b956126e061239c565b975f8901906126ee916123aa565b60208801906126fc916123b8565b61270590612407565b604087019061271391612413565b606086019061272191612416565b61272a9061247b565b608085019061273891612487565b612741906124c3565b60a084019061274f916124cf565b612758906124f3565b60c0830190612766916124ff565b60e082019061277491612502565b600161020101612783906113fa565b925f61278e906111e5565b5b806127a261279c86610454565b91610454565b11612805576127fb906127be866127b88361252c565b906135fd565b612800576127f36127d3600180018390610a64565b5060208601516127e3849261265f565b6127ed8383612548565b52612548565b51505b612510565b61278f565b6127f6565b509250905090565b5f7f6e6f206d6967726174696f6e0000000000000000000000000000000000000000910152565b612841600c602092610895565b61284a8161280d565b0190565b6128639060208101905f818303910152612834565b90565b1561286d57565b6128756100d2565b62461bcd60e51b81528061288b6004820161284e565b0390fd5b6128a8906128a361289e61355a565b612866565b612a3e565b565b5f7f77726f6e67206d6967726174696f6e2069640000000000000000000000000000910152565b6128de6012602092610895565b6128e7816128aa565b0190565b6129009060208101905f8183039101526128d1565b90565b1561290a57565b6129126100d2565b62461bcd60e51b815280612928600482016128eb565b0390fd5b61293660406112ac565b90565b9061296f6129665f61294961292c565b9461296061295883830161098a565b8388016112ce565b01610a39565b602084016112dc565b565b61297a90612939565b90565b5f7f6e6f742070756c6c696e67000000000000000000000000000000000000000000910152565b6129b1600b602092610895565b6129ba8161297d565b0190565b6129d39060208101905f8183039101526129a4565b90565b156129dd57565b6129e56100d2565b62461bcd60e51b8152806129fb600482016129be565b0390fd5b612a089061031f565b9052565b604090612a35612a3c9496959396612a2b60608401985f850190611acf565b60208301906129ff565b0190610f3b565b565b612a6690612a60612a5a612a555f61020901611837565b6104f7565b916104f7565b14612903565b612aeb612ae0612a82612a7d5f6001013390610957565b612971565b612a95612a905f83016112ea565b6109f0565b612ac0612abb612aa96001610209016113fa565b612ab56020850161133c565b9061363b565b6129d6565b612ada6020612ad36001610209016113fa565b920161133c565b9061367a565b60016102090161141d565b612b09612b01612afc61020c610dba565b610ddb565b61020c610e4a565b612b176001610209016113fa565b612b29612b235f6111e5565b91610454565b145f14612b8657612b3d5f61020901611837565b33612b4961020c610dba565b91612b807f01269879535f40ee8957e15e160bf1866c5e2728ff0cbc583d848821e2639b4e93612b776100d2565b93849384612a0c565b0390a15b565b612b935f61020901611837565b33612b9f61020c610dba565b91612bd67faf5e90e72015f43138f66b4cd08bd1dfa2839030104f22a00af843fe847c6d1993612bcd6100d2565b93849384612a0c565b0390a1612b84565b612be79061288f565b565b612c1690612c1133612c0b612c05612c005f610888565b61031f565b9161031f565b146110f5565b612eb7565b565b5f7f696e206b65797370616365000000000000000000000000000000000000000000910152565b612c4c600b602092610895565b612c5581612c18565b0190565b612c6e9060208101905f818303910152612c3f565b90565b15612c7857565b612c806100d2565b62461bcd60e51b815280612c9660048201612c59565b0390fd5b5f80910155565b905f03612cb357612cb190612c9a565b565b610a8c565b90612ccb905f1990602003600802610c3f565b8154169055565b905f91612ce9612ce182610b34565b928354610c58565b905555565b919290602082105f14612d4757601f8411600114612d1757612d11929350610c58565b90555b5b565b5090612d3d612d42936001612d34612d2e85610b34565b92610b3d565b82019101610bc9565b612cd2565b612d14565b50612d7e8293612d58600194610b34565b612d77612d6485610b3d565b820192601f861680612d89575b50610b3d565b0190610bc9565b600202179055612d15565b612d9590888603612cb8565b5f612d71565b929091680100000000000000008211612dfb576020115f14612dec57602081105f14612dd057612dca91610c58565b90555b5b565b60019160ff1916612de084610b34565b55600202019055612dcd565b60019150600202019055612dce565b610ae2565b908154612e0c81610b0a565b90818311612e35575b818310612e23575b50505050565b612e2c93612cee565b5f808080612e1d565b612e4183838387612d9b565b612e15565b5f612e5091612e00565b565b905f03612e6457612e6290612e46565b565b610a8c565b5f6001612e7b92828082015501612e52565b565b905f03612e8f57612e8d90612e69565b565b610a8c565b916020612eb5929493612eae60408201965f8301906129ff565b0190610f3b565b565b612f7c612f71612ef05f612ed7612ed2826001018790610957565b61096d565b612eea612ee583830161098a565b6109f0565b01610a39565b612ef861355a565b5f1461300e57612f20612f195f612f1261020382906118a2565b50016113fa565b82906135fd565b80612fe0575b612f2f90612c71565b5b612f475f612f42816001018790610957565b612ca1565b612f5e612f58600180018390610a64565b90612e7d565b612f6c6102016001016113fa565b61367a565b61020160010161141d565b612f9a612f92612f8d61020c610dba565b610ddb565b61020c610e4a565b612fa561020c610dba565b7f6a1d7ddc82d57e783a3ae60737a6c1a4704fcf38d966561fea0af8564f2d895d91612fdb612fd26100d2565b92839283612e94565b0390a1565b50612f2f6130076130005f612ff96102036001906118a2565b50016113fa565b83906135fd565b9050612f26565b6130556130506130495f61304261020361303c61302c610207611837565b6130366002611847565b90611877565b906118a2565b50016113fa565b83906135fd565b612c71565b612f30565b61306390612be9565b565b6130929061308d3361308761308161307c5f610888565b61031f565b9161031f565b146110f5565b613094565b565b6130ad906130a86130a361355a565b612866565b6130ee565b565b6130b8906104f7565b5f81146130c6576001900390565b610dc7565b9160206130ec9294936130e560408201965f830190611acf565b0190610f3b565b565b6131169061311061310a6131055f61020901611837565b6104f7565b916104f7565b14612903565b61313461312c613127610207611837565b6130af565b610207611a46565b61314b6131405f6111e5565b60016102090161141d565b61316961316161315c61020c610dba565b610ddb565b61020c610e4a565b6131765f61020901611837565b61318161020c610dba565b7ff73240422246f63ed633ef3ce0726b8ab8fb69d46c8a4e5ecb0b2922668674a1916131b76131ae6100d2565b928392836130cb565b0390a1565b6131c590613065565b565b6131f4906131ef336131e96131e36131de5f610888565b61031f565b9161031f565b146110f5565b6131f6565b565b613200815f610ac2565b61321e61321661321161020c610dba565b610ddb565b61020c610e4a565b61322961020c610dba565b7f476610ebc6647c15376100955efbf22ef2a0c3b923fc00b380b660c873ef20ac9161325f6132566100d2565b92839283612e94565b0390a1565b61326d906131c7565b565b61328861328361327d61355a565b1561114e565b611680565b613290613292565b565b6132ab6132a66132a0613588565b1561114e565b611726565b6132b36132b5565b565b6132cd5f6132c7816001013390610957565b0161098a565b8015613350575b6132dd906108f7565b6132eb335f61020b01610ac2565b6133096133016132fc61020c610dba565b610ddb565b61020c610e4a565b3361331561020c610dba565b7fbc2748cf02f7a1291525e866efc76ab3b96d32d7afcbb26c53daec617b38b4799161334b6133426100d2565b92839283612e94565b0390a1565b506132dd3361336f6133696133645f610888565b61031f565b9161031f565b1490506132d4565b61337f61326f565b565b5f7f656d707479206f70657261746f72206461746100000000000000000000000000910152565b6133b56013602092610895565b6133be81613381565b0190565b6133d79060208101905f8183039101526133a8565b90565b156133e157565b6133e96100d2565b62461bcd60e51b8152806133ff600482016133c2565b0390fd5b61341761341261341c92610511565b610920565b610454565b90565b5f7f6f70657261746f72206461746120746f6f206c61726765000000000000000000910152565b6134536017602092610895565b61345c8161341f565b0190565b6134759060208101905f818303910152613446565b90565b1561347f57565b6134876100d2565b62461bcd60e51b81528061349d60048201613460565b0390fd5b6134e6906134c1816134bb6134b55f6111e5565b91610454565b116133da565b6134df6134d96134d45f6102080161243f565b613403565b91610454565b1115613478565b565b6134fc6134f761350192610168565b610920565b610454565b90565b6135239061351d61351761352894610454565b91610454565b90610b47565b610454565b90565b61355290613537610bb1565b509161354d6135476001926134e8565b9161229a565b613504565b1790565b5f90565b613562613556565b506135716001610209016113fa565b61358361357d5f6111e5565b91610454565b141590565b613590613556565b5061359e5f61020b01610888565b6135b86135b26135ad5f611dff565b61031f565b9161031f565b141590565b6135d1906135c9613556565b509119610454565b166135e46135de5f6111e5565b91610454565b1490565b6135fa906135f4610bb1565b5061386d565b90565b61362490613609613556565b509161361f6136196001926134e8565b9161229a565b613504565b166136376136315f6111e5565b91610454565b1490565b61366290613647613556565b509161365d6136576001926134e8565b9161229a565b613504565b1661367561366f5f6111e5565b91610454565b141590565b6136a46136aa91613689610bb1565b509261369f6136996001926134e8565b9161229a565b613504565b19610454565b1690565b90565b6136c56136c06136ca926136ae565b610920565b610454565b90565b90565b6136e46136df6136e9926136cd565b610920565b610168565b90565b61370b906137056136ff61371094610168565b91610454565b90610b47565b610454565b90565b6137329061372c61372661373794610454565b91610454565b90610c3f565b610454565b90565b90565b61375161374c6137569261373a565b610920565b610454565b90565b90565b61377061376b61377592613759565b610920565b610168565b90565b90565b61378f61378a61379492613778565b610920565b610454565b90565b90565b6137ae6137a96137b392613797565b610920565b610168565b90565b90565b6137cd6137c86137d2926137b6565b610920565b610454565b90565b90565b6137ec6137e76137f1926137d5565b610920565b610168565b90565b90565b61380b613806613810926137f4565b610920565b610454565b90565b90565b61382a61382561382f92613813565b610920565b610168565b90565b90565b61384961384461384e92613832565b610920565b610454565b90565b61386561386061386a92611844565b610920565b610168565b90565b613875610bb1565b506138b56138a58261389f6138996fffffffffffffffffffffffffffffffff6136b1565b91610454565b11613a02565b6138af60076136d0565b906136ec565b6138f66138e66138c6848490613713565b6138e06138da67ffffffffffffffff61373d565b91610454565b11613a02565b6138f0600661375c565b906136ec565b17613934613924613908848490613713565b61391e61391863ffffffff61377b565b91610454565b11613a02565b61392e600561379a565b906136ec565b17613970613960613946848490613713565b61395a61395461ffff6137b9565b91610454565b11613a02565b61396a60046137d8565b906136ec565b176139ab61399b613982848490613713565b61399561398f60ff6137f7565b91610454565b11613a02565b6139a56003613816565b906136ec565b176139e66139d66139bd848490613713565b6139d06139ca600f613835565b91610454565b11613a02565b6139e06002613851565b906136ec565b17906d010102020202030303030303030360801b90821c1a1790565b613a0a610bb1565b5015159056fea2646970667358221220bc4a2db5c2380b433af49bee3a9ba8346459244bbf4bf330a5ad42faf155a8c364736f6c634300081c0033","sourceMap":"993:7551:24:-:0;;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;:::i;:::-;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;:::i;:::-;;;;;;;;;;:::o;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;:::o;:::-;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;:::o;:::-;;;:::o;:::-;;:::o;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;:::o;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;:::i;:::-;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;:::o;:::-;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;:::i;:::-;:::o;:::-;;;;:::o;:::-;;:::o;:::-;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;:::o;:::-;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;:::o;:::-;;;;;;;:::o;:::-;;;:::o;:::-;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;:::i;:::-;;;;;:::i;:::-;;;:::o;:::-;;;:::o;:::-;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;;;;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;:::o;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;:::i;:::-;;;;;;:::o;:::-;;;;;:::i;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;;;;:::i;:::-;:::o;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;:::o;:::-;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;:::o;:::-;;:::i;1315:800::-;1510:26;1315:800;1410:61;1418:23;:16;:23;:::i;:::-;:30;;1445:3;1418:30;:::i;:::-;;;:::i;:::-;;;1410:61;:::i;:::-;1482:18;1490:10;1482:18;;:::i;:::-;1510:26;;:::i;:::-;1568:13;1580:1;1568:13;:::i;:::-;1612:3;1583:1;:27;;1587:23;:16;:23;:::i;:::-;1583:27;:::i;:::-;;;:::i;:::-;;;;;1612:3;1656:16;:31;;:24;:19;:16;1673:1;1656:19;;:::i;:::-;;:24;;:31;:::i;:::-;;:::i;:::-;1702:87;1710:56;1711:55;;:47;:13;;:21;1733:24;:16;:19;:16;1750:1;1733:19;;:::i;:::-;;:24;;:::i;:::-;1711:47;;:::i;:::-;:55;;:::i;:::-;1710:56;;:::i;:::-;1702:87;:::i;:::-;1804:94;1874:4;1854:44;1887:8;1893:1;1887:8;:::i;:::-;1854:44;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::i;:::-;1804:47;:21;:13;:21;1826:24;;:19;:16;1843:1;1826:19;;:::i;:::-;;:24;;:::i;:::-;1804:47;;:::i;:::-;:94;:::i;:::-;1912:44;1937:19;:16;1954:1;1937:19;;:::i;:::-;;1912:22;:19;:13;:19;1932:1;1912:22;;:::i;:::-;:44;;:::i;:::-;1612:3;:::i;:::-;1568:13;;1583:27;;2001:44;2014:30;2020:23;1977:68;1583:27;2020:23;:::i;:::-;2014:30;:::i;:::-;2001:44;:::i;:::-;1977:21;:13;:21;:68;:::i;:::-;2055:53;2087:21;;:13;:21;;:::i;:::-;2055:29;:12;:9;2065:1;2055:12;;:::i;:::-;;:29;:53;:::i;:::-;1315:800::o;993:7551::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;8083:205;8207:74;8083:205;8156:41;8164:5;:9;;8172:1;8164:9;:::i;:::-;;;:::i;:::-;;8156:41;:::i;:::-;8215:38;;8224:29;;:8;:29;;:::i;:::-;8215:38;:::i;:::-;;;:::i;:::-;;;8207:74;:::i;:::-;8083:205::o;993:7551::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;:::o;:::-;;:::i;9237:101::-;9311:15;9310:21;9237:101;9283:7;;:::i;:::-;9311:1;:15;9316:10;9311:1;9324;9316:10;:::i;:::-;9311:15;;:::i;:::-;;:::i;:::-;9310:21;9330:1;9310:21;:::i;:::-;;;:::i;:::-;9303:28;:::o","linkReferences":{}},"deployedBytecode":{"object":"0x60806040526004361015610013575b6107fc565b61001d5f356100cc565b806326322217146100c75780632b726062146100c257806347011c5c146100bd57806353bfb584146100b857806365706f9c146100b357806375418b9d146100ae5780639d44e717146100a9578063c05665dd146100a4578063e88e97491461009f578063f2fde38b1461009a5763f5f2d9f10361000e576107c9565b610796565b610763565b610730565b6106bc565b610646565b6102e1565b61027d565b61023b565b6101d6565b610135565b60e01c90565b60405190565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b908160409103126100f65790565b6100e4565b9060208282031261012b575f82013567ffffffffffffffff81116101265761012392016100e8565b90565b6100e0565b6100dc565b5f0190565b346101635761014d6101483660046100fb565b610f6e565b6101556100d2565b8061015f81610130565b0390f35b6100d8565b60ff1690565b61017781610168565b0361017e57565b5f80fd5b9050359061018f8261016e565b565b9190916040818403126101d1576101aa835f8301610182565b92602082013567ffffffffffffffff81116101cc576101c992016100e8565b90565b6100e0565b6100dc565b34610205576101ef6101e9366004610191565b906115ec565b6101f76100d2565b8061020181610130565b0390f35b6100d8565b908160409103126102185790565b6100e4565b9060408282031261023657610233915f0161020a565b90565b6100dc565b346102695761025361024e36600461021d565b611d3c565b61025b6100d2565b8061026581610130565b0390f35b6100d8565b5f91031261027857565b6100dc565b346102ab5761028d36600461026e565b610295611ef1565b61029d6100d2565b806102a781610130565b0390f35b6100d8565b908160209103126102be5790565b6100e4565b906020828203126102dc576102d9915f016102b0565b90565b6100dc565b3461030f576102f96102f43660046102c3565b612097565b6103016100d2565b8061030b81610130565b0390f35b6100d8565b60018060a01b031690565b61032890610314565b90565b6103349061031f565b9052565b5190565b60209181520190565b60200190565b5190565b60209181520190565b90825f9392825e0152565b601f801991011690565b61038c61039560209361039a936103838161034b565b9384809361034f565b95869101610358565b610363565b0190565b6103c991602060408201926103b95f8201515f85019061032b565b015190602081840391015261036d565b90565b906103d69161039e565b90565b60200190565b906103f36103ec83610338565b809261033c565b908161040460208302840194610345565b925f915b83831061041757505050505090565b90919293946020610439610433838560019503875289516103cc565b976103d9565b9301930191939290610408565b50600290565b905090565b90565b90565b61046090610454565b9052565b61046d90610168565b9052565b90602080610493936104895f8201515f860190610457565b0151910190610464565b565b906104a281604093610471565b0190565b60200190565b6104c86104c26104bb83610446565b809461044c565b91610451565b5f915b8383106104d85750505050565b6104ee6104e86001928451610495565b926104a6565b920191906104cb565b67ffffffffffffffff1690565b61050d906104f7565b9052565b61ffff1690565b61052190610511565b9052565b905f80610536930151910190610518565b565b9060208061055a936105505f8201515f860190610504565b0151910190610457565b565b905f8061056d93015191019061032b565b565b6fffffffffffffffffffffffffffffffff1690565b61058d9061056f565b9052565b9061062b9061016060e06105c561018084016105b35f8801515f87019061032b565b602087015185820360208701526103df565b946105d8604082015160408601906104ac565b6105ea606082015160c0860190610504565b6105fb608082015183860190610525565b61060e60a0820151610100860190610538565b61062160c082015161014086019061055c565b0151910190610584565b90565b6106439160208201915f818403910152610591565b90565b346106765761065636600461026e565b61067261066161266b565b6106696100d2565b9182918261062e565b0390f35b6100d8565b610684816104f7565b0361068b57565b5f80fd5b9050359061069c8261067b565b565b906020828203126106b7576106b4915f0161068f565b90565b6100dc565b346106ea576106d46106cf36600461069e565b612bde565b6106dc6100d2565b806106e681610130565b0390f35b6100d8565b6106f88161031f565b036106ff57565b5f80fd5b90503590610710826106ef565b565b9060208282031261072b57610728915f01610703565b90565b6100dc565b3461075e57610748610743366004610712565b61305a565b6107506100d2565b8061075a81610130565b0390f35b6100d8565b346107915761077b61077636600461069e565b6131bc565b6107836100d2565b8061078d81610130565b0390f35b6100d8565b346107c4576107ae6107a9366004610712565b613264565b6107b66100d2565b806107c081610130565b0390f35b6100d8565b346107f7576107d936600461026e565b6107e1613377565b6107e96100d2565b806107f381610130565b0390f35b6100d8565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b90359060016020038136030382121561084e570180359067ffffffffffffffff82116108495760200191600182023603831361084457565b610808565b610804565b610800565b5090565b35610861816106ef565b90565b5f1c90565b60018060a01b031690565b61088061088591610864565b610869565b90565b6108929054610874565b90565b60209181520190565b5f7f756e617574686f72697a65640000000000000000000000000000000000000000910152565b6108d2600c602092610895565b6108db8161089e565b0190565b6108f49060208101905f8183039101526108c5565b90565b156108fe57565b6109066100d2565b62461bcd60e51b81528061091c600482016108df565b0390fd5b90565b61093761093261093c92610314565b610920565b610314565b90565b61094890610923565b90565b6109549061093f565b90565b906109619061094b565b5f5260205260405f2090565b90565b60ff1690565b61098261098791610864565b610970565b90565b6109949054610976565b90565b5f7f756e6b6e6f776e206f70657261746f7200000000000000000000000000000000910152565b6109cb6010602092610895565b6109d481610997565b0190565b6109ed9060208101905f8183039101526109be565b90565b156109f757565b6109ff6100d2565b62461bcd60e51b815280610a15600482016109d8565b0390fd5b60081c90565b60ff1690565b610a31610a3691610a19565b610a1f565b90565b610a439054610a25565b90565b634e487b7160e01b5f52603260045260245ffd5b5061010090565b90565b610a6d81610a5a565b821015610a8757610a7f600291610a61565b910201905f90565b610a46565b634e487b7160e01b5f525f60045260245ffd5b5f1b90565b90610ab560018060a01b0391610a9f565b9181191691161790565b90565b90610ad7610ad2610ade9261094b565b610abf565b8254610aa4565b9055565b634e487b7160e01b5f52604160045260245ffd5b634e487b7160e01b5f52602260045260245ffd5b9060016002830492168015610b2a575b6020831014610b2557565b610af6565b91607f1691610b1a565b5f5260205f2090565b601f602091010490565b1b90565b91906008610b66910291610b605f1984610b47565b92610b47565b9181191691161790565b610b84610b7f610b8992610454565b610920565b610454565b90565b90565b9190610ba5610ba0610bad93610b70565b610b8c565b908354610b4b565b9055565b5f90565b610bc791610bc1610bb1565b91610b8f565b565b5b818110610bd5575050565b80610be25f600193610bb5565b01610bca565b9190601f8111610bf8575b505050565b610c04610c2993610b34565b906020610c1084610b3d565b83019310610c31575b610c2290610b3d565b0190610bc9565b5f8080610bf3565b9150610c2281929050610c19565b1c90565b90610c53905f1990600802610c3f565b191690565b81610c6291610c43565b906002021790565b91610c759082610853565b9067ffffffffffffffff8211610d3457610c9982610c938554610b0a565b85610be8565b5f90601f8311600114610ccc57918091610cbb935f92610cc0575b5050610c58565b90555b565b90915001355f80610cb4565b601f19831691610cdb85610b34565b925f5b818110610d1c57509160029391856001969410610d02575b50505002019055610cbe565b610d12910135601f841690610c43565b90555f8080610cf6565b91936020600181928787013581550195019201610cde565b610ae2565b90610d449291610c6a565b565b90610d736001610d7993610d675f8201610d615f8701610857565b90610ac2565b0191602081019061080c565b91610d39565b565b9190610d8c57610d8a91610d46565b565b610a8c565b6fffffffffffffffffffffffffffffffff1690565b610db2610db791610864565b610d91565b90565b610dc49054610da6565b90565b634e487b7160e01b5f52601160045260245ffd5b610de49061056f565b6fffffffffffffffffffffffffffffffff8114610e015760010190565b610dc7565b90610e216fffffffffffffffffffffffffffffffff91610a9f565b9181191691161790565b610e3f610e3a610e449261056f565b610920565b61056f565b90565b90565b90610e5f610e5a610e6692610e2b565b610e47565b8254610e06565b9055565b50610e79906020810190610703565b90565b5f80fd5b5f80fd5b5f80fd5b9035600160200382360303811215610ec957016020813591019167ffffffffffffffff8211610ec4576001820236038313610ebf57565b610e80565b610e7c565b610e84565b90825f939282370152565b9190610ef381610eec81610ef89561034f565b8095610ece565b610363565b0190565b610f3891610f2a6040820192610f20610f175f830183610e6a565b5f85019061032b565b6020810190610e88565b916020818503910152610ed9565b90565b610f449061056f565b9052565b92916020610f64610f6c9360408701908782035f890152610efc565b940190610f3b565b565b610f8d610f88610f8283602081019061080c565b90610853565b6134a1565b33610faa610fa4610f9f5f8501610857565b61031f565b9161031f565b148015611075575b610fbb906108f7565b611011610fde610fd95f600101610fd35f8601610857565b90610957565b61096d565b610ff1610fec5f830161098a565b6109f0565b61100b83916110055f600180019201610a39565b90610a64565b90610d7b565b61102f61102761102261020c610dba565b610ddb565b61020c610e4a565b61103a61020c610dba565b7f5aab2c32b1e447db4dba1d2790fe8b863d4775042b10b92e00dab9d6b671b5b5916110706110676100d2565b92839283610f48565b0390a1565b50610fbb3361109461108e6110895f610888565b61031f565b9161031f565b149050610fb2565b5f7f6e6f7420746865206f776e657200000000000000000000000000000000000000910152565b6110d0600d602092610895565b6110d98161109c565b0190565b6110f29060208101905f8183039101526110c3565b90565b156110fc57565b6111046100d2565b62461bcd60e51b81528061111a600482016110dd565b0390fd5b9061114c916111473361114161113b6111365f610888565b61031f565b9161031f565b146110f5565b61147f565b565b151590565b5f7f616c726561647920657869737473000000000000000000000000000000000000910152565b611187600e602092610895565b61119081611153565b0190565b6111a99060208101905f81830391015261117a565b90565b156111b357565b6111bb6100d2565b62461bcd60e51b8152806111d160048201611194565b0390fd5b6111df9054610b0a565b90565b90565b6111f96111f46111fe926111e2565b610920565b610454565b90565b5f7f736c6f74206f6363757069656400000000000000000000000000000000000000910152565b611235600d602092610895565b61123e81611201565b0190565b6112579060208101905f818303910152611228565b90565b1561126157565b6112696100d2565b62461bcd60e51b81528061127f60048201611242565b0390fd5b9061128d90610363565b810190811067ffffffffffffffff8211176112a757604052565b610ae2565b906112bf6112b86100d2565b9283611283565b565b6112cb60406112ac565b90565b906112d89061114e565b9052565b906112e690610168565b9052565b6112f4905161114e565b90565b9061130360ff91610a9f565b9181191691161790565b6113169061114e565b90565b90565b9061133161132c6113389261130d565b611319565b82546112f7565b9055565b6113469051610168565b90565b60081b90565b9061135c61ff0091611349565b9181191691161790565b61137a61137561137f92610168565b610920565b610168565b90565b90565b9061139a6113956113a192611366565b611382565b825461134f565b9055565b906113cf60205f6113d5946113c78282016113c18488016112ea565b9061131c565b01920161133c565b90611385565b565b906113e1916113a5565b565b90565b6113f26113f791610864565b6113e3565b90565b61140490546113e6565b90565b906114135f1991610a9f565b9181191691161790565b9061143261142d61143992610b70565b610b8c565b8254611407565b9055565b61144690610168565b9052565b93929061147560409161147d9461146860608901925f8a019061143d565b8782036020890152610efc565b940190610f3b565b565b61149e61149961149384602081019061080c565b90610853565b6134a1565b6114d16114cc6114c65f6114c0816001016114ba838901610857565b90610957565b0161098a565b1561114e565b6111ac565b6115056114ed60016114e68180018590610a64565b50016111d5565b6114ff6114f95f6111e5565b91610454565b1461125a565b611548600161152b836115226115196112c1565b935f85016112ce565b602083016112dc565b6115435f60010161153d5f8701610857565b90610957565b6113d7565b6115608261155a600180018490610a64565b90610d7b565b61158661157b6115746102016001016113fa565b839061352b565b61020160010161141d565b6115a461159c61159761020c610dba565b610ddb565b61020c610e4a565b906115b061020c610dba565b916115e77f952e65f049c574f487580ba41dcf6b0ea8350ef8abc8647a8a11dfaa7af6bad6936115de6100d2565b9384938461144a565b0390a1565b906115f69161111e565b565b611625906116203361161a61161461160f5f610888565b61031f565b9161031f565b146110f5565b6116a9565b565b5f7f6d6967726174696f6e20696e2070726f67726573730000000000000000000000910152565b61165b6015602092610895565b61166481611627565b0190565b61167d9060208101905f81830391015261164e565b90565b1561168757565b61168f6100d2565b62461bcd60e51b8152806116a560048201611668565b0390fd5b6116cb906116c66116c16116bb61355a565b1561114e565b611680565b61174f565b565b5f7f6d61696e74656e616e636520696e2070726f6772657373000000000000000000910152565b6117016017602092610895565b61170a816116cd565b0190565b6117239060208101905f8183039101526116f4565b90565b1561172d57565b6117356100d2565b62461bcd60e51b81528061174b6004820161170e565b0390fd5b6117719061176c611767611761613588565b1561114e565b611726565b611b76565b565b61177c81610454565b0361178357565b5f80fd5b3561179181611773565b90565b5f7f696e76616c6964206269746d61736b0000000000000000000000000000000000910152565b6117c8600f602092610895565b6117d181611794565b0190565b6117ea9060208101905f8183039101526117bb565b90565b156117f457565b6117fc6100d2565b62461bcd60e51b815280611812600482016117d5565b0390fd5b67ffffffffffffffff1690565b61182f61183491610864565b611816565b90565b6118419054611823565b90565b90565b61185b61185661186092611844565b610920565b6104f7565b90565b634e487b7160e01b5f52601260045260245ffd5b611883611889916104f7565b916104f7565b908115611894570690565b611863565b50600290565b90565b6118ab81611899565b8210156118c5576118bd60029161189f565b910201905f90565b610a46565b906118d490610454565b9052565b6118e46118e991610864565b610a1f565b90565b6118f690546118d8565b90565b61190360406112ac565b90565b9061193d61193460016119176118f9565b9461192e6119265f83016113fa565b5f88016118ca565b016118ec565b602084016112dc565b565b61194890611906565b90565b6119559051610454565b90565b356119628161016e565b90565b5f7f73616d65206b6579737061636500000000000000000000000000000000000000910152565b611999600d602092610895565b6119a281611965565b0190565b6119bb9060208101905f81830391015261198c565b90565b156119c557565b6119cd6100d2565b62461bcd60e51b8152806119e3600482016119a6565b0390fd5b6119f0906104f7565b67ffffffffffffffff8114611a055760010190565b610dc7565b90611a1d67ffffffffffffffff91610a9f565b9181191691161790565b611a3b611a36611a40926104f7565b610920565b6104f7565b90565b90565b90611a5b611a56611a6292611a27565b611a43565b8254611a0a565b9055565b90611a7b611a76611a8292611366565b611382565b82546112f7565b9055565b90611ab160206001611ab794611aa95f8201611aa35f8801611787565b9061141d565b019201611958565b90611a66565b565b9190611aca57611ac891611a86565b565b610a8c565b611ad8906104f7565b9052565b90503590611ae982611773565b565b50611afa906020810190611adc565b90565b50611b0c906020810190610182565b90565b906020611b3a611b4293611b31611b285f830183611aeb565b5f860190610457565b82810190611afd565b910190610464565b565b606090611b6d611b749496959396611b6360808401985f850190611acf565b6020830190611b0f565b0190610f3b565b565b611ba0611b9b611b875f8401611787565b611b956102016001016113fa565b906135bd565b6117ed565b611c0d611bd6611bd0610203611bca611bba610207611837565b611bc46002611847565b90611877565b906118a2565b5061193f565b611be15f820161194b565b611bfd611bf7611bf25f8701611787565b610454565b91610454565b1415908115611d0a575b506119be565b611c2c5f61020901611c26611c2182611837565b6119e7565b90611a46565b611c4a611c42611c3d610207611837565b6119e7565b610207611a46565b611c7e81611c78610203611c72611c62610207611837565b611c6c6002611847565b90611877565b906118a2565b90611ab9565b611c97611c8c5f8301611787565b60016102090161141d565b611cb5611cad611ca861020c610dba565b610ddb565b61020c610e4a565b611cc25f61020901611837565b90611cce61020c610dba565b91611d057f490341fd8fc7a8294fbad1cc0db9f41ae0ac5aeb655ea31b46a475ec3a77749c93611cfc6100d2565b93849384611b44565b0390a1565b611d17915060200161133c565b611d34611d2e611d2960208601611958565b610168565b91610168565b14155f611c07565b611d45906115f8565b565b5f7f6e6f206d61696e74656e616e6365000000000000000000000000000000000000910152565b611d7b600e602092610895565b611d8481611d47565b0190565b611d9d9060208101905f818303910152611d6e565b90565b15611da757565b611daf6100d2565b62461bcd60e51b815280611dc560048201611d88565b0390fd5b611dd9611dd4613588565b611da0565b611de1611e20565b565b611df7611df2611dfc926111e2565b610920565b610314565b90565b611e0890611de3565b90565b9190611e1e905f60208501940190610f3b565b565b611e2d5f61020b01610888565b611e3f611e393361031f565b9161031f565b148015611eca575b611e50906108f7565b611e66611e5c5f611dff565b5f61020b01610ac2565b611e84611e7c611e7761020c610dba565b610ddb565b61020c610e4a565b611e8f61020c610dba565b611ec57f11943d6deda6f0591d72674788d272eb0209e18b8a3a021fa51cb3b5e9a2ab6191611ebc6100d2565b91829182611e0b565b0390a1565b50611e5033611ee9611ee3611ede5f610888565b61031f565b9161031f565b149050611e47565b611ef9611dc9565b565b611f2890611f2333611f1d611f17611f125f610888565b61031f565b9161031f565b146110f5565b612027565b565b611f3381610511565b03611f3a57565b5f80fd5b35611f4881611f2a565b90565b90611f5861ffff91610a9f565b9181191691161790565b611f76611f71611f7b92610511565b610920565b610511565b90565b90565b90611f96611f91611f9d92611f62565b611f7e565b8254611f4b565b9055565b90611fb35f80611fb994019201611f3e565b90611f81565b565b90611fc591611fa1565b565b90503590611fd482611f2a565b565b50611fe5906020810190611fc7565b90565b905f611ffa6120029382810190611fd6565b910190610518565b565b91602061202592949361201e60408201965f830190611fe8565b0190610f3b565b565b61203381610208611fbb565b61205161204961204461020c610dba565b610ddb565b61020c610e4a565b61205c61020c610dba565b7fb24d8d9dcfbb6be13176c1c7bfb0e76445a9ba2a3553b413d8671446f1030830916120926120896100d2565b92839283612004565b0390a1565b6120a090611efb565b565b6120ad6101006112ac565b90565b5f90565b606090565b67ffffffffffffffff81116120ce5760200290565b610ae2565b6120df6120e4916120b9565b6112ac565b90565b5f90565b5f90565b6120f76118f9565b90602080836121046120e7565b81520161210f6120eb565b81525050565b61211d6120ef565b90565b5f5b82811061212e57505050565b602090612139612115565b8184015201612122565b90612161612150836120d3565b9261215b84916120b9565b90612120565b565b61216d6002612143565b90565b5f90565b61217e60206112ac565b90565b5f90565b61218d612174565b90602082612199612181565b81525050565b6121a7612185565b90565b6121b460406112ac565b90565b6121bf6121aa565b90602080836121cc612170565b8152016121d76120e7565b81525050565b6121e56121b7565b90565b6121f260206112ac565b90565b6121fd6121e8565b906020826122096120b0565b81525050565b6122176121f5565b90565b5f90565b6122266120a2565b90602080808080808080896122396120b0565b8152016122446120b4565b81520161224f612163565b81520161225a612170565b81520161226561219f565b8152016122706121dd565b81520161227b61220f565b81520161228661221a565b81525050565b61229461221e565b90565b90565b6122ae6122a96122b392612297565b610920565b610454565b90565b6122c56122cb91939293610454565b92610454565b82018092116122d657565b610dc7565b67ffffffffffffffff81116122f35760208091020190565b610ae2565b9061230a612305836122db565b6112ac565b918252565b61231960406112ac565b90565b606090565b61232961230f565b90602080836123366120b0565b81520161234161231c565b81525050565b61234f612321565b90565b5f5b82811061236057505050565b60209061236b612347565b8184015201612354565b9061239a612382836122f8565b9260208061239086936122db565b9201910390612352565b565b6123a76101006112ac565b90565b906123b49061031f565b9052565b52565b906123c582611899565b6123ce816120d3565b926123d9849161189f565b5f915b8383106123e95750505050565b600260206001926123f98561193f565b8152019201920191906123dc565b612410906123bb565b90565b52565b90612420906104f7565b9052565b61ffff1690565b61243761243c91610864565b612424565b90565b612449905461242b565b90565b9061245690610511565b9052565b906124796124715f61246a612174565b940161243f565b5f840161244c565b565b6124849061245a565b90565b52565b906124c16124b8600161249b6121aa565b946124b26124aa5f8301611837565b5f8801612416565b016113fa565b602084016118ca565b565b6124cc9061248a565b90565b52565b906124f16124e95f6124e26121e8565b9401610888565b5f84016123aa565b565b6124fc906124d2565b90565b52565b9061250c9061056f565b9052565b61251990610454565b5f1981146125275760010190565b610dc7565b61254061253b61254592610454565b610920565b610168565b90565b9061255282610338565b811015612563576020809102010190565b610a46565b905f929180549061258261257b83610b0a565b809461034f565b916001811690815f146125d9575060011461259d575b505050565b6125aa9192939450610b34565b915f925b8184106125c157505001905f8080612598565b600181602092959395548486015201910192906125ae565b92949550505060ff19168252151560200201905f8080612598565b906125fe91612568565b90565b9061262161261a926126116100d2565b938480926125f4565b0383611283565b565b52565b9061265d612654600161263761230f565b9461264e6126465f8301610888565b5f88016123aa565b01612601565b60208401612623565b565b61266890612626565b90565b61267361228c565b50600161020101612683906113fa565b61268c906135e8565b6126955f610888565b8160016126a19061229a565b6126aa916122b6565b6126b390612375565b6102036126c1610207611837565b6102086102099161020b936126d761020c610dba565b956126e061239c565b975f8901906126ee916123aa565b60208801906126fc916123b8565b61270590612407565b604087019061271391612413565b606086019061272191612416565b61272a9061247b565b608085019061273891612487565b612741906124c3565b60a084019061274f916124cf565b612758906124f3565b60c0830190612766916124ff565b60e082019061277491612502565b600161020101612783906113fa565b925f61278e906111e5565b5b806127a261279c86610454565b91610454565b11612805576127fb906127be866127b88361252c565b906135fd565b612800576127f36127d3600180018390610a64565b5060208601516127e3849261265f565b6127ed8383612548565b52612548565b51505b612510565b61278f565b6127f6565b509250905090565b5f7f6e6f206d6967726174696f6e0000000000000000000000000000000000000000910152565b612841600c602092610895565b61284a8161280d565b0190565b6128639060208101905f818303910152612834565b90565b1561286d57565b6128756100d2565b62461bcd60e51b81528061288b6004820161284e565b0390fd5b6128a8906128a361289e61355a565b612866565b612a3e565b565b5f7f77726f6e67206d6967726174696f6e2069640000000000000000000000000000910152565b6128de6012602092610895565b6128e7816128aa565b0190565b6129009060208101905f8183039101526128d1565b90565b1561290a57565b6129126100d2565b62461bcd60e51b815280612928600482016128eb565b0390fd5b61293660406112ac565b90565b9061296f6129665f61294961292c565b9461296061295883830161098a565b8388016112ce565b01610a39565b602084016112dc565b565b61297a90612939565b90565b5f7f6e6f742070756c6c696e67000000000000000000000000000000000000000000910152565b6129b1600b602092610895565b6129ba8161297d565b0190565b6129d39060208101905f8183039101526129a4565b90565b156129dd57565b6129e56100d2565b62461bcd60e51b8152806129fb600482016129be565b0390fd5b612a089061031f565b9052565b604090612a35612a3c9496959396612a2b60608401985f850190611acf565b60208301906129ff565b0190610f3b565b565b612a6690612a60612a5a612a555f61020901611837565b6104f7565b916104f7565b14612903565b612aeb612ae0612a82612a7d5f6001013390610957565b612971565b612a95612a905f83016112ea565b6109f0565b612ac0612abb612aa96001610209016113fa565b612ab56020850161133c565b9061363b565b6129d6565b612ada6020612ad36001610209016113fa565b920161133c565b9061367a565b60016102090161141d565b612b09612b01612afc61020c610dba565b610ddb565b61020c610e4a565b612b176001610209016113fa565b612b29612b235f6111e5565b91610454565b145f14612b8657612b3d5f61020901611837565b33612b4961020c610dba565b91612b807f01269879535f40ee8957e15e160bf1866c5e2728ff0cbc583d848821e2639b4e93612b776100d2565b93849384612a0c565b0390a15b565b612b935f61020901611837565b33612b9f61020c610dba565b91612bd67faf5e90e72015f43138f66b4cd08bd1dfa2839030104f22a00af843fe847c6d1993612bcd6100d2565b93849384612a0c565b0390a1612b84565b612be79061288f565b565b612c1690612c1133612c0b612c05612c005f610888565b61031f565b9161031f565b146110f5565b612eb7565b565b5f7f696e206b65797370616365000000000000000000000000000000000000000000910152565b612c4c600b602092610895565b612c5581612c18565b0190565b612c6e9060208101905f818303910152612c3f565b90565b15612c7857565b612c806100d2565b62461bcd60e51b815280612c9660048201612c59565b0390fd5b5f80910155565b905f03612cb357612cb190612c9a565b565b610a8c565b90612ccb905f1990602003600802610c3f565b8154169055565b905f91612ce9612ce182610b34565b928354610c58565b905555565b919290602082105f14612d4757601f8411600114612d1757612d11929350610c58565b90555b5b565b5090612d3d612d42936001612d34612d2e85610b34565b92610b3d565b82019101610bc9565b612cd2565b612d14565b50612d7e8293612d58600194610b34565b612d77612d6485610b3d565b820192601f861680612d89575b50610b3d565b0190610bc9565b600202179055612d15565b612d9590888603612cb8565b5f612d71565b929091680100000000000000008211612dfb576020115f14612dec57602081105f14612dd057612dca91610c58565b90555b5b565b60019160ff1916612de084610b34565b55600202019055612dcd565b60019150600202019055612dce565b610ae2565b908154612e0c81610b0a565b90818311612e35575b818310612e23575b50505050565b612e2c93612cee565b5f808080612e1d565b612e4183838387612d9b565b612e15565b5f612e5091612e00565b565b905f03612e6457612e6290612e46565b565b610a8c565b5f6001612e7b92828082015501612e52565b565b905f03612e8f57612e8d90612e69565b565b610a8c565b916020612eb5929493612eae60408201965f8301906129ff565b0190610f3b565b565b612f7c612f71612ef05f612ed7612ed2826001018790610957565b61096d565b612eea612ee583830161098a565b6109f0565b01610a39565b612ef861355a565b5f1461300e57612f20612f195f612f1261020382906118a2565b50016113fa565b82906135fd565b80612fe0575b612f2f90612c71565b5b612f475f612f42816001018790610957565b612ca1565b612f5e612f58600180018390610a64565b90612e7d565b612f6c6102016001016113fa565b61367a565b61020160010161141d565b612f9a612f92612f8d61020c610dba565b610ddb565b61020c610e4a565b612fa561020c610dba565b7f6a1d7ddc82d57e783a3ae60737a6c1a4704fcf38d966561fea0af8564f2d895d91612fdb612fd26100d2565b92839283612e94565b0390a1565b50612f2f6130076130005f612ff96102036001906118a2565b50016113fa565b83906135fd565b9050612f26565b6130556130506130495f61304261020361303c61302c610207611837565b6130366002611847565b90611877565b906118a2565b50016113fa565b83906135fd565b612c71565b612f30565b61306390612be9565b565b6130929061308d3361308761308161307c5f610888565b61031f565b9161031f565b146110f5565b613094565b565b6130ad906130a86130a361355a565b612866565b6130ee565b565b6130b8906104f7565b5f81146130c6576001900390565b610dc7565b9160206130ec9294936130e560408201965f830190611acf565b0190610f3b565b565b6131169061311061310a6131055f61020901611837565b6104f7565b916104f7565b14612903565b61313461312c613127610207611837565b6130af565b610207611a46565b61314b6131405f6111e5565b60016102090161141d565b61316961316161315c61020c610dba565b610ddb565b61020c610e4a565b6131765f61020901611837565b61318161020c610dba565b7ff73240422246f63ed633ef3ce0726b8ab8fb69d46c8a4e5ecb0b2922668674a1916131b76131ae6100d2565b928392836130cb565b0390a1565b6131c590613065565b565b6131f4906131ef336131e96131e36131de5f610888565b61031f565b9161031f565b146110f5565b6131f6565b565b613200815f610ac2565b61321e61321661321161020c610dba565b610ddb565b61020c610e4a565b61322961020c610dba565b7f476610ebc6647c15376100955efbf22ef2a0c3b923fc00b380b660c873ef20ac9161325f6132566100d2565b92839283612e94565b0390a1565b61326d906131c7565b565b61328861328361327d61355a565b1561114e565b611680565b613290613292565b565b6132ab6132a66132a0613588565b1561114e565b611726565b6132b36132b5565b565b6132cd5f6132c7816001013390610957565b0161098a565b8015613350575b6132dd906108f7565b6132eb335f61020b01610ac2565b6133096133016132fc61020c610dba565b610ddb565b61020c610e4a565b3361331561020c610dba565b7fbc2748cf02f7a1291525e866efc76ab3b96d32d7afcbb26c53daec617b38b4799161334b6133426100d2565b92839283612e94565b0390a1565b506132dd3361336f6133696133645f610888565b61031f565b9161031f565b1490506132d4565b61337f61326f565b565b5f7f656d707479206f70657261746f72206461746100000000000000000000000000910152565b6133b56013602092610895565b6133be81613381565b0190565b6133d79060208101905f8183039101526133a8565b90565b156133e157565b6133e96100d2565b62461bcd60e51b8152806133ff600482016133c2565b0390fd5b61341761341261341c92610511565b610920565b610454565b90565b5f7f6f70657261746f72206461746120746f6f206c61726765000000000000000000910152565b6134536017602092610895565b61345c8161341f565b0190565b6134759060208101905f818303910152613446565b90565b1561347f57565b6134876100d2565b62461bcd60e51b81528061349d60048201613460565b0390fd5b6134e6906134c1816134bb6134b55f6111e5565b91610454565b116133da565b6134df6134d96134d45f6102080161243f565b613403565b91610454565b1115613478565b565b6134fc6134f761350192610168565b610920565b610454565b90565b6135239061351d61351761352894610454565b91610454565b90610b47565b610454565b90565b61355290613537610bb1565b509161354d6135476001926134e8565b9161229a565b613504565b1790565b5f90565b613562613556565b506135716001610209016113fa565b61358361357d5f6111e5565b91610454565b141590565b613590613556565b5061359e5f61020b01610888565b6135b86135b26135ad5f611dff565b61031f565b9161031f565b141590565b6135d1906135c9613556565b509119610454565b166135e46135de5f6111e5565b91610454565b1490565b6135fa906135f4610bb1565b5061386d565b90565b61362490613609613556565b509161361f6136196001926134e8565b9161229a565b613504565b166136376136315f6111e5565b91610454565b1490565b61366290613647613556565b509161365d6136576001926134e8565b9161229a565b613504565b1661367561366f5f6111e5565b91610454565b141590565b6136a46136aa91613689610bb1565b509261369f6136996001926134e8565b9161229a565b613504565b19610454565b1690565b90565b6136c56136c06136ca926136ae565b610920565b610454565b90565b90565b6136e46136df6136e9926136cd565b610920565b610168565b90565b61370b906137056136ff61371094610168565b91610454565b90610b47565b610454565b90565b6137329061372c61372661373794610454565b91610454565b90610c3f565b610454565b90565b90565b61375161374c6137569261373a565b610920565b610454565b90565b90565b61377061376b61377592613759565b610920565b610168565b90565b90565b61378f61378a61379492613778565b610920565b610454565b90565b90565b6137ae6137a96137b392613797565b610920565b610168565b90565b90565b6137cd6137c86137d2926137b6565b610920565b610454565b90565b90565b6137ec6137e76137f1926137d5565b610920565b610168565b90565b90565b61380b613806613810926137f4565b610920565b610454565b90565b90565b61382a61382561382f92613813565b610920565b610168565b90565b90565b61384961384461384e92613832565b610920565b610454565b90565b61386561386061386a92611844565b610920565b610168565b90565b613875610bb1565b506138b56138a58261389f6138996fffffffffffffffffffffffffffffffff6136b1565b91610454565b11613a02565b6138af60076136d0565b906136ec565b6138f66138e66138c6848490613713565b6138e06138da67ffffffffffffffff61373d565b91610454565b11613a02565b6138f0600661375c565b906136ec565b17613934613924613908848490613713565b61391e61391863ffffffff61377b565b91610454565b11613a02565b61392e600561379a565b906136ec565b17613970613960613946848490613713565b61395a61395461ffff6137b9565b91610454565b11613a02565b61396a60046137d8565b906136ec565b176139ab61399b613982848490613713565b61399561398f60ff6137f7565b91610454565b11613a02565b6139a56003613816565b906136ec565b176139e66139d66139bd848490613713565b6139d06139ca600f613835565b91610454565b11613a02565b6139e06002613851565b906136ec565b17906d010102020202030303030303030360801b90821c1a1790565b613a0a610bb1565b5015159056fea2646970667358221220bc4a2db5c2380b433af49bee3a9ba8346459244bbf4bf330a5ad42faf155a8c364736f6c634300081c0033","sourceMap":"993:7551:24:-:0;;;;;;;;;-1:-1:-1;993:7551:24;:::i;:::-;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;;;:::o;:::-;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;:::i;:::-;;;;:::o;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;:::o;:::-;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;:::i;:::-;;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;:::o;:::-;;;;;;;:::o;:::-;;;;:::o;:::-;;;:::o;:::-;;;;;;;:::o;:::-;;;;;;;;;;:::o;:::-;;;;;;;;:::o;:::-;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;;;;;;:::o;:::-;;;;:::o;:::-;;:::o;:::-;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;:::o;:::-;;;;;;;:::i;:::-;;;:::o;:::-;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;;;;:::o;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;;;:::i;:::-;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;;;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;:::o;:::-;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;:::o;:::-;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;:::o;:::-;;:::o;:::-;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;:::o;:::-;;;;;;;:::o;:::-;;;:::o;:::-;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;:::i;:::-;;;;;:::i;:::-;;;:::o;:::-;;;:::o;:::-;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;;;;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;:::o;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;:::i;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;;;;:::i;:::-;:::o;:::-;;:::i;:::-;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;;;;;;;;;:::o;:::-;;;;;;;;;;:::i;:::-;;;;:::i;:::-;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;:::o;5599:469::-;5703:20;;:13;:8;:13;;;;;:::i;:::-;:20;;:::i;:::-;;:::i;:::-;5742:10;:27;;5756:13;;:8;:13;;:::i;:::-;5742:27;:::i;:::-;;;:::i;:::-;;:50;;;;5599:469;5734:75;;;:::i;:::-;5948:41;5820:59;5843:36;:21;:13;:21;5865:13;;:8;:13;;:::i;:::-;5843:36;;:::i;:::-;5820:59;:::i;:::-;5889:40;5897:11;;:3;:11;;:::i;:::-;5889:40;:::i;:::-;5948:30;5981:8;5948:13;5968:9;;5948:19;:13;:19;5968:3;:9;;:::i;:::-;5948:30;;:::i;:::-;:41;;:::i;:::-;5999:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;6053:7;;;:::i;:::-;6023:38;;;;;:::i;:::-;;;;;;:::i;:::-;;;;5599:469::o;5742:50::-;5773:10;5734:75;5773:10;:19;;5787:5;;;:::i;:::-;5773:19;:::i;:::-;;;:::i;:::-;;5742:50;;;;993:7551;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;2121:94;;2207:1;2121:94;2152:45;2160:10;:19;;2174:5;;;:::i;:::-;2160:19;:::i;:::-;;;:::i;:::-;;2152:45;:::i;:::-;2207:1;:::i;:::-;2121:94::o;993:7551::-;;;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;:::i;:::-;;;;:::i;:::-;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;:::i;:::-;:::o;:::-;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;:::i;:::-;:::o;5001:592::-;5123:20;;:13;:8;:13;;;;;:::i;:::-;:20;;:::i;:::-;;:::i;:::-;5154:72;5162:45;5163:44;;:36;:13;;:21;5185:13;:8;;:13;;:::i;:::-;5163:36;;:::i;:::-;:44;;:::i;:::-;5162:45;;:::i;:::-;5154:72;:::i;:::-;5236:67;5244:36;:29;:24;:13;;:19;5264:3;5244:24;;:::i;:::-;;:29;:36;:::i;:::-;:41;;5284:1;5244:41;:::i;:::-;;;:::i;:::-;;5236:67;:::i;:::-;5322:78;5381:4;5361:39;5394:3;5361:39;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::i;:::-;5322:36;:21;:13;:21;5344:13;;:8;:13;;:::i;:::-;5322:36;;:::i;:::-;:78;:::i;:::-;5410:35;5437:8;5410:24;:19;:13;:19;5430:3;5410:24;;:::i;:::-;:35;;:::i;:::-;5455:55;5479:31;:21;;:13;:21;;:::i;:::-;5506:3;5479:31;;:::i;:::-;5455:21;:13;:21;:55;:::i;:::-;5521:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;5568:8;5578:7;;;:::i;:::-;5545:41;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;5001:592::o;:::-;;;;;:::i;:::-;:::o;2121:94::-;2207:1;2121:94;2152:45;2160:10;:19;;2174:5;;;:::i;:::-;2160:19;:::i;:::-;;;:::i;:::-;;2152:45;:::i;:::-;2207:1;:::i;:::-;2121:94::o;993:7551::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;2327:109;2428:1;2327:109;2360:58;2368:24;2369:23;;:::i;:::-;2368:24;;:::i;:::-;2360:58;:::i;:::-;2428:1;:::i;:::-;2327:109::o;993:7551::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;2554:115;2661:1;2554:115;2589:62;2597:26;2598:25;;:::i;:::-;2597:26;;:::i;:::-;2589:62;:::i;:::-;2661:1;:::i;:::-;2554:115::o;993:7551::-;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;:::o;:::-;;:::i;:::-;;;;:::o;:::-;;:::o;:::-;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;:::o;:::-;;:::i;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;;;;:::i;:::-;:::o;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;:::i;:::-;:::o;2675:763::-;2785:90;2793:62;:28;;:11;:28;;:::i;:::-;2833:21;;:13;:21;;:::i;:::-;2793:62;;:::i;:::-;2785:90;:::i;:::-;2956:202;2886:60;2916:30;:9;2926:19;:15;;;:::i;:::-;:19;2944:1;2926:19;:::i;:::-;;;:::i;:::-;2916:30;;:::i;:::-;;2886:60;:::i;:::-;2977:28;;:11;:28;;:::i;:::-;:60;;3009:28;;:11;:28;;:::i;:::-;2977:60;:::i;:::-;;;:::i;:::-;;;:142;;;;;2675:763;2956:202;;:::i;:::-;3173:14;:12;:9;:12;:14;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;3198:17;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;3225:44;3258:11;3225:30;:9;3235:19;:15;;;:::i;:::-;:19;3253:1;3235:19;:::i;:::-;;;:::i;:::-;3225:30;;:::i;:::-;:44;;:::i;:::-;3280:64;3316:28;;:11;:28;;:::i;:::-;3280:33;:9;:33;:64;:::i;:::-;3355:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;3396:12;;:9;:12;;:::i;:::-;3410:11;3423:7;;;:::i;:::-;3379:52;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;2675:763::o;2977:142::-;3053:31;:11;;:31;;;:::i;:::-;:66;;3088:31;;:11;:31;;:::i;:::-;3053:66;:::i;:::-;;;:::i;:::-;;;2977:142;;;2675:763;;;;:::i;:::-;:::o;993:7551::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;2442:106;2478:52;2486:25;;:::i;:::-;2478:52;:::i;:::-;2540:1;;:::i;:::-;2442:106::o;993:7551::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;:::i;:::-;:::o;4744:251::-;4815:16;;:11;:16;;:::i;:::-;:30;;4835:10;4815:30;:::i;:::-;;;:::i;:::-;;:53;;;;4744:251;4807:78;;;:::i;:::-;4896:29;4915:10;4923:1;4915:10;:::i;:::-;4896:16;:11;:16;:29;:::i;:::-;4936:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;4980:7;;;:::i;:::-;4960:28;;;;;:::i;:::-;;;;;;:::i;:::-;;;;4744:251::o;4815:53::-;4849:10;4807:78;4849:10;:19;;4863:5;;;:::i;:::-;4849:19;:::i;:::-;;;:::i;:::-;;4815:53;;;;4744:251;;;:::i;:::-;:::o;2121:94::-;2207:1;2121:94;2152:45;2160:10;:19;;2174:5;;;:::i;:::-;2160:19;:::i;:::-;;;:::i;:::-;;2152:45;:::i;:::-;2207:1;:::i;:::-;2121:94::o;993:7551::-;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;:::i;:::-;:::o;:::-;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;:::o;6866:184::-;6950:22;6961:11;6950:22;;:::i;:::-;6982:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;7035:7;;;:::i;:::-;7006:37;;;;;:::i;:::-;;;;;;:::i;:::-;;;;6866:184::o;:::-;;;;:::i;:::-;:::o;993:7551::-;;;;:::i;:::-;;:::o;:::-;;;:::o;:::-;;;:::o;:::-;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;:::o;:::-;;;:::o;:::-;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::o;:::-;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;:::o;:::-;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;:::o;:::-;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::o;:::-;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::o;:::-;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::o;:::-;;;:::i;:::-;;:::o;:::-;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::o;:::-;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;:::i;:::-;;:::i;:::-;;;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;:::o;:::-;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::o;:::-;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;:::o;:::-;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;:::o;:::-;;;;;:::i;:::-;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;;;;:::o;:::-;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;:::i;:::-;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;:::i;:::-;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;:::i;:::-;;:::o;7232:845::-;7272:18;;:::i;:::-;7327:13;;:21;;;;;:::i;:::-;:32;;;:::i;:::-;7440:5;;;:::i;:::-;7497:14;7514:1;7497:18;;;:::i;:::-;;;;:::i;:::-;7478:38;;;:::i;:::-;7541:9;7581:15;;;:::i;:::-;7620:8;7653:9;7689:11;;7723:7;;;;:::i;:::-;7407:334;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;7783:13;:21;;;;;:::i;:::-;7832:1;;7820:13;;;:::i;:::-;7856:3;7835:1;:19;;7840:14;7835:19;:::i;:::-;;;:::i;:::-;;;;7856:3;7879:20;:34;:20;7904:8;7910:1;7904:8;:::i;:::-;7879:34;;:::i;:::-;7875:81;;7970:57;8005:22;:19;:13;:19;8025:1;8005:22;;:::i;:::-;;7970:29;:11;:29;;:57;8000:1;7970:57;;:::i;:::-;;;;;:::i;:::-;;;:::i;:::-;;;7820:13;7856:3;:::i;:::-;7820:13;;7875:81;7933:8;;7835:19;;;;;;8052:18;:::o;993:7551::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;2221:100;2313:1;2221:100;2255:48;2263:23;;:::i;:::-;2255:48;:::i;:::-;2313:1;:::i;:::-;2221:100::o;993:7551::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;:::i;:::-;:::o;3444:709::-;3514:49;3444:709;3522:18;;3528:12;;:9;:12;;:::i;:::-;3522:18;:::i;:::-;;;:::i;:::-;;3514:49;:::i;:::-;3796:93;3832:57;3574:63;3604:33;:21;:13;:21;3626:10;3604:33;;:::i;:::-;3574:63;:::i;:::-;3647:48;3655:19;;:11;:19;;:::i;:::-;3647:48;:::i;:::-;3705:80;3713:56;:33;;:9;:33;;:::i;:::-;3751:17;;:11;:17;;:::i;:::-;3713:56;;:::i;:::-;3705:80;:::i;:::-;3871:17;;3832:33;;:9;:33;;:::i;:::-;3871:11;:17;;:::i;:::-;3832:57;;:::i;:::-;3796:33;:9;:33;:93;:::i;:::-;3904:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;3927:33;;:9;:33;;:::i;:::-;:38;;3964:1;3927:38;:::i;:::-;;;:::i;:::-;;3923:224;;;;4005:12;;:9;:12;;:::i;:::-;4019:10;4031:7;;;:::i;:::-;3986:53;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;3923:224;3444:709::o;3923:224::-;4102:12;;:9;:12;;:::i;:::-;4116:10;4128:7;;;:::i;:::-;4075:61;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;3923:224;;3444:709;;;;:::i;:::-;:::o;2121:94::-;2207:1;2121:94;2152:45;2160:10;:19;;2174:5;;;:::i;:::-;2160:19;:::i;:::-;;;:::i;:::-;;2152:45;:::i;:::-;2207:1;:::i;:::-;2121:94::o;993:7551::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;;;:::o;:::-;;;;;;;;;:::i;:::-;:::o;:::-;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;:::o;:::-;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;:::o;:::-;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;-1:-1:-1;993:7551:24;;;;;;;;;;;;;;:::i;:::-;;;;;:::o;:::-;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;:::o;:::-;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;:::i;:::-;:::o;:::-;;:::i;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;:::i;:::-;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;:::o;6074:786::-;6718:55;6742:31;6297:13;;6156:65;6183:38;:13;;:21;6205:15;6183:38;;:::i;:::-;6156:65;:::i;:::-;6231:44;6239:15;:7;;:15;;:::i;:::-;6231:44;:::i;:::-;6297:13;;:::i;:::-;6325:23;;:::i;:::-;6321:281;;;;6384:38;:29;;:12;:9;6394:1;6384:12;;:::i;:::-;;:29;;:::i;:::-;6418:3;6384:38;;:::i;:::-;:80;;;6321:281;6376:104;;;:::i;:::-;6321:281;6620:46;;6627:38;:13;;:21;6649:15;6627:38;;:::i;:::-;6620:46;:::i;:::-;6676:32;6683:24;:19;:13;:19;6703:3;6683:24;;:::i;:::-;6676:32;;:::i;:::-;6742:21;;:13;:21;;:::i;:::-;:31;:::i;:::-;6718:21;:13;:21;:55;:::i;:::-;6784:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;6845:7;;;:::i;:::-;6808:45;;;;;:::i;:::-;;;;;;:::i;:::-;;;;6074:786::o;6384:80::-;6426:9;6376:104;6426:38;:29;;:12;:9;6436:1;6426:12;;:::i;:::-;;:29;;:::i;:::-;6460:3;6426:38;;:::i;:::-;6384:80;;;;6321:281;6511:80;6519:56;:47;;:30;:9;6529:19;:15;;;:::i;:::-;:19;6547:1;6529:19;:::i;:::-;;;:::i;:::-;6519:30;;:::i;:::-;;:47;;:::i;:::-;6571:3;6519:56;;:::i;:::-;6511:80;:::i;:::-;6321:281;;6074:786;;;;:::i;:::-;:::o;2121:94::-;2207:1;2121:94;2152:45;2160:10;:19;;2174:5;;;:::i;:::-;2160:19;:::i;:::-;;;:::i;:::-;;2152:45;:::i;:::-;2207:1;:::i;:::-;2121:94::o;2221:100::-;2313:1;2221:100;2255:48;2263:23;;:::i;:::-;2255:48;:::i;:::-;2313:1;:::i;:::-;2221:100::o;993:7551::-;;;;:::i;:::-;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;:::o;4159:282::-;4236:49;4159:282;4244:18;;4250:12;;:9;:12;;:::i;:::-;4244:18;:::i;:::-;;;:::i;:::-;;4236:49;:::i;:::-;4296:17;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;4323:37;;4359:1;4323:37;:::i;:::-;:33;:9;:33;:37;:::i;:::-;4371:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;4412:12;;:9;:12;;:::i;:::-;4426:7;;;:::i;:::-;4395:39;;;;;:::i;:::-;;;;;;:::i;:::-;;;;4159:282::o;:::-;;;;:::i;:::-;:::o;2121:94::-;2207:1;2121:94;2152:45;2160:10;:19;;2174:5;;;:::i;:::-;2160:19;:::i;:::-;;;:::i;:::-;;2152:45;:::i;:::-;2207:1;:::i;:::-;2121:94::o;7056:170::-;7130:16;7138:8;7130:16;;:::i;:::-;7156:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;7211:7;;;:::i;:::-;7180:39;;;;;:::i;:::-;;;;;;:::i;:::-;;;;7056:170::o;:::-;;;;:::i;:::-;:::o;2327:109::-;2360:58;2368:24;2369:23;;:::i;:::-;2368:24;;:::i;:::-;2360:58;:::i;:::-;2428:1;;:::i;:::-;2327:109::o;2554:115::-;2589:62;2597:26;2598:25;;:::i;:::-;2597:26;;:::i;:::-;2589:62;:::i;:::-;2661:1;;:::i;:::-;2554:115::o;4447:291::-;4528:41;;:33;:13;;:21;4550:10;4528:33;;:::i;:::-;:41;;:::i;:::-;:64;;;;4447:291;4520:89;;;:::i;:::-;4628:29;4647:10;4628:16;:11;:16;:29;:::i;:::-;4668:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;4711:10;4723:7;;;:::i;:::-;4692:39;;;;;:::i;:::-;;;;;;:::i;:::-;;;;4447:291::o;4528:64::-;4573:10;4520:89;4573:10;:19;;4587:5;;;:::i;:::-;4573:19;:::i;:::-;;;:::i;:::-;;4528:64;;;;4447:291;;;:::i;:::-;:::o;993:7551::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;8083:205;8207:74;8083:205;8156:41;8164:5;:9;;8172:1;8164:9;:::i;:::-;;;:::i;:::-;;8156:41;:::i;:::-;8215:38;;8224:29;;:8;:29;;:::i;:::-;8215:38;:::i;:::-;;;:::i;:::-;;;8207:74;:::i;:::-;8083:205::o;993:7551::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;:::i;:::-;;:::o;9344:122::-;9444:15;9344:122;9407:7;;:::i;:::-;9434;9444:1;:15;9449:10;9444:1;9457;9449:10;:::i;:::-;9444:15;;:::i;:::-;;:::i;:::-;9434:25;9427:32;:::o;993:7551::-;;;:::o;8294:124::-;8350:4;;:::i;:::-;8373:9;:33;;:9;:33;;:::i;:::-;:38;;8410:1;8373:38;:::i;:::-;;;:::i;:::-;;;8366:45;:::o;8424:118::-;8482:4;;:::i;:::-;8505:11;:16;;:11;:16;;:::i;:::-;:30;;8525:10;8533:1;8525:10;:::i;:::-;8505:30;:::i;:::-;;;:::i;:::-;;;8498:37;:::o;10172:120::-;10274:6;10172:120;10244:4;;:::i;:::-;10267;10275:5;10274:6;;:::i;:::-;10267:13;:18;;10284:1;10267:18;:::i;:::-;;;:::i;:::-;;10260:25;:::o;10053:113::-;10137:18;10053:113;10111:7;;:::i;:::-;10147;10137:18;:::i;:::-;10130:25;:::o;9736:127::-;9834:15;9736:127;9798:4;;:::i;:::-;9823:7;9834:1;:15;9839:10;9834:1;9847;9839:10;:::i;:::-;9834:15;;:::i;:::-;;:::i;:::-;9823:27;9822:34;;9855:1;9822:34;:::i;:::-;;;:::i;:::-;;9815:41;:::o;9603:127::-;9701:15;9603:127;9665:4;;:::i;:::-;9690:7;9701:1;:15;9706:10;9701:1;9714;9706:10;:::i;:::-;9701:15;;:::i;:::-;;:::i;:::-;9690:27;9689:34;;9722:1;9689:34;:::i;:::-;;;:::i;:::-;;;9682:41;:::o;9472:125::-;9574:15;9572:18;9472:125;9535:7;;:::i;:::-;9562;9574:1;:15;9579:10;9574:1;9587;9579:10;:::i;:::-;9574:15;;:::i;:::-;;:::i;:::-;9572:18;;:::i;:::-;9562:28;9555:35;:::o;993:7551::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;26222:2393:21:-;26270:9;;:::i;:::-;26383:1;26367:60;:55;26383:1;:38;;26387:34;26383:38;:::i;:::-;;;:::i;:::-;;26367:55;:::i;:::-;:60;26426:1;26367:60;:::i;:::-;;;:::i;:::-;26508:51;:46;26525:6;:1;26530;26525:6;;:::i;:::-;26524:29;;26535:18;26524:29;:::i;:::-;;;:::i;:::-;;26508:46;:::i;:::-;:51;26558:1;26508:51;:::i;:::-;;;:::i;:::-;26503:56;26639:43;:38;26656:6;:1;26661;26656:6;;:::i;:::-;26655:21;;26666:10;26655:21;:::i;:::-;;;:::i;:::-;;26639:38;:::i;:::-;:43;26681:1;26639:43;:::i;:::-;;;:::i;:::-;26634:48;26762:39;:34;26779:6;:1;26784;26779:6;;:::i;:::-;26778:17;;26789:6;26778:17;:::i;:::-;;;:::i;:::-;;26762:34;:::i;:::-;:39;26800:1;26762:39;:::i;:::-;;;:::i;:::-;26757:44;26879:37;:32;26896:6;:1;26901;26896:6;;:::i;:::-;26895:15;;26906:4;26895:15;:::i;:::-;;;:::i;:::-;;26879:32;:::i;:::-;:37;26915:1;26879:37;:::i;:::-;;;:::i;:::-;26874:42;26993:36;:31;27010:6;:1;27015;27010:6;;:::i;:::-;27009:14;;27020:3;27009:14;:::i;:::-;;;:::i;:::-;;26993:31;:::i;:::-;:36;27028:1;26993:36;:::i;:::-;;;:::i;:::-;26988:41;28465:144;;;;;;;;;26222:2393;:::o;34795:145:22:-;34842:9;;:::i;:::-;34863:71;;;34795:145;:::o","linkReferences":{}},"methodIdentifiers":{"abortMigration(uint64)":"e88e9749","addNodeOperator(uint8,(address,bytes))":"2b726062","completeMigration(uint64)":"9d44e717","finishMaintenance()":"53bfb584","getView()":"75418b9d","removeNodeOperator(address)":"c05665dd","startMaintenance()":"f5f2d9f1","startMigration((uint256,uint8))":"47011c5c","transferOwnership(address)":"f2fde38b","updateNodeOperator((address,bytes))":"26322217","updateSettings((uint16))":"65706f9c"},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.28+commit.7893614a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"components\":[{\"internalType\":\"uint16\",\"name\":\"maxOperatorDataBytes\",\"type\":\"uint16\"}],\"internalType\":\"struct Settings\",\"name\":\"initialSettings\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"struct NodeOperator[]\",\"name\":\"initialOperators\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"MaintenanceFinished\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"MaintenanceStarted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"MigrationAborted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"operatorAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"MigrationCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"operatorAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"MigrationDataPullCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"operatorsBitmask\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"replicationStrategy\",\"type\":\"uint8\"}],\"indexed\":false,\"internalType\":\"struct Keyspace\",\"name\":\"newKeyspace\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"MigrationStarted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"idx\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"struct NodeOperator\",\"name\":\"operator\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"NodeOperatorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"operatorAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"NodeOperatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"struct NodeOperator\",\"name\":\"operator\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"NodeOperatorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"cluserVersion\",\"type\":\"uint128\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint16\",\"name\":\"maxOperatorDataBytes\",\"type\":\"uint16\"}],\"indexed\":false,\"internalType\":\"struct Settings\",\"name\":\"newSettings\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"SettingsUpdated\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"}],\"name\":\"abortMigration\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"idx\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"struct NodeOperator\",\"name\":\"operator\",\"type\":\"tuple\"}],\"name\":\"addNodeOperator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"}],\"name\":\"completeMigration\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"finishMaintenance\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getView\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"struct NodeOperator[]\",\"name\":\"nodeOperatorSlots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"operatorsBitmask\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"replicationStrategy\",\"type\":\"uint8\"}],\"internalType\":\"struct Keyspace[2]\",\"name\":\"keyspaces\",\"type\":\"tuple[2]\"},{\"internalType\":\"uint64\",\"name\":\"keyspaceVersion\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint16\",\"name\":\"maxOperatorDataBytes\",\"type\":\"uint16\"}],\"internalType\":\"struct Settings\",\"name\":\"settings\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"pullingOperatorsBitmask\",\"type\":\"uint256\"}],\"internalType\":\"struct Migration\",\"name\":\"migration\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"slot\",\"type\":\"address\"}],\"internalType\":\"struct Maintenance\",\"name\":\"maintenance\",\"type\":\"tuple\"},{\"internalType\":\"uint128\",\"name\":\"version\",\"type\":\"uint128\"}],\"internalType\":\"struct ClusterView\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operatorAddress\",\"type\":\"address\"}],\"name\":\"removeNodeOperator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startMaintenance\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"operatorsBitmask\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"replicationStrategy\",\"type\":\"uint8\"}],\"internalType\":\"struct Keyspace\",\"name\":\"newKeyspace\",\"type\":\"tuple\"}],\"name\":\"startMigration\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"struct NodeOperator\",\"name\":\"operator\",\"type\":\"tuple\"}],\"name\":\"updateNodeOperator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint16\",\"name\":\"maxOperatorDataBytes\",\"type\":\"uint16\"}],\"internalType\":\"struct Settings\",\"name\":\"newSettings\",\"type\":\"tuple\"}],\"name\":\"updateSettings\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/Cluster.sol\":\"Cluster\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[\":@openzeppelin-contracts-5.3.0/=dependencies/@openzeppelin-contracts-5.3.0/\",\":forge-std-1.9.7/=dependencies/forge-std-1.9.7/src/\",\":forge-std/=dependencies/forge-std/src/\",\":openzeppelin-contracts/=dependencies/@openzeppelin-contracts-5.3.0/\"],\"viaIR\":true},\"sources\":{\"dependencies/openzeppelin-contracts/utils/Panic.sol\":{\"keccak256\":\"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a\",\"dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG\"]},\"dependencies/openzeppelin-contracts/utils/math/Math.sol\":{\"keccak256\":\"0x1225214420c83ebcca88f2ae2b50f053aaa7df7bd684c3e878d334627f2edfc6\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6c5fab4970634f9ab9a620983dc1c8a30153981a0b1a521666e269d0a11399d3\",\"dweb:/ipfs/QmVRnBC575MESGkEHndjujtR7qub2FzU9RWy9eKLp4hPZB\"]},\"dependencies/openzeppelin-contracts/utils/math/SafeCast.sol\":{\"keccak256\":\"0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b1d578337048cad08c1c03041cca5978eff5428aa130c781b271ad9e5566e1f8\",\"dweb:/ipfs/QmPFKL2r9CBsMwmUqqdcFPfHZB2qcs9g1HDrPxzWSxomvy\"]},\"src/Cluster.sol\":{\"keccak256\":\"0xc78e6f85b957de947ea15d06612efc306c2cd979f8f08d37e4484a65880ffb48\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c14a8b6856276888d44ba5368193e7b0ca9cd898d3cdc90d272edc32aef830be\",\"dweb:/ipfs/QmQkuwMCYXcuv1g68FsC7ZrpAdCKQS7KmHQZwRUftXKJVa\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.28+commit.7893614a"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"struct Settings","name":"initialSettings","type":"tuple","components":[{"internalType":"uint16","name":"maxOperatorDataBytes","type":"uint16"}]},{"internalType":"struct NodeOperator[]","name":"initialOperators","type":"tuple[]","components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}]}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"MaintenanceFinished","anonymous":false},{"inputs":[{"internalType":"address","name":"addr","type":"address","indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"MaintenanceStarted","anonymous":false},{"inputs":[{"internalType":"uint64","name":"id","type":"uint64","indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"MigrationAborted","anonymous":false},{"inputs":[{"internalType":"uint64","name":"id","type":"uint64","indexed":false},{"internalType":"address","name":"operatorAddress","type":"address","indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"MigrationCompleted","anonymous":false},{"inputs":[{"internalType":"uint64","name":"id","type":"uint64","indexed":false},{"internalType":"address","name":"operatorAddress","type":"address","indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"MigrationDataPullCompleted","anonymous":false},{"inputs":[{"internalType":"uint64","name":"id","type":"uint64","indexed":false},{"internalType":"struct Keyspace","name":"newKeyspace","type":"tuple","components":[{"internalType":"uint256","name":"operatorsBitmask","type":"uint256"},{"internalType":"uint8","name":"replicationStrategy","type":"uint8"}],"indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"MigrationStarted","anonymous":false},{"inputs":[{"internalType":"uint8","name":"idx","type":"uint8","indexed":false},{"internalType":"struct NodeOperator","name":"operator","type":"tuple","components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"NodeOperatorAdded","anonymous":false},{"inputs":[{"internalType":"address","name":"operatorAddress","type":"address","indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"NodeOperatorRemoved","anonymous":false},{"inputs":[{"internalType":"struct NodeOperator","name":"operator","type":"tuple","components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"NodeOperatorUpdated","anonymous":false},{"inputs":[{"internalType":"address","name":"newOwner","type":"address","indexed":false},{"internalType":"uint128","name":"cluserVersion","type":"uint128","indexed":false}],"type":"event","name":"OwnershipTransferred","anonymous":false},{"inputs":[{"internalType":"struct Settings","name":"newSettings","type":"tuple","components":[{"internalType":"uint16","name":"maxOperatorDataBytes","type":"uint16"}],"indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"SettingsUpdated","anonymous":false},{"inputs":[{"internalType":"uint64","name":"id","type":"uint64"}],"stateMutability":"nonpayable","type":"function","name":"abortMigration"},{"inputs":[{"internalType":"uint8","name":"idx","type":"uint8"},{"internalType":"struct NodeOperator","name":"operator","type":"tuple","components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}]}],"stateMutability":"nonpayable","type":"function","name":"addNodeOperator"},{"inputs":[{"internalType":"uint64","name":"id","type":"uint64"}],"stateMutability":"nonpayable","type":"function","name":"completeMigration"},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"finishMaintenance"},{"inputs":[],"stateMutability":"view","type":"function","name":"getView","outputs":[{"internalType":"struct ClusterView","name":"","type":"tuple","components":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"struct NodeOperator[]","name":"nodeOperatorSlots","type":"tuple[]","components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}]},{"internalType":"struct Keyspace[2]","name":"keyspaces","type":"tuple[2]","components":[{"internalType":"uint256","name":"operatorsBitmask","type":"uint256"},{"internalType":"uint8","name":"replicationStrategy","type":"uint8"}]},{"internalType":"uint64","name":"keyspaceVersion","type":"uint64"},{"internalType":"struct Settings","name":"settings","type":"tuple","components":[{"internalType":"uint16","name":"maxOperatorDataBytes","type":"uint16"}]},{"internalType":"struct Migration","name":"migration","type":"tuple","components":[{"internalType":"uint64","name":"id","type":"uint64"},{"internalType":"uint256","name":"pullingOperatorsBitmask","type":"uint256"}]},{"internalType":"struct Maintenance","name":"maintenance","type":"tuple","components":[{"internalType":"address","name":"slot","type":"address"}]},{"internalType":"uint128","name":"version","type":"uint128"}]}]},{"inputs":[{"internalType":"address","name":"operatorAddress","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"removeNodeOperator"},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"startMaintenance"},{"inputs":[{"internalType":"struct Keyspace","name":"newKeyspace","type":"tuple","components":[{"internalType":"uint256","name":"operatorsBitmask","type":"uint256"},{"internalType":"uint8","name":"replicationStrategy","type":"uint8"}]}],"stateMutability":"nonpayable","type":"function","name":"startMigration"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"transferOwnership"},{"inputs":[{"internalType":"struct NodeOperator","name":"operator","type":"tuple","components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}]}],"stateMutability":"nonpayable","type":"function","name":"updateNodeOperator"},{"inputs":[{"internalType":"struct Settings","name":"newSettings","type":"tuple","components":[{"internalType":"uint16","name":"maxOperatorDataBytes","type":"uint16"}]}],"stateMutability":"nonpayable","type":"function","name":"updateSettings"}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"remappings":["@openzeppelin-contracts-5.3.0/=dependencies/@openzeppelin-contracts-5.3.0/","forge-std-1.9.7/=dependencies/forge-std-1.9.7/src/","forge-std/=dependencies/forge-std/src/","openzeppelin-contracts/=dependencies/@openzeppelin-contracts-5.3.0/"],"optimizer":{"enabled":false,"runs":200},"metadata":{"bytecodeHash":"ipfs"},"compilationTarget":{"src/Cluster.sol":"Cluster"},"evmVersion":"cancun","libraries":{},"viaIR":true},"sources":{"dependencies/openzeppelin-contracts/utils/Panic.sol":{"keccak256":"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a","urls":["bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a","dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG"],"license":"MIT"},"dependencies/openzeppelin-contracts/utils/math/Math.sol":{"keccak256":"0x1225214420c83ebcca88f2ae2b50f053aaa7df7bd684c3e878d334627f2edfc6","urls":["bzz-raw://6c5fab4970634f9ab9a620983dc1c8a30153981a0b1a521666e269d0a11399d3","dweb:/ipfs/QmVRnBC575MESGkEHndjujtR7qub2FzU9RWy9eKLp4hPZB"],"license":"MIT"},"dependencies/openzeppelin-contracts/utils/math/SafeCast.sol":{"keccak256":"0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54","urls":["bzz-raw://b1d578337048cad08c1c03041cca5978eff5428aa130c781b271ad9e5566e1f8","dweb:/ipfs/QmPFKL2r9CBsMwmUqqdcFPfHZB2qcs9g1HDrPxzWSxomvy"],"license":"MIT"},"src/Cluster.sol":{"keccak256":"0xc78e6f85b957de947ea15d06612efc306c2cd979f8f08d37e4484a65880ffb48","urls":["bzz-raw://c14a8b6856276888d44ba5368193e7b0ca9cd898d3cdc90d272edc32aef830be","dweb:/ipfs/QmQkuwMCYXcuv1g68FsC7ZrpAdCKQS7KmHQZwRUftXKJVa"],"license":"MIT"}},"version":1},"id":24} \ No newline at end of file +{"abi":[{"type":"constructor","inputs":[{"name":"initialSettings","type":"tuple","internalType":"struct Settings","components":[{"name":"maxOperatorDataBytes","type":"uint16","internalType":"uint16"}]},{"name":"initialOperators","type":"tuple[]","internalType":"struct NodeOperator[]","components":[{"name":"addr","type":"address","internalType":"address"},{"name":"data","type":"bytes","internalType":"bytes"}]}],"stateMutability":"nonpayable"},{"type":"function","name":"abortMigration","inputs":[{"name":"id","type":"uint64","internalType":"uint64"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"addNodeOperator","inputs":[{"name":"idx","type":"uint8","internalType":"uint8"},{"name":"operator","type":"tuple","internalType":"struct NodeOperator","components":[{"name":"addr","type":"address","internalType":"address"},{"name":"data","type":"bytes","internalType":"bytes"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"completeMigration","inputs":[{"name":"id","type":"uint64","internalType":"uint64"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"finishMaintenance","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"getView","inputs":[],"outputs":[{"name":"","type":"tuple","internalType":"struct ClusterView","components":[{"name":"owner","type":"address","internalType":"address"},{"name":"nodeOperatorSlots","type":"tuple[]","internalType":"struct NodeOperator[]","components":[{"name":"addr","type":"address","internalType":"address"},{"name":"data","type":"bytes","internalType":"bytes"}]},{"name":"keyspaces","type":"tuple[2]","internalType":"struct Keyspace[2]","components":[{"name":"operatorsBitmask","type":"uint256","internalType":"uint256"},{"name":"replicationStrategy","type":"uint8","internalType":"uint8"}]},{"name":"keyspaceVersion","type":"uint64","internalType":"uint64"},{"name":"settings","type":"tuple","internalType":"struct Settings","components":[{"name":"maxOperatorDataBytes","type":"uint16","internalType":"uint16"}]},{"name":"migration","type":"tuple","internalType":"struct Migration","components":[{"name":"id","type":"uint64","internalType":"uint64"},{"name":"pullingOperatorsBitmask","type":"uint256","internalType":"uint256"}]},{"name":"maintenance","type":"tuple","internalType":"struct Maintenance","components":[{"name":"slot","type":"address","internalType":"address"}]},{"name":"version","type":"uint128","internalType":"uint128"}]}],"stateMutability":"view"},{"type":"function","name":"removeNodeOperator","inputs":[{"name":"operatorAddress","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"startMaintenance","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"startMigration","inputs":[{"name":"newKeyspace","type":"tuple","internalType":"struct Keyspace","components":[{"name":"operatorsBitmask","type":"uint256","internalType":"uint256"},{"name":"replicationStrategy","type":"uint8","internalType":"uint8"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"transferOwnership","inputs":[{"name":"newOwner","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateNodeOperator","inputs":[{"name":"operator","type":"tuple","internalType":"struct NodeOperator","components":[{"name":"addr","type":"address","internalType":"address"},{"name":"data","type":"bytes","internalType":"bytes"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateSettings","inputs":[{"name":"newSettings","type":"tuple","internalType":"struct Settings","components":[{"name":"maxOperatorDataBytes","type":"uint16","internalType":"uint16"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"event","name":"MaintenanceFinished","inputs":[{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"MaintenanceStarted","inputs":[{"name":"addr","type":"address","indexed":false,"internalType":"address"},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"MigrationAborted","inputs":[{"name":"id","type":"uint64","indexed":false,"internalType":"uint64"},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"MigrationCompleted","inputs":[{"name":"id","type":"uint64","indexed":false,"internalType":"uint64"},{"name":"operatorAddress","type":"address","indexed":false,"internalType":"address"},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"MigrationDataPullCompleted","inputs":[{"name":"id","type":"uint64","indexed":false,"internalType":"uint64"},{"name":"operatorAddress","type":"address","indexed":false,"internalType":"address"},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"MigrationStarted","inputs":[{"name":"id","type":"uint64","indexed":false,"internalType":"uint64"},{"name":"newKeyspace","type":"tuple","indexed":false,"internalType":"struct Keyspace","components":[{"name":"operatorsBitmask","type":"uint256","internalType":"uint256"},{"name":"replicationStrategy","type":"uint8","internalType":"uint8"}]},{"name":"newKeyspaceVersion","type":"uint64","indexed":false,"internalType":"uint64"},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"NodeOperatorAdded","inputs":[{"name":"idx","type":"uint8","indexed":false,"internalType":"uint8"},{"name":"operator","type":"tuple","indexed":false,"internalType":"struct NodeOperator","components":[{"name":"addr","type":"address","internalType":"address"},{"name":"data","type":"bytes","internalType":"bytes"}]},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"NodeOperatorRemoved","inputs":[{"name":"operatorAddress","type":"address","indexed":false,"internalType":"address"},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"NodeOperatorUpdated","inputs":[{"name":"operator","type":"tuple","indexed":false,"internalType":"struct NodeOperator","components":[{"name":"addr","type":"address","internalType":"address"},{"name":"data","type":"bytes","internalType":"bytes"}]},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"name":"newOwner","type":"address","indexed":false,"internalType":"address"},{"name":"cluserVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"SettingsUpdated","inputs":[{"name":"newSettings","type":"tuple","indexed":false,"internalType":"struct Settings","components":[{"name":"maxOperatorDataBytes","type":"uint16","internalType":"uint16"}]},{"name":"clusterVersion","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false}],"bytecode":{"object":"0x6080604052346100305761001a61001461030f565b90610acf565b610022610035565b613a5d610ed38239613a5d90f35b61003b565b60405190565b5f80fd5b601f801991011690565b634e487b7160e01b5f52604160045260245ffd5b906100679061003f565b810190811060018060401b0382111761007f57604052565b610049565b90610097610090610035565b928361005d565b565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b61ffff1690565b6100b9816100a9565b036100c057565b5f80fd5b905051906100d1826100b0565b565b91906020838203126100fb576100f5906100ed6020610084565b935f016100c4565b5f830152565b6100a1565b5f80fd5b60018060401b03811161011a5760208091020190565b610049565b5f80fd5b60018060a01b031690565b61013790610123565b90565b6101438161012e565b0361014a57565b5f80fd5b9050519061015b8261013a565b565b5f80fd5b60018060401b03811161017d5761017960209161003f565b0190565b610049565b90825f9392825e0152565b909291926101a261019d82610161565b610084565b938185526020850190828401116101be576101bc92610182565b565b61015d565b9080601f830112156101e1578160206101de9351910161018d565b90565b610100565b919091604081840312610236576101fd6040610084565b9261020a815f840161014e565b5f850152602082015160018060401b0381116102315761022a92016101c3565b6020830152565b6100a5565b6100a1565b92919061024f61024a82610104565b610084565b93818552602080860192028101918383116102a45781905b838210610275575050505050565b815160018060401b03811161029f5760209161029487849387016101e6565b815201910190610267565b610100565b61011f565b9080601f830112156102c7578160206102c49351910161023b565b90565b610100565b91909160408184031261030a576102e5835f83016100d3565b92602082015160018060401b0381116103055761030292016102a9565b90565b61009d565b610099565b61032d6149308038038061032281610084565b9283398101906102cc565b9091565b5190565b90565b90565b90565b61035261034d61035792610338565b61033b565b610335565b90565b60209181520190565b5f7f746f6f206d616e79206f70657261746f72730000000000000000000000000000910152565b610397601260209261035a565b6103a081610363565b0190565b6103b99060208101905f81830391015261038a565b90565b156103c357565b6103cb610035565b62461bcd60e51b8152806103e1600482016103a4565b0390fd5b5f1b90565b906103fb60018060a01b03916103e5565b9181191691161790565b61041961041461041e92610123565b61033b565b610123565b90565b61042a90610405565b90565b61043690610421565b90565b90565b9061045161044c6104589261042d565b610439565b82546103ea565b9055565b634e487b7160e01b5f525f60045260245ffd5b61047990516100a9565b90565b9061048961ffff916103e5565b9181191691161790565b6104a76104a26104ac926100a9565b61033b565b6100a9565b90565b90565b906104c76104c26104ce92610493565b6104af565b825461047c565b9055565b906104e45f806104ea9401920161046f565b906104b2565b565b906104f6916104d2565b565b90565b61050f61050a610514926104f8565b61033b565b610335565b90565b60016105239101610335565b90565b634e487b7160e01b5f52603260045260245ffd5b9061054482610331565b811015610555576020809102010190565b610526565b5190565b610568905161012e565b90565b906105759061042d565b5f5260205260405f2090565b5f1c90565b60ff1690565b61059861059d91610581565b610586565b90565b6105aa905461058c565b90565b151590565b5f7f6475706c6963617465206f70657261746f720000000000000000000000000000910152565b6105e6601260209261035a565b6105ef816105b2565b0190565b6106089060208101905f8183039101526105d9565b90565b1561061257565b61061a610035565b62461bcd60e51b815280610630600482016105f3565b0390fd5b60ff1690565b61064e61064961065392610335565b61033b565b610634565b90565b6106606040610084565b90565b9061066d906105ad565b9052565b9061067b90610634565b9052565b61068990516105ad565b90565b9061069860ff916103e5565b9181191691161790565b6106ab906105ad565b90565b90565b906106c66106c16106cd926106a2565b6106ae565b825461068c565b9055565b6106db9051610634565b90565b60081b90565b906106f161ff00916106de565b9181191691161790565b61070f61070a61071492610634565b61033b565b610634565b90565b90565b9061072f61072a610736926106fb565b610717565b82546106e4565b9055565b9061076460205f61076a9461075c82820161075684880161067f565b906106b1565b0192016106d1565b9061071a565b565b906107769161073a565b565b5061010090565b90565b61078b81610778565b8210156107a55761079d60029161077f565b910201905f90565b610526565b5190565b634e487b7160e01b5f52602260045260245ffd5b90600160028304921680156107e2575b60208310146107dd57565b6107ae565b91607f16916107d2565b5f5260205f2090565b601f602091010490565b1b90565b9190600861081e9102916108185f19846107ff565b926107ff565b9181191691161790565b61083c61083761084192610335565b61033b565b610335565b90565b90565b919061085d61085861086593610828565b610844565b908354610803565b9055565b5f90565b61087f91610879610869565b91610847565b565b5b81811061088d575050565b8061089a5f60019361086d565b01610882565b9190601f81116108b0575b505050565b6108bc6108e1936107ec565b9060206108c8846107f5565b830193106108e9575b6108da906107f5565b0190610881565b5f80806108ab565b91506108da819290506108d1565b1c90565b9061090b905f19906008026108f7565b191690565b8161091a916108fb565b906002021790565b9061092c8161055a565b9060018060401b0382116109ea5761094e8261094885546107c2565b856108a0565b602090601f831160011461098257918091610971935f92610976575b5050610910565b90555b565b90915001515f8061096a565b601f19831691610991856107ec565b925f5b8181106109d2575091600293918560019694106109b8575b50505002019055610974565b6109c8910151601f8416906108fb565b90555f80806109ac565b91936020600181928787015181550195019201610994565b610049565b906109f991610922565b565b90610a2660206001610a2c94610a1e5f8201610a185f880161055e565b9061043c565b0192016107aa565b906109ef565b565b9190610a3f57610a3d916109fb565b565b61045c565b90610a505f19916103e5565b9181191691161790565b90610a6f610a6a610a7692610828565b610844565b8254610a44565b9055565b90565b610a89610a8e91610581565b610a7a565b90565b610a9b9054610a7d565b90565b50600290565b90565b610ab081610a9e565b821015610aca57610ac2600291610aa4565b910201905f90565b610526565b610b0c90610afa610adf84610331565b610af3610aed61010061033e565b91610335565b11156103bc565b610b04335f61043c565b6102086104ec565b610b155f6104fb565b5b80610b31610b2b610b2685610331565b610335565b91610335565b1015610c1c57610c1790610b5b610b566020610b4e86859061053a565b51015161055a565b610db4565b610b99610b94610b8e5f610b8881600101610b8283610b7b8b8a9061053a565b510161055e565b9061056b565b016105a0565b156105ad565b61060b565b610bef6001610bc7610baa8461063a565b610bbe610bb5610656565b935f8501610663565b60208301610671565b610bea5f600101610be45f610bdd89889061053a565b510161055e565b9061056b565b61076c565b610c12610bfd84839061053a565b51610c0c600180018490610782565b90610a2e565b610517565b610b16565b50610c39610c34610c2f610c4493610331565b61063a565b610e96565b610201600101610a5a565b610c6a610c55610201600101610a91565b5f610c636102038290610aa7565b5001610a5a565b565b5f7f656d707479206f70657261746f72206461746100000000000000000000000000910152565b610ca0601360209261035a565b610ca981610c6c565b0190565b610cc29060208101905f818303910152610c93565b90565b15610ccc57565b610cd4610035565b62461bcd60e51b815280610cea60048201610cad565b0390fd5b61ffff1690565b610d01610d0691610581565b610cee565b90565b610d139054610cf5565b90565b610d2a610d25610d2f926100a9565b61033b565b610335565b90565b5f7f6f70657261746f72206461746120746f6f206c61726765000000000000000000910152565b610d66601760209261035a565b610d6f81610d32565b0190565b610d889060208101905f818303910152610d59565b90565b15610d9257565b610d9a610035565b62461bcd60e51b815280610db060048201610d73565b0390fd5b610df990610dd481610dce610dc85f6104fb565b91610335565b11610cc5565b610df2610dec610de75f61020801610d09565b610d16565b91610335565b1115610d8b565b565b610e0f610e0a610e1492610634565b61033b565b610335565b90565b90565b610e2e610e29610e3392610e17565b61033b565b610335565b90565b610e5590610e4f610e49610e5a94610335565b91610335565b906107ff565b610335565b90565b634e487b7160e01b5f52601160045260245ffd5b610e80610e8691939293610335565b92610335565b8203918211610e9157565b610e5d565b610ebf610ecf91610ea5610869565b50610eba610eb4600192610dfb565b91610e1a565b610e36565b610ec96001610e1a565b90610e71565b9056fe60806040526004361015610013575b6107fc565b61001d5f356100cc565b806326322217146100c75780632b726062146100c257806347011c5c146100bd57806353bfb584146100b857806365706f9c146100b357806375418b9d146100ae5780639d44e717146100a9578063c05665dd146100a4578063e88e97491461009f578063f2fde38b1461009a5763f5f2d9f10361000e576107c9565b610796565b610763565b610730565b6106bc565b610646565b6102e1565b61027d565b61023b565b6101d6565b610135565b60e01c90565b60405190565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b908160409103126100f65790565b6100e4565b9060208282031261012b575f82013567ffffffffffffffff81116101265761012392016100e8565b90565b6100e0565b6100dc565b5f0190565b346101635761014d6101483660046100fb565b610f6e565b6101556100d2565b8061015f81610130565b0390f35b6100d8565b60ff1690565b61017781610168565b0361017e57565b5f80fd5b9050359061018f8261016e565b565b9190916040818403126101d1576101aa835f8301610182565b92602082013567ffffffffffffffff81116101cc576101c992016100e8565b90565b6100e0565b6100dc565b34610205576101ef6101e9366004610191565b906115ec565b6101f76100d2565b8061020181610130565b0390f35b6100d8565b908160409103126102185790565b6100e4565b9060408282031261023657610233915f0161020a565b90565b6100dc565b346102695761025361024e36600461021d565b611d53565b61025b6100d2565b8061026581610130565b0390f35b6100d8565b5f91031261027857565b6100dc565b346102ab5761028d36600461026e565b610295611f08565b61029d6100d2565b806102a781610130565b0390f35b6100d8565b908160209103126102be5790565b6100e4565b906020828203126102dc576102d9915f016102b0565b90565b6100dc565b3461030f576102f96102f43660046102c3565b6120ae565b6103016100d2565b8061030b81610130565b0390f35b6100d8565b60018060a01b031690565b61032890610314565b90565b6103349061031f565b9052565b5190565b60209181520190565b60200190565b5190565b60209181520190565b90825f9392825e0152565b601f801991011690565b61038c61039560209361039a936103838161034b565b9384809361034f565b95869101610358565b610363565b0190565b6103c991602060408201926103b95f8201515f85019061032b565b015190602081840391015261036d565b90565b906103d69161039e565b90565b60200190565b906103f36103ec83610338565b809261033c565b908161040460208302840194610345565b925f915b83831061041757505050505090565b90919293946020610439610433838560019503875289516103cc565b976103d9565b9301930191939290610408565b50600290565b905090565b90565b90565b61046090610454565b9052565b61046d90610168565b9052565b90602080610493936104895f8201515f860190610457565b0151910190610464565b565b906104a281604093610471565b0190565b60200190565b6104c86104c26104bb83610446565b809461044c565b91610451565b5f915b8383106104d85750505050565b6104ee6104e86001928451610495565b926104a6565b920191906104cb565b67ffffffffffffffff1690565b61050d906104f7565b9052565b61ffff1690565b61052190610511565b9052565b905f80610536930151910190610518565b565b9060208061055a936105505f8201515f860190610504565b0151910190610457565b565b905f8061056d93015191019061032b565b565b6fffffffffffffffffffffffffffffffff1690565b61058d9061056f565b9052565b9061062b9061016060e06105c561018084016105b35f8801515f87019061032b565b602087015185820360208701526103df565b946105d8604082015160408601906104ac565b6105ea606082015160c0860190610504565b6105fb608082015183860190610525565b61060e60a0820151610100860190610538565b61062160c082015161014086019061055c565b0151910190610584565b90565b6106439160208201915f818403910152610591565b90565b346106765761065636600461026e565b610672610661612682565b6106696100d2565b9182918261062e565b0390f35b6100d8565b610684816104f7565b0361068b57565b5f80fd5b9050359061069c8261067b565b565b906020828203126106b7576106b4915f0161068f565b90565b6100dc565b346106ea576106d46106cf36600461069e565b612bf5565b6106dc6100d2565b806106e681610130565b0390f35b6100d8565b6106f88161031f565b036106ff57565b5f80fd5b90503590610710826106ef565b565b9060208282031261072b57610728915f01610703565b90565b6100dc565b3461075e57610748610743366004610712565b613071565b6107506100d2565b8061075a81610130565b0390f35b6100d8565b346107915761077b61077636600461069e565b6131d3565b6107836100d2565b8061078d81610130565b0390f35b6100d8565b346107c4576107ae6107a9366004610712565b61327b565b6107b66100d2565b806107c081610130565b0390f35b6100d8565b346107f7576107d936600461026e565b6107e161338e565b6107e96100d2565b806107f381610130565b0390f35b6100d8565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b90359060016020038136030382121561084e570180359067ffffffffffffffff82116108495760200191600182023603831361084457565b610808565b610804565b610800565b5090565b35610861816106ef565b90565b5f1c90565b60018060a01b031690565b61088061088591610864565b610869565b90565b6108929054610874565b90565b60209181520190565b5f7f756e617574686f72697a65640000000000000000000000000000000000000000910152565b6108d2600c602092610895565b6108db8161089e565b0190565b6108f49060208101905f8183039101526108c5565b90565b156108fe57565b6109066100d2565b62461bcd60e51b81528061091c600482016108df565b0390fd5b90565b61093761093261093c92610314565b610920565b610314565b90565b61094890610923565b90565b6109549061093f565b90565b906109619061094b565b5f5260205260405f2090565b90565b60ff1690565b61098261098791610864565b610970565b90565b6109949054610976565b90565b5f7f756e6b6e6f776e206f70657261746f7200000000000000000000000000000000910152565b6109cb6010602092610895565b6109d481610997565b0190565b6109ed9060208101905f8183039101526109be565b90565b156109f757565b6109ff6100d2565b62461bcd60e51b815280610a15600482016109d8565b0390fd5b60081c90565b60ff1690565b610a31610a3691610a19565b610a1f565b90565b610a439054610a25565b90565b634e487b7160e01b5f52603260045260245ffd5b5061010090565b90565b610a6d81610a5a565b821015610a8757610a7f600291610a61565b910201905f90565b610a46565b634e487b7160e01b5f525f60045260245ffd5b5f1b90565b90610ab560018060a01b0391610a9f565b9181191691161790565b90565b90610ad7610ad2610ade9261094b565b610abf565b8254610aa4565b9055565b634e487b7160e01b5f52604160045260245ffd5b634e487b7160e01b5f52602260045260245ffd5b9060016002830492168015610b2a575b6020831014610b2557565b610af6565b91607f1691610b1a565b5f5260205f2090565b601f602091010490565b1b90565b91906008610b66910291610b605f1984610b47565b92610b47565b9181191691161790565b610b84610b7f610b8992610454565b610920565b610454565b90565b90565b9190610ba5610ba0610bad93610b70565b610b8c565b908354610b4b565b9055565b5f90565b610bc791610bc1610bb1565b91610b8f565b565b5b818110610bd5575050565b80610be25f600193610bb5565b01610bca565b9190601f8111610bf8575b505050565b610c04610c2993610b34565b906020610c1084610b3d565b83019310610c31575b610c2290610b3d565b0190610bc9565b5f8080610bf3565b9150610c2281929050610c19565b1c90565b90610c53905f1990600802610c3f565b191690565b81610c6291610c43565b906002021790565b91610c759082610853565b9067ffffffffffffffff8211610d3457610c9982610c938554610b0a565b85610be8565b5f90601f8311600114610ccc57918091610cbb935f92610cc0575b5050610c58565b90555b565b90915001355f80610cb4565b601f19831691610cdb85610b34565b925f5b818110610d1c57509160029391856001969410610d02575b50505002019055610cbe565b610d12910135601f841690610c43565b90555f8080610cf6565b91936020600181928787013581550195019201610cde565b610ae2565b90610d449291610c6a565b565b90610d736001610d7993610d675f8201610d615f8701610857565b90610ac2565b0191602081019061080c565b91610d39565b565b9190610d8c57610d8a91610d46565b565b610a8c565b6fffffffffffffffffffffffffffffffff1690565b610db2610db791610864565b610d91565b90565b610dc49054610da6565b90565b634e487b7160e01b5f52601160045260245ffd5b610de49061056f565b6fffffffffffffffffffffffffffffffff8114610e015760010190565b610dc7565b90610e216fffffffffffffffffffffffffffffffff91610a9f565b9181191691161790565b610e3f610e3a610e449261056f565b610920565b61056f565b90565b90565b90610e5f610e5a610e6692610e2b565b610e47565b8254610e06565b9055565b50610e79906020810190610703565b90565b5f80fd5b5f80fd5b5f80fd5b9035600160200382360303811215610ec957016020813591019167ffffffffffffffff8211610ec4576001820236038313610ebf57565b610e80565b610e7c565b610e84565b90825f939282370152565b9190610ef381610eec81610ef89561034f565b8095610ece565b610363565b0190565b610f3891610f2a6040820192610f20610f175f830183610e6a565b5f85019061032b565b6020810190610e88565b916020818503910152610ed9565b90565b610f449061056f565b9052565b92916020610f64610f6c9360408701908782035f890152610efc565b940190610f3b565b565b610f8d610f88610f8283602081019061080c565b90610853565b6134b8565b33610faa610fa4610f9f5f8501610857565b61031f565b9161031f565b148015611075575b610fbb906108f7565b611011610fde610fd95f600101610fd35f8601610857565b90610957565b61096d565b610ff1610fec5f830161098a565b6109f0565b61100b83916110055f600180019201610a39565b90610a64565b90610d7b565b61102f61102761102261020c610dba565b610ddb565b61020c610e4a565b61103a61020c610dba565b7f5aab2c32b1e447db4dba1d2790fe8b863d4775042b10b92e00dab9d6b671b5b5916110706110676100d2565b92839283610f48565b0390a1565b50610fbb3361109461108e6110895f610888565b61031f565b9161031f565b149050610fb2565b5f7f6e6f7420746865206f776e657200000000000000000000000000000000000000910152565b6110d0600d602092610895565b6110d98161109c565b0190565b6110f29060208101905f8183039101526110c3565b90565b156110fc57565b6111046100d2565b62461bcd60e51b81528061111a600482016110dd565b0390fd5b9061114c916111473361114161113b6111365f610888565b61031f565b9161031f565b146110f5565b61147f565b565b151590565b5f7f616c726561647920657869737473000000000000000000000000000000000000910152565b611187600e602092610895565b61119081611153565b0190565b6111a99060208101905f81830391015261117a565b90565b156111b357565b6111bb6100d2565b62461bcd60e51b8152806111d160048201611194565b0390fd5b6111df9054610b0a565b90565b90565b6111f96111f46111fe926111e2565b610920565b610454565b90565b5f7f736c6f74206f6363757069656400000000000000000000000000000000000000910152565b611235600d602092610895565b61123e81611201565b0190565b6112579060208101905f818303910152611228565b90565b1561126157565b6112696100d2565b62461bcd60e51b81528061127f60048201611242565b0390fd5b9061128d90610363565b810190811067ffffffffffffffff8211176112a757604052565b610ae2565b906112bf6112b86100d2565b9283611283565b565b6112cb60406112ac565b90565b906112d89061114e565b9052565b906112e690610168565b9052565b6112f4905161114e565b90565b9061130360ff91610a9f565b9181191691161790565b6113169061114e565b90565b90565b9061133161132c6113389261130d565b611319565b82546112f7565b9055565b6113469051610168565b90565b60081b90565b9061135c61ff0091611349565b9181191691161790565b61137a61137561137f92610168565b610920565b610168565b90565b90565b9061139a6113956113a192611366565b611382565b825461134f565b9055565b906113cf60205f6113d5946113c78282016113c18488016112ea565b9061131c565b01920161133c565b90611385565b565b906113e1916113a5565b565b90565b6113f26113f791610864565b6113e3565b90565b61140490546113e6565b90565b906114135f1991610a9f565b9181191691161790565b9061143261142d61143992610b70565b610b8c565b8254611407565b9055565b61144690610168565b9052565b93929061147560409161147d9461146860608901925f8a019061143d565b8782036020890152610efc565b940190610f3b565b565b61149e61149961149384602081019061080c565b90610853565b6134b8565b6114d16114cc6114c65f6114c0816001016114ba838901610857565b90610957565b0161098a565b1561114e565b6111ac565b6115056114ed60016114e68180018590610a64565b50016111d5565b6114ff6114f95f6111e5565b91610454565b1461125a565b611548600161152b836115226115196112c1565b935f85016112ce565b602083016112dc565b6115435f60010161153d5f8701610857565b90610957565b6113d7565b6115608261155a600180018490610a64565b90610d7b565b61158661157b6115746102016001016113fa565b8390613542565b61020160010161141d565b6115a461159c61159761020c610dba565b610ddb565b61020c610e4a565b906115b061020c610dba565b916115e77f952e65f049c574f487580ba41dcf6b0ea8350ef8abc8647a8a11dfaa7af6bad6936115de6100d2565b9384938461144a565b0390a1565b906115f69161111e565b565b611625906116203361161a61161461160f5f610888565b61031f565b9161031f565b146110f5565b6116a9565b565b5f7f6d6967726174696f6e20696e2070726f67726573730000000000000000000000910152565b61165b6015602092610895565b61166481611627565b0190565b61167d9060208101905f81830391015261164e565b90565b1561168757565b61168f6100d2565b62461bcd60e51b8152806116a560048201611668565b0390fd5b6116cb906116c66116c16116bb613571565b1561114e565b611680565b61174f565b565b5f7f6d61696e74656e616e636520696e2070726f6772657373000000000000000000910152565b6117016017602092610895565b61170a816116cd565b0190565b6117239060208101905f8183039101526116f4565b90565b1561172d57565b6117356100d2565b62461bcd60e51b81528061174b6004820161170e565b0390fd5b6117719061176c61176761176161359f565b1561114e565b611726565b611b82565b565b61177c81610454565b0361178357565b5f80fd5b3561179181611773565b90565b5f7f696e76616c6964206269746d61736b0000000000000000000000000000000000910152565b6117c8600f602092610895565b6117d181611794565b0190565b6117ea9060208101905f8183039101526117bb565b90565b156117f457565b6117fc6100d2565b62461bcd60e51b815280611812600482016117d5565b0390fd5b67ffffffffffffffff1690565b61182f61183491610864565b611816565b90565b6118419054611823565b90565b90565b61185b61185661186092611844565b610920565b6104f7565b90565b634e487b7160e01b5f52601260045260245ffd5b611883611889916104f7565b916104f7565b908115611894570690565b611863565b50600290565b90565b6118ab81611899565b8210156118c5576118bd60029161189f565b910201905f90565b610a46565b906118d490610454565b9052565b6118e46118e991610864565b610a1f565b90565b6118f690546118d8565b90565b61190360406112ac565b90565b9061193d61193460016119176118f9565b9461192e6119265f83016113fa565b5f88016118ca565b016118ec565b602084016112dc565b565b61194890611906565b90565b6119559051610454565b90565b356119628161016e565b90565b5f7f73616d65206b6579737061636500000000000000000000000000000000000000910152565b611999600d602092610895565b6119a281611965565b0190565b6119bb9060208101905f81830391015261198c565b90565b156119c557565b6119cd6100d2565b62461bcd60e51b8152806119e3600482016119a6565b0390fd5b6119f0906104f7565b67ffffffffffffffff8114611a055760010190565b610dc7565b90611a1d67ffffffffffffffff91610a9f565b9181191691161790565b611a3b611a36611a40926104f7565b610920565b6104f7565b90565b90565b90611a5b611a56611a6292611a27565b611a43565b8254611a0a565b9055565b90611a7b611a76611a8292611366565b611382565b82546112f7565b9055565b90611ab160206001611ab794611aa95f8201611aa35f8801611787565b9061141d565b019201611958565b90611a66565b565b9190611aca57611ac891611a86565b565b610a8c565b611ad8906104f7565b9052565b90503590611ae982611773565b565b50611afa906020810190611adc565b90565b50611b0c906020810190610182565b90565b906020611b3a611b4293611b31611b285f830183611aeb565b5f860190610457565b82810190611afd565b910190610464565b565b611b79611b8094611b6f608094989795611b6560a086019a5f870190611acf565b6020850190611b0f565b6060830190611acf565b0190610f3b565b565b611bac611ba7611b935f8401611787565b611ba16102016001016113fa565b906135d4565b6117ed565b611c19611be2611bdc610203611bd6611bc6610207611837565b611bd06002611847565b90611877565b906118a2565b5061193f565b611bed5f820161194b565b611c09611c03611bfe5f8701611787565b610454565b91610454565b1415908115611d21575b506119be565b611c385f61020901611c32611c2d82611837565b6119e7565b90611a46565b611c56611c4e611c49610207611837565b6119e7565b610207611a46565b611c8a81611c84610203611c7e611c6e610207611837565b611c786002611847565b90611877565b906118a2565b90611ab9565b611ca3611c985f8301611787565b60016102090161141d565b611cc1611cb9611cb461020c610dba565b610ddb565b61020c610e4a565b611cce5f61020901611837565b90611cda610207611837565b91611d1c611ce961020c610dba565b7f8b6495d1a64e57453f038b5fe923459a17fc3f4d5420af6c58007bdc78aa868494611d136100d2565b94859485611b44565b0390a1565b611d2e915060200161133c565b611d4b611d45611d4060208601611958565b610168565b91610168565b14155f611c13565b611d5c906115f8565b565b5f7f6e6f206d61696e74656e616e6365000000000000000000000000000000000000910152565b611d92600e602092610895565b611d9b81611d5e565b0190565b611db49060208101905f818303910152611d85565b90565b15611dbe57565b611dc66100d2565b62461bcd60e51b815280611ddc60048201611d9f565b0390fd5b611df0611deb61359f565b611db7565b611df8611e37565b565b611e0e611e09611e13926111e2565b610920565b610314565b90565b611e1f90611dfa565b90565b9190611e35905f60208501940190610f3b565b565b611e445f61020b01610888565b611e56611e503361031f565b9161031f565b148015611ee1575b611e67906108f7565b611e7d611e735f611e16565b5f61020b01610ac2565b611e9b611e93611e8e61020c610dba565b610ddb565b61020c610e4a565b611ea661020c610dba565b611edc7f11943d6deda6f0591d72674788d272eb0209e18b8a3a021fa51cb3b5e9a2ab6191611ed36100d2565b91829182611e22565b0390a1565b50611e6733611f00611efa611ef55f610888565b61031f565b9161031f565b149050611e5e565b611f10611de0565b565b611f3f90611f3a33611f34611f2e611f295f610888565b61031f565b9161031f565b146110f5565b61203e565b565b611f4a81610511565b03611f5157565b5f80fd5b35611f5f81611f41565b90565b90611f6f61ffff91610a9f565b9181191691161790565b611f8d611f88611f9292610511565b610920565b610511565b90565b90565b90611fad611fa8611fb492611f79565b611f95565b8254611f62565b9055565b90611fca5f80611fd094019201611f55565b90611f98565b565b90611fdc91611fb8565b565b90503590611feb82611f41565b565b50611ffc906020810190611fde565b90565b905f6120116120199382810190611fed565b910190610518565b565b91602061203c92949361203560408201965f830190611fff565b0190610f3b565b565b61204a81610208611fd2565b61206861206061205b61020c610dba565b610ddb565b61020c610e4a565b61207361020c610dba565b7fb24d8d9dcfbb6be13176c1c7bfb0e76445a9ba2a3553b413d8671446f1030830916120a96120a06100d2565b9283928361201b565b0390a1565b6120b790611f12565b565b6120c46101006112ac565b90565b5f90565b606090565b67ffffffffffffffff81116120e55760200290565b610ae2565b6120f66120fb916120d0565b6112ac565b90565b5f90565b5f90565b61210e6118f9565b906020808361211b6120fe565b815201612126612102565b81525050565b612134612106565b90565b5f5b82811061214557505050565b60209061215061212c565b8184015201612139565b90612178612167836120ea565b9261217284916120d0565b90612137565b565b612184600261215a565b90565b5f90565b61219560206112ac565b90565b5f90565b6121a461218b565b906020826121b0612198565b81525050565b6121be61219c565b90565b6121cb60406112ac565b90565b6121d66121c1565b90602080836121e3612187565b8152016121ee6120fe565b81525050565b6121fc6121ce565b90565b61220960206112ac565b90565b6122146121ff565b906020826122206120c7565b81525050565b61222e61220c565b90565b5f90565b61223d6120b9565b90602080808080808080896122506120c7565b81520161225b6120cb565b81520161226661217a565b815201612271612187565b81520161227c6121b6565b8152016122876121f4565b815201612292612226565b81520161229d612231565b81525050565b6122ab612235565b90565b90565b6122c56122c06122ca926122ae565b610920565b610454565b90565b6122dc6122e291939293610454565b92610454565b82018092116122ed57565b610dc7565b67ffffffffffffffff811161230a5760208091020190565b610ae2565b9061232161231c836122f2565b6112ac565b918252565b61233060406112ac565b90565b606090565b612340612326565b906020808361234d6120c7565b815201612358612333565b81525050565b612366612338565b90565b5f5b82811061237757505050565b60209061238261235e565b818401520161236b565b906123b16123998361230f565b926020806123a786936122f2565b9201910390612369565b565b6123be6101006112ac565b90565b906123cb9061031f565b9052565b52565b906123dc82611899565b6123e5816120ea565b926123f0849161189f565b5f915b8383106124005750505050565b600260206001926124108561193f565b8152019201920191906123f3565b612427906123d2565b90565b52565b90612437906104f7565b9052565b61ffff1690565b61244e61245391610864565b61243b565b90565b6124609054612442565b90565b9061246d90610511565b9052565b906124906124885f61248161218b565b9401612456565b5f8401612463565b565b61249b90612471565b90565b52565b906124d86124cf60016124b26121c1565b946124c96124c15f8301611837565b5f880161242d565b016113fa565b602084016118ca565b565b6124e3906124a1565b90565b52565b906125086125005f6124f96121ff565b9401610888565b5f84016123c1565b565b612513906124e9565b90565b52565b906125239061056f565b9052565b61253090610454565b5f19811461253e5760010190565b610dc7565b61255761255261255c92610454565b610920565b610168565b90565b9061256982610338565b81101561257a576020809102010190565b610a46565b905f929180549061259961259283610b0a565b809461034f565b916001811690815f146125f057506001146125b4575b505050565b6125c19192939450610b34565b915f925b8184106125d857505001905f80806125af565b600181602092959395548486015201910192906125c5565b92949550505060ff19168252151560200201905f80806125af565b906126159161257f565b90565b90612638612631926126286100d2565b9384809261260b565b0383611283565b565b52565b9061267461266b600161264e612326565b9461266561265d5f8301610888565b5f88016123c1565b01612618565b6020840161263a565b565b61267f9061263d565b90565b61268a6122a3565b5060016102010161269a906113fa565b6126a3906135ff565b6126ac5f610888565b8160016126b8906122b1565b6126c1916122cd565b6126ca9061238c565b6102036126d8610207611837565b6102086102099161020b936126ee61020c610dba565b956126f76123b3565b975f890190612705916123c1565b6020880190612713916123cf565b61271c9061241e565b604087019061272a9161242a565b60608601906127389161242d565b61274190612492565b608085019061274f9161249e565b612758906124da565b60a0840190612766916124e6565b61276f9061250a565b60c083019061277d91612516565b60e082019061278b91612519565b60016102010161279a906113fa565b925f6127a5906111e5565b5b806127b96127b386610454565b91610454565b1161281c57612812906127d5866127cf83612543565b90613614565b6128175761280a6127ea600180018390610a64565b5060208601516127fa8492612676565b612804838361255f565b5261255f565b51505b612527565b6127a6565b61280d565b509250905090565b5f7f6e6f206d6967726174696f6e0000000000000000000000000000000000000000910152565b612858600c602092610895565b61286181612824565b0190565b61287a9060208101905f81830391015261284b565b90565b1561288457565b61288c6100d2565b62461bcd60e51b8152806128a260048201612865565b0390fd5b6128bf906128ba6128b5613571565b61287d565b612a55565b565b5f7f77726f6e67206d6967726174696f6e2069640000000000000000000000000000910152565b6128f56012602092610895565b6128fe816128c1565b0190565b6129179060208101905f8183039101526128e8565b90565b1561292157565b6129296100d2565b62461bcd60e51b81528061293f60048201612902565b0390fd5b61294d60406112ac565b90565b9061298661297d5f612960612943565b9461297761296f83830161098a565b8388016112ce565b01610a39565b602084016112dc565b565b61299190612950565b90565b5f7f6e6f742070756c6c696e67000000000000000000000000000000000000000000910152565b6129c8600b602092610895565b6129d181612994565b0190565b6129ea9060208101905f8183039101526129bb565b90565b156129f457565b6129fc6100d2565b62461bcd60e51b815280612a12600482016129d5565b0390fd5b612a1f9061031f565b9052565b604090612a4c612a539496959396612a4260608401985f850190611acf565b6020830190612a16565b0190610f3b565b565b612a7d90612a77612a71612a6c5f61020901611837565b6104f7565b916104f7565b1461291a565b612b02612af7612a99612a945f6001013390610957565b612988565b612aac612aa75f83016112ea565b6109f0565b612ad7612ad2612ac06001610209016113fa565b612acc6020850161133c565b90613652565b6129ed565b612af16020612aea6001610209016113fa565b920161133c565b90613691565b60016102090161141d565b612b20612b18612b1361020c610dba565b610ddb565b61020c610e4a565b612b2e6001610209016113fa565b612b40612b3a5f6111e5565b91610454565b145f14612b9d57612b545f61020901611837565b33612b6061020c610dba565b91612b977f01269879535f40ee8957e15e160bf1866c5e2728ff0cbc583d848821e2639b4e93612b8e6100d2565b93849384612a23565b0390a15b565b612baa5f61020901611837565b33612bb661020c610dba565b91612bed7faf5e90e72015f43138f66b4cd08bd1dfa2839030104f22a00af843fe847c6d1993612be46100d2565b93849384612a23565b0390a1612b9b565b612bfe906128a6565b565b612c2d90612c2833612c22612c1c612c175f610888565b61031f565b9161031f565b146110f5565b612ece565b565b5f7f696e206b65797370616365000000000000000000000000000000000000000000910152565b612c63600b602092610895565b612c6c81612c2f565b0190565b612c859060208101905f818303910152612c56565b90565b15612c8f57565b612c976100d2565b62461bcd60e51b815280612cad60048201612c70565b0390fd5b5f80910155565b905f03612cca57612cc890612cb1565b565b610a8c565b90612ce2905f1990602003600802610c3f565b8154169055565b905f91612d00612cf882610b34565b928354610c58565b905555565b919290602082105f14612d5e57601f8411600114612d2e57612d28929350610c58565b90555b5b565b5090612d54612d59936001612d4b612d4585610b34565b92610b3d565b82019101610bc9565b612ce9565b612d2b565b50612d958293612d6f600194610b34565b612d8e612d7b85610b3d565b820192601f861680612da0575b50610b3d565b0190610bc9565b600202179055612d2c565b612dac90888603612ccf565b5f612d88565b929091680100000000000000008211612e12576020115f14612e0357602081105f14612de757612de191610c58565b90555b5b565b60019160ff1916612df784610b34565b55600202019055612de4565b60019150600202019055612de5565b610ae2565b908154612e2381610b0a565b90818311612e4c575b818310612e3a575b50505050565b612e4393612d05565b5f808080612e34565b612e5883838387612db2565b612e2c565b5f612e6791612e17565b565b905f03612e7b57612e7990612e5d565b565b610a8c565b5f6001612e9292828082015501612e69565b565b905f03612ea657612ea490612e80565b565b610a8c565b916020612ecc929493612ec560408201965f830190612a16565b0190610f3b565b565b612f93612f88612f075f612eee612ee9826001018790610957565b61096d565b612f01612efc83830161098a565b6109f0565b01610a39565b612f0f613571565b5f1461302557612f37612f305f612f2961020382906118a2565b50016113fa565b8290613614565b80612ff7575b612f4690612c88565b5b612f5e5f612f59816001018790610957565b612cb8565b612f75612f6f600180018390610a64565b90612e94565b612f836102016001016113fa565b613691565b61020160010161141d565b612fb1612fa9612fa461020c610dba565b610ddb565b61020c610e4a565b612fbc61020c610dba565b7f6a1d7ddc82d57e783a3ae60737a6c1a4704fcf38d966561fea0af8564f2d895d91612ff2612fe96100d2565b92839283612eab565b0390a1565b50612f4661301e6130175f6130106102036001906118a2565b50016113fa565b8390613614565b9050612f3d565b61306c6130676130605f613059610203613053613043610207611837565b61304d6002611847565b90611877565b906118a2565b50016113fa565b8390613614565b612c88565b612f47565b61307a90612c00565b565b6130a9906130a43361309e6130986130935f610888565b61031f565b9161031f565b146110f5565b6130ab565b565b6130c4906130bf6130ba613571565b61287d565b613105565b565b6130cf906104f7565b5f81146130dd576001900390565b610dc7565b9160206131039294936130fc60408201965f830190611acf565b0190610f3b565b565b61312d9061312761312161311c5f61020901611837565b6104f7565b916104f7565b1461291a565b61314b61314361313e610207611837565b6130c6565b610207611a46565b6131626131575f6111e5565b60016102090161141d565b61318061317861317361020c610dba565b610ddb565b61020c610e4a565b61318d5f61020901611837565b61319861020c610dba565b7ff73240422246f63ed633ef3ce0726b8ab8fb69d46c8a4e5ecb0b2922668674a1916131ce6131c56100d2565b928392836130e2565b0390a1565b6131dc9061307c565b565b61320b90613206336132006131fa6131f55f610888565b61031f565b9161031f565b146110f5565b61320d565b565b613217815f610ac2565b61323561322d61322861020c610dba565b610ddb565b61020c610e4a565b61324061020c610dba565b7f476610ebc6647c15376100955efbf22ef2a0c3b923fc00b380b660c873ef20ac9161327661326d6100d2565b92839283612eab565b0390a1565b613284906131de565b565b61329f61329a613294613571565b1561114e565b611680565b6132a76132a9565b565b6132c26132bd6132b761359f565b1561114e565b611726565b6132ca6132cc565b565b6132e45f6132de816001013390610957565b0161098a565b8015613367575b6132f4906108f7565b613302335f61020b01610ac2565b61332061331861331361020c610dba565b610ddb565b61020c610e4a565b3361332c61020c610dba565b7fbc2748cf02f7a1291525e866efc76ab3b96d32d7afcbb26c53daec617b38b479916133626133596100d2565b92839283612eab565b0390a1565b506132f43361338661338061337b5f610888565b61031f565b9161031f565b1490506132eb565b613396613286565b565b5f7f656d707479206f70657261746f72206461746100000000000000000000000000910152565b6133cc6013602092610895565b6133d581613398565b0190565b6133ee9060208101905f8183039101526133bf565b90565b156133f857565b6134006100d2565b62461bcd60e51b815280613416600482016133d9565b0390fd5b61342e61342961343392610511565b610920565b610454565b90565b5f7f6f70657261746f72206461746120746f6f206c61726765000000000000000000910152565b61346a6017602092610895565b61347381613436565b0190565b61348c9060208101905f81830391015261345d565b90565b1561349657565b61349e6100d2565b62461bcd60e51b8152806134b460048201613477565b0390fd5b6134fd906134d8816134d26134cc5f6111e5565b91610454565b116133f1565b6134f66134f06134eb5f61020801612456565b61341a565b91610454565b111561348f565b565b61351361350e61351892610168565b610920565b610454565b90565b61353a9061353461352e61353f94610454565b91610454565b90610b47565b610454565b90565b6135699061354e610bb1565b509161356461355e6001926134ff565b916122b1565b61351b565b1790565b5f90565b61357961356d565b506135886001610209016113fa565b61359a6135945f6111e5565b91610454565b141590565b6135a761356d565b506135b55f61020b01610888565b6135cf6135c96135c45f611e16565b61031f565b9161031f565b141590565b6135e8906135e061356d565b509119610454565b166135fb6135f55f6111e5565b91610454565b1490565b6136119061360b610bb1565b50613884565b90565b61363b9061362061356d565b50916136366136306001926134ff565b916122b1565b61351b565b1661364e6136485f6111e5565b91610454565b1490565b6136799061365e61356d565b509161367461366e6001926134ff565b916122b1565b61351b565b1661368c6136865f6111e5565b91610454565b141590565b6136bb6136c1916136a0610bb1565b50926136b66136b06001926134ff565b916122b1565b61351b565b19610454565b1690565b90565b6136dc6136d76136e1926136c5565b610920565b610454565b90565b90565b6136fb6136f6613700926136e4565b610920565b610168565b90565b6137229061371c61371661372794610168565b91610454565b90610b47565b610454565b90565b6137499061374361373d61374e94610454565b91610454565b90610c3f565b610454565b90565b90565b61376861376361376d92613751565b610920565b610454565b90565b90565b61378761378261378c92613770565b610920565b610168565b90565b90565b6137a66137a16137ab9261378f565b610920565b610454565b90565b90565b6137c56137c06137ca926137ae565b610920565b610168565b90565b90565b6137e46137df6137e9926137cd565b610920565b610454565b90565b90565b6138036137fe613808926137ec565b610920565b610168565b90565b90565b61382261381d6138279261380b565b610920565b610454565b90565b90565b61384161383c6138469261382a565b610920565b610168565b90565b90565b61386061385b61386592613849565b610920565b610454565b90565b61387c61387761388192611844565b610920565b610168565b90565b61388c610bb1565b506138cc6138bc826138b66138b06fffffffffffffffffffffffffffffffff6136c8565b91610454565b11613a19565b6138c660076136e7565b90613703565b61390d6138fd6138dd84849061372a565b6138f76138f167ffffffffffffffff613754565b91610454565b11613a19565b6139076006613773565b90613703565b1761394b61393b61391f84849061372a565b61393561392f63ffffffff613792565b91610454565b11613a19565b61394560056137b1565b90613703565b1761398761397761395d84849061372a565b61397161396b61ffff6137d0565b91610454565b11613a19565b61398160046137ef565b90613703565b176139c26139b261399984849061372a565b6139ac6139a660ff61380e565b91610454565b11613a19565b6139bc600361382d565b90613703565b176139fd6139ed6139d484849061372a565b6139e76139e1600f61384c565b91610454565b11613a19565b6139f76002613868565b90613703565b17906d010102020202030303030303030360801b90821c1a1790565b613a21610bb1565b5015159056fea2646970667358221220c28697cc6a6540c09428c2e17f38085e7684669de4a6b573cbcc14d6da425e7264736f6c634300081c0033","sourceMap":"1020:7568:24:-:0;;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;:::i;:::-;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;:::i;:::-;;;;;;;;;;:::o;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;:::o;:::-;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;:::o;:::-;;;:::o;:::-;;:::o;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;:::o;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;:::i;:::-;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;:::o;:::-;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;:::i;:::-;:::o;:::-;;;;:::o;:::-;;:::o;:::-;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;:::o;:::-;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;:::o;:::-;;;;;;;:::o;:::-;;;:::o;:::-;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;:::i;:::-;;;;;:::i;:::-;;;:::o;:::-;;;:::o;:::-;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;;;;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;:::o;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;:::i;:::-;;;;;;:::o;:::-;;;;;:::i;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;;;;:::i;:::-;:::o;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;:::o;:::-;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;:::o;:::-;;:::i;1342:800::-;1537:26;1342:800;1437:61;1445:23;:16;:23;:::i;:::-;:30;;1472:3;1445:30;:::i;:::-;;;:::i;:::-;;;1437:61;:::i;:::-;1509:18;1517:10;1509:18;;:::i;:::-;1537:26;;:::i;:::-;1595:13;1607:1;1595:13;:::i;:::-;1639:3;1610:1;:27;;1614:23;:16;:23;:::i;:::-;1610:27;:::i;:::-;;;:::i;:::-;;;;;1639:3;1683:16;:31;;:24;:19;:16;1700:1;1683:19;;:::i;:::-;;:24;;:31;:::i;:::-;;:::i;:::-;1729:87;1737:56;1738:55;;:47;:13;;:21;1760:24;:16;:19;:16;1777:1;1760:19;;:::i;:::-;;:24;;:::i;:::-;1738:47;;:::i;:::-;:55;;:::i;:::-;1737:56;;:::i;:::-;1729:87;:::i;:::-;1831:94;1901:4;1881:44;1914:8;1920:1;1914:8;:::i;:::-;1881:44;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::i;:::-;1831:47;:21;:13;:21;1853:24;;:19;:16;1870:1;1853:19;;:::i;:::-;;:24;;:::i;:::-;1831:47;;:::i;:::-;:94;:::i;:::-;1939:44;1964:19;:16;1981:1;1964:19;;:::i;:::-;;1939:22;:19;:13;:19;1959:1;1939:22;;:::i;:::-;:44;;:::i;:::-;1639:3;:::i;:::-;1595:13;;1610:27;;2028:44;2041:30;2047:23;2004:68;1610:27;2047:23;:::i;:::-;2041:30;:::i;:::-;2028:44;:::i;:::-;2004:21;:13;:21;:68;:::i;:::-;2082:53;2114:21;;:13;:21;;:::i;:::-;2082:29;:12;:9;2092:1;2082:12;;:::i;:::-;;:29;:53;:::i;:::-;1342:800::o;1020:7568::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;8127:205;8251:74;8127:205;8200:41;8208:5;:9;;8216:1;8208:9;:::i;:::-;;;:::i;:::-;;8200:41;:::i;:::-;8259:38;;8268:29;;:8;:29;;:::i;:::-;8259:38;:::i;:::-;;;:::i;:::-;;;8251:74;:::i;:::-;8127:205::o;1020:7568::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;:::o;:::-;;:::i;9281:101::-;9355:15;9354:21;9281:101;9327:7;;:::i;:::-;9355:1;:15;9360:10;9355:1;9368;9360:10;:::i;:::-;9355:15;;:::i;:::-;;:::i;:::-;9354:21;9374:1;9354:21;:::i;:::-;;;:::i;:::-;9347:28;:::o","linkReferences":{}},"deployedBytecode":{"object":"0x60806040526004361015610013575b6107fc565b61001d5f356100cc565b806326322217146100c75780632b726062146100c257806347011c5c146100bd57806353bfb584146100b857806365706f9c146100b357806375418b9d146100ae5780639d44e717146100a9578063c05665dd146100a4578063e88e97491461009f578063f2fde38b1461009a5763f5f2d9f10361000e576107c9565b610796565b610763565b610730565b6106bc565b610646565b6102e1565b61027d565b61023b565b6101d6565b610135565b60e01c90565b60405190565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b908160409103126100f65790565b6100e4565b9060208282031261012b575f82013567ffffffffffffffff81116101265761012392016100e8565b90565b6100e0565b6100dc565b5f0190565b346101635761014d6101483660046100fb565b610f6e565b6101556100d2565b8061015f81610130565b0390f35b6100d8565b60ff1690565b61017781610168565b0361017e57565b5f80fd5b9050359061018f8261016e565b565b9190916040818403126101d1576101aa835f8301610182565b92602082013567ffffffffffffffff81116101cc576101c992016100e8565b90565b6100e0565b6100dc565b34610205576101ef6101e9366004610191565b906115ec565b6101f76100d2565b8061020181610130565b0390f35b6100d8565b908160409103126102185790565b6100e4565b9060408282031261023657610233915f0161020a565b90565b6100dc565b346102695761025361024e36600461021d565b611d53565b61025b6100d2565b8061026581610130565b0390f35b6100d8565b5f91031261027857565b6100dc565b346102ab5761028d36600461026e565b610295611f08565b61029d6100d2565b806102a781610130565b0390f35b6100d8565b908160209103126102be5790565b6100e4565b906020828203126102dc576102d9915f016102b0565b90565b6100dc565b3461030f576102f96102f43660046102c3565b6120ae565b6103016100d2565b8061030b81610130565b0390f35b6100d8565b60018060a01b031690565b61032890610314565b90565b6103349061031f565b9052565b5190565b60209181520190565b60200190565b5190565b60209181520190565b90825f9392825e0152565b601f801991011690565b61038c61039560209361039a936103838161034b565b9384809361034f565b95869101610358565b610363565b0190565b6103c991602060408201926103b95f8201515f85019061032b565b015190602081840391015261036d565b90565b906103d69161039e565b90565b60200190565b906103f36103ec83610338565b809261033c565b908161040460208302840194610345565b925f915b83831061041757505050505090565b90919293946020610439610433838560019503875289516103cc565b976103d9565b9301930191939290610408565b50600290565b905090565b90565b90565b61046090610454565b9052565b61046d90610168565b9052565b90602080610493936104895f8201515f860190610457565b0151910190610464565b565b906104a281604093610471565b0190565b60200190565b6104c86104c26104bb83610446565b809461044c565b91610451565b5f915b8383106104d85750505050565b6104ee6104e86001928451610495565b926104a6565b920191906104cb565b67ffffffffffffffff1690565b61050d906104f7565b9052565b61ffff1690565b61052190610511565b9052565b905f80610536930151910190610518565b565b9060208061055a936105505f8201515f860190610504565b0151910190610457565b565b905f8061056d93015191019061032b565b565b6fffffffffffffffffffffffffffffffff1690565b61058d9061056f565b9052565b9061062b9061016060e06105c561018084016105b35f8801515f87019061032b565b602087015185820360208701526103df565b946105d8604082015160408601906104ac565b6105ea606082015160c0860190610504565b6105fb608082015183860190610525565b61060e60a0820151610100860190610538565b61062160c082015161014086019061055c565b0151910190610584565b90565b6106439160208201915f818403910152610591565b90565b346106765761065636600461026e565b610672610661612682565b6106696100d2565b9182918261062e565b0390f35b6100d8565b610684816104f7565b0361068b57565b5f80fd5b9050359061069c8261067b565b565b906020828203126106b7576106b4915f0161068f565b90565b6100dc565b346106ea576106d46106cf36600461069e565b612bf5565b6106dc6100d2565b806106e681610130565b0390f35b6100d8565b6106f88161031f565b036106ff57565b5f80fd5b90503590610710826106ef565b565b9060208282031261072b57610728915f01610703565b90565b6100dc565b3461075e57610748610743366004610712565b613071565b6107506100d2565b8061075a81610130565b0390f35b6100d8565b346107915761077b61077636600461069e565b6131d3565b6107836100d2565b8061078d81610130565b0390f35b6100d8565b346107c4576107ae6107a9366004610712565b61327b565b6107b66100d2565b806107c081610130565b0390f35b6100d8565b346107f7576107d936600461026e565b6107e161338e565b6107e96100d2565b806107f381610130565b0390f35b6100d8565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b90359060016020038136030382121561084e570180359067ffffffffffffffff82116108495760200191600182023603831361084457565b610808565b610804565b610800565b5090565b35610861816106ef565b90565b5f1c90565b60018060a01b031690565b61088061088591610864565b610869565b90565b6108929054610874565b90565b60209181520190565b5f7f756e617574686f72697a65640000000000000000000000000000000000000000910152565b6108d2600c602092610895565b6108db8161089e565b0190565b6108f49060208101905f8183039101526108c5565b90565b156108fe57565b6109066100d2565b62461bcd60e51b81528061091c600482016108df565b0390fd5b90565b61093761093261093c92610314565b610920565b610314565b90565b61094890610923565b90565b6109549061093f565b90565b906109619061094b565b5f5260205260405f2090565b90565b60ff1690565b61098261098791610864565b610970565b90565b6109949054610976565b90565b5f7f756e6b6e6f776e206f70657261746f7200000000000000000000000000000000910152565b6109cb6010602092610895565b6109d481610997565b0190565b6109ed9060208101905f8183039101526109be565b90565b156109f757565b6109ff6100d2565b62461bcd60e51b815280610a15600482016109d8565b0390fd5b60081c90565b60ff1690565b610a31610a3691610a19565b610a1f565b90565b610a439054610a25565b90565b634e487b7160e01b5f52603260045260245ffd5b5061010090565b90565b610a6d81610a5a565b821015610a8757610a7f600291610a61565b910201905f90565b610a46565b634e487b7160e01b5f525f60045260245ffd5b5f1b90565b90610ab560018060a01b0391610a9f565b9181191691161790565b90565b90610ad7610ad2610ade9261094b565b610abf565b8254610aa4565b9055565b634e487b7160e01b5f52604160045260245ffd5b634e487b7160e01b5f52602260045260245ffd5b9060016002830492168015610b2a575b6020831014610b2557565b610af6565b91607f1691610b1a565b5f5260205f2090565b601f602091010490565b1b90565b91906008610b66910291610b605f1984610b47565b92610b47565b9181191691161790565b610b84610b7f610b8992610454565b610920565b610454565b90565b90565b9190610ba5610ba0610bad93610b70565b610b8c565b908354610b4b565b9055565b5f90565b610bc791610bc1610bb1565b91610b8f565b565b5b818110610bd5575050565b80610be25f600193610bb5565b01610bca565b9190601f8111610bf8575b505050565b610c04610c2993610b34565b906020610c1084610b3d565b83019310610c31575b610c2290610b3d565b0190610bc9565b5f8080610bf3565b9150610c2281929050610c19565b1c90565b90610c53905f1990600802610c3f565b191690565b81610c6291610c43565b906002021790565b91610c759082610853565b9067ffffffffffffffff8211610d3457610c9982610c938554610b0a565b85610be8565b5f90601f8311600114610ccc57918091610cbb935f92610cc0575b5050610c58565b90555b565b90915001355f80610cb4565b601f19831691610cdb85610b34565b925f5b818110610d1c57509160029391856001969410610d02575b50505002019055610cbe565b610d12910135601f841690610c43565b90555f8080610cf6565b91936020600181928787013581550195019201610cde565b610ae2565b90610d449291610c6a565b565b90610d736001610d7993610d675f8201610d615f8701610857565b90610ac2565b0191602081019061080c565b91610d39565b565b9190610d8c57610d8a91610d46565b565b610a8c565b6fffffffffffffffffffffffffffffffff1690565b610db2610db791610864565b610d91565b90565b610dc49054610da6565b90565b634e487b7160e01b5f52601160045260245ffd5b610de49061056f565b6fffffffffffffffffffffffffffffffff8114610e015760010190565b610dc7565b90610e216fffffffffffffffffffffffffffffffff91610a9f565b9181191691161790565b610e3f610e3a610e449261056f565b610920565b61056f565b90565b90565b90610e5f610e5a610e6692610e2b565b610e47565b8254610e06565b9055565b50610e79906020810190610703565b90565b5f80fd5b5f80fd5b5f80fd5b9035600160200382360303811215610ec957016020813591019167ffffffffffffffff8211610ec4576001820236038313610ebf57565b610e80565b610e7c565b610e84565b90825f939282370152565b9190610ef381610eec81610ef89561034f565b8095610ece565b610363565b0190565b610f3891610f2a6040820192610f20610f175f830183610e6a565b5f85019061032b565b6020810190610e88565b916020818503910152610ed9565b90565b610f449061056f565b9052565b92916020610f64610f6c9360408701908782035f890152610efc565b940190610f3b565b565b610f8d610f88610f8283602081019061080c565b90610853565b6134b8565b33610faa610fa4610f9f5f8501610857565b61031f565b9161031f565b148015611075575b610fbb906108f7565b611011610fde610fd95f600101610fd35f8601610857565b90610957565b61096d565b610ff1610fec5f830161098a565b6109f0565b61100b83916110055f600180019201610a39565b90610a64565b90610d7b565b61102f61102761102261020c610dba565b610ddb565b61020c610e4a565b61103a61020c610dba565b7f5aab2c32b1e447db4dba1d2790fe8b863d4775042b10b92e00dab9d6b671b5b5916110706110676100d2565b92839283610f48565b0390a1565b50610fbb3361109461108e6110895f610888565b61031f565b9161031f565b149050610fb2565b5f7f6e6f7420746865206f776e657200000000000000000000000000000000000000910152565b6110d0600d602092610895565b6110d98161109c565b0190565b6110f29060208101905f8183039101526110c3565b90565b156110fc57565b6111046100d2565b62461bcd60e51b81528061111a600482016110dd565b0390fd5b9061114c916111473361114161113b6111365f610888565b61031f565b9161031f565b146110f5565b61147f565b565b151590565b5f7f616c726561647920657869737473000000000000000000000000000000000000910152565b611187600e602092610895565b61119081611153565b0190565b6111a99060208101905f81830391015261117a565b90565b156111b357565b6111bb6100d2565b62461bcd60e51b8152806111d160048201611194565b0390fd5b6111df9054610b0a565b90565b90565b6111f96111f46111fe926111e2565b610920565b610454565b90565b5f7f736c6f74206f6363757069656400000000000000000000000000000000000000910152565b611235600d602092610895565b61123e81611201565b0190565b6112579060208101905f818303910152611228565b90565b1561126157565b6112696100d2565b62461bcd60e51b81528061127f60048201611242565b0390fd5b9061128d90610363565b810190811067ffffffffffffffff8211176112a757604052565b610ae2565b906112bf6112b86100d2565b9283611283565b565b6112cb60406112ac565b90565b906112d89061114e565b9052565b906112e690610168565b9052565b6112f4905161114e565b90565b9061130360ff91610a9f565b9181191691161790565b6113169061114e565b90565b90565b9061133161132c6113389261130d565b611319565b82546112f7565b9055565b6113469051610168565b90565b60081b90565b9061135c61ff0091611349565b9181191691161790565b61137a61137561137f92610168565b610920565b610168565b90565b90565b9061139a6113956113a192611366565b611382565b825461134f565b9055565b906113cf60205f6113d5946113c78282016113c18488016112ea565b9061131c565b01920161133c565b90611385565b565b906113e1916113a5565b565b90565b6113f26113f791610864565b6113e3565b90565b61140490546113e6565b90565b906114135f1991610a9f565b9181191691161790565b9061143261142d61143992610b70565b610b8c565b8254611407565b9055565b61144690610168565b9052565b93929061147560409161147d9461146860608901925f8a019061143d565b8782036020890152610efc565b940190610f3b565b565b61149e61149961149384602081019061080c565b90610853565b6134b8565b6114d16114cc6114c65f6114c0816001016114ba838901610857565b90610957565b0161098a565b1561114e565b6111ac565b6115056114ed60016114e68180018590610a64565b50016111d5565b6114ff6114f95f6111e5565b91610454565b1461125a565b611548600161152b836115226115196112c1565b935f85016112ce565b602083016112dc565b6115435f60010161153d5f8701610857565b90610957565b6113d7565b6115608261155a600180018490610a64565b90610d7b565b61158661157b6115746102016001016113fa565b8390613542565b61020160010161141d565b6115a461159c61159761020c610dba565b610ddb565b61020c610e4a565b906115b061020c610dba565b916115e77f952e65f049c574f487580ba41dcf6b0ea8350ef8abc8647a8a11dfaa7af6bad6936115de6100d2565b9384938461144a565b0390a1565b906115f69161111e565b565b611625906116203361161a61161461160f5f610888565b61031f565b9161031f565b146110f5565b6116a9565b565b5f7f6d6967726174696f6e20696e2070726f67726573730000000000000000000000910152565b61165b6015602092610895565b61166481611627565b0190565b61167d9060208101905f81830391015261164e565b90565b1561168757565b61168f6100d2565b62461bcd60e51b8152806116a560048201611668565b0390fd5b6116cb906116c66116c16116bb613571565b1561114e565b611680565b61174f565b565b5f7f6d61696e74656e616e636520696e2070726f6772657373000000000000000000910152565b6117016017602092610895565b61170a816116cd565b0190565b6117239060208101905f8183039101526116f4565b90565b1561172d57565b6117356100d2565b62461bcd60e51b81528061174b6004820161170e565b0390fd5b6117719061176c61176761176161359f565b1561114e565b611726565b611b82565b565b61177c81610454565b0361178357565b5f80fd5b3561179181611773565b90565b5f7f696e76616c6964206269746d61736b0000000000000000000000000000000000910152565b6117c8600f602092610895565b6117d181611794565b0190565b6117ea9060208101905f8183039101526117bb565b90565b156117f457565b6117fc6100d2565b62461bcd60e51b815280611812600482016117d5565b0390fd5b67ffffffffffffffff1690565b61182f61183491610864565b611816565b90565b6118419054611823565b90565b90565b61185b61185661186092611844565b610920565b6104f7565b90565b634e487b7160e01b5f52601260045260245ffd5b611883611889916104f7565b916104f7565b908115611894570690565b611863565b50600290565b90565b6118ab81611899565b8210156118c5576118bd60029161189f565b910201905f90565b610a46565b906118d490610454565b9052565b6118e46118e991610864565b610a1f565b90565b6118f690546118d8565b90565b61190360406112ac565b90565b9061193d61193460016119176118f9565b9461192e6119265f83016113fa565b5f88016118ca565b016118ec565b602084016112dc565b565b61194890611906565b90565b6119559051610454565b90565b356119628161016e565b90565b5f7f73616d65206b6579737061636500000000000000000000000000000000000000910152565b611999600d602092610895565b6119a281611965565b0190565b6119bb9060208101905f81830391015261198c565b90565b156119c557565b6119cd6100d2565b62461bcd60e51b8152806119e3600482016119a6565b0390fd5b6119f0906104f7565b67ffffffffffffffff8114611a055760010190565b610dc7565b90611a1d67ffffffffffffffff91610a9f565b9181191691161790565b611a3b611a36611a40926104f7565b610920565b6104f7565b90565b90565b90611a5b611a56611a6292611a27565b611a43565b8254611a0a565b9055565b90611a7b611a76611a8292611366565b611382565b82546112f7565b9055565b90611ab160206001611ab794611aa95f8201611aa35f8801611787565b9061141d565b019201611958565b90611a66565b565b9190611aca57611ac891611a86565b565b610a8c565b611ad8906104f7565b9052565b90503590611ae982611773565b565b50611afa906020810190611adc565b90565b50611b0c906020810190610182565b90565b906020611b3a611b4293611b31611b285f830183611aeb565b5f860190610457565b82810190611afd565b910190610464565b565b611b79611b8094611b6f608094989795611b6560a086019a5f870190611acf565b6020850190611b0f565b6060830190611acf565b0190610f3b565b565b611bac611ba7611b935f8401611787565b611ba16102016001016113fa565b906135d4565b6117ed565b611c19611be2611bdc610203611bd6611bc6610207611837565b611bd06002611847565b90611877565b906118a2565b5061193f565b611bed5f820161194b565b611c09611c03611bfe5f8701611787565b610454565b91610454565b1415908115611d21575b506119be565b611c385f61020901611c32611c2d82611837565b6119e7565b90611a46565b611c56611c4e611c49610207611837565b6119e7565b610207611a46565b611c8a81611c84610203611c7e611c6e610207611837565b611c786002611847565b90611877565b906118a2565b90611ab9565b611ca3611c985f8301611787565b60016102090161141d565b611cc1611cb9611cb461020c610dba565b610ddb565b61020c610e4a565b611cce5f61020901611837565b90611cda610207611837565b91611d1c611ce961020c610dba565b7f8b6495d1a64e57453f038b5fe923459a17fc3f4d5420af6c58007bdc78aa868494611d136100d2565b94859485611b44565b0390a1565b611d2e915060200161133c565b611d4b611d45611d4060208601611958565b610168565b91610168565b14155f611c13565b611d5c906115f8565b565b5f7f6e6f206d61696e74656e616e6365000000000000000000000000000000000000910152565b611d92600e602092610895565b611d9b81611d5e565b0190565b611db49060208101905f818303910152611d85565b90565b15611dbe57565b611dc66100d2565b62461bcd60e51b815280611ddc60048201611d9f565b0390fd5b611df0611deb61359f565b611db7565b611df8611e37565b565b611e0e611e09611e13926111e2565b610920565b610314565b90565b611e1f90611dfa565b90565b9190611e35905f60208501940190610f3b565b565b611e445f61020b01610888565b611e56611e503361031f565b9161031f565b148015611ee1575b611e67906108f7565b611e7d611e735f611e16565b5f61020b01610ac2565b611e9b611e93611e8e61020c610dba565b610ddb565b61020c610e4a565b611ea661020c610dba565b611edc7f11943d6deda6f0591d72674788d272eb0209e18b8a3a021fa51cb3b5e9a2ab6191611ed36100d2565b91829182611e22565b0390a1565b50611e6733611f00611efa611ef55f610888565b61031f565b9161031f565b149050611e5e565b611f10611de0565b565b611f3f90611f3a33611f34611f2e611f295f610888565b61031f565b9161031f565b146110f5565b61203e565b565b611f4a81610511565b03611f5157565b5f80fd5b35611f5f81611f41565b90565b90611f6f61ffff91610a9f565b9181191691161790565b611f8d611f88611f9292610511565b610920565b610511565b90565b90565b90611fad611fa8611fb492611f79565b611f95565b8254611f62565b9055565b90611fca5f80611fd094019201611f55565b90611f98565b565b90611fdc91611fb8565b565b90503590611feb82611f41565b565b50611ffc906020810190611fde565b90565b905f6120116120199382810190611fed565b910190610518565b565b91602061203c92949361203560408201965f830190611fff565b0190610f3b565b565b61204a81610208611fd2565b61206861206061205b61020c610dba565b610ddb565b61020c610e4a565b61207361020c610dba565b7fb24d8d9dcfbb6be13176c1c7bfb0e76445a9ba2a3553b413d8671446f1030830916120a96120a06100d2565b9283928361201b565b0390a1565b6120b790611f12565b565b6120c46101006112ac565b90565b5f90565b606090565b67ffffffffffffffff81116120e55760200290565b610ae2565b6120f66120fb916120d0565b6112ac565b90565b5f90565b5f90565b61210e6118f9565b906020808361211b6120fe565b815201612126612102565b81525050565b612134612106565b90565b5f5b82811061214557505050565b60209061215061212c565b8184015201612139565b90612178612167836120ea565b9261217284916120d0565b90612137565b565b612184600261215a565b90565b5f90565b61219560206112ac565b90565b5f90565b6121a461218b565b906020826121b0612198565b81525050565b6121be61219c565b90565b6121cb60406112ac565b90565b6121d66121c1565b90602080836121e3612187565b8152016121ee6120fe565b81525050565b6121fc6121ce565b90565b61220960206112ac565b90565b6122146121ff565b906020826122206120c7565b81525050565b61222e61220c565b90565b5f90565b61223d6120b9565b90602080808080808080896122506120c7565b81520161225b6120cb565b81520161226661217a565b815201612271612187565b81520161227c6121b6565b8152016122876121f4565b815201612292612226565b81520161229d612231565b81525050565b6122ab612235565b90565b90565b6122c56122c06122ca926122ae565b610920565b610454565b90565b6122dc6122e291939293610454565b92610454565b82018092116122ed57565b610dc7565b67ffffffffffffffff811161230a5760208091020190565b610ae2565b9061232161231c836122f2565b6112ac565b918252565b61233060406112ac565b90565b606090565b612340612326565b906020808361234d6120c7565b815201612358612333565b81525050565b612366612338565b90565b5f5b82811061237757505050565b60209061238261235e565b818401520161236b565b906123b16123998361230f565b926020806123a786936122f2565b9201910390612369565b565b6123be6101006112ac565b90565b906123cb9061031f565b9052565b52565b906123dc82611899565b6123e5816120ea565b926123f0849161189f565b5f915b8383106124005750505050565b600260206001926124108561193f565b8152019201920191906123f3565b612427906123d2565b90565b52565b90612437906104f7565b9052565b61ffff1690565b61244e61245391610864565b61243b565b90565b6124609054612442565b90565b9061246d90610511565b9052565b906124906124885f61248161218b565b9401612456565b5f8401612463565b565b61249b90612471565b90565b52565b906124d86124cf60016124b26121c1565b946124c96124c15f8301611837565b5f880161242d565b016113fa565b602084016118ca565b565b6124e3906124a1565b90565b52565b906125086125005f6124f96121ff565b9401610888565b5f84016123c1565b565b612513906124e9565b90565b52565b906125239061056f565b9052565b61253090610454565b5f19811461253e5760010190565b610dc7565b61255761255261255c92610454565b610920565b610168565b90565b9061256982610338565b81101561257a576020809102010190565b610a46565b905f929180549061259961259283610b0a565b809461034f565b916001811690815f146125f057506001146125b4575b505050565b6125c19192939450610b34565b915f925b8184106125d857505001905f80806125af565b600181602092959395548486015201910192906125c5565b92949550505060ff19168252151560200201905f80806125af565b906126159161257f565b90565b90612638612631926126286100d2565b9384809261260b565b0383611283565b565b52565b9061267461266b600161264e612326565b9461266561265d5f8301610888565b5f88016123c1565b01612618565b6020840161263a565b565b61267f9061263d565b90565b61268a6122a3565b5060016102010161269a906113fa565b6126a3906135ff565b6126ac5f610888565b8160016126b8906122b1565b6126c1916122cd565b6126ca9061238c565b6102036126d8610207611837565b6102086102099161020b936126ee61020c610dba565b956126f76123b3565b975f890190612705916123c1565b6020880190612713916123cf565b61271c9061241e565b604087019061272a9161242a565b60608601906127389161242d565b61274190612492565b608085019061274f9161249e565b612758906124da565b60a0840190612766916124e6565b61276f9061250a565b60c083019061277d91612516565b60e082019061278b91612519565b60016102010161279a906113fa565b925f6127a5906111e5565b5b806127b96127b386610454565b91610454565b1161281c57612812906127d5866127cf83612543565b90613614565b6128175761280a6127ea600180018390610a64565b5060208601516127fa8492612676565b612804838361255f565b5261255f565b51505b612527565b6127a6565b61280d565b509250905090565b5f7f6e6f206d6967726174696f6e0000000000000000000000000000000000000000910152565b612858600c602092610895565b61286181612824565b0190565b61287a9060208101905f81830391015261284b565b90565b1561288457565b61288c6100d2565b62461bcd60e51b8152806128a260048201612865565b0390fd5b6128bf906128ba6128b5613571565b61287d565b612a55565b565b5f7f77726f6e67206d6967726174696f6e2069640000000000000000000000000000910152565b6128f56012602092610895565b6128fe816128c1565b0190565b6129179060208101905f8183039101526128e8565b90565b1561292157565b6129296100d2565b62461bcd60e51b81528061293f60048201612902565b0390fd5b61294d60406112ac565b90565b9061298661297d5f612960612943565b9461297761296f83830161098a565b8388016112ce565b01610a39565b602084016112dc565b565b61299190612950565b90565b5f7f6e6f742070756c6c696e67000000000000000000000000000000000000000000910152565b6129c8600b602092610895565b6129d181612994565b0190565b6129ea9060208101905f8183039101526129bb565b90565b156129f457565b6129fc6100d2565b62461bcd60e51b815280612a12600482016129d5565b0390fd5b612a1f9061031f565b9052565b604090612a4c612a539496959396612a4260608401985f850190611acf565b6020830190612a16565b0190610f3b565b565b612a7d90612a77612a71612a6c5f61020901611837565b6104f7565b916104f7565b1461291a565b612b02612af7612a99612a945f6001013390610957565b612988565b612aac612aa75f83016112ea565b6109f0565b612ad7612ad2612ac06001610209016113fa565b612acc6020850161133c565b90613652565b6129ed565b612af16020612aea6001610209016113fa565b920161133c565b90613691565b60016102090161141d565b612b20612b18612b1361020c610dba565b610ddb565b61020c610e4a565b612b2e6001610209016113fa565b612b40612b3a5f6111e5565b91610454565b145f14612b9d57612b545f61020901611837565b33612b6061020c610dba565b91612b977f01269879535f40ee8957e15e160bf1866c5e2728ff0cbc583d848821e2639b4e93612b8e6100d2565b93849384612a23565b0390a15b565b612baa5f61020901611837565b33612bb661020c610dba565b91612bed7faf5e90e72015f43138f66b4cd08bd1dfa2839030104f22a00af843fe847c6d1993612be46100d2565b93849384612a23565b0390a1612b9b565b612bfe906128a6565b565b612c2d90612c2833612c22612c1c612c175f610888565b61031f565b9161031f565b146110f5565b612ece565b565b5f7f696e206b65797370616365000000000000000000000000000000000000000000910152565b612c63600b602092610895565b612c6c81612c2f565b0190565b612c859060208101905f818303910152612c56565b90565b15612c8f57565b612c976100d2565b62461bcd60e51b815280612cad60048201612c70565b0390fd5b5f80910155565b905f03612cca57612cc890612cb1565b565b610a8c565b90612ce2905f1990602003600802610c3f565b8154169055565b905f91612d00612cf882610b34565b928354610c58565b905555565b919290602082105f14612d5e57601f8411600114612d2e57612d28929350610c58565b90555b5b565b5090612d54612d59936001612d4b612d4585610b34565b92610b3d565b82019101610bc9565b612ce9565b612d2b565b50612d958293612d6f600194610b34565b612d8e612d7b85610b3d565b820192601f861680612da0575b50610b3d565b0190610bc9565b600202179055612d2c565b612dac90888603612ccf565b5f612d88565b929091680100000000000000008211612e12576020115f14612e0357602081105f14612de757612de191610c58565b90555b5b565b60019160ff1916612df784610b34565b55600202019055612de4565b60019150600202019055612de5565b610ae2565b908154612e2381610b0a565b90818311612e4c575b818310612e3a575b50505050565b612e4393612d05565b5f808080612e34565b612e5883838387612db2565b612e2c565b5f612e6791612e17565b565b905f03612e7b57612e7990612e5d565b565b610a8c565b5f6001612e9292828082015501612e69565b565b905f03612ea657612ea490612e80565b565b610a8c565b916020612ecc929493612ec560408201965f830190612a16565b0190610f3b565b565b612f93612f88612f075f612eee612ee9826001018790610957565b61096d565b612f01612efc83830161098a565b6109f0565b01610a39565b612f0f613571565b5f1461302557612f37612f305f612f2961020382906118a2565b50016113fa565b8290613614565b80612ff7575b612f4690612c88565b5b612f5e5f612f59816001018790610957565b612cb8565b612f75612f6f600180018390610a64565b90612e94565b612f836102016001016113fa565b613691565b61020160010161141d565b612fb1612fa9612fa461020c610dba565b610ddb565b61020c610e4a565b612fbc61020c610dba565b7f6a1d7ddc82d57e783a3ae60737a6c1a4704fcf38d966561fea0af8564f2d895d91612ff2612fe96100d2565b92839283612eab565b0390a1565b50612f4661301e6130175f6130106102036001906118a2565b50016113fa565b8390613614565b9050612f3d565b61306c6130676130605f613059610203613053613043610207611837565b61304d6002611847565b90611877565b906118a2565b50016113fa565b8390613614565b612c88565b612f47565b61307a90612c00565b565b6130a9906130a43361309e6130986130935f610888565b61031f565b9161031f565b146110f5565b6130ab565b565b6130c4906130bf6130ba613571565b61287d565b613105565b565b6130cf906104f7565b5f81146130dd576001900390565b610dc7565b9160206131039294936130fc60408201965f830190611acf565b0190610f3b565b565b61312d9061312761312161311c5f61020901611837565b6104f7565b916104f7565b1461291a565b61314b61314361313e610207611837565b6130c6565b610207611a46565b6131626131575f6111e5565b60016102090161141d565b61318061317861317361020c610dba565b610ddb565b61020c610e4a565b61318d5f61020901611837565b61319861020c610dba565b7ff73240422246f63ed633ef3ce0726b8ab8fb69d46c8a4e5ecb0b2922668674a1916131ce6131c56100d2565b928392836130e2565b0390a1565b6131dc9061307c565b565b61320b90613206336132006131fa6131f55f610888565b61031f565b9161031f565b146110f5565b61320d565b565b613217815f610ac2565b61323561322d61322861020c610dba565b610ddb565b61020c610e4a565b61324061020c610dba565b7f476610ebc6647c15376100955efbf22ef2a0c3b923fc00b380b660c873ef20ac9161327661326d6100d2565b92839283612eab565b0390a1565b613284906131de565b565b61329f61329a613294613571565b1561114e565b611680565b6132a76132a9565b565b6132c26132bd6132b761359f565b1561114e565b611726565b6132ca6132cc565b565b6132e45f6132de816001013390610957565b0161098a565b8015613367575b6132f4906108f7565b613302335f61020b01610ac2565b61332061331861331361020c610dba565b610ddb565b61020c610e4a565b3361332c61020c610dba565b7fbc2748cf02f7a1291525e866efc76ab3b96d32d7afcbb26c53daec617b38b479916133626133596100d2565b92839283612eab565b0390a1565b506132f43361338661338061337b5f610888565b61031f565b9161031f565b1490506132eb565b613396613286565b565b5f7f656d707479206f70657261746f72206461746100000000000000000000000000910152565b6133cc6013602092610895565b6133d581613398565b0190565b6133ee9060208101905f8183039101526133bf565b90565b156133f857565b6134006100d2565b62461bcd60e51b815280613416600482016133d9565b0390fd5b61342e61342961343392610511565b610920565b610454565b90565b5f7f6f70657261746f72206461746120746f6f206c61726765000000000000000000910152565b61346a6017602092610895565b61347381613436565b0190565b61348c9060208101905f81830391015261345d565b90565b1561349657565b61349e6100d2565b62461bcd60e51b8152806134b460048201613477565b0390fd5b6134fd906134d8816134d26134cc5f6111e5565b91610454565b116133f1565b6134f66134f06134eb5f61020801612456565b61341a565b91610454565b111561348f565b565b61351361350e61351892610168565b610920565b610454565b90565b61353a9061353461352e61353f94610454565b91610454565b90610b47565b610454565b90565b6135699061354e610bb1565b509161356461355e6001926134ff565b916122b1565b61351b565b1790565b5f90565b61357961356d565b506135886001610209016113fa565b61359a6135945f6111e5565b91610454565b141590565b6135a761356d565b506135b55f61020b01610888565b6135cf6135c96135c45f611e16565b61031f565b9161031f565b141590565b6135e8906135e061356d565b509119610454565b166135fb6135f55f6111e5565b91610454565b1490565b6136119061360b610bb1565b50613884565b90565b61363b9061362061356d565b50916136366136306001926134ff565b916122b1565b61351b565b1661364e6136485f6111e5565b91610454565b1490565b6136799061365e61356d565b509161367461366e6001926134ff565b916122b1565b61351b565b1661368c6136865f6111e5565b91610454565b141590565b6136bb6136c1916136a0610bb1565b50926136b66136b06001926134ff565b916122b1565b61351b565b19610454565b1690565b90565b6136dc6136d76136e1926136c5565b610920565b610454565b90565b90565b6136fb6136f6613700926136e4565b610920565b610168565b90565b6137229061371c61371661372794610168565b91610454565b90610b47565b610454565b90565b6137499061374361373d61374e94610454565b91610454565b90610c3f565b610454565b90565b90565b61376861376361376d92613751565b610920565b610454565b90565b90565b61378761378261378c92613770565b610920565b610168565b90565b90565b6137a66137a16137ab9261378f565b610920565b610454565b90565b90565b6137c56137c06137ca926137ae565b610920565b610168565b90565b90565b6137e46137df6137e9926137cd565b610920565b610454565b90565b90565b6138036137fe613808926137ec565b610920565b610168565b90565b90565b61382261381d6138279261380b565b610920565b610454565b90565b90565b61384161383c6138469261382a565b610920565b610168565b90565b90565b61386061385b61386592613849565b610920565b610454565b90565b61387c61387761388192611844565b610920565b610168565b90565b61388c610bb1565b506138cc6138bc826138b66138b06fffffffffffffffffffffffffffffffff6136c8565b91610454565b11613a19565b6138c660076136e7565b90613703565b61390d6138fd6138dd84849061372a565b6138f76138f167ffffffffffffffff613754565b91610454565b11613a19565b6139076006613773565b90613703565b1761394b61393b61391f84849061372a565b61393561392f63ffffffff613792565b91610454565b11613a19565b61394560056137b1565b90613703565b1761398761397761395d84849061372a565b61397161396b61ffff6137d0565b91610454565b11613a19565b61398160046137ef565b90613703565b176139c26139b261399984849061372a565b6139ac6139a660ff61380e565b91610454565b11613a19565b6139bc600361382d565b90613703565b176139fd6139ed6139d484849061372a565b6139e76139e1600f61384c565b91610454565b11613a19565b6139f76002613868565b90613703565b17906d010102020202030303030303030360801b90821c1a1790565b613a21610bb1565b5015159056fea2646970667358221220c28697cc6a6540c09428c2e17f38085e7684669de4a6b573cbcc14d6da425e7264736f6c634300081c0033","sourceMap":"1020:7568:24:-:0;;;;;;;;;-1:-1:-1;1020:7568:24;:::i;:::-;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;;;:::o;:::-;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;:::i;:::-;;;;:::o;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;:::o;:::-;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;:::i;:::-;;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;:::o;:::-;;;;;;;:::o;:::-;;;;:::o;:::-;;;:::o;:::-;;;;;;;:::o;:::-;;;;;;;;;;:::o;:::-;;;;;;;;:::o;:::-;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;;;;;;:::o;:::-;;;;:::o;:::-;;:::o;:::-;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;:::o;:::-;;;;;;;:::i;:::-;;;:::o;:::-;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;;;;:::o;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;;;:::i;:::-;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::i;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;;;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;:::o;:::-;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;:::o;:::-;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;:::o;:::-;;:::o;:::-;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;:::o;:::-;;;;;;;:::o;:::-;;;:::o;:::-;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;:::i;:::-;;;;;:::i;:::-;;;:::o;:::-;;;:::o;:::-;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;;;;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;:::o;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;:::i;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;;;;:::i;:::-;:::o;:::-;;:::i;:::-;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;;;;;;;;;:::o;:::-;;;;;;;;;;:::i;:::-;;;;:::i;:::-;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;:::o;5643:469::-;5747:20;;:13;:8;:13;;;;;:::i;:::-;:20;;:::i;:::-;;:::i;:::-;5786:10;:27;;5800:13;;:8;:13;;:::i;:::-;5786:27;:::i;:::-;;;:::i;:::-;;:50;;;;5643:469;5778:75;;;:::i;:::-;5992:41;5864:59;5887:36;:21;:13;:21;5909:13;;:8;:13;;:::i;:::-;5887:36;;:::i;:::-;5864:59;:::i;:::-;5933:40;5941:11;;:3;:11;;:::i;:::-;5933:40;:::i;:::-;5992:30;6025:8;5992:13;6012:9;;5992:19;:13;:19;6012:3;:9;;:::i;:::-;5992:30;;:::i;:::-;:41;;:::i;:::-;6043:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;6097:7;;;:::i;:::-;6067:38;;;;;:::i;:::-;;;;;;:::i;:::-;;;;5643:469::o;5786:50::-;5817:10;5778:75;5817:10;:19;;5831:5;;;:::i;:::-;5817:19;:::i;:::-;;;:::i;:::-;;5786:50;;;;1020:7568;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;2148:94;;2234:1;2148:94;2179:45;2187:10;:19;;2201:5;;;:::i;:::-;2187:19;:::i;:::-;;;:::i;:::-;;2179:45;:::i;:::-;2234:1;:::i;:::-;2148:94::o;1020:7568::-;;;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;:::i;:::-;;;;:::i;:::-;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;:::i;:::-;:::o;:::-;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;:::i;:::-;:::o;5045:592::-;5167:20;;:13;:8;:13;;;;;:::i;:::-;:20;;:::i;:::-;;:::i;:::-;5198:72;5206:45;5207:44;;:36;:13;;:21;5229:13;:8;;:13;;:::i;:::-;5207:36;;:::i;:::-;:44;;:::i;:::-;5206:45;;:::i;:::-;5198:72;:::i;:::-;5280:67;5288:36;:29;:24;:13;;:19;5308:3;5288:24;;:::i;:::-;;:29;:36;:::i;:::-;:41;;5328:1;5288:41;:::i;:::-;;;:::i;:::-;;5280:67;:::i;:::-;5366:78;5425:4;5405:39;5438:3;5405:39;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::i;:::-;5366:36;:21;:13;:21;5388:13;;:8;:13;;:::i;:::-;5366:36;;:::i;:::-;:78;:::i;:::-;5454:35;5481:8;5454:24;:19;:13;:19;5474:3;5454:24;;:::i;:::-;:35;;:::i;:::-;5499:55;5523:31;:21;;:13;:21;;:::i;:::-;5550:3;5523:31;;:::i;:::-;5499:21;:13;:21;:55;:::i;:::-;5565:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;5612:8;5622:7;;;:::i;:::-;5589:41;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;5045:592::o;:::-;;;;;:::i;:::-;:::o;2148:94::-;2234:1;2148:94;2179:45;2187:10;:19;;2201:5;;;:::i;:::-;2187:19;:::i;:::-;;;:::i;:::-;;2179:45;:::i;:::-;2234:1;:::i;:::-;2148:94::o;1020:7568::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;2354:109;2455:1;2354:109;2387:58;2395:24;2396:23;;:::i;:::-;2395:24;;:::i;:::-;2387:58;:::i;:::-;2455:1;:::i;:::-;2354:109::o;1020:7568::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;2581:115;2688:1;2581:115;2616:62;2624:26;2625:25;;:::i;:::-;2624:26;;:::i;:::-;2616:62;:::i;:::-;2688:1;:::i;:::-;2581:115::o;1020:7568::-;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;:::o;:::-;;:::i;:::-;;;;:::o;:::-;;:::o;:::-;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;:::o;:::-;;:::i;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;;;;:::i;:::-;:::o;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;:::i;:::-;:::o;2702:780::-;2812:90;2820:62;:28;;:11;:28;;:::i;:::-;2860:21;;:13;:21;;:::i;:::-;2820:62;;:::i;:::-;2812:90;:::i;:::-;2983:202;2913:60;2943:30;:9;2953:19;:15;;;:::i;:::-;:19;2971:1;2953:19;:::i;:::-;;;:::i;:::-;2943:30;;:::i;:::-;;2913:60;:::i;:::-;3004:28;;:11;:28;;:::i;:::-;:60;;3036:28;;:11;:28;;:::i;:::-;3004:60;:::i;:::-;;;:::i;:::-;;;:142;;;;;2702:780;2983:202;;:::i;:::-;3200:14;:12;:9;:12;:14;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;3225:17;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;3252:44;3285:11;3252:30;:9;3262:19;:15;;;:::i;:::-;:19;3280:1;3262:19;:::i;:::-;;;:::i;:::-;3252:30;;:::i;:::-;:44;;:::i;:::-;3307:64;3343:28;;:11;:28;;:::i;:::-;3307:33;:9;:33;:64;:::i;:::-;3382:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;3423:12;;:9;:12;;:::i;:::-;3437:11;3450:15;;;:::i;:::-;3467:7;3406:69;3467:7;;;:::i;:::-;3406:69;;;;:::i;:::-;;;;;;:::i;:::-;;;;2702:780::o;3004:142::-;3080:31;:11;;:31;;;:::i;:::-;:66;;3115:31;;:11;:31;;:::i;:::-;3080:66;:::i;:::-;;;:::i;:::-;;;3004:142;;;2702:780;;;;:::i;:::-;:::o;1020:7568::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;2469:106;2505:52;2513:25;;:::i;:::-;2505:52;:::i;:::-;2567:1;;:::i;:::-;2469:106::o;1020:7568::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;:::i;:::-;:::o;4788:251::-;4859:16;;:11;:16;;:::i;:::-;:30;;4879:10;4859:30;:::i;:::-;;;:::i;:::-;;:53;;;;4788:251;4851:78;;;:::i;:::-;4940:29;4959:10;4967:1;4959:10;:::i;:::-;4940:16;:11;:16;:29;:::i;:::-;4980:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;5024:7;;;:::i;:::-;5004:28;;;;;:::i;:::-;;;;;;:::i;:::-;;;;4788:251::o;4859:53::-;4893:10;4851:78;4893:10;:19;;4907:5;;;:::i;:::-;4893:19;:::i;:::-;;;:::i;:::-;;4859:53;;;;4788:251;;;:::i;:::-;:::o;2148:94::-;2234:1;2148:94;2179:45;2187:10;:19;;2201:5;;;:::i;:::-;2187:19;:::i;:::-;;;:::i;:::-;;2179:45;:::i;:::-;2234:1;:::i;:::-;2148:94::o;1020:7568::-;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;;:::i;:::-;:::o;:::-;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;:::o;6910:184::-;6994:22;7005:11;6994:22;;:::i;:::-;7026:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;7079:7;;;:::i;:::-;7050:37;;;;;:::i;:::-;;;;;;:::i;:::-;;;;6910:184::o;:::-;;;;:::i;:::-;:::o;1020:7568::-;;;;:::i;:::-;;:::o;:::-;;;:::o;:::-;;;:::o;:::-;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;:::o;:::-;;;:::o;:::-;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::o;:::-;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;:::o;:::-;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;:::i;:::-;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;:::o;:::-;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::o;:::-;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::o;:::-;;;:::i;:::-;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::o;:::-;;;:::i;:::-;;:::o;:::-;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::o;:::-;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;:::i;:::-;;:::i;:::-;;;;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;:::o;:::-;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::o;:::-;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;:::o;:::-;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;:::o;:::-;;;;;:::i;:::-;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;;;;:::o;:::-;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;:::o;:::-;;;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;:::i;:::-;;;:::o;:::-;;;;:::i;:::-;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;:::i;:::-;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;:::i;:::-;:::o;:::-;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;:::i;:::-;;:::o;7276:845::-;7316:18;;:::i;:::-;7371:13;;:21;;;;;:::i;:::-;:32;;;:::i;:::-;7484:5;;;:::i;:::-;7541:14;7558:1;7541:18;;;:::i;:::-;;;;:::i;:::-;7522:38;;;:::i;:::-;7585:9;7625:15;;;:::i;:::-;7664:8;7697:9;7733:11;;7767:7;;;;:::i;:::-;7451:334;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;7827:13;:21;;;;;:::i;:::-;7876:1;;7864:13;;;:::i;:::-;7900:3;7879:1;:19;;7884:14;7879:19;:::i;:::-;;;:::i;:::-;;;;7900:3;7923:20;:34;:20;7948:8;7954:1;7948:8;:::i;:::-;7923:34;;:::i;:::-;7919:81;;8014:57;8049:22;:19;:13;:19;8069:1;8049:22;;:::i;:::-;;8014:29;:11;:29;;:57;8044:1;8014:57;;:::i;:::-;;;;;:::i;:::-;;;:::i;:::-;;;7864:13;7900:3;:::i;:::-;7864:13;;7919:81;7977:8;;7879:19;;;;;;8096:18;:::o;1020:7568::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;2248:100;2340:1;2248:100;2282:48;2290:23;;:::i;:::-;2282:48;:::i;:::-;2340:1;:::i;:::-;2248:100::o;1020:7568::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;:::i;:::-;;;;;:::i;:::-;:::o;:::-;;;;:::i;:::-;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;:::i;:::-;:::o;3488:709::-;3558:49;3488:709;3566:18;;3572:12;;:9;:12;;:::i;:::-;3566:18;:::i;:::-;;;:::i;:::-;;3558:49;:::i;:::-;3840:93;3876:57;3618:63;3648:33;:21;:13;:21;3670:10;3648:33;;:::i;:::-;3618:63;:::i;:::-;3691:48;3699:19;;:11;:19;;:::i;:::-;3691:48;:::i;:::-;3749:80;3757:56;:33;;:9;:33;;:::i;:::-;3795:17;;:11;:17;;:::i;:::-;3757:56;;:::i;:::-;3749:80;:::i;:::-;3915:17;;3876:33;;:9;:33;;:::i;:::-;3915:11;:17;;:::i;:::-;3876:57;;:::i;:::-;3840:33;:9;:33;:93;:::i;:::-;3948:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;3971:33;;:9;:33;;:::i;:::-;:38;;4008:1;3971:38;:::i;:::-;;;:::i;:::-;;3967:224;;;;4049:12;;:9;:12;;:::i;:::-;4063:10;4075:7;;;:::i;:::-;4030:53;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;3967:224;3488:709::o;3967:224::-;4146:12;;:9;:12;;:::i;:::-;4160:10;4172:7;;;:::i;:::-;4119:61;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;3967:224;;3488:709;;;;:::i;:::-;:::o;2148:94::-;2234:1;2148:94;2179:45;2187:10;:19;;2201:5;;;:::i;:::-;2187:19;:::i;:::-;;;:::i;:::-;;2179:45;:::i;:::-;2234:1;:::i;:::-;2148:94::o;1020:7568::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;;;:::o;:::-;;;;;;;;;:::i;:::-;:::o;:::-;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;:::o;:::-;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;:::o;:::-;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;-1:-1:-1;1020:7568:24;;;;;;;;;;;;;;:::i;:::-;;;;;:::o;:::-;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;:::o;:::-;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;:::i;:::-;:::o;:::-;;:::i;:::-;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;;;;;;;:::i;:::-;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;:::o;6118:786::-;6762:55;6786:31;6341:13;;6200:65;6227:38;:13;;:21;6249:15;6227:38;;:::i;:::-;6200:65;:::i;:::-;6275:44;6283:15;:7;;:15;;:::i;:::-;6275:44;:::i;:::-;6341:13;;:::i;:::-;6369:23;;:::i;:::-;6365:281;;;;6428:38;:29;;:12;:9;6438:1;6428:12;;:::i;:::-;;:29;;:::i;:::-;6462:3;6428:38;;:::i;:::-;:80;;;6365:281;6420:104;;;:::i;:::-;6365:281;6664:46;;6671:38;:13;;:21;6693:15;6671:38;;:::i;:::-;6664:46;:::i;:::-;6720:32;6727:24;:19;:13;:19;6747:3;6727:24;;:::i;:::-;6720:32;;:::i;:::-;6786:21;;:13;:21;;:::i;:::-;:31;:::i;:::-;6762:21;:13;:21;:55;:::i;:::-;6828:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;6889:7;;;:::i;:::-;6852:45;;;;;:::i;:::-;;;;;;:::i;:::-;;;;6118:786::o;6428:80::-;6470:9;6420:104;6470:38;:29;;:12;:9;6480:1;6470:12;;:::i;:::-;;:29;;:::i;:::-;6504:3;6470:38;;:::i;:::-;6428:80;;;;6365:281;6555:80;6563:56;:47;;:30;:9;6573:19;:15;;;:::i;:::-;:19;6591:1;6573:19;:::i;:::-;;;:::i;:::-;6563:30;;:::i;:::-;;:47;;:::i;:::-;6615:3;6563:56;;:::i;:::-;6555:80;:::i;:::-;6365:281;;6118:786;;;;:::i;:::-;:::o;2148:94::-;2234:1;2148:94;2179:45;2187:10;:19;;2201:5;;;:::i;:::-;2187:19;:::i;:::-;;;:::i;:::-;;2179:45;:::i;:::-;2234:1;:::i;:::-;2148:94::o;2248:100::-;2340:1;2248:100;2282:48;2290:23;;:::i;:::-;2282:48;:::i;:::-;2340:1;:::i;:::-;2248:100::o;1020:7568::-;;;;:::i;:::-;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;:::o;4203:282::-;4280:49;4203:282;4288:18;;4294:12;;:9;:12;;:::i;:::-;4288:18;:::i;:::-;;;:::i;:::-;;4280:49;:::i;:::-;4340:17;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;4367:37;;4403:1;4367:37;:::i;:::-;:33;:9;:33;:37;:::i;:::-;4415:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;4456:12;;:9;:12;;:::i;:::-;4470:7;;;:::i;:::-;4439:39;;;;;:::i;:::-;;;;;;:::i;:::-;;;;4203:282::o;:::-;;;;:::i;:::-;:::o;2148:94::-;2234:1;2148:94;2179:45;2187:10;:19;;2201:5;;;:::i;:::-;2187:19;:::i;:::-;;;:::i;:::-;;2179:45;:::i;:::-;2234:1;:::i;:::-;2148:94::o;7100:170::-;7174:16;7182:8;7174:16;;:::i;:::-;7200:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;7255:7;;;:::i;:::-;7224:39;;;;;:::i;:::-;;;;;;:::i;:::-;;;;7100:170::o;:::-;;;;:::i;:::-;:::o;2354:109::-;2387:58;2395:24;2396:23;;:::i;:::-;2395:24;;:::i;:::-;2387:58;:::i;:::-;2455:1;;:::i;:::-;2354:109::o;2581:115::-;2616:62;2624:26;2625:25;;:::i;:::-;2624:26;;:::i;:::-;2616:62;:::i;:::-;2688:1;;:::i;:::-;2581:115::o;4491:291::-;4572:41;;:33;:13;;:21;4594:10;4572:33;;:::i;:::-;:41;;:::i;:::-;:64;;;;4491:291;4564:89;;;:::i;:::-;4672:29;4691:10;4672:16;:11;:16;:29;:::i;:::-;4712:9;;;;;:::i;:::-;;:::i;:::-;;;:::i;:::-;4755:10;4767:7;;;:::i;:::-;4736:39;;;;;:::i;:::-;;;;;;:::i;:::-;;;;4491:291::o;4572:64::-;4617:10;4564:89;4617:10;:19;;4631:5;;;:::i;:::-;4617:19;:::i;:::-;;;:::i;:::-;;4572:64;;;;4491:291;;;:::i;:::-;:::o;1020:7568::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;:::o;:::-;;;;;;:::i;:::-;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;:::o;:::-;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;8127:205;8251:74;8127:205;8200:41;8208:5;:9;;8216:1;8208:9;:::i;:::-;;;:::i;:::-;;8200:41;:::i;:::-;8259:38;;8268:29;;:8;:29;;:::i;:::-;8259:38;:::i;:::-;;;:::i;:::-;;;8251:74;:::i;:::-;8127:205::o;1020:7568::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;:::i;:::-;;:::o;9388:122::-;9488:15;9388:122;9451:7;;:::i;:::-;9478;9488:1;:15;9493:10;9488:1;9501;9493:10;:::i;:::-;9488:15;;:::i;:::-;;:::i;:::-;9478:25;9471:32;:::o;1020:7568::-;;;:::o;8338:124::-;8394:4;;:::i;:::-;8417:9;:33;;:9;:33;;:::i;:::-;:38;;8454:1;8417:38;:::i;:::-;;;:::i;:::-;;;8410:45;:::o;8468:118::-;8526:4;;:::i;:::-;8549:11;:16;;:11;:16;;:::i;:::-;:30;;8569:10;8577:1;8569:10;:::i;:::-;8549:30;:::i;:::-;;;:::i;:::-;;;8542:37;:::o;10216:120::-;10318:6;10216:120;10288:4;;:::i;:::-;10311;10319:5;10318:6;;:::i;:::-;10311:13;:18;;10328:1;10311:18;:::i;:::-;;;:::i;:::-;;10304:25;:::o;10097:113::-;10181:18;10097:113;10155:7;;:::i;:::-;10191;10181:18;:::i;:::-;10174:25;:::o;9780:127::-;9878:15;9780:127;9842:4;;:::i;:::-;9867:7;9878:1;:15;9883:10;9878:1;9891;9883:10;:::i;:::-;9878:15;;:::i;:::-;;:::i;:::-;9867:27;9866:34;;9899:1;9866:34;:::i;:::-;;;:::i;:::-;;9859:41;:::o;9647:127::-;9745:15;9647:127;9709:4;;:::i;:::-;9734:7;9745:1;:15;9750:10;9745:1;9758;9750:10;:::i;:::-;9745:15;;:::i;:::-;;:::i;:::-;9734:27;9733:34;;9766:1;9733:34;:::i;:::-;;;:::i;:::-;;;9726:41;:::o;9516:125::-;9618:15;9616:18;9516:125;9579:7;;:::i;:::-;9606;9618:1;:15;9623:10;9618:1;9631;9623:10;:::i;:::-;9618:15;;:::i;:::-;;:::i;:::-;9616:18;;:::i;:::-;9606:28;9599:35;:::o;1020:7568::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;:::-;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::o;26222:2393:21:-;26270:9;;:::i;:::-;26383:1;26367:60;:55;26383:1;:38;;26387:34;26383:38;:::i;:::-;;;:::i;:::-;;26367:55;:::i;:::-;:60;26426:1;26367:60;:::i;:::-;;;:::i;:::-;26508:51;:46;26525:6;:1;26530;26525:6;;:::i;:::-;26524:29;;26535:18;26524:29;:::i;:::-;;;:::i;:::-;;26508:46;:::i;:::-;:51;26558:1;26508:51;:::i;:::-;;;:::i;:::-;26503:56;26639:43;:38;26656:6;:1;26661;26656:6;;:::i;:::-;26655:21;;26666:10;26655:21;:::i;:::-;;;:::i;:::-;;26639:38;:::i;:::-;:43;26681:1;26639:43;:::i;:::-;;;:::i;:::-;26634:48;26762:39;:34;26779:6;:1;26784;26779:6;;:::i;:::-;26778:17;;26789:6;26778:17;:::i;:::-;;;:::i;:::-;;26762:34;:::i;:::-;:39;26800:1;26762:39;:::i;:::-;;;:::i;:::-;26757:44;26879:37;:32;26896:6;:1;26901;26896:6;;:::i;:::-;26895:15;;26906:4;26895:15;:::i;:::-;;;:::i;:::-;;26879:32;:::i;:::-;:37;26915:1;26879:37;:::i;:::-;;;:::i;:::-;26874:42;26993:36;:31;27010:6;:1;27015;27010:6;;:::i;:::-;27009:14;;27020:3;27009:14;:::i;:::-;;;:::i;:::-;;26993:31;:::i;:::-;:36;27028:1;26993:36;:::i;:::-;;;:::i;:::-;26988:41;28465:144;;;;;;;;;26222:2393;:::o;34795:145:22:-;34842:9;;:::i;:::-;34863:71;;;34795:145;:::o","linkReferences":{}},"methodIdentifiers":{"abortMigration(uint64)":"e88e9749","addNodeOperator(uint8,(address,bytes))":"2b726062","completeMigration(uint64)":"9d44e717","finishMaintenance()":"53bfb584","getView()":"75418b9d","removeNodeOperator(address)":"c05665dd","startMaintenance()":"f5f2d9f1","startMigration((uint256,uint8))":"47011c5c","transferOwnership(address)":"f2fde38b","updateNodeOperator((address,bytes))":"26322217","updateSettings((uint16))":"65706f9c"},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.28+commit.7893614a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"components\":[{\"internalType\":\"uint16\",\"name\":\"maxOperatorDataBytes\",\"type\":\"uint16\"}],\"internalType\":\"struct Settings\",\"name\":\"initialSettings\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"struct NodeOperator[]\",\"name\":\"initialOperators\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"MaintenanceFinished\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"MaintenanceStarted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"MigrationAborted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"operatorAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"MigrationCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"operatorAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"MigrationDataPullCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"operatorsBitmask\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"replicationStrategy\",\"type\":\"uint8\"}],\"indexed\":false,\"internalType\":\"struct Keyspace\",\"name\":\"newKeyspace\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"newKeyspaceVersion\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"MigrationStarted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"idx\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"struct NodeOperator\",\"name\":\"operator\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"NodeOperatorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"operatorAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"NodeOperatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"struct NodeOperator\",\"name\":\"operator\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"NodeOperatorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"cluserVersion\",\"type\":\"uint128\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint16\",\"name\":\"maxOperatorDataBytes\",\"type\":\"uint16\"}],\"indexed\":false,\"internalType\":\"struct Settings\",\"name\":\"newSettings\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"clusterVersion\",\"type\":\"uint128\"}],\"name\":\"SettingsUpdated\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"}],\"name\":\"abortMigration\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"idx\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"struct NodeOperator\",\"name\":\"operator\",\"type\":\"tuple\"}],\"name\":\"addNodeOperator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"}],\"name\":\"completeMigration\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"finishMaintenance\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getView\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"struct NodeOperator[]\",\"name\":\"nodeOperatorSlots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"operatorsBitmask\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"replicationStrategy\",\"type\":\"uint8\"}],\"internalType\":\"struct Keyspace[2]\",\"name\":\"keyspaces\",\"type\":\"tuple[2]\"},{\"internalType\":\"uint64\",\"name\":\"keyspaceVersion\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint16\",\"name\":\"maxOperatorDataBytes\",\"type\":\"uint16\"}],\"internalType\":\"struct Settings\",\"name\":\"settings\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"pullingOperatorsBitmask\",\"type\":\"uint256\"}],\"internalType\":\"struct Migration\",\"name\":\"migration\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"slot\",\"type\":\"address\"}],\"internalType\":\"struct Maintenance\",\"name\":\"maintenance\",\"type\":\"tuple\"},{\"internalType\":\"uint128\",\"name\":\"version\",\"type\":\"uint128\"}],\"internalType\":\"struct ClusterView\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operatorAddress\",\"type\":\"address\"}],\"name\":\"removeNodeOperator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startMaintenance\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"operatorsBitmask\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"replicationStrategy\",\"type\":\"uint8\"}],\"internalType\":\"struct Keyspace\",\"name\":\"newKeyspace\",\"type\":\"tuple\"}],\"name\":\"startMigration\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"struct NodeOperator\",\"name\":\"operator\",\"type\":\"tuple\"}],\"name\":\"updateNodeOperator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint16\",\"name\":\"maxOperatorDataBytes\",\"type\":\"uint16\"}],\"internalType\":\"struct Settings\",\"name\":\"newSettings\",\"type\":\"tuple\"}],\"name\":\"updateSettings\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/Cluster.sol\":\"Cluster\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[\":@openzeppelin-contracts-5.3.0/=dependencies/@openzeppelin-contracts-5.3.0/\",\":forge-std-1.9.7/=dependencies/forge-std-1.9.7/src/\",\":forge-std/=dependencies/forge-std/src/\",\":openzeppelin-contracts/=dependencies/@openzeppelin-contracts-5.3.0/\"],\"viaIR\":true},\"sources\":{\"dependencies/openzeppelin-contracts/utils/Panic.sol\":{\"keccak256\":\"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a\",\"dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG\"]},\"dependencies/openzeppelin-contracts/utils/math/Math.sol\":{\"keccak256\":\"0x1225214420c83ebcca88f2ae2b50f053aaa7df7bd684c3e878d334627f2edfc6\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6c5fab4970634f9ab9a620983dc1c8a30153981a0b1a521666e269d0a11399d3\",\"dweb:/ipfs/QmVRnBC575MESGkEHndjujtR7qub2FzU9RWy9eKLp4hPZB\"]},\"dependencies/openzeppelin-contracts/utils/math/SafeCast.sol\":{\"keccak256\":\"0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b1d578337048cad08c1c03041cca5978eff5428aa130c781b271ad9e5566e1f8\",\"dweb:/ipfs/QmPFKL2r9CBsMwmUqqdcFPfHZB2qcs9g1HDrPxzWSxomvy\"]},\"src/Cluster.sol\":{\"keccak256\":\"0xac5b938cdbe809da30fdf59bd2492c6aa341ff7ea88f152be3543202b7485a44\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://d5a43c1a46e45e9b06a441c5f0bd6cd2cba55c7a2aa2ffe605c2b51bd1823b89\",\"dweb:/ipfs/QmcSR9umgpQyM4YtDCrBC7nhSQD1UuTdUqEUCwCohB58Fy\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.28+commit.7893614a"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"struct Settings","name":"initialSettings","type":"tuple","components":[{"internalType":"uint16","name":"maxOperatorDataBytes","type":"uint16"}]},{"internalType":"struct NodeOperator[]","name":"initialOperators","type":"tuple[]","components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}]}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"MaintenanceFinished","anonymous":false},{"inputs":[{"internalType":"address","name":"addr","type":"address","indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"MaintenanceStarted","anonymous":false},{"inputs":[{"internalType":"uint64","name":"id","type":"uint64","indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"MigrationAborted","anonymous":false},{"inputs":[{"internalType":"uint64","name":"id","type":"uint64","indexed":false},{"internalType":"address","name":"operatorAddress","type":"address","indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"MigrationCompleted","anonymous":false},{"inputs":[{"internalType":"uint64","name":"id","type":"uint64","indexed":false},{"internalType":"address","name":"operatorAddress","type":"address","indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"MigrationDataPullCompleted","anonymous":false},{"inputs":[{"internalType":"uint64","name":"id","type":"uint64","indexed":false},{"internalType":"struct Keyspace","name":"newKeyspace","type":"tuple","components":[{"internalType":"uint256","name":"operatorsBitmask","type":"uint256"},{"internalType":"uint8","name":"replicationStrategy","type":"uint8"}],"indexed":false},{"internalType":"uint64","name":"newKeyspaceVersion","type":"uint64","indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"MigrationStarted","anonymous":false},{"inputs":[{"internalType":"uint8","name":"idx","type":"uint8","indexed":false},{"internalType":"struct NodeOperator","name":"operator","type":"tuple","components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"NodeOperatorAdded","anonymous":false},{"inputs":[{"internalType":"address","name":"operatorAddress","type":"address","indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"NodeOperatorRemoved","anonymous":false},{"inputs":[{"internalType":"struct NodeOperator","name":"operator","type":"tuple","components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"NodeOperatorUpdated","anonymous":false},{"inputs":[{"internalType":"address","name":"newOwner","type":"address","indexed":false},{"internalType":"uint128","name":"cluserVersion","type":"uint128","indexed":false}],"type":"event","name":"OwnershipTransferred","anonymous":false},{"inputs":[{"internalType":"struct Settings","name":"newSettings","type":"tuple","components":[{"internalType":"uint16","name":"maxOperatorDataBytes","type":"uint16"}],"indexed":false},{"internalType":"uint128","name":"clusterVersion","type":"uint128","indexed":false}],"type":"event","name":"SettingsUpdated","anonymous":false},{"inputs":[{"internalType":"uint64","name":"id","type":"uint64"}],"stateMutability":"nonpayable","type":"function","name":"abortMigration"},{"inputs":[{"internalType":"uint8","name":"idx","type":"uint8"},{"internalType":"struct NodeOperator","name":"operator","type":"tuple","components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}]}],"stateMutability":"nonpayable","type":"function","name":"addNodeOperator"},{"inputs":[{"internalType":"uint64","name":"id","type":"uint64"}],"stateMutability":"nonpayable","type":"function","name":"completeMigration"},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"finishMaintenance"},{"inputs":[],"stateMutability":"view","type":"function","name":"getView","outputs":[{"internalType":"struct ClusterView","name":"","type":"tuple","components":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"struct NodeOperator[]","name":"nodeOperatorSlots","type":"tuple[]","components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}]},{"internalType":"struct Keyspace[2]","name":"keyspaces","type":"tuple[2]","components":[{"internalType":"uint256","name":"operatorsBitmask","type":"uint256"},{"internalType":"uint8","name":"replicationStrategy","type":"uint8"}]},{"internalType":"uint64","name":"keyspaceVersion","type":"uint64"},{"internalType":"struct Settings","name":"settings","type":"tuple","components":[{"internalType":"uint16","name":"maxOperatorDataBytes","type":"uint16"}]},{"internalType":"struct Migration","name":"migration","type":"tuple","components":[{"internalType":"uint64","name":"id","type":"uint64"},{"internalType":"uint256","name":"pullingOperatorsBitmask","type":"uint256"}]},{"internalType":"struct Maintenance","name":"maintenance","type":"tuple","components":[{"internalType":"address","name":"slot","type":"address"}]},{"internalType":"uint128","name":"version","type":"uint128"}]}]},{"inputs":[{"internalType":"address","name":"operatorAddress","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"removeNodeOperator"},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"startMaintenance"},{"inputs":[{"internalType":"struct Keyspace","name":"newKeyspace","type":"tuple","components":[{"internalType":"uint256","name":"operatorsBitmask","type":"uint256"},{"internalType":"uint8","name":"replicationStrategy","type":"uint8"}]}],"stateMutability":"nonpayable","type":"function","name":"startMigration"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"transferOwnership"},{"inputs":[{"internalType":"struct NodeOperator","name":"operator","type":"tuple","components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}]}],"stateMutability":"nonpayable","type":"function","name":"updateNodeOperator"},{"inputs":[{"internalType":"struct Settings","name":"newSettings","type":"tuple","components":[{"internalType":"uint16","name":"maxOperatorDataBytes","type":"uint16"}]}],"stateMutability":"nonpayable","type":"function","name":"updateSettings"}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"remappings":["@openzeppelin-contracts-5.3.0/=dependencies/@openzeppelin-contracts-5.3.0/","forge-std-1.9.7/=dependencies/forge-std-1.9.7/src/","forge-std/=dependencies/forge-std/src/","openzeppelin-contracts/=dependencies/@openzeppelin-contracts-5.3.0/"],"optimizer":{"enabled":false,"runs":200},"metadata":{"bytecodeHash":"ipfs"},"compilationTarget":{"src/Cluster.sol":"Cluster"},"evmVersion":"cancun","libraries":{},"viaIR":true},"sources":{"dependencies/openzeppelin-contracts/utils/Panic.sol":{"keccak256":"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a","urls":["bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a","dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG"],"license":"MIT"},"dependencies/openzeppelin-contracts/utils/math/Math.sol":{"keccak256":"0x1225214420c83ebcca88f2ae2b50f053aaa7df7bd684c3e878d334627f2edfc6","urls":["bzz-raw://6c5fab4970634f9ab9a620983dc1c8a30153981a0b1a521666e269d0a11399d3","dweb:/ipfs/QmVRnBC575MESGkEHndjujtR7qub2FzU9RWy9eKLp4hPZB"],"license":"MIT"},"dependencies/openzeppelin-contracts/utils/math/SafeCast.sol":{"keccak256":"0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54","urls":["bzz-raw://b1d578337048cad08c1c03041cca5978eff5428aa130c781b271ad9e5566e1f8","dweb:/ipfs/QmPFKL2r9CBsMwmUqqdcFPfHZB2qcs9g1HDrPxzWSxomvy"],"license":"MIT"},"src/Cluster.sol":{"keccak256":"0xac5b938cdbe809da30fdf59bd2492c6aa341ff7ea88f152be3543202b7485a44","urls":["bzz-raw://d5a43c1a46e45e9b06a441c5f0bd6cd2cba55c7a2aa2ffe605c2b51bd1823b89","dweb:/ipfs/QmcSR9umgpQyM4YtDCrBC7nhSQD1UuTdUqEUCwCohB58Fy"],"license":"MIT"}},"version":1},"id":24} \ No newline at end of file diff --git a/contracts/src/Cluster.sol b/contracts/src/Cluster.sol index d2cd7263..71b7a53b 100644 --- a/contracts/src/Cluster.sol +++ b/contracts/src/Cluster.sol @@ -7,7 +7,7 @@ struct Settings { uint16 maxOperatorDataBytes; } -event MigrationStarted(uint64 id, Keyspace newKeyspace, uint128 clusterVersion); +event MigrationStarted(uint64 id, Keyspace newKeyspace, uint64 newKeyspaceVersion, uint128 clusterVersion); event MigrationDataPullCompleted(uint64 id, address operatorAddress, uint128 clusterVersion); event MigrationCompleted(uint64 id, address operatorAddress, uint128 clusterVersion); event MigrationAborted(uint64 id, uint128 clusterVersion); @@ -102,7 +102,7 @@ contract Cluster { migration.pullingOperatorsBitmask = newKeyspace.operatorsBitmask; version++; - emit MigrationStarted(migration.id, newKeyspace, version); + emit MigrationStarted(migration.id, newKeyspace, keyspaceVersion, version); } function completeMigration(uint64 id) external hasMigration { diff --git a/contracts/test/Suite.sol b/contracts/test/Suite.sol index 5047257b..be498c80 100644 --- a/contracts/test/Suite.sol +++ b/contracts/test/Suite.sol @@ -269,7 +269,7 @@ contract ClusterTest is Test { function test_startMigrationEmitsMigrationStartedEvent() public { Keyspace memory keyspace = newKeyspace("01111"); vm.expectEmit(); - emit MigrationStarted(1, keyspace, 1); + emit MigrationStarted(1, keyspace, 1, 1); startMigration(OWNER, keyspace); } diff --git a/crates/cluster/Cargo.toml b/crates/cluster/Cargo.toml index f4a7cbfa..9622013a 100644 --- a/crates/cluster/Cargo.toml +++ b/crates/cluster/Cargo.toml @@ -8,19 +8,22 @@ workspace = true [dependencies] derive_more = { workspace = true, features = ["try_from", "into"] } +derivative = { workspace = true } libp2p = { workspace = true } itertools = { workspace = true } futures = { workspace = true } +backoff = { workspace = true } +tracing = { workspace = true } +tokio-stream = { workspace = true } sharding = { path = "../sharding" } -alloy = { version = "1.0", default-features = false, features = ["sol-types", "contract", "signer-local", "network", "reqwest"] } +alloy = { version = "1.0", default-features = false, features = ["sol-types", "contract", "signer-local", "network", "reqwest", "provider-ws", "rpc-types"] } anyhow = "1" thiserror = "1" tap = "1.0" -tracing = "0.1" serde = { version = "1", features = ["derive"] } postcard = { version = "1.0", default-features = false, features = ["alloc"] } @@ -35,3 +38,9 @@ arc-swap = "1.7" alloy = { version = "1.0", default-features = false, features = ["provider-anvil-node"] } tokio = { version = "1", default-features = false } hex = "0.4" + +tracing-subscriber = { version = "0.3", features = [ + "env-filter", + "parking_lot", + "json", +] } diff --git a/crates/cluster/src/keyspace.rs b/crates/cluster/src/keyspace.rs index 1b9f53cb..3b041563 100644 --- a/crates/cluster/src/keyspace.rs +++ b/crates/cluster/src/keyspace.rs @@ -1,5 +1,6 @@ use { crate::node_operator::{self}, + derivative::Derivative, derive_more::TryFrom, sharding::ShardId, std::collections::HashSet, @@ -16,9 +17,14 @@ pub const REPLICATION_FACTOR: usize = 5; /// /// [`Keyspace`] is being split into a set of equally sized [`Shards`], /// and each [`Shard`] is being assigned to a set of [`node_operator`]s. +#[derive(Clone, Derivative)] +#[derivative(Debug)] pub struct Keyspace { operators: HashSet, + + #[derivative(Debug = "ignore")] shards: S, + replication_strategy: ReplicationStrategy, version: u64, @@ -72,7 +78,7 @@ impl Keyspace { }) } - pub(crate) async fn calculate_shards(self) -> Keyspace + pub(crate) async fn calculate(self) -> Keyspace where Self: sealed::Calculate, { @@ -141,6 +147,8 @@ pub enum CreationError { pub struct SameKeyspaceError; pub(crate) mod sealed { + use std::future::Future; + #[allow(unused_imports)] use super::*; @@ -151,7 +159,7 @@ pub(crate) mod sealed { /// It's highly CPU intensive task (order of seconds), so the task is /// being [spawned](tokio::task::spawn_blocking) to the /// [`tokio`] threadpool. - async fn calculate_shards(self) -> Keyspace; + fn calculate_shards(self) -> impl Future> + Send; } } diff --git a/crates/cluster/src/lib.rs b/crates/cluster/src/lib.rs index 50b5b5e7..b3663a6c 100644 --- a/crates/cluster/src/lib.rs +++ b/crates/cluster/src/lib.rs @@ -1,8 +1,12 @@ +//! WalletConnect Network Cluster. + use { arc_swap::ArcSwap, + futures::Stream, itertools::Itertools, smart_contract::evm, std::{collections::HashSet, sync::Arc}, + tokio::sync::watch, }; pub mod smart_contract; @@ -38,6 +42,9 @@ pub use migration::Migration; pub mod maintenance; pub use maintenance::Maintenance; +mod task; +use task::Task; + /// Maximum number of [`NodeOperator`]s within a WCN [`Cluster`]. pub const MAX_OPERATORS: usize = keyspace::MAX_OPERATORS; @@ -50,9 +57,15 @@ pub const MIN_OPERATORS: usize = keyspace::REPLICATION_FACTOR; /// /// Performs preliminary invariant validation before calling the actual /// [`SmartContract`] methods. -pub struct Cluster { +pub struct Cluster { + inner: Arc>, + _task_guard: Arc, +} + +struct Inner { smart_contract: SC, - view: ArcSwap>>, + view: ArcSwap>, + watch: watch::Receiver<()>, } /// Version of a WCN [`Cluster`]. @@ -64,7 +77,8 @@ pub struct Cluster { pub type Version = u128; /// Events happening within a WCN [`Cluster`]. -pub enum Event { +#[derive(Debug)] +pub enum Event { /// [`Migration`] has started. MigrationStarted(migration::Started), @@ -84,10 +98,10 @@ pub enum Event { MaintenanceFinished(maintenance::Finished), /// [`NodeOperator`] has been updated. - NodeOperatorAdded(node_operator::Added), + NodeOperatorAdded(node_operator::Added), /// [`NodeOperator`] has been updated. - NodeOperatorUpdated(node_operator::Updated), + NodeOperatorUpdated(node_operator::Updated), /// [`NodeOperator`] has been removed. NodeOperatorRemoved(node_operator::Removed), @@ -99,11 +113,18 @@ pub enum Event { OwnershipTransferred(ownership::Transferred), } -impl Cluster { +/// [`Event`] with [`node_operator::SerializedData`]. +pub type SerializedEvent = Event; + +impl Cluster +where + SC: smart_contract::Read, + Shards: Clone + Send + Sync + 'static, + Keyspace: keyspace::sealed::Calculate, +{ /// Deploys a new WCN [`Cluster`]. pub async fn deploy( - signer: smart_contract::Signer, - rpc_url: smart_contract::RpcUrl, + deployer: &impl smart_contract::Deployer, initial_settings: Settings, initial_operators: Vec, ) -> Result { @@ -118,38 +139,79 @@ impl Cluster { let operators = NodeOperators::new(operators.into_iter().map(Some))?; - let contract = SC::deploy(signer, rpc_url, initial_settings, operators).await?; - - let view = contract.cluster_view().await?.deserialize()?; + let contract = deployer.deploy(initial_settings, operators).await?; - Ok(Self { - smart_contract: contract, - view: ArcSwap::new(Arc::new(Arc::new(view))), - }) + Self::new(contract).await.map_err(Into::into) } /// Connects to an existing WCN [`Cluster`]. pub async fn connect( - smart_contract_address: smart_contract::Address, - signer: smart_contract::Signer, - rpc_url: smart_contract::RpcUrl, - ) -> Result { - let contract = SC::connect(smart_contract_address, signer, rpc_url).await?; - let view = contract.cluster_view().await?.deserialize()?; + connector: &impl smart_contract::Connector, + contract_address: smart_contract::Address, + ) -> Result { + let contract = connector.connect(contract_address).await?; + Self::new(contract).await.map_err(Into::into) + } - Ok(Self { + async fn new(contract: SC) -> Result { + let events = contract.events().await?; + let view = View::fetch(&contract).await?.calculate_keyspace().await; + + let (tx, rx) = watch::channel(()); + let inner = Arc::new(Inner { smart_contract: contract, - view: ArcSwap::new(Arc::new(Arc::new(view))), + view: ArcSwap::new(Arc::new(view)), + watch: rx, + }); + + let guard = Task { + initial_events: Some(events), + inner: inner.clone(), + watch: tx, + } + .spawn(); + + Ok(Self { + inner, + _task_guard: Arc::new(guard), }) } } +impl Cluster { + /// Passes the current [`cluster::View`] into the provided closure. + /// + /// More efficient than calling [`Cluster::view`]. + pub fn using_view(&self, f: impl FnOnce(&View) -> T) -> T { + f(&self.inner.view.load()) + } + + /// Returns the current [`cluster::View`]. + pub fn view(&self) -> Arc> { + self.inner.view.load_full() + } + + /// Returns a [`Stream`] that emits an item each time a [`Cluster`] update + /// occurs. + /// + /// Caller is expected to use [`Cluster::using_view`] or [`Cluster::view`] + /// to see the updated state. + pub fn updates(&self) -> impl Stream + Send + 'static { + tokio_stream::wrappers::WatchStream::new(self.inner.watch.clone()) + } + + /// Returns reference to the underlying [`SmartContract`]. + pub fn smart_contract(&self) -> &SC { + &self.inner.smart_contract + } +} + impl Cluster { /// Builds a new [`Keyspace`] using the provided [`migration::Plan`] and /// calls [`SmartContract::start_migration`]. pub async fn start_migration(&self, plan: migration::Plan) -> Result<(), StartMigrationError> { let new_keyspace = self.using_view(move |view| { - view.ownership().require_owner(&self.smart_contract)?; + view.ownership().require_owner(&self.inner.smart_contract)?; view.require_no_migration()?; view.require_no_maintenance()?; @@ -189,7 +251,10 @@ impl Cluster { Ok(new_keyspace) })?; - self.smart_contract.start_migration(new_keyspace).await?; + self.inner + .smart_contract + .start_migration(new_keyspace) + .await?; Ok(()) } @@ -202,7 +267,7 @@ impl Cluster { self.using_view(|view| { let operator_idx = view .node_operators() - .require_idx(self.smart_contract.signer())?; + .require_idx(self.inner.smart_contract.signer().address())?; view.require_migration()? .require_id(id)? @@ -211,7 +276,7 @@ impl Cluster { Ok::<_, CompleteMigrationError>(()) })?; - self.smart_contract.complete_migration(id).await?; + self.inner.smart_contract.complete_migration(id).await?; Ok(()) } @@ -219,13 +284,14 @@ impl Cluster { /// Calls [`SmartContract::abort_migration`]. pub async fn abort_migration(&self, id: migration::Id) -> Result<(), AbortMigrationError> { self.using_view(|view| { - view.ownership().require_owner(&self.smart_contract)?; + view.ownership().require_owner(&self.inner.smart_contract)?; view.require_migration()?.require_id(id)?; Ok::<_, AbortMigrationError>(()) })?; - self.smart_contract + self.inner + .smart_contract .abort_migration(id) .await .map_err(Into::into) @@ -233,7 +299,7 @@ impl Cluster { /// Calls [`SmartContract::start_maintenance`]. pub async fn start_maintenance(&self) -> Result<(), StartMaintenanceError> { - let signer = self.smart_contract.signer(); + let signer = self.inner.smart_contract.signer().address(); self.using_view(move |view| { if !(view.node_operators().contains(signer) || view.ownership().is_owner(signer)) { @@ -246,14 +312,14 @@ impl Cluster { Ok::<_, StartMaintenanceError>(()) })?; - self.smart_contract.start_maintenance().await?; + self.inner.smart_contract.start_maintenance().await?; Ok(()) } /// Calls [`SmartContract::finish_maintenance`]. pub async fn finish_maintenance(&self) -> Result<(), FinishMaintenanceError> { - let signer = self.smart_contract.signer(); + let signer = self.inner.smart_contract.signer().address(); self.using_view(|view| { let maintenance = view.require_maintenance()?; @@ -265,7 +331,7 @@ impl Cluster { Ok(()) })?; - self.smart_contract.finish_maintenance().await?; + self.inner.smart_contract.finish_maintenance().await?; Ok(()) } @@ -277,7 +343,7 @@ impl Cluster { operator: NodeOperator, ) -> Result<(), AddNodeOperatorError> { let operator = self.using_view(|view| { - view.ownership().require_owner(&self.smart_contract)?; + view.ownership().require_owner(&self.inner.smart_contract)?; view.node_operators().require_not_exists(&operator.id)?; view.node_operators().require_free_slot(idx)?; @@ -287,7 +353,10 @@ impl Cluster { Ok::<_, AddNodeOperatorError>(operator) })?; - self.smart_contract.add_node_operator(idx, operator).await?; + self.inner + .smart_contract + .add_node_operator(idx, operator) + .await?; Ok(()) } @@ -297,7 +366,7 @@ impl Cluster { &self, operator: NodeOperator, ) -> Result<(), UpdateNodeOperatorError> { - let signer = self.smart_contract.signer(); + let signer = self.inner.smart_contract.signer().address(); let operator = self.using_view(|view| { if !(signer == &operator.id || view.ownership().is_owner(signer)) { @@ -312,7 +381,10 @@ impl Cluster { Ok::<_, UpdateNodeOperatorError>(operator) })?; - self.smart_contract.update_node_operator(operator).await?; + self.inner + .smart_contract + .update_node_operator(operator) + .await?; Ok(()) } @@ -338,13 +410,36 @@ impl Cluster { Ok::<_, RemoveNodeOperatorError>(()) })?; - self.smart_contract.remove_node_operator(id).await?; + self.inner.smart_contract.remove_node_operator(id).await?; + + Ok(()) + } + + /// Calls [`SmartContract::update_settings`]. + pub async fn update_settings(&self, new_settings: Settings) -> Result<(), UpdateSettingsError> { + self.using_view(move |view| view.ownership().require_owner(&self.inner.smart_contract))?; + + self.inner + .smart_contract + .update_settings(new_settings) + .await?; Ok(()) } - fn using_view(&self, f: impl FnOnce(&View) -> T) -> T { - f(&self.view.load()) + /// Calls [`SmartContract::transfer_ownership`]. + pub async fn transfer_ownership( + &self, + new_owner: smart_contract::AccountAddress, + ) -> Result<(), TransferOwnershipError> { + self.using_view(move |view| view.ownership().require_owner(&self.inner.smart_contract))?; + + self.inner + .smart_contract + .transfer_ownership(new_owner) + .await?; + + Ok(()) } } @@ -363,21 +458,21 @@ pub enum DeploymentError { #[error(transparent)] DataTooLarge(#[from] node_operator::DataTooLargeError), + #[error(transparent)] + FetchView(#[from] view::FetchError), + #[error("Smart-contract: {0}")] - SmartContract(#[from] smart_contract::Error), + SmartContract(#[from] smart_contract::DeploymentError), } /// [`Cluster::connect`] error. #[derive(Debug, thiserror::Error)] -pub enum ConnectError { +pub enum ConnectionError { #[error(transparent)] - SmartContract(#[from] smart_contract::ConnectError), + SmartContract(#[from] smart_contract::ConnectionError), #[error(transparent)] - GetClusterView(#[from] smart_contract::Error), - - #[error(transparent)] - DataDeserialization(#[from] node_operator::DataDeserializationError), + FetchView(#[from] view::FetchError), } /// [`Cluster::start_migration`] error. @@ -408,7 +503,7 @@ pub enum StartMigrationError { SameKeyspace(#[from] keyspace::SameKeyspaceError), #[error("Smart-contract: {0}")] - SmartContract(#[from] smart_contract::Error), + SmartContract(#[from] smart_contract::WriteError), } /// [`Cluster::complete_migration`] error. @@ -427,7 +522,7 @@ pub enum CompleteMigrationError { OperatorNotPulling(#[from] migration::OperatorNotPullingError), #[error("Smart-contract: {0}")] - SmartContract(#[from] smart_contract::Error), + SmartContract(#[from] smart_contract::WriteError), } /// [`Cluster::abort_migration`] error. @@ -443,7 +538,7 @@ pub enum AbortMigrationError { WrongMigrationId(#[from] migration::WrongIdError), #[error("Smart-contract: {0}")] - SmartContract(#[from] smart_contract::Error), + SmartContract(#[from] smart_contract::WriteError), } /// [`Cluster::start_maintenance`] error. @@ -459,7 +554,7 @@ pub enum StartMaintenanceError { MaintenanceInProgress(#[from] maintenance::InProgressError), #[error("Smart-contract: {0}")] - SmartContract(#[from] smart_contract::Error), + SmartContract(#[from] smart_contract::WriteError), } /// [`Cluster::finish_maintenance`] error. @@ -472,7 +567,7 @@ pub enum FinishMaintenanceError { Unauthorized, #[error("Smart-contract: {0}")] - SmartContract(#[from] smart_contract::Error), + SmartContract(#[from] smart_contract::WriteError), } /// [`Cluster::add_node_operator`] error. @@ -494,7 +589,7 @@ pub enum AddNodeOperatorError { DataTooLarge(#[from] node_operator::DataTooLargeError), #[error("Smart-contract: {0}")] - SmartContract(#[from] smart_contract::Error), + SmartContract(#[from] smart_contract::WriteError), } /// [`Cluster::update_node_operator`] error. @@ -513,7 +608,7 @@ pub enum UpdateNodeOperatorError { DataTooLarge(#[from] node_operator::DataTooLargeError), #[error("Smart-contract: {0}")] - SmartContract(#[from] smart_contract::Error), + SmartContract(#[from] smart_contract::WriteError), } /// [`Cluster::remove_node_operator`] error. @@ -529,7 +624,27 @@ pub enum RemoveNodeOperatorError { InKeyspace, #[error("Smart-contract: {0}")] - SmartContract(#[from] smart_contract::Error), + SmartContract(#[from] smart_contract::WriteError), +} + +/// [`Cluster::update_settings`] error. +#[derive(Debug, thiserror::Error)] +pub enum UpdateSettingsError { + #[error(transparent)] + NotOwner(#[from] ownership::NotOwnerError), + + #[error("Smart-contract: {0}")] + SmartContract(#[from] smart_contract::WriteError), +} + +/// [`Cluster::transfer_ownership`] error. +#[derive(Debug, thiserror::Error)] +pub enum TransferOwnershipError { + #[error(transparent)] + NotOwner(#[from] ownership::NotOwnerError), + + #[error("Smart-contract: {0}")] + SmartContract(#[from] smart_contract::WriteError), } impl Event { @@ -549,3 +664,21 @@ impl Event { } } } + +impl SerializedEvent { + fn deserialize(self) -> Result { + Ok(match self { + Event::MigrationStarted(evt) => Event::MigrationStarted(evt), + Event::MigrationDataPullCompleted(evt) => Event::MigrationDataPullCompleted(evt), + Event::MigrationCompleted(evt) => Event::MigrationCompleted(evt), + Event::MigrationAborted(evt) => Event::MigrationAborted(evt), + Event::MaintenanceStarted(evt) => Event::MaintenanceStarted(evt), + Event::MaintenanceFinished(evt) => Event::MaintenanceFinished(evt), + Event::NodeOperatorAdded(evt) => Event::NodeOperatorAdded(evt.deserialize()?), + Event::NodeOperatorUpdated(evt) => Event::NodeOperatorUpdated(evt.deserialize()?), + Event::NodeOperatorRemoved(evt) => Event::NodeOperatorRemoved(evt), + Event::SettingsUpdated(evt) => Event::SettingsUpdated(evt), + Event::OwnershipTransferred(evt) => Event::OwnershipTransferred(evt), + }) + } +} diff --git a/crates/cluster/src/maintenance.rs b/crates/cluster/src/maintenance.rs index 67f80ff1..63c060c0 100644 --- a/crates/cluster/src/maintenance.rs +++ b/crates/cluster/src/maintenance.rs @@ -4,6 +4,7 @@ use crate::{node_operator, Version as ClusterVersion}; /// /// Only a single [`node_operator`] at a time is allowed to be under /// maintenance. +#[derive(Clone)] pub struct Maintenance { slot: node_operator::Id, } @@ -20,6 +21,7 @@ impl Maintenance { } /// [`Maintenance`] has started. +#[derive(Debug)] pub struct Started { /// ID of the [`node_operator`] that started the [`Maintenance`]. pub operator_id: node_operator::Id, @@ -29,6 +31,7 @@ pub struct Started { } /// [`Maintenance`] has been finished. +#[derive(Debug)] pub struct Finished { /// Updated [`ClusterVersion`]. pub cluster_version: ClusterVersion, diff --git a/crates/cluster/src/migration.rs b/crates/cluster/src/migration.rs index 3bcf3103..f7d6b447 100644 --- a/crates/cluster/src/migration.rs +++ b/crates/cluster/src/migration.rs @@ -5,16 +5,17 @@ use { Keyspace, Version as ClusterVersion, }, - std::collections::HashSet, + std::{collections::HashSet, sync::Arc}, }; /// Identifier of a [`Migration`]. pub type Id = u64; /// Data migration process within a WCN cluster. +#[derive(Clone)] pub struct Migration { id: Id, - keyspace: Keyspace, + keyspace: Arc>, pulling_operators: HashSet, } @@ -39,7 +40,7 @@ impl Migration { ) -> Self { Self { id, - keyspace, + keyspace: Arc::new(keyspace), pulling_operators: pulling_operators.into_iter().collect(), } } @@ -59,7 +60,7 @@ impl Migration { // &mut self.keyspace // } - pub(super) fn into_keyspace(self) -> Keyspace { + pub(super) fn into_keyspace(self) -> Arc> { self.keyspace } @@ -69,10 +70,6 @@ impl Migration { self.pulling_operators.contains(&idx) } - pub(crate) fn pulling_operators_count(&self) -> usize { - self.pulling_operators.len() - } - pub(crate) fn complete_pull(&mut self, idx: node_operator::Idx) { self.pulling_operators.remove(&idx); } @@ -110,16 +107,20 @@ impl Migration { } impl Migration { - pub(crate) async fn calculate_keyspace_shards(self) -> Migration { + pub(crate) async fn calculate_keyspace(self) -> Migration + where + Keyspace: keyspace::sealed::Calculate, + { Migration { id: self.id, - keyspace: self.keyspace.calculate_shards().await, + keyspace: Arc::new((*self.keyspace).clone().calculate().await), pulling_operators: self.pulling_operators, } } } /// [`Migration`] has started. +#[derive(Debug)] pub struct Started { /// [`Id`] of the [`Migration`] being started. pub migration_id: Id, @@ -132,6 +133,7 @@ pub struct Started { } /// [`NodeOperator`](crate::NodeOperator) has completed the data pull. +#[derive(Debug)] pub struct DataPullCompleted { /// [`Id`] of the [`Migration`]. pub migration_id: Id, @@ -144,6 +146,7 @@ pub struct DataPullCompleted { } /// [`Migration`] has been completed. +#[derive(Debug)] pub struct Completed { /// [`Id`] of the completed [`Migration`]. pub migration_id: Id, @@ -156,6 +159,7 @@ pub struct Completed { } /// [`Migration`] has been aborted. +#[derive(Debug)] pub struct Aborted { /// [`Id`] of the [`Migration`]. pub migration_id: Id, diff --git a/crates/cluster/src/node.rs b/crates/cluster/src/node.rs index 74807af7..85a3c603 100644 --- a/crates/cluster/src/node.rs +++ b/crates/cluster/src/node.rs @@ -10,6 +10,7 @@ use { /// /// The IP address is currently being encrypted using a format-preserving /// encryption algorithm. +// TODO: encrypt #[derive(Debug, Clone, Copy)] pub struct Node { /// [`PeerId`] of the [`Node`]. @@ -22,18 +23,6 @@ pub struct Node { pub addr: SocketAddrV4, } -impl Node { - pub(super) fn encrypt(&mut self) { - // TODO - } - - pub(super) fn decrypt(&mut self) { - // TODO - // FF1::new(key, radix); - // let fpe_ff = FF1::::new(&[0; 32], 256).unwrap(); - } -} - // NOTE: The on-chain serialization is non self-describing! Every change to // the schema should be handled by creating a new version. #[derive(Clone, Copy, Debug, Serialize, Deserialize)] diff --git a/crates/cluster/src/node_operator.rs b/crates/cluster/src/node_operator.rs index 59b36e54..043f1b38 100644 --- a/crates/cluster/src/node_operator.rs +++ b/crates/cluster/src/node_operator.rs @@ -79,28 +79,50 @@ pub struct NodeOperator { } /// Event of a new [`NodeOperator`] being added to a WCN cluster. -pub struct Added { +#[derive(Debug)] +pub struct Added { /// [`Idx`] in the [`NodeOperators`] slot map the [`NodeOperator`] is being /// placed to. pub idx: Idx, /// [`NodeOperator`] being added. - pub operator: NodeOperator, + pub operator: NodeOperator, /// Updated [`ClusterVersion`]. pub cluster_version: ClusterVersion, } +impl Added { + pub(super) fn deserialize(self) -> Result { + Ok(Added { + idx: self.idx, + operator: self.operator.deserialize()?, + cluster_version: self.cluster_version, + }) + } +} + /// Event of a [`NodeOperator`] being updated. -pub struct Updated { +#[derive(Debug)] +pub struct Updated { /// Updated [`NodeOperator`]. - pub operator: NodeOperator, + pub operator: NodeOperator, /// Updated [`ClusterVersion`]. pub cluster_version: ClusterVersion, } +impl Updated { + pub(super) fn deserialize(self) -> Result { + Ok(Updated { + operator: self.operator.deserialize()?, + cluster_version: self.cluster_version, + }) + } +} + /// Event of a [`NodeOperator`] being removed from a WCN cluster. +#[derive(Debug)] pub struct Removed { /// [`Id`] of the [`NodeOperator`] being removed. pub id: Id, diff --git a/crates/cluster/src/node_operators.rs b/crates/cluster/src/node_operators.rs index 33684328..922a96e1 100644 --- a/crates/cluster/src/node_operators.rs +++ b/crates/cluster/src/node_operators.rs @@ -83,26 +83,15 @@ impl NodeOperators { } /// Gets an [`NodeOperator`] by [`Id`]. - pub(super) fn get(&self, id: &node_operator::Id) -> Option<&NodeOperator> { + pub fn get(&self, id: &node_operator::Id) -> Option<&NodeOperator> { self.get_by_idx(self.get_idx(id)?) } - /// Gets a mutable reference to a [`NodeOperator`] [`Data`]. - pub(super) fn get_data_mut(&mut self, id: &node_operator::Id) -> Option<&mut Data> { - self.get_by_idx_mut(self.get_idx(id)?) - .map(|operator| &mut operator.data) - } - /// Gets an [`NodeOperator`] by [`Idx`]. pub(super) fn get_by_idx(&self, idx: node_operator::Idx) -> Option<&NodeOperator> { self.slots.get(idx as usize)?.as_ref() } - /// Mutable version of [`NodeOperators::get_by_idx`]. - fn get_by_idx_mut(&mut self, idx: node_operator::Idx) -> Option<&mut NodeOperator> { - self.slots.get_mut(idx as usize)?.as_mut() - } - /// Gets an [`Idx`] by [`Id`]. pub(super) fn get_idx(&self, id: &node_operator::Id) -> Option { self.id_to_idx.get(id).copied() diff --git a/crates/cluster/src/ownership.rs b/crates/cluster/src/ownership.rs index 89d7fb35..0d1d79d2 100644 --- a/crates/cluster/src/ownership.rs +++ b/crates/cluster/src/ownership.rs @@ -6,6 +6,7 @@ use crate::{smart_contract, SmartContract, Version as ClusterVersion}; /// /// Cluster has a single owner, and some [`smart_contract`] methods are /// resticted to be executed only by the owner. +#[derive(Clone)] pub struct Ownership { owner: smart_contract::AccountAddress, } @@ -23,7 +24,7 @@ impl Ownership { &self, smart_contract: &impl SmartContract, ) -> Result<(), NotOwnerError> { - if !self.is_owner(smart_contract.signer()) { + if !self.is_owner(smart_contract.signer().address()) { return Err(NotOwnerError); } @@ -36,6 +37,7 @@ impl Ownership { } /// Event of [`Ownership`] being transferred. +#[derive(Debug)] pub struct Transferred { /// New owner of the WCN cluster. pub new_owner: smart_contract::AccountAddress, diff --git a/crates/cluster/src/settings.rs b/crates/cluster/src/settings.rs index 440031e8..0f8a6cf4 100644 --- a/crates/cluster/src/settings.rs +++ b/crates/cluster/src/settings.rs @@ -9,6 +9,7 @@ pub struct Settings { } /// Event of [`Settings`] being updated. +#[derive(Debug)] pub struct Updated { /// Updated [`Settings`]. pub settings: Settings, diff --git a/crates/cluster/src/smart_contract/evm.rs b/crates/cluster/src/smart_contract/evm.rs index 66c4076c..1e9db5b7 100644 --- a/crates/cluster/src/smart_contract/evm.rs +++ b/crates/cluster/src/smart_contract/evm.rs @@ -1,27 +1,48 @@ //! EVM implementation of [`SmartContract`](super::SmartContract). use { - super::{AccountAddress, ConnectError, Error, Result, RpcUrl, Signer, SignerInner}, + super::{ + AccountAddress, + ConnectionError, + Connector, + Deployer, + DeploymentError, + ReadError, + ReadResult, + RpcUrl, + Signer, + SignerKind, + WriteError, + WriteResult, + }, crate::{ self as cluster, + maintenance, migration, node_operator, + ownership, + settings, smart_contract, + Event, Keyspace, Maintenance, Migration, NodeOperator, NodeOperators, Ownership, + SerializedEvent, Settings, }, alloy::{ contract::{CallBuilder, CallDecoder}, network::EthereumWallet, primitives::Uint, - providers::{DynProvider, Provider, ProviderBuilder}, + providers::{DynProvider, Provider, ProviderBuilder, WsConnect}, + rpc::types::{Filter, Log}, + sol_types::SolEvent, }, - std::{collections::HashSet, time::Duration}, + futures::{Stream, StreamExt as _}, + std::{collections::HashSet, fmt, sync::Arc, time::Duration}, }; mod bindings { @@ -33,33 +54,66 @@ mod bindings { ); } +pub(crate) type Address = alloy::primitives::Address; + type AlloyContract = bindings::Cluster::ClusterInstance; type U256 = Uint<256, 4>; -/// EVM implementation of [`SmartContract`](super::SmartContract). -#[derive(Clone)] -pub struct SmartContract { - signer_addr: S, - alloy: AlloyContract, +/// RPC provider for EVM chains. +pub struct RpcProvider { + signer: S, + alloy: DynProvider, } -/// EVM implementation of -/// [`ReadOnlySmartContract`](super::ReadOnlySmartContract). -pub type SmartContractRO = SmartContract<()>; +impl RpcProvider { + /// Creates a new [`RpcProvider`]. + pub async fn new( + url: RpcUrl, + signer: Signer, + ) -> Result, RpcProviderCreationError> { + let wallet: EthereumWallet = match &signer.kind { + SignerKind::PrivateKey(key) => key.clone().into(), + }; -pub(crate) type Address = alloy::primitives::Address; + let provider = ProviderBuilder::new() + .wallet(wallet) + .connect_ws(WsConnect::new(url.0)) + .await?; -impl super::SmartContract for SmartContract { - type ReadOnly = SmartContractRO; + Ok(RpcProvider { + signer, + alloy: DynProvider::new(provider), + }) + } + + /// Creates a new read-only [`RpcProvider`]. + pub async fn new_ro(self, url: RpcUrl) -> Result, RpcProviderCreationError> { + let provider = ProviderBuilder::new() + .connect_ws(WsConnect::new(url.0)) + .await?; + + Ok(RpcProvider { + signer: (), + alloy: DynProvider::new(provider), + }) + } +} +/// EVM implementation of WCN Cluster smart contract. +#[derive(Clone)] +pub struct SmartContract { + signer: S, + alloy: AlloyContract, +} + +impl Deployer> for RpcProvider { async fn deploy( - signer: Signer, - rpc_url: RpcUrl, + &self, initial_settings: Settings, initial_operators: NodeOperators, - ) -> Result { - let signer_addr = signer.address(); + ) -> Result, DeploymentError> { + let signer = self.signer.clone(); let settings = initial_settings.into(); let operators = initial_operators @@ -68,56 +122,64 @@ impl super::SmartContract for SmartContract { .filter_map(|op| op.map(Into::into)) .collect(); - bindings::Cluster::deploy(new_provier(signer, rpc_url), settings, operators) + bindings::Cluster::deploy(self.alloy.clone(), settings, operators) .await - .map(|alloy| Self { signer_addr, alloy }) + .map(|alloy| SmartContract { signer, alloy }) .map_err(Into::into) } +} +impl Connector> for RpcProvider { async fn connect( + &self, address: smart_contract::Address, - signer: Signer, - rpc_url: RpcUrl, - ) -> Result { - let signer_addr = signer.address(); + ) -> Result, ConnectionError> { + let signer = self.signer.clone(); - connect(address, new_provier(signer, rpc_url)) + let code = self + .alloy + .get_code_at(address.0) .await - .map(|alloy| Self { signer_addr, alloy }) - } + .map_err(|err| ConnectionError::Other(err.to_string()))?; - async fn connect_ro( - address: smart_contract::Address, - rpc_url: RpcUrl, - ) -> Result { - let signer_addr = (); + if code.is_empty() { + return Err(ConnectionError::UnknownContract); + } - connect(address, new_ro_provier(rpc_url)) - .await - .map(|alloy| Self::ReadOnly { signer_addr, alloy }) + // TODO: false positive + // if code != bindings::Cluster::BYTECODE { + // return Err(ConnectionError::WrongContract); + // } + + Ok(SmartContract { + signer, + alloy: bindings::Cluster::new(address.0, self.alloy.clone()), + }) } +} - fn signer(&self) -> &AccountAddress { - &self.signer_addr +impl smart_contract::Write for SmartContract { + fn signer(&self) -> &Signer { + &self.signer } - async fn start_migration(&self, new_keyspace: Keyspace) -> Result<()> { + async fn start_migration(&self, new_keyspace: Keyspace) -> WriteResult<()> { check_receipt(self.alloy.startMigration(new_keyspace.into())).await } - async fn complete_migration(&self, id: migration::Id) -> Result<()> { + async fn complete_migration(&self, id: migration::Id) -> WriteResult<()> { check_receipt(self.alloy.completeMigration(id)).await } - async fn abort_migration(&self, id: migration::Id) -> Result<()> { + async fn abort_migration(&self, id: migration::Id) -> WriteResult<()> { check_receipt(self.alloy.abortMigration(id)).await } - async fn start_maintenance(&self) -> Result<()> { + async fn start_maintenance(&self) -> WriteResult<()> { check_receipt(self.alloy.startMaintenance()).await } - async fn finish_maintenance(&self) -> Result<()> { + async fn finish_maintenance(&self) -> WriteResult<()> { check_receipt(self.alloy.finishMaintenance()).await } @@ -125,28 +187,28 @@ impl super::SmartContract for SmartContract { &self, idx: node_operator::Idx, operator: NodeOperator, - ) -> Result<()> { + ) -> WriteResult<()> { check_receipt(self.alloy.addNodeOperator(idx, operator.into())).await } - async fn update_node_operator(&self, operator: node_operator::Serialized) -> super::Result<()> { + async fn update_node_operator(&self, operator: node_operator::Serialized) -> WriteResult<()> { check_receipt(self.alloy.updateNodeOperator(operator.into())).await } - async fn remove_node_operator(&self, id: node_operator::Id) -> Result<()> { + async fn remove_node_operator(&self, id: node_operator::Id) -> WriteResult<()> { check_receipt(self.alloy.removeNodeOperator(id.0)).await } - async fn update_settings(&self, new_settings: Settings) -> Result<()> { + async fn update_settings(&self, new_settings: Settings) -> WriteResult<()> { check_receipt(self.alloy.updateSettings(new_settings.into())).await } - async fn transfer_ownership(&self, new_owner: AccountAddress) -> Result<()> { + async fn transfer_ownership(&self, new_owner: AccountAddress) -> WriteResult<()> { check_receipt(self.alloy.transferOwnership(new_owner.0)).await } } -async fn check_receipt(call: CallBuilder<&DynProvider, D>) -> Result<(), Error> +async fn check_receipt(call: CallBuilder<&DynProvider, D>) -> WriteResult<()> where D: CallDecoder, { @@ -158,65 +220,194 @@ where .await?; if !receipt.status() { - return Err(Error::Revert(format!("{}", receipt.transaction_hash))); + return Err(WriteError::Revert(format!("{}", receipt.transaction_hash))); } Ok(()) } -impl super::ReadOnlySmartContract for SmartContract { - async fn cluster_view(&self) -> Result> { +impl smart_contract::Read for SmartContract { + fn address(&self) -> smart_contract::Address { + smart_contract::Address(*self.alloy.address()) + } + + async fn cluster_view(&self) -> ReadResult> { self.alloy.getView().call().await?.try_into() } + + async fn events( + &self, + ) -> ReadResult> + Send + 'static> { + let filter = Filter::new().address(*self.alloy.address()); + + Ok(self + .alloy + .provider() + .subscribe_logs(&filter) + .await? + .into_stream() + .map(TryFrom::try_from)) + } } -async fn connect( - address: smart_contract::Address, - provider: DynProvider, -) -> Result { - let code = provider - .get_code_at(address.0) - .await - .map_err(|err| ConnectError::Other(err.to_string()))?; +impl TryFrom for Event { + type Error = ReadError; + + fn try_from(log: Log) -> Result { + use bindings::Cluster; + + let topics = log.topics(); + let data = &log.data().data; + + Ok(match log.topics().get(0) { + Some(&Cluster::MigrationStarted::SIGNATURE_HASH) => { + Cluster::MigrationStarted::decode_raw_log_validate(topics, data)?.try_into()? + } + Some(&Cluster::MigrationDataPullCompleted::SIGNATURE_HASH) => { + Cluster::MigrationDataPullCompleted::decode_raw_log_validate(topics, data)?.into() + } + Some(&Cluster::MigrationCompleted::SIGNATURE_HASH) => { + Cluster::MigrationCompleted::decode_raw_log_validate(topics, data)?.into() + } + Some(&Cluster::MigrationAborted::SIGNATURE_HASH) => { + Cluster::MigrationAborted::decode_raw_log_validate(topics, data)?.into() + } + + Some(&Cluster::MaintenanceStarted::SIGNATURE_HASH) => { + Cluster::MaintenanceStarted::decode_raw_log_validate(topics, data)?.into() + } + Some(&Cluster::MaintenanceFinished::SIGNATURE_HASH) => { + Cluster::MaintenanceFinished::decode_raw_log_validate(topics, data)?.into() + } + + Some(&Cluster::NodeOperatorAdded::SIGNATURE_HASH) => { + Cluster::NodeOperatorAdded::decode_raw_log_validate(topics, data)?.into() + } + Some(&Cluster::NodeOperatorUpdated::SIGNATURE_HASH) => { + Cluster::NodeOperatorUpdated::decode_raw_log_validate(topics, data)?.into() + } + Some(&Cluster::NodeOperatorRemoved::SIGNATURE_HASH) => { + Cluster::NodeOperatorRemoved::decode_raw_log_validate(topics, data)?.into() + } + + Some(&Cluster::SettingsUpdated::SIGNATURE_HASH) => { + Cluster::SettingsUpdated::decode_raw_log_validate(topics, data)?.into() + } + + Some(&Cluster::OwnershipTransferred::SIGNATURE_HASH) => { + Cluster::OwnershipTransferred::decode_raw_log_validate(topics, data)?.into() + } - if code.is_empty() { - return Err(ConnectError::UnknownContract); + other => { + return Err(ReadError::InvalidData(format!( + "Unexpected event: {other:?}" + ))) + } + }) } +} + +impl TryFrom for Event { + type Error = ReadError; - if code != bindings::Cluster::BYTECODE { - return Err(ConnectError::WrongContract); + fn try_from(evt: bindings::Cluster::MigrationStarted) -> ReadResult { + Ok(Self::MigrationStarted(migration::Started { + migration_id: evt.id, + new_keyspace: Keyspace::try_from_alloy(&evt.newKeyspace, evt.newKeyspaceVersion)?, + cluster_version: evt.clusterVersion, + })) } +} - Ok(bindings::Cluster::new(address.0, provider)) +impl From for Event { + fn from(evt: bindings::Cluster::MigrationDataPullCompleted) -> Self { + Self::MigrationDataPullCompleted(migration::DataPullCompleted { + migration_id: evt.id, + operator_id: evt.operatorAddress.into(), + cluster_version: evt.clusterVersion, + }) + } } -fn new_provier(signer: Signer, rpc_url: RpcUrl) -> DynProvider { - let wallet: EthereumWallet = match signer.inner { - SignerInner::PrivateKey(key) => key.into(), - }; +impl From for Event { + fn from(evt: bindings::Cluster::MigrationCompleted) -> Self { + Self::MigrationCompleted(migration::Completed { + migration_id: evt.id, + operator_id: evt.operatorAddress.into(), + cluster_version: evt.clusterVersion, + }) + } +} - let provider = ProviderBuilder::new() - .wallet(wallet) - // .with_chain_id(10) - .connect_http(rpc_url.0); +impl From for Event { + fn from(evt: bindings::Cluster::MigrationAborted) -> Self { + Self::MigrationAborted(migration::Aborted { + migration_id: evt.id, + cluster_version: evt.clusterVersion, + }) + } +} - DynProvider::new(provider) +impl From for Event { + fn from(evt: bindings::Cluster::MaintenanceStarted) -> Self { + Self::MaintenanceStarted(maintenance::Started { + operator_id: evt.addr.into(), + cluster_version: evt.clusterVersion, + }) + } } -fn new_ro_provier(rpc_url: RpcUrl) -> DynProvider { - let provider = ProviderBuilder::new().connect_http(rpc_url.0); - DynProvider::new(provider) +impl From for Event { + fn from(evt: bindings::Cluster::MaintenanceFinished) -> Self { + Self::MaintenanceFinished(maintenance::Finished { + cluster_version: evt.clusterVersion, + }) + } } -impl From for Error { - fn from(err: alloy::contract::Error) -> Self { - Self::Other(format!("{err:?}")) +impl From for Event { + fn from(evt: bindings::Cluster::NodeOperatorAdded) -> Self { + Self::NodeOperatorAdded(node_operator::Added { + idx: evt.idx, + operator: evt.operator.into(), + cluster_version: evt.clusterVersion, + }) } } -impl From for Error { - fn from(err: alloy::providers::PendingTransactionError) -> Self { - Self::Other(format!("{err:?}")) +impl From for Event { + fn from(evt: bindings::Cluster::NodeOperatorUpdated) -> Self { + Self::NodeOperatorUpdated(node_operator::Updated { + operator: evt.operator.into(), + cluster_version: evt.clusterVersion, + }) + } +} + +impl From for Event { + fn from(evt: bindings::Cluster::NodeOperatorRemoved) -> Self { + Self::NodeOperatorRemoved(node_operator::Removed { + id: evt.operatorAddress.into(), + cluster_version: evt.clusterVersion, + }) + } +} + +impl From for Event { + fn from(evt: bindings::Cluster::SettingsUpdated) -> Self { + Self::SettingsUpdated(settings::Updated { + settings: evt.newSettings.into(), + cluster_version: evt.clusterVersion, + }) + } +} + +impl From for Event { + fn from(evt: bindings::Cluster::OwnershipTransferred) -> Self { + Self::OwnershipTransferred(ownership::Transferred { + new_owner: evt.newOwner.into(), + cluster_version: evt.cluserVersion, + }) } } @@ -270,7 +461,10 @@ impl From for bindings::Cluster::Keyspace { } impl Keyspace { - fn try_from_alloy(keyspace: &bindings::Cluster::Keyspace, version: u64) -> Result { + fn try_from_alloy( + keyspace: &bindings::Cluster::Keyspace, + version: u64, + ) -> Result { let mut operators = HashSet::new(); // TODO: do less iterations @@ -280,13 +474,12 @@ impl Keyspace { } } - let replication_strategy = keyspace - .replicationStrategy - .try_into() - .map_err(|err| Error::Other(format!("Invalid ReplicationStrategy: {err:?}")))?; + let replication_strategy = keyspace.replicationStrategy.try_into().map_err(|err| { + ReadError::InvalidData(format!("Invalid ReplicationStrategy: {err:?}")) + })?; Self::new(operators, replication_strategy, version) - .map_err(|err| Error::Other(format!("Invalid Keyspace: {err:?}"))) + .map_err(|err| ReadError::InvalidData(format!("Invalid Keyspace: {err:?}"))) } } @@ -316,7 +509,7 @@ impl From for Option { } impl TryFrom for cluster::View<(), node_operator::SerializedData> { - type Error = Error; + type Error = ReadError; fn try_from(view: bindings::Cluster::ClusterView) -> Result { let node_operators = @@ -327,7 +520,7 @@ impl TryFrom for cluster::View<(), node_operator Some(operator.into()) } })) - .map_err(|err| Error::Other(format!("Invalid NodeOperators: {err:?}")))?; + .map_err(|err| ReadError::InvalidData(format!("Invalid NodeOperators: {err:?}")))?; // assert array length let _: &[_; 2] = &view.keyspaces; @@ -345,7 +538,7 @@ impl TryFrom for cluster::View<(), node_operator let prev_keyspace_version = view .keyspaceVersion .checked_sub(1) - .ok_or_else(|| Error::Other(format!("Invalid keyspace::Version")))?; + .ok_or_else(|| ReadError::InvalidData(format!("Invalid keyspace::Version")))?; let keyspace = try_keyspace(prev_keyspace_version)?; let migration_keyspace = try_keyspace(view.keyspaceVersion)?; @@ -358,10 +551,68 @@ impl TryFrom for cluster::View<(), node_operator node_operators, ownership: Ownership::new(view.owner.into()), settings: view.settings.into(), - keyspace, + keyspace: Arc::new(keyspace), migration, maintenance: view.maintenance.into(), cluster_version: view.version, }) } } + +impl From for DeploymentError { + fn from(err: alloy::contract::Error) -> Self { + Self(format!("{err:?}")) + } +} + +impl From> for WriteError { + fn from(err: alloy::transports::RpcError) -> Self { + WriteError::Transport(format!("{err:?}")) + } +} + +impl From> for ReadError { + fn from(err: alloy::transports::RpcError) -> Self { + ReadError::Transport(format!("{err:?}")) + } +} + +impl From for WriteError { + fn from(err: alloy::providers::PendingTransactionError) -> Self { + Self::Other(format!("{err:?}")) + } +} + +impl From for WriteError { + fn from(err: alloy::contract::Error) -> Self { + match err { + alloy::contract::Error::TransportError(err) => Self::Transport(format!("{err:?}")), + _ => Self::Other(format!("{err:?}")), + } + } +} + +impl From for ReadError { + fn from(err: alloy::contract::Error) -> Self { + match err { + alloy::contract::Error::TransportError(err) => Self::Transport(format!("{err:?}")), + _ => Self::Other(format!("{err:?}")), + } + } +} + +impl From for ReadError { + fn from(err: alloy::sol_types::Error) -> Self { + ReadError::InvalidData(format!("{err:?}")) + } +} + +#[derive(Debug, thiserror::Error)] +#[error("{_0}")] +pub struct RpcProviderCreationError(String); + +impl From for RpcProviderCreationError { + fn from(err: alloy::transports::TransportError) -> Self { + Self(format!("alloy transport: {err:?}")) + } +} diff --git a/crates/cluster/src/smart_contract/mod.rs b/crates/cluster/src/smart_contract/mod.rs index 09ef2aab..c7b292c7 100644 --- a/crates/cluster/src/smart_contract/mod.rs +++ b/crates/cluster/src/smart_contract/mod.rs @@ -3,41 +3,49 @@ pub mod evm; use { - crate::{self as cluster, migration, node_operator, Keyspace, NodeOperators, Settings}, - alloy::{network::TxSigner as _, signers::local::PrivateKeySigner, transports::http::reqwest}, + crate::{ + self as cluster, + migration, + node_operator, + Keyspace, + NodeOperators, + SerializedEvent, + Settings, + }, + alloy::{signers::local::PrivateKeySigner, transports::http::reqwest}, derive_more::derive::{Display, From}, + futures::Stream, serde::{Deserialize, Serialize}, - std::str::FromStr, + std::{future::Future, str::FromStr}, }; -/// Smart-contract managing the state of a WCN cluster. -/// -/// Logic invariants documented on the methods of this trait MUST be -/// implemented inside the on-chain implementation of the smart-contract itself. -pub trait SmartContract: ReadOnlySmartContract { - type ReadOnly: ReadOnlySmartContract; - - /// Deploys a new smart-contract. - async fn deploy( - signer: Signer, - rpc_url: RpcUrl, +/// Deployer of WCN Cluster [`SmartContract`]s. +pub trait Deployer { + /// Deploys a new [`SmartContract`]. + fn deploy( + &self, initial_settings: Settings, initial_operators: NodeOperators, - ) -> Result; + ) -> impl Future>; +} - /// Connects to an existing smart-contract. - async fn connect( - address: Address, - signer: Signer, - rpc_url: RpcUrl, - ) -> Result; +/// Connector to WCN Cluster [`SmartContract`]s. +pub trait Connector { + /// Connects to an existing [`SmartContract`]. + fn connect(&self, address: Address) -> impl Future>; +} - /// Connects to an existing smart-contract in read-only mode. - async fn connect_ro(address: Address, rpc_url: RpcUrl) -> Result; +/// Smart-contract managing the state of a WCN cluster. +pub trait SmartContract: Read + Write {} - /// Returns the [`AccountAddress`] of the [`Signer`] which is currently - /// being used for signing transactions of [`SmartContract`] instance. - fn signer(&self) -> &AccountAddress; +/// Write [`SmartContract`] calls. +/// +/// Logic invariants documented on the methods of this trait MUST be +/// implemented inside the on-chain implementation of the smart-contract itself. +// TODO: docs are outdated, revisit +pub trait Write { + /// Returns the [`Signer`] being used to sign transactions. + fn signer(&self) -> &Signer; /// Starts a new data [`migration`] process using the provided /// [`migration::Plan`]. @@ -49,7 +57,7 @@ pub trait SmartContract: ReadOnlySmartContract { /// [`SmartContract`] /// /// The implementation MUST emit [`migration::Started`] event on success. - async fn start_migration(&self, new_keyspace: Keyspace) -> Result<()>; + fn start_migration(&self, new_keyspace: Keyspace) -> impl Future>; /// Marks that the [`signer`](SmartContract::signer) has completed the data /// pull required for completion of the current [`migration`]. @@ -68,7 +76,7 @@ pub trait SmartContract: ReadOnlySmartContract { /// /// The implementation MAY be idempotent. In case of an idempotent /// execution the event MUST not be emitted. - async fn complete_migration(&self, id: migration::Id) -> Result<()>; + fn complete_migration(&self, id: migration::Id) -> impl Future>; /// Aborts the ongoing data [`migration`] process restoring the WCN cluster /// to the original state it had before the migration had started. @@ -79,7 +87,7 @@ pub trait SmartContract: ReadOnlySmartContract { /// [`SmartContract`] /// /// The implementation MUST emit [`migration::Aborted`] event on success. - async fn abort_migration(&self, id: migration::Id) -> Result<()>; + fn abort_migration(&self, id: migration::Id) -> impl Future>; /// Starts a [`maintenance`] process for the [`node::Operator`] being the /// current [`signer`](Manager::signer). @@ -91,7 +99,7 @@ pub trait SmartContract: ReadOnlySmartContract { /// provided [`node::OperatorIdx`] /// /// The implementation MUST emit [`maintenance::Started`] event on success. - async fn start_maintenance(&self) -> Result<()>; + fn start_maintenance(&self) -> impl Future>; /// Completes the ongoing [`maintenance`] process. /// @@ -102,13 +110,13 @@ pub trait SmartContract: ReadOnlySmartContract { /// /// The implementation MUST emit [`maintenance::Completed`] event on /// success. - async fn finish_maintenance(&self) -> Result<()>; + fn finish_maintenance(&self) -> impl Future>; - async fn add_node_operator( + fn add_node_operator( &self, idx: node_operator::Idx, operator: node_operator::Serialized, - ) -> Result<()>; + ) -> impl Future>; /// Updates on-chain data of a [`node::Operator`]. /// @@ -117,19 +125,37 @@ pub trait SmartContract: ReadOnlySmartContract { /// provided [`node::OperatorIdx`] /// /// The implementation MUST emit [`node::OperatorUpdated`] event on success. - async fn update_node_operator(&self, operator: node_operator::Serialized) -> Result<()>; + fn update_node_operator( + &self, + operator: node_operator::Serialized, + ) -> impl Future>; - async fn remove_node_operator(&self, id: node_operator::Id) -> Result<()>; + fn remove_node_operator(&self, id: node_operator::Id) -> impl Future>; - async fn update_settings(&self, new_settings: Settings) -> Result<()>; + fn update_settings(&self, new_settings: Settings) -> impl Future>; - async fn transfer_ownership(&self, new_owner: AccountAddress) -> Result<()>; + fn transfer_ownership( + &self, + new_owner: AccountAddress, + ) -> impl Future>; } -/// Read-only handle to a smart-contract managing the state of a WCN cluster. -pub trait ReadOnlySmartContract: Sized + Send + Sync + 'static { - /// Returns the current [`ClusterView`]. - async fn cluster_view(&self) -> Result>; +/// Read [`SmartContract`] calls. +pub trait Read: Sized + Send + Sync + 'static { + /// Returns [`Address`] of this [`SmartContract`]. + fn address(&self) -> Address; + + /// Returns the current [`cluster::View`]. + fn cluster_view( + &self, + ) -> impl Future>> + Send; + + /// Subscribes to WCN Cluster [`Events`]. + fn events( + &self, + ) -> impl Future< + Output = ReadResult> + Send + 'static>, + > + Send; } /// [`SmartContract`] address. @@ -141,16 +167,23 @@ pub struct Address(evm::Address); pub struct AccountAddress(evm::Address); /// Transaction signer. +#[derive(Clone)] pub struct Signer { - inner: SignerInner, + address: AccountAddress, + kind: SignerKind, } /// RPC provider URL. pub struct RpcUrl(reqwest::Url); -/// Error of [`SmartContract::connect`] and [`SmartContract::connect_ro`]. +/// Error of [`Deployer::deploy`]. #[derive(Debug, thiserror::Error)] -pub enum ConnectError { +#[error("{_0}")] +pub struct DeploymentError(String); + +/// Error of [`Connector::connect`]. +#[derive(Debug, thiserror::Error)] +pub enum ConnectionError { #[error("Smart-contract with the provided address doesn't exist")] UnknownContract, @@ -161,43 +194,58 @@ pub enum ConnectError { Other(String), } -/// [`SmartContract`] error. +/// [`Write`] error. #[derive(Debug, thiserror::Error)] -pub enum Error { - #[error("Revert: {0}")] +pub enum WriteError { + #[error("Transport: {0}")] + Transport(String), + + #[error("Transaction reverted: {0}")] Revert(String), #[error("Other: {0}")] Other(String), } -/// [`ReadOnlySmartContract`] error. +/// [`Read`] error. #[derive(Debug, thiserror::Error)] -#[error("{0}")] -pub struct ReadError(String); -/// [`SmartContract`] result. -pub type Result = std::result::Result; +pub enum ReadError { + #[error("Transport: {0}")] + Transport(String), -/// [`ReadOnlySmartContract`] result. -pub type ReadResult = std::result::Result; + #[error("Invalid data: {0}")] + InvalidData(String), + + #[error("Other: {0}")] + Other(String), +} + +/// [`Write`] result. +pub type WriteResult = std::result::Result; + +/// [`Read`] result. +pub type ReadResult = std::result::Result; impl Signer { pub fn try_from_private_key(hex: &str) -> Result { - PrivateKeySigner::from_str(hex) - .map(SignerInner::PrivateKey) - .map(|inner| Self { inner }) - .map_err(|err| InvalidPrivateKeyError(err.to_string())) + let private_key = PrivateKeySigner::from_str(hex) + .map_err(|err| InvalidPrivateKeyError(err.to_string()))?; + + Ok(Self { + address: AccountAddress(private_key.address()), + kind: SignerKind::PrivateKey(private_key), + }) } - pub fn address(&self) -> AccountAddress { - match &self.inner { - SignerInner::PrivateKey(key) => AccountAddress(key.address()), - } + /// Returns [`AccountAddress`] of this [`Signer`]. + pub fn address(&self) -> &AccountAddress { + &self.address } } -enum SignerInner { +#[derive(Clone)] +enum SignerKind { PrivateKey(PrivateKeySigner), } @@ -246,3 +294,5 @@ impl FromStr for Address { .map_err(|err| InvalidAddressError(err.to_string())) } } + +impl SmartContract for SC where SC: Read + Write {} diff --git a/crates/cluster/src/task.rs b/crates/cluster/src/task.rs new file mode 100644 index 00000000..af274025 --- /dev/null +++ b/crates/cluster/src/task.rs @@ -0,0 +1,117 @@ +use { + crate::{ + keyspace, + node_operator, + smart_contract, + view, + Inner, + Keyspace, + SerializedEvent, + View, + }, + futures::{Stream, StreamExt}, + std::{pin::pin, sync::Arc, time::Duration}, + tokio::sync::watch, +}; + +pub(super) struct Task { + pub initial_events: Option, + pub inner: Arc>, + pub watch: watch::Sender<()>, +} + +pub(super) struct Guard(tokio::task::JoinHandle<()>); + +impl Drop for Guard { + fn drop(&mut self) { + self.0.abort(); + tracing::info!("aborted"); + } +} + +impl Task +where + SC: smart_contract::Read, + Shards: Clone + Send + Sync + 'static, + Events: Stream> + Send + 'static, + Keyspace: keyspace::sealed::Calculate, +{ + pub(super) fn spawn(self) -> Guard { + let guard = Guard(tokio::spawn(self.run())); + tracing::info!("spawned"); + guard + } + + async fn run(mut self) { + loop { + // apply initial events until they finish / first error + if let Some(events) = self.initial_events.take() { + match self.apply_events(events).await { + Ok(()) => tracing::warn!("Initial event stream finished"), + Err(err) => tracing::error!(%err, "Failed to apply initial events"), + } + } + + loop { + // when we fail for whatever reason - subscribe again and refetch the whole + // state + match self.update_view().await { + Ok(()) => tracing::warn!("Event stream finished"), + Err(err) => { + tracing::error!(%err, "Failed to update cluster::View"); + tokio::time::sleep(Duration::from_secs(60)).await; + } + } + } + } + } + + async fn update_view(&mut self) -> Result<()> { + let events = self.inner.smart_contract.events().await?; + + let new_view = View::fetch(&self.inner.smart_contract).await?; + if self.inner.view.load().cluster_version != new_view.cluster_version { + let new_view = Arc::new(new_view.calculate_keyspace().await); + self.inner.view.store(new_view); + let _ = self.watch.send(()); + } + + self.apply_events(events).await + } + + async fn apply_events( + &mut self, + events: impl Stream>, + ) -> Result<()> { + let mut events = pin!(events); + + while let Some(res) = events.next().await { + let event = res?.deserialize()?; + tracing::info!(?event, "received"); + + let view = self.inner.view.load_full(); + let view = Arc::new((*view).clone().apply_event(event).await?); + self.inner.view.store(view); + let _ = self.watch.send(()); + } + + Ok(()) + } +} + +#[derive(Debug, thiserror::Error)] +enum Error { + #[error(transparent)] + ApplyEvent(#[from] view::Error), + + #[error(transparent)] + DataDeserialization(#[from] node_operator::DataDeserializationError), + + #[error(transparent)] + ViewFetch(#[from] view::FetchError), + + #[error(transparent)] + SmartContractRead(#[from] smart_contract::ReadError), +} + +type Result = std::result::Result; diff --git a/crates/cluster/src/view.rs b/crates/cluster/src/view.rs index 1b3bcba1..2eaf6fdf 100644 --- a/crates/cluster/src/view.rs +++ b/crates/cluster/src/view.rs @@ -10,6 +10,7 @@ use { node_operators, ownership, settings, + smart_contract, Event, Keyspace, Maintenance, @@ -19,16 +20,18 @@ use { Settings, }, futures::future::OptionFuture, + std::sync::Arc, }; /// Read-only view of a WCN cluster. +#[derive(Clone)] pub struct View { pub(super) node_operators: NodeOperators, pub(super) ownership: Ownership, pub(super) settings: Settings, - pub(super) keyspace: Keyspace, + pub(super) keyspace: Arc>, pub(super) migration: Option>, pub(super) maintenance: Option, @@ -36,6 +39,13 @@ pub struct View { } impl View { + pub(super) async fn fetch(contract: &impl smart_contract::Read) -> Result + where + Keyspace: keyspace::sealed::Calculate, + { + Ok(contract.cluster_view().await?.deserialize()?) + } + /// Returns [`Ownership`] of the WCN cluster. pub fn ownership(&self) -> &Ownership { &self.ownership @@ -125,17 +135,20 @@ impl View { } impl View { - pub(super) async fn calculate_keyspace_shards(self) -> View { + pub(super) async fn calculate_keyspace(self) -> View + where + Keyspace: keyspace::sealed::Calculate, + { let (keyspace, migration) = tokio::join!( - self.keyspace.calculate_shards(), - OptionFuture::from(self.migration.map(Migration::calculate_keyspace_shards)) + (*self.keyspace).clone().calculate(), + OptionFuture::from(self.migration.map(Migration::calculate_keyspace)) ); View { node_operators: self.node_operators, ownership: self.ownership, settings: self.settings, - keyspace, + keyspace: Arc::new(keyspace), migration, maintenance: self.maintenance, cluster_version: self.cluster_version, @@ -170,7 +183,7 @@ impl migration::Started { view.migration = Some(Migration::new( self.migration_id, - self.new_keyspace.calculate_shards().await, + self.new_keyspace.calculate().await, view.node_operators.occupied_indexes(), )); @@ -325,3 +338,13 @@ pub enum Error { /// Result of [`View::apply_event`]. pub type Result = std::result::Result; + +/// Error of fetching [`View`] from a [`smart_contract`]. +#[derive(Debug, thiserror::Error)] +pub enum FetchError { + #[error(transparent)] + DataDeserialization(#[from] node_operator::DataDeserializationError), + + #[error("Smart-contract: {0}")] + SmartContractRead(#[from] smart_contract::ReadError), +} diff --git a/crates/cluster/tests/integration.rs b/crates/cluster/tests/integration.rs index 49078be5..da66702f 100644 --- a/crates/cluster/tests/integration.rs +++ b/crates/cluster/tests/integration.rs @@ -1,51 +1,124 @@ use { cluster::{ + keyspace::ReplicationStrategy, node_operator, - smart_contract::{evm, Signer}, + smart_contract::{ + self, + evm::{self, RpcProvider}, + Read, + Signer, + }, Cluster, Node, NodeOperator, Settings, }, libp2p::PeerId, - std::net::SocketAddrV4, + std::{collections::HashSet, net::SocketAddrV4, time::Duration}, + tracing_subscriber::EnvFilter, }; +// Anvil private keys with balances +const PRIVATE_KEYS: [&'static str; 10] = [ + "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", + "0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d", + "0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a", + "0x7c852118294e51e653712a81e05800f419141751be58f605c371e15141b007a6", + "0x47e179ec197488593b187f80a00eb0da91f1b9d0b13f8733639f19c30a34926a", + "0x8b3a350cf5c34c9194ca85829a2df0ec3153be0318b5e2d3348e872092edffba", + "0x92db14e403b83dfe3df233f83dfa3a0d7096f21ca9b0d6d6b8d88b2b4ec1564e", + "0x4bbbf85ce3377467afe5d46f804f221813b2bb87f24d81f60f1fcdbf7cbf4356", + "0xdbda1821b80551c9d65939329250298aa3472ba22feea921c0cf5d620ea67b97", + "0x2a871d0798f97d79848a013d4936a73bf4cc922c825d33c1cf7073dff6d409c6", +]; + #[tokio::test] async fn test_suite() { + let subscriber = tracing_subscriber::FmtSubscriber::builder() + .with_max_level(tracing::Level::INFO) + .with_env_filter(EnvFilter::from_default_env()) + .finish(); + tracing::subscriber::set_global_default(subscriber).unwrap(); + let settings = Settings { max_node_operator_data_bytes: 4096, }; - // let signer = - // Signer::try_from_private_key(&std::env::var("SIGNER_PRIVATE_KEY"). - // unwrap()).unwrap(); - let signer = Signer::try_from_private_key( "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", ) .unwrap(); - // let rpc_url = "https://mainnet.optimism.io".parse().unwrap(); + let provider = provider(signer).await; - let rpc_url = "http://127.0.0.1:8545".parse().unwrap(); + let operators = (1..=5).map(|n| new_node_operator(n)).collect(); - let operators = (1..=5).map(|n| test_node_operator(n)).collect(); + let cluster = Cluster::>::deploy(&provider, settings, operators) + .await + .unwrap(); - let contract = Cluster::::deploy(signer, rpc_url, settings, operators) + for idx in 5..=7 { + cluster + .add_node_operator(idx, new_node_operator(idx + 1)) + .await + .unwrap(); + } + + cluster + .start_migration(cluster::migration::Plan { + remove: [operator_id(1)].into_iter().collect(), + add: [operator_id(6), operator_id(7), operator_id(8)] + .into_iter() + .collect(), + replication_strategy: ReplicationStrategy::UniformDistribution, + }) .await .unwrap(); - // let contract_address = "0xcefa8836c9cd102c3b118b7681cf09d839cb324e" - // .parse() - // .unwrap(); + for idx in 1..=7 { + connect(idx + 1, cluster.smart_contract().address()) + .await + .complete_migration(1) + .await + .unwrap(); + } + + tokio::time::sleep(Duration::from_secs(1)).await; - // let contract = Cluster::::connect(contract_address, - // signer, rpc_url) .await - // .unwrap(); + cluster + .start_migration(cluster::migration::Plan { + remove: HashSet::default(), + add: [operator_id(1)].into_iter().collect(), + replication_strategy: ReplicationStrategy::UniformDistribution, + }) + .await + .unwrap(); + + cluster.abort_migration(2).await.unwrap(); + + cluster.start_maintenance().await.unwrap(); + cluster.finish_maintenance().await.unwrap(); + + cluster.remove_node_operator(operator_id(1)).await.unwrap(); + + let mut operator2 = new_node_operator(2); + operator2.data.name = node_operator::Name::new("NewName").unwrap(); + cluster.update_node_operator(operator2).await.unwrap(); + + cluster + .update_settings(Settings { + max_node_operator_data_bytes: 10000, + }) + .await + .unwrap(); + + cluster + .transfer_ownership(*new_signer(9).address()) + .await + .unwrap(); } -fn test_node_operator(n: u8) -> NodeOperator { +fn new_node_operator(n: u8) -> NodeOperator { let data = node_operator::Data { name: node_operator::Name::new(format!("Operator{n}")).unwrap(), nodes: vec![Node { @@ -55,13 +128,32 @@ fn test_node_operator(n: u8) -> NodeOperator { clients: vec![], }; - let mut private_key: [u8; 32] = Default::default(); - private_key[0] = n; - - let signer = Signer::try_from_private_key(&format!("0x{}", hex::encode(&private_key))).unwrap(); - NodeOperator { - id: signer.address(), + id: operator_id(n), data, } } + +fn operator_id(n: u8) -> node_operator::Id { + *new_signer(n).address() +} + +fn new_signer(n: u8) -> Signer { + Signer::try_from_private_key(PRIVATE_KEYS[n as usize]).unwrap() +} + +async fn provider(signer: Signer) -> RpcProvider { + RpcProvider::new("ws://127.0.0.1:8545".parse().unwrap(), signer) + .await + .unwrap() +} + +async fn connect( + operator: u8, + address: smart_contract::Address, +) -> Cluster> { + let provider = provider(new_signer(operator)).await; + Cluster::>::connect(&provider, address) + .await + .unwrap() +} diff --git a/flake.lock b/flake.lock index 917983d2..3c6f36b3 100644 --- a/flake.lock +++ b/flake.lock @@ -8,11 +8,11 @@ "rust-analyzer-src": "rust-analyzer-src" }, "locked": { - "lastModified": 1729492502, - "narHash": "sha256-d6L4bBlUWr4sHC+eRXo+4acFPEFXKmqHpM/BfQ5gQQw=", + "lastModified": 1749105720, + "narHash": "sha256-R3mjXc+LF74COXMDfJLuKEUPliXqOqe0wgErgTOFovI=", "owner": "nix-community", "repo": "fenix", - "rev": "4002a1ec3486b855f341d2b864ba06b61e73af28", + "rev": "fd217600040e0e7c7ea844af027f3dc1f4b35e6c", "type": "github" }, "original": { @@ -65,11 +65,11 @@ "rust-analyzer-src": { "flake": false, "locked": { - "lastModified": 1729454508, - "narHash": "sha256-1W5B/CnLgdC03iIFG0wtawO1+dGDWDpc84PeOHo2ecU=", + "lastModified": 1749033758, + "narHash": "sha256-Ie003Weeg3Lsly9QuFJtw8W1JXnxoYD3FeV9KIxE+Ss=", "owner": "rust-lang", "repo": "rust-analyzer", - "rev": "9323b5385863739d1c113f02e4cf3f2777c09977", + "rev": "55b733103efa59f3504e308629b59d49da69bd9a", "type": "github" }, "original": { From 8af8b74ba4807877cab472e285f19deac7d4a38d Mon Sep 17 00:00:00 2001 From: Github Bot Date: Fri, 6 Jun 2025 10:42:09 +0000 Subject: [PATCH 38/79] Bump VERSION to 250606.0 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 3f784cea..0d1280d9 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -250605.0 +250606.0 From 76b393a3ba2f8a6bf7a5cad94ff8a740afe92414 Mon Sep 17 00:00:00 2001 From: Darksome Date: Fri, 6 Jun 2025 10:46:47 +0000 Subject: [PATCH 39/79] remove cluster --- crates/cluster/Cargo.toml | 46 -- crates/cluster/src/client.rs | 36 -- crates/cluster/src/keyspace.rs | 198 ------- crates/cluster/src/lib.rs | 684 ----------------------- crates/cluster/src/maintenance.rs | 46 -- crates/cluster/src/migration.rs | 189 ------- crates/cluster/src/node.rs | 56 -- crates/cluster/src/node_operator.rs | 276 --------- crates/cluster/src/node_operators.rs | 167 ------ crates/cluster/src/ownership.rs | 51 -- crates/cluster/src/settings.rs | 19 - crates/cluster/src/smart_contract/evm.rs | 618 -------------------- crates/cluster/src/smart_contract/mod.rs | 298 ---------- crates/cluster/src/task.rs | 117 ---- crates/cluster/src/view.rs | 350 ------------ crates/cluster/tests/integration.rs | 159 ------ 16 files changed, 3310 deletions(-) delete mode 100644 crates/cluster/Cargo.toml delete mode 100644 crates/cluster/src/client.rs delete mode 100644 crates/cluster/src/keyspace.rs delete mode 100644 crates/cluster/src/lib.rs delete mode 100644 crates/cluster/src/maintenance.rs delete mode 100644 crates/cluster/src/migration.rs delete mode 100644 crates/cluster/src/node.rs delete mode 100644 crates/cluster/src/node_operator.rs delete mode 100644 crates/cluster/src/node_operators.rs delete mode 100644 crates/cluster/src/ownership.rs delete mode 100644 crates/cluster/src/settings.rs delete mode 100644 crates/cluster/src/smart_contract/evm.rs delete mode 100644 crates/cluster/src/smart_contract/mod.rs delete mode 100644 crates/cluster/src/task.rs delete mode 100644 crates/cluster/src/view.rs delete mode 100644 crates/cluster/tests/integration.rs diff --git a/crates/cluster/Cargo.toml b/crates/cluster/Cargo.toml deleted file mode 100644 index 9622013a..00000000 --- a/crates/cluster/Cargo.toml +++ /dev/null @@ -1,46 +0,0 @@ -[package] -name = "cluster" -version = "0.1.0" -edition = "2021" - -[lints] -workspace = true - -[dependencies] -derive_more = { workspace = true, features = ["try_from", "into"] } -derivative = { workspace = true } -libp2p = { workspace = true } -itertools = { workspace = true } -futures = { workspace = true } -backoff = { workspace = true } -tracing = { workspace = true } -tokio-stream = { workspace = true } - -sharding = { path = "../sharding" } - -alloy = { version = "1.0", default-features = false, features = ["sol-types", "contract", "signer-local", "network", "reqwest", "provider-ws", "rpc-types"] } - -anyhow = "1" -thiserror = "1" - -tap = "1.0" -serde = { version = "1", features = ["derive"] } -postcard = { version = "1.0", default-features = false, features = ["alloc"] } - -xxhash-rust = { version = "0.8", features = ["xxh3", "const_xxh3"] } -fpe = "0.6" -aes = "0.8" - -tokio = { version = "1", features = ["full"] } -arc-swap = "1.7" - -[dev-dependencies] -alloy = { version = "1.0", default-features = false, features = ["provider-anvil-node"] } -tokio = { version = "1", default-features = false } -hex = "0.4" - -tracing-subscriber = { version = "0.3", features = [ - "env-filter", - "parking_lot", - "json", -] } diff --git a/crates/cluster/src/client.rs b/crates/cluster/src/client.rs deleted file mode 100644 index 200939a7..00000000 --- a/crates/cluster/src/client.rs +++ /dev/null @@ -1,36 +0,0 @@ -//! Client of a WCN cluster. - -use { - libp2p::identity::PeerId, - serde::{Deserialize, Serialize}, -}; - -/// Client of a WCN cluster. -#[derive(Debug, Clone)] -pub struct Client { - /// [`PeerId`] of the [`Client`]. Used for authentication. - pub peer_id: PeerId, -} - -// NOTE: The on-chain serialization is non self-describing! Every change to -// the schema should be handled by creating a new version. -#[derive(Clone, Copy, Debug, Serialize, Deserialize)] -pub(crate) struct V0 { - pub peer_id: PeerId, -} - -impl From for V0 { - fn from(client: Client) -> Self { - Self { - peer_id: client.peer_id, - } - } -} - -impl From for Client { - fn from(client: V0) -> Self { - Self { - peer_id: client.peer_id, - } - } -} diff --git a/crates/cluster/src/keyspace.rs b/crates/cluster/src/keyspace.rs deleted file mode 100644 index 3b041563..00000000 --- a/crates/cluster/src/keyspace.rs +++ /dev/null @@ -1,198 +0,0 @@ -use { - crate::node_operator::{self}, - derivative::Derivative, - derive_more::TryFrom, - sharding::ShardId, - std::collections::HashSet, - xxhash_rust::xxh3::Xxh3Builder, -}; - -/// Maximum number of [`node_operator`]s within a [`Keyspace`]. -pub const MAX_OPERATORS: usize = 256; - -/// Number of [`node_operator`]s within a [`ReplicaSet`]. -pub const REPLICATION_FACTOR: usize = 5; - -/// Continuous space of `u64` keys. -/// -/// [`Keyspace`] is being split into a set of equally sized [`Shards`], -/// and each [`Shard`] is being assigned to a set of [`node_operator`]s. -#[derive(Clone, Derivative)] -#[derivative(Debug)] -pub struct Keyspace { - operators: HashSet, - - #[derivative(Debug = "ignore")] - shards: S, - - replication_strategy: ReplicationStrategy, - - version: u64, -} - -/// All [`Shard`]s within a [`Keyspace`]. -pub struct Shards(sharding::Keyspace); - -/// A single [`Shard`] within a [`Keyspace`]. -#[derive(Clone, Copy, Debug)] -pub struct Shard { - replica_set: [node_operator::Idx; REPLICATION_FACTOR], -} - -/// Strategy of distributing [`Shard`]s to [`node_operator`]s. -#[repr(u8)] -#[derive(Clone, Copy, Debug, Default, TryFrom, Eq, PartialEq)] -#[try_from(repr)] -pub enum ReplicationStrategy { - /// [`Shard`]s are being uniformly distributed across [`node_operator`]s. - #[default] - UniformDistribution = 0, -} - -/// Set of [`node_operator`]s assigned to a [`Shard`]. -pub type ReplicaSet = [T; REPLICATION_FACTOR]; - -/// [`Keyspace`] version. -pub type Version = u64; - -impl Keyspace { - /// Creates a new [`Keyspace`]. - pub fn new( - operators: HashSet, - replication_strategy: ReplicationStrategy, - version: u64, - ) -> Result { - if operators.len() < REPLICATION_FACTOR { - return Err(CreationError::TooFewOperators(operators.len())); - } - - if operators.len() > MAX_OPERATORS { - return Err(CreationError::TooManyOperators(operators.len())); - } - - Ok(Keyspace { - operators, - shards: (), - replication_strategy, - version, - }) - } - - pub(crate) async fn calculate(self) -> Keyspace - where - Self: sealed::Calculate, - { - sealed::Calculate::::calculate_shards(self).await - } -} - -impl Keyspace { - /// Returns the [`Shard`] that contains the specified key. - pub fn shard(&self, key: u64) -> Shard { - Shard { - replica_set: *self.shards.0.shard_replicas(ShardId::from_key(key)), - } - } -} - -impl Keyspace { - /// Returns an [`Iterator`] over [`node_operator`]s of this [`Keyspace`]. - pub fn operators(&self) -> impl Iterator + '_ { - self.operators.iter().copied() - } - - /// Returns [`ReplicationStrategy`] of this [`Keyspace`]. - pub fn replication_strategy(&self) -> ReplicationStrategy { - self.replication_strategy - } - - /// Returns [`Version`] of this [`Keyspace`]. - pub fn version(&self) -> Version { - self.version - } - - pub(super) fn contains_operator(&self, idx: node_operator::Idx) -> bool { - self.operators.contains(&idx) - } - - pub(super) fn require_diff(&self, other: &Keyspace) -> Result<(), SameKeyspaceError> { - if self.operators == other.operators - && self.replication_strategy == other.replication_strategy - { - return Err(SameKeyspaceError); - } - - Ok(()) - } -} - -impl Shard { - /// Returns [`ReplicaSet`] assigned to this [`Shard`]. - pub fn replica_set(&self) -> ReplicaSet { - self.replica_set - } -} - -#[derive(Debug, thiserror::Error)] -pub enum CreationError { - #[error("Too few operators within a Keyspace: {_0} < {REPLICATION_FACTOR}")] - TooFewOperators(usize), - - #[error("Too many operators within a Keyspace: {_0} > {MAX_OPERATORS}")] - TooManyOperators(usize), -} - -#[derive(Debug, thiserror::Error)] -#[error("The new Keyspace doesn't differ from the old one")] -pub struct SameKeyspaceError; - -pub(crate) mod sealed { - use std::future::Future; - - #[allow(unused_imports)] - use super::*; - - /// Trait to make `Keyspace<()>` and `Keyspace` polymorphic. - pub trait Calculate { - /// Calculates [`Shards`] of a [`Keyspace`]. - /// - /// It's highly CPU intensive task (order of seconds), so the task is - /// being [spawned](tokio::task::spawn_blocking) to the - /// [`tokio`] threadpool. - fn calculate_shards(self) -> impl Future> + Send; - } -} - -impl sealed::Calculate for Keyspace { - async fn calculate_shards(self) -> Keyspace { - let operators = self.operators.clone(); - let res = tokio::task::spawn_blocking(move || { - sharding::Keyspace::new(operators.into_iter(), &Xxh3Builder::default(), || { - sharding::DefaultReplicationStrategy - }) - }) - .await - .unwrap(); // we don't expect the task to panic - - match res { - Ok(sharding) => Keyspace { - operators: self.operators, - shards: Shards(sharding), - replication_strategy: ReplicationStrategy::UniformDistribution, - version: self.version, - }, - - // we checked this in the `Keyspace` constructor - Err(sharding::Error::InvalidNodesCount(_)) => unreachable!(), - - // impossible with the default replication strategy - Err(sharding::Error::IncompleteReplicaSet) => unreachable!(), - } - } -} - -impl sealed::Calculate<()> for Keyspace { - async fn calculate_shards(self) -> Keyspace { - self - } -} diff --git a/crates/cluster/src/lib.rs b/crates/cluster/src/lib.rs deleted file mode 100644 index b3663a6c..00000000 --- a/crates/cluster/src/lib.rs +++ /dev/null @@ -1,684 +0,0 @@ -//! WalletConnect Network Cluster. - -use { - arc_swap::ArcSwap, - futures::Stream, - itertools::Itertools, - smart_contract::evm, - std::{collections::HashSet, sync::Arc}, - tokio::sync::watch, -}; - -pub mod smart_contract; -pub use smart_contract::SmartContract; - -pub mod view; -pub use view::View; - -pub mod settings; -pub use settings::Settings; - -pub mod ownership; -pub use ownership::Ownership; - -pub mod client; -pub use client::Client; - -pub mod node; -pub use node::Node; - -pub mod node_operator; -pub use node_operator::NodeOperator; - -pub mod node_operators; -pub use node_operators::NodeOperators; - -pub mod keyspace; -pub use keyspace::Keyspace; - -pub mod migration; -pub use migration::Migration; - -pub mod maintenance; -pub use maintenance::Maintenance; - -mod task; -use task::Task; - -/// Maximum number of [`NodeOperator`]s within a WCN [`Cluster`]. -pub const MAX_OPERATORS: usize = keyspace::MAX_OPERATORS; - -/// Minimum number fo [`NodeOperator`]s within a WCN [`Cluster`]. -pub const MIN_OPERATORS: usize = keyspace::REPLICATION_FACTOR; - -/// WCN cluster. -/// -/// Thin wrapper around the underlying [`SmartContract`] implementation. -/// -/// Performs preliminary invariant validation before calling the actual -/// [`SmartContract`] methods. -pub struct Cluster { - inner: Arc>, - _task_guard: Arc, -} - -struct Inner { - smart_contract: SC, - view: ArcSwap>, - watch: watch::Receiver<()>, -} - -/// Version of a WCN [`Cluster`]. -/// -/// Should only monotonically increase. If you observe a jump backwards it means -/// that a chain reorg has occured on the underlying [`SmartContract`] chain. -/// -/// For each version bump a corresponding [`Event`] should be emitted. -pub type Version = u128; - -/// Events happening within a WCN [`Cluster`]. -#[derive(Debug)] -pub enum Event { - /// [`Migration`] has started. - MigrationStarted(migration::Started), - - /// [`NodeOperator`] has completed the data pull. - MigrationDataPullCompleted(migration::DataPullCompleted), - - /// [`Migration`] has been completed. - MigrationCompleted(migration::Completed), - - /// [`Migration`] has been aborted. - MigrationAborted(migration::Aborted), - - /// [`Maintenance`] has started. - MaintenanceStarted(maintenance::Started), - - /// [`Maintenance`] has been finished. - MaintenanceFinished(maintenance::Finished), - - /// [`NodeOperator`] has been updated. - NodeOperatorAdded(node_operator::Added), - - /// [`NodeOperator`] has been updated. - NodeOperatorUpdated(node_operator::Updated), - - /// [`NodeOperator`] has been removed. - NodeOperatorRemoved(node_operator::Removed), - - /// [`Settings`] have been updated. - SettingsUpdated(settings::Updated), - - /// [`Ownership`] has been transferred. - OwnershipTransferred(ownership::Transferred), -} - -/// [`Event`] with [`node_operator::SerializedData`]. -pub type SerializedEvent = Event; - -impl Cluster -where - SC: smart_contract::Read, - Shards: Clone + Send + Sync + 'static, - Keyspace: keyspace::sealed::Calculate, -{ - /// Deploys a new WCN [`Cluster`]. - pub async fn deploy( - deployer: &impl smart_contract::Deployer, - initial_settings: Settings, - initial_operators: Vec, - ) -> Result { - let operators: Vec<_> = initial_operators - .into_iter() - .map(|op| { - let op = op.serialize()?; - op.data.validate(&initial_settings)?; - Ok::<_, DeploymentError>(op) - }) - .try_collect()?; - - let operators = NodeOperators::new(operators.into_iter().map(Some))?; - - let contract = deployer.deploy(initial_settings, operators).await?; - - Self::new(contract).await.map_err(Into::into) - } - - /// Connects to an existing WCN [`Cluster`]. - pub async fn connect( - connector: &impl smart_contract::Connector, - contract_address: smart_contract::Address, - ) -> Result { - let contract = connector.connect(contract_address).await?; - Self::new(contract).await.map_err(Into::into) - } - - async fn new(contract: SC) -> Result { - let events = contract.events().await?; - let view = View::fetch(&contract).await?.calculate_keyspace().await; - - let (tx, rx) = watch::channel(()); - let inner = Arc::new(Inner { - smart_contract: contract, - view: ArcSwap::new(Arc::new(view)), - watch: rx, - }); - - let guard = Task { - initial_events: Some(events), - inner: inner.clone(), - watch: tx, - } - .spawn(); - - Ok(Self { - inner, - _task_guard: Arc::new(guard), - }) - } -} - -impl Cluster { - /// Passes the current [`cluster::View`] into the provided closure. - /// - /// More efficient than calling [`Cluster::view`]. - pub fn using_view(&self, f: impl FnOnce(&View) -> T) -> T { - f(&self.inner.view.load()) - } - - /// Returns the current [`cluster::View`]. - pub fn view(&self) -> Arc> { - self.inner.view.load_full() - } - - /// Returns a [`Stream`] that emits an item each time a [`Cluster`] update - /// occurs. - /// - /// Caller is expected to use [`Cluster::using_view`] or [`Cluster::view`] - /// to see the updated state. - pub fn updates(&self) -> impl Stream + Send + 'static { - tokio_stream::wrappers::WatchStream::new(self.inner.watch.clone()) - } - - /// Returns reference to the underlying [`SmartContract`]. - pub fn smart_contract(&self) -> &SC { - &self.inner.smart_contract - } -} - -impl Cluster { - /// Builds a new [`Keyspace`] using the provided [`migration::Plan`] and - /// calls [`SmartContract::start_migration`]. - pub async fn start_migration(&self, plan: migration::Plan) -> Result<(), StartMigrationError> { - let new_keyspace = self.using_view(move |view| { - view.ownership().require_owner(&self.inner.smart_contract)?; - view.require_no_migration()?; - view.require_no_maintenance()?; - - let operators = view.node_operators(); - let keyspace = view.keyspace(); - - let mut new_operators: HashSet<_> = view.node_operators().occupied_indexes().collect(); - - for id in plan.remove { - let idx = operators.require_idx(&id)?; - - if !keyspace.contains_operator(idx) { - return Err(StartMigrationError::NotInKeyspace(id)); - } - - new_operators.remove(&idx); - } - - for id in plan.add { - let idx = operators.require_idx(&id)?; - - if keyspace.contains_operator(idx) { - return Err(StartMigrationError::AlreadyInKeyspace(id)); - } - - new_operators.insert(idx); - } - - let new_keyspace = Keyspace::new( - new_operators, - plan.replication_strategy, - keyspace.version() + 1, - )?; - - keyspace.require_diff(&new_keyspace)?; - - Ok(new_keyspace) - })?; - - self.inner - .smart_contract - .start_migration(new_keyspace) - .await?; - - Ok(()) - } - - /// Calls [`SmartContract::complete_migration`]. - pub async fn complete_migration( - &self, - id: migration::Id, - ) -> Result<(), CompleteMigrationError> { - self.using_view(|view| { - let operator_idx = view - .node_operators() - .require_idx(self.inner.smart_contract.signer().address())?; - - view.require_migration()? - .require_id(id)? - .require_pulling(operator_idx)?; - - Ok::<_, CompleteMigrationError>(()) - })?; - - self.inner.smart_contract.complete_migration(id).await?; - - Ok(()) - } - - /// Calls [`SmartContract::abort_migration`]. - pub async fn abort_migration(&self, id: migration::Id) -> Result<(), AbortMigrationError> { - self.using_view(|view| { - view.ownership().require_owner(&self.inner.smart_contract)?; - view.require_migration()?.require_id(id)?; - - Ok::<_, AbortMigrationError>(()) - })?; - - self.inner - .smart_contract - .abort_migration(id) - .await - .map_err(Into::into) - } - - /// Calls [`SmartContract::start_maintenance`]. - pub async fn start_maintenance(&self) -> Result<(), StartMaintenanceError> { - let signer = self.inner.smart_contract.signer().address(); - - self.using_view(move |view| { - if !(view.node_operators().contains(signer) || view.ownership().is_owner(signer)) { - return Err(StartMaintenanceError::Unauthorized); - } - - view.require_no_migration()?; - view.require_no_maintenance()?; - - Ok::<_, StartMaintenanceError>(()) - })?; - - self.inner.smart_contract.start_maintenance().await?; - - Ok(()) - } - - /// Calls [`SmartContract::finish_maintenance`]. - pub async fn finish_maintenance(&self) -> Result<(), FinishMaintenanceError> { - let signer = self.inner.smart_contract.signer().address(); - - self.using_view(|view| { - let maintenance = view.require_maintenance()?; - - if !(signer == maintenance.slot() || view.ownership().is_owner(signer)) { - return Err(FinishMaintenanceError::Unauthorized); - } - - Ok(()) - })?; - - self.inner.smart_contract.finish_maintenance().await?; - - Ok(()) - } - - /// Calls [`SmartContract::add_node_operator`]. - pub async fn add_node_operator( - &self, - idx: node_operator::Idx, - operator: NodeOperator, - ) -> Result<(), AddNodeOperatorError> { - let operator = self.using_view(|view| { - view.ownership().require_owner(&self.inner.smart_contract)?; - view.node_operators().require_not_exists(&operator.id)?; - view.node_operators().require_free_slot(idx)?; - - let operator = operator.serialize()?; - operator.data.validate(view.settings())?; - - Ok::<_, AddNodeOperatorError>(operator) - })?; - - self.inner - .smart_contract - .add_node_operator(idx, operator) - .await?; - - Ok(()) - } - - /// Calls [`SmartContract::update_node_operator`]. - pub async fn update_node_operator( - &self, - operator: NodeOperator, - ) -> Result<(), UpdateNodeOperatorError> { - let signer = self.inner.smart_contract.signer().address(); - - let operator = self.using_view(|view| { - if !(signer == &operator.id || view.ownership().is_owner(signer)) { - return Err(UpdateNodeOperatorError::Unauthorized); - } - - let _idx = view.node_operators().require_idx(&operator.id)?; - - let operator = operator.serialize()?; - operator.data.validate(view.settings())?; - - Ok::<_, UpdateNodeOperatorError>(operator) - })?; - - self.inner - .smart_contract - .update_node_operator(operator) - .await?; - - Ok(()) - } - - /// Calls [`SmartContract::remove_node_operator`]. - pub async fn remove_node_operator( - &self, - id: node_operator::Id, - ) -> Result<(), RemoveNodeOperatorError> { - self.using_view(|view| { - let idx = view.node_operators().require_idx(&id)?; - - if view.keyspace().contains_operator(idx) { - return Err(RemoveNodeOperatorError::InKeyspace); - } - - if let Some(keyspace) = view.migration().map(Migration::keyspace) { - if keyspace.contains_operator(idx) { - return Err(RemoveNodeOperatorError::InKeyspace); - } - } - - Ok::<_, RemoveNodeOperatorError>(()) - })?; - - self.inner.smart_contract.remove_node_operator(id).await?; - - Ok(()) - } - - /// Calls [`SmartContract::update_settings`]. - pub async fn update_settings(&self, new_settings: Settings) -> Result<(), UpdateSettingsError> { - self.using_view(move |view| view.ownership().require_owner(&self.inner.smart_contract))?; - - self.inner - .smart_contract - .update_settings(new_settings) - .await?; - - Ok(()) - } - - /// Calls [`SmartContract::transfer_ownership`]. - pub async fn transfer_ownership( - &self, - new_owner: smart_contract::AccountAddress, - ) -> Result<(), TransferOwnershipError> { - self.using_view(move |view| view.ownership().require_owner(&self.inner.smart_contract))?; - - self.inner - .smart_contract - .transfer_ownership(new_owner) - .await?; - - Ok(()) - } -} - -/// [`Cluster::deploy`] error. -#[derive(Debug, thiserror::Error)] -pub enum DeploymentError { - #[error(transparent)] - NodeOperatorsCreation(#[from] node_operators::CreationError), - - #[error(transparent)] - DataSerialization(#[from] node_operator::DataSerializationError), - - #[error(transparent)] - DataDeserialization(#[from] node_operator::DataDeserializationError), - - #[error(transparent)] - DataTooLarge(#[from] node_operator::DataTooLargeError), - - #[error(transparent)] - FetchView(#[from] view::FetchError), - - #[error("Smart-contract: {0}")] - SmartContract(#[from] smart_contract::DeploymentError), -} - -/// [`Cluster::connect`] error. -#[derive(Debug, thiserror::Error)] -pub enum ConnectionError { - #[error(transparent)] - SmartContract(#[from] smart_contract::ConnectionError), - - #[error(transparent)] - FetchView(#[from] view::FetchError), -} - -/// [`Cluster::start_migration`] error. -#[derive(Debug, thiserror::Error)] -pub enum StartMigrationError { - #[error(transparent)] - NotOwner(#[from] ownership::NotOwnerError), - - #[error(transparent)] - MigrationInProgress(#[from] migration::InProgressError), - - #[error(transparent)] - MaintenanceInProgress(#[from] maintenance::InProgressError), - - #[error(transparent)] - UnknownOperator(#[from] node_operator::NotFoundError), - - #[error("NodeOperator(id: {_0}) is not in the Keyspace")] - NotInKeyspace(node_operator::Id), - - #[error("NodeOperator(id: {_0}) is already in the Keyspace")] - AlreadyInKeyspace(node_operator::Id), - - #[error(transparent)] - KeyspaceCreation(#[from] keyspace::CreationError), - - #[error(transparent)] - SameKeyspace(#[from] keyspace::SameKeyspaceError), - - #[error("Smart-contract: {0}")] - SmartContract(#[from] smart_contract::WriteError), -} - -/// [`Cluster::complete_migration`] error. -#[derive(Debug, thiserror::Error)] -pub enum CompleteMigrationError { - #[error(transparent)] - UnknownOperator(#[from] node_operator::NotFoundError), - - #[error(transparent)] - NoMigration(#[from] migration::NotFoundError), - - #[error(transparent)] - WrongMigrationId(#[from] migration::WrongIdError), - - #[error(transparent)] - OperatorNotPulling(#[from] migration::OperatorNotPullingError), - - #[error("Smart-contract: {0}")] - SmartContract(#[from] smart_contract::WriteError), -} - -/// [`Cluster::abort_migration`] error. -#[derive(Debug, thiserror::Error)] -pub enum AbortMigrationError { - #[error(transparent)] - NotOwner(#[from] ownership::NotOwnerError), - - #[error(transparent)] - NoMigration(#[from] migration::NotFoundError), - - #[error(transparent)] - WrongMigrationId(#[from] migration::WrongIdError), - - #[error("Smart-contract: {0}")] - SmartContract(#[from] smart_contract::WriteError), -} - -/// [`Cluster::start_maintenance`] error. -#[derive(Debug, thiserror::Error)] -pub enum StartMaintenanceError { - #[error("Signer should either be a node operator or the owner")] - Unauthorized, - - #[error(transparent)] - MigrationInProgress(#[from] migration::InProgressError), - - #[error(transparent)] - MaintenanceInProgress(#[from] maintenance::InProgressError), - - #[error("Smart-contract: {0}")] - SmartContract(#[from] smart_contract::WriteError), -} - -/// [`Cluster::finish_maintenance`] error. -#[derive(Debug, thiserror::Error)] -pub enum FinishMaintenanceError { - #[error(transparent)] - NoMaintenance(#[from] maintenance::NotFoundError), - - #[error("Signer should either be a node operator that started the maintenance or the owner")] - Unauthorized, - - #[error("Smart-contract: {0}")] - SmartContract(#[from] smart_contract::WriteError), -} - -/// [`Cluster::add_node_operator`] error. -#[derive(Debug, thiserror::Error)] -pub enum AddNodeOperatorError { - #[error(transparent)] - NotOwner(#[from] ownership::NotOwnerError), - - #[error(transparent)] - AlreadyExists(#[from] node_operator::AlreadyExistsError), - - #[error(transparent)] - SlotOccupied(#[from] node_operators::SlotOccupiedError), - - #[error(transparent)] - DataSerialization(#[from] node_operator::DataSerializationError), - - #[error(transparent)] - DataTooLarge(#[from] node_operator::DataTooLargeError), - - #[error("Smart-contract: {0}")] - SmartContract(#[from] smart_contract::WriteError), -} - -/// [`Cluster::update_node_operator`] error. -#[derive(Debug, thiserror::Error)] -pub enum UpdateNodeOperatorError { - #[error("Signer should either be the NodeOperator being updated or the owner")] - Unauthorized, - - #[error(transparent)] - NotFoundError(#[from] node_operator::NotFoundError), - - #[error(transparent)] - DataSerialization(#[from] node_operator::DataSerializationError), - - #[error(transparent)] - DataTooLarge(#[from] node_operator::DataTooLargeError), - - #[error("Smart-contract: {0}")] - SmartContract(#[from] smart_contract::WriteError), -} - -/// [`Cluster::remove_node_operator`] error. -#[derive(Debug, thiserror::Error)] -pub enum RemoveNodeOperatorError { - #[error(transparent)] - NotOwner(#[from] ownership::NotOwnerError), - - #[error(transparent)] - NotFoundError(#[from] node_operator::NotFoundError), - - #[error("Node operator is still within a Keyspace")] - InKeyspace, - - #[error("Smart-contract: {0}")] - SmartContract(#[from] smart_contract::WriteError), -} - -/// [`Cluster::update_settings`] error. -#[derive(Debug, thiserror::Error)] -pub enum UpdateSettingsError { - #[error(transparent)] - NotOwner(#[from] ownership::NotOwnerError), - - #[error("Smart-contract: {0}")] - SmartContract(#[from] smart_contract::WriteError), -} - -/// [`Cluster::transfer_ownership`] error. -#[derive(Debug, thiserror::Error)] -pub enum TransferOwnershipError { - #[error(transparent)] - NotOwner(#[from] ownership::NotOwnerError), - - #[error("Smart-contract: {0}")] - SmartContract(#[from] smart_contract::WriteError), -} - -impl Event { - fn cluster_version(&self) -> Version { - match self { - Event::MigrationStarted(evt) => evt.cluster_version, - Event::MigrationDataPullCompleted(evt) => evt.cluster_version, - Event::MigrationCompleted(evt) => evt.cluster_version, - Event::MigrationAborted(evt) => evt.cluster_version, - Event::MaintenanceStarted(evt) => evt.cluster_version, - Event::MaintenanceFinished(evt) => evt.cluster_version, - Event::NodeOperatorAdded(evt) => evt.cluster_version, - Event::NodeOperatorUpdated(evt) => evt.cluster_version, - Event::NodeOperatorRemoved(evt) => evt.cluster_version, - Event::SettingsUpdated(evt) => evt.cluster_version, - Event::OwnershipTransferred(evt) => evt.cluster_version, - } - } -} - -impl SerializedEvent { - fn deserialize(self) -> Result { - Ok(match self { - Event::MigrationStarted(evt) => Event::MigrationStarted(evt), - Event::MigrationDataPullCompleted(evt) => Event::MigrationDataPullCompleted(evt), - Event::MigrationCompleted(evt) => Event::MigrationCompleted(evt), - Event::MigrationAborted(evt) => Event::MigrationAborted(evt), - Event::MaintenanceStarted(evt) => Event::MaintenanceStarted(evt), - Event::MaintenanceFinished(evt) => Event::MaintenanceFinished(evt), - Event::NodeOperatorAdded(evt) => Event::NodeOperatorAdded(evt.deserialize()?), - Event::NodeOperatorUpdated(evt) => Event::NodeOperatorUpdated(evt.deserialize()?), - Event::NodeOperatorRemoved(evt) => Event::NodeOperatorRemoved(evt), - Event::SettingsUpdated(evt) => Event::SettingsUpdated(evt), - Event::OwnershipTransferred(evt) => Event::OwnershipTransferred(evt), - }) - } -} diff --git a/crates/cluster/src/maintenance.rs b/crates/cluster/src/maintenance.rs deleted file mode 100644 index 63c060c0..00000000 --- a/crates/cluster/src/maintenance.rs +++ /dev/null @@ -1,46 +0,0 @@ -use crate::{node_operator, Version as ClusterVersion}; - -/// Maintenance process within a WCN cluster. -/// -/// Only a single [`node_operator`] at a time is allowed to be under -/// maintenance. -#[derive(Clone)] -pub struct Maintenance { - slot: node_operator::Id, -} - -impl Maintenance { - pub fn new(slot: node_operator::Id) -> Self { - Self { slot } - } - - /// Returns [`node_operator::Id`] that occupies the [`Maintenance`] slot. - pub fn slot(&self) -> &node_operator::Id { - &self.slot - } -} - -/// [`Maintenance`] has started. -#[derive(Debug)] -pub struct Started { - /// ID of the [`node_operator`] that started the [`Maintenance`]. - pub operator_id: node_operator::Id, - - /// Updated [`ClusterVersion`]. - pub cluster_version: ClusterVersion, -} - -/// [`Maintenance`] has been finished. -#[derive(Debug)] -pub struct Finished { - /// Updated [`ClusterVersion`]. - pub cluster_version: ClusterVersion, -} - -#[derive(Debug, thiserror::Error)] -#[error("Maintenance(slot: {_0}) in progress")] -pub struct InProgressError(pub node_operator::Id); - -#[derive(Debug, thiserror::Error)] -#[error("No maintenance")] -pub struct NotFoundError; diff --git a/crates/cluster/src/migration.rs b/crates/cluster/src/migration.rs deleted file mode 100644 index f7d6b447..00000000 --- a/crates/cluster/src/migration.rs +++ /dev/null @@ -1,189 +0,0 @@ -use { - crate::{ - keyspace::{self, ReplicationStrategy}, - node_operator, - Keyspace, - Version as ClusterVersion, - }, - std::{collections::HashSet, sync::Arc}, -}; - -/// Identifier of a [`Migration`]. -pub type Id = u64; - -/// Data migration process within a WCN cluster. -#[derive(Clone)] -pub struct Migration { - id: Id, - keyspace: Arc>, - pulling_operators: HashSet, -} - -/// [`Migration`] plan. -pub struct Plan { - /// Set of [`node_operator`]s to remove from the current [`Keyspace`]. - pub remove: HashSet, - - /// Set of [`node_operator`]s to add to the current [`Keyspace`]. - pub add: HashSet, - - /// New [`ReplicationStrategy`] to use. - pub replication_strategy: ReplicationStrategy, -} - -impl Migration { - /// Creates a new [`Migration`]. - pub(super) fn new( - id: Id, - keyspace: Keyspace, - pulling_operators: impl IntoIterator, - ) -> Self { - Self { - id, - keyspace: Arc::new(keyspace), - pulling_operators: pulling_operators.into_iter().collect(), - } - } - - /// Returns [`Id`] of this [`Migration`]. - pub fn id(&self) -> Id { - self.id - } - - /// Returns the new [`Keyspace`] this [`Migration`] is migrating to. - pub fn keyspace(&self) -> &Keyspace { - &self.keyspace - } - - // /// Mutable version of [`Migration::keyspace`]. - // pub fn keyspace_mut(&mut self) -> &mut Keyspace { - // &mut self.keyspace - // } - - pub(super) fn into_keyspace(self) -> Arc> { - self.keyspace - } - - /// Indicates whether the specified [`node_operator`] is still in process of - /// pulling the data. - pub fn is_pulling(&self, idx: node_operator::Idx) -> bool { - self.pulling_operators.contains(&idx) - } - - pub(crate) fn complete_pull(&mut self, idx: node_operator::Idx) { - self.pulling_operators.remove(&idx); - } - - pub(crate) fn require_id(&self, id: Id) -> Result<&Migration, WrongIdError> { - if id != self.id { - return Err(WrongIdError(id, self.id)); - } - - Ok(self) - } - - pub(crate) fn require_pulling( - &self, - idx: node_operator::Idx, - ) -> Result<&Migration, OperatorNotPullingError> { - if !self.is_pulling(idx) { - return Err(OperatorNotPullingError(idx)); - } - - Ok(self) - } - - pub(crate) fn require_pulling_count( - &self, - expected: usize, - ) -> Result<&Migration, WrongPullingOperatorsCountError> { - let count = self.pulling_operators.len(); - if count != expected { - return Err(WrongPullingOperatorsCountError(expected, count)); - } - - Ok(self) - } -} - -impl Migration { - pub(crate) async fn calculate_keyspace(self) -> Migration - where - Keyspace: keyspace::sealed::Calculate, - { - Migration { - id: self.id, - keyspace: Arc::new((*self.keyspace).clone().calculate().await), - pulling_operators: self.pulling_operators, - } - } -} - -/// [`Migration`] has started. -#[derive(Debug)] -pub struct Started { - /// [`Id`] of the [`Migration`] being started. - pub migration_id: Id, - - /// New [`Keyspace`] to migrate to. - pub new_keyspace: Keyspace, - - /// Updated [`ClusterVersion`]. - pub cluster_version: ClusterVersion, -} - -/// [`NodeOperator`](crate::NodeOperator) has completed the data pull. -#[derive(Debug)] -pub struct DataPullCompleted { - /// [`Id`] of the [`Migration`]. - pub migration_id: Id, - - /// ID of the [`node_operator`] that completed the pull. - pub operator_id: node_operator::Id, - - /// Updated [`ClusterVersion`]. - pub cluster_version: ClusterVersion, -} - -/// [`Migration`] has been completed. -#[derive(Debug)] -pub struct Completed { - /// [`Id`] of the completed [`Migration`]. - pub migration_id: Id, - - /// ID of the [`node_operator`] that completed the last data pull. - pub operator_id: node_operator::Id, - - /// Updated [`ClusterVersion`]. - pub cluster_version: ClusterVersion, -} - -/// [`Migration`] has been aborted. -#[derive(Debug)] -pub struct Aborted { - /// [`Id`] of the [`Migration`]. - pub migration_id: Id, - - /// Updated [`ClusterVersion`]. - pub cluster_version: ClusterVersion, -} - -#[derive(Debug, thiserror::Error)] -#[error("Migration(id: {_0}) in progress")] -pub struct InProgressError(pub Id); - -#[derive(Debug, thiserror::Error)] -#[error("No migration")] -pub struct NotFoundError; - -#[derive(Debug, thiserror::Error)] -#[error("Wrong migration ID: {_0} != {_1}")] -pub struct WrongIdError(pub Id, pub Id); - -#[derive(Debug, thiserror::Error)] -#[error("NodeOperator(idx: {_0}) is not currently pulling data")] -pub struct OperatorNotPullingError(pub node_operator::Idx); - -#[derive(Debug, thiserror::Error)] -#[error("Wrong pulling operators count: {_0} != {_1}")] -pub struct WrongPullingOperatorsCountError(pub usize, pub usize); diff --git a/crates/cluster/src/node.rs b/crates/cluster/src/node.rs deleted file mode 100644 index 85a3c603..00000000 --- a/crates/cluster/src/node.rs +++ /dev/null @@ -1,56 +0,0 @@ -//! Node within a WCN cluster. - -use { - libp2p::identity::PeerId, - serde::{Deserialize, Serialize}, - std::net::SocketAddrV4, -}; - -/// Node within a WCN cluster. -/// -/// The IP address is currently being encrypted using a format-preserving -/// encryption algorithm. -// TODO: encrypt -#[derive(Debug, Clone, Copy)] -pub struct Node { - /// [`PeerId`] of the [`Node`]. - /// - /// Used for authentication. Multiple nodes managed by the same - /// node operator are allowed to have the same [`PeerId`]. - pub peer_id: PeerId, - - /// [`SocketAddrV4`] of the [`Node`]. - pub addr: SocketAddrV4, -} - -// NOTE: The on-chain serialization is non self-describing! Every change to -// the schema should be handled by creating a new version. -#[derive(Clone, Copy, Debug, Serialize, Deserialize)] -pub(crate) struct V0 { - /// [`PeerId`] of this [`Node`]. - /// - /// Used for authentication. Multiple nodes managed by the same - /// [`NodeOperator`] are allowed to have the same [`PeerId`]. - pub peer_id: PeerId, - - /// [`SocketAddrV4`] of this [`Node`]. - pub addr: SocketAddrV4, -} - -impl From for V0 { - fn from(node: Node) -> Self { - Self { - peer_id: node.peer_id, - addr: node.addr, - } - } -} - -impl From for Node { - fn from(node: V0) -> Self { - Self { - peer_id: node.peer_id, - addr: node.addr, - } - } -} diff --git a/crates/cluster/src/node_operator.rs b/crates/cluster/src/node_operator.rs deleted file mode 100644 index 043f1b38..00000000 --- a/crates/cluster/src/node_operator.rs +++ /dev/null @@ -1,276 +0,0 @@ -//! Entity operating a set of nodes within a WCN cluster. - -use { - crate::{ - self as cluster, - client, - node, - smart_contract, - Client, - Node, - Version as ClusterVersion, - }, - derive_more::derive::Into, - serde::{Deserialize, Serialize}, -}; - -/// Globally unique identifier of a [`NodeOperator`]; -pub type Id = smart_contract::AccountAddress; - -/// Locally unique identifier of a [`NodeOperator`] within a WCN cluster. -/// -/// Refers to a position within the [`NodeOperators`] slot map. -pub type Idx = u8; - -/// Name of a [`NodeOperator`]. -/// -/// Used for informational purposes only. -/// Expected to be unique within the cluster, but not enforced to. -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct Name(String); - -impl Name { - /// Maximum allowed length of a [`Name`] (in bytes). - pub const MAX_LENGTH: usize = 32; - - /// Tries to create a new [`Name`] out of the provided [`ToString`]. - /// - /// Returns `None` if the string length exceeds [`Self::MAX_LENGTH`]. - pub fn new(s: impl ToString) -> Option { - let s = s.to_string(); - (s.len() <= Self::MAX_LENGTH).then_some(Self(s)) - } - - /// Returns a reference to the underlying string. - pub fn as_str(&self) -> &str { - &self.0 - } -} - -/// On-chain data of a [`NodeOperator`]. -#[derive(Clone, Debug)] -pub struct Data { - /// Name of the [`NodeOperator`]. - pub name: Name, - - /// List of [`Node`]s of the [`NodeOperator`]. - pub nodes: Vec, - - /// List of [`Client`]s authorized to use the WCN cluster on behalf of the - /// [`NodeOperator`]. - pub clients: Vec, -} - -/// [`NodeOperator`] [`Data`] serialized for on-chain storage. -#[derive(Debug, Into)] -pub struct SerializedData(pub(crate) Vec); - -/// [`NodeOperator`] with [`SerializedData`]. -pub type Serialized = NodeOperator; - -/// Entity operating a set of [`Node`]s within a WCN cluster. -#[derive(Clone, Debug)] -pub struct NodeOperator { - /// ID of this [`NodeOperator`]. - pub id: Id, - - /// On-chain data of this [`NodeOperator`]. - pub data: D, -} - -/// Event of a new [`NodeOperator`] being added to a WCN cluster. -#[derive(Debug)] -pub struct Added { - /// [`Idx`] in the [`NodeOperators`] slot map the [`NodeOperator`] is being - /// placed to. - pub idx: Idx, - - /// [`NodeOperator`] being added. - pub operator: NodeOperator, - - /// Updated [`ClusterVersion`]. - pub cluster_version: ClusterVersion, -} - -impl Added { - pub(super) fn deserialize(self) -> Result { - Ok(Added { - idx: self.idx, - operator: self.operator.deserialize()?, - cluster_version: self.cluster_version, - }) - } -} - -/// Event of a [`NodeOperator`] being updated. -#[derive(Debug)] -pub struct Updated { - /// Updated [`NodeOperator`]. - pub operator: NodeOperator, - - /// Updated [`ClusterVersion`]. - pub cluster_version: ClusterVersion, -} - -impl Updated { - pub(super) fn deserialize(self) -> Result { - Ok(Updated { - operator: self.operator.deserialize()?, - cluster_version: self.cluster_version, - }) - } -} - -/// Event of a [`NodeOperator`] being removed from a WCN cluster. -#[derive(Debug)] -pub struct Removed { - /// [`Id`] of the [`NodeOperator`] being removed. - pub id: Id, - - /// Updated [`ClusterVersion`]. - pub cluster_version: ClusterVersion, -} - -impl NodeOperator { - pub(super) fn serialize(self) -> Result, DataSerializationError> { - Ok(NodeOperator { - id: self.id, - data: self.data.serialize()?, - }) - } -} - -impl Data { - pub(super) fn serialize(self) -> Result { - use DataSerializationError as Error; - - // TODO: encrypt - - let data = DataV0 { - name: self.name, - nodes: self.nodes.into_iter().map(Into::into).collect(), - clients: self.clients.into_iter().map(Into::into).collect(), - }; - - let size = postcard::experimental::serialized_size(&data).map_err(Error::from_postcard)?; - - // reserve first byte for versioning - let mut buf = vec![0; size + 1]; - buf[0] = 0; // current schema version - postcard::to_slice(&data, &mut buf[1..]).map_err(Error::from_postcard)?; - Ok(SerializedData(buf)) - } -} - -impl NodeOperator { - pub(super) fn deserialize(self) -> Result { - use DataDeserializationError as Error; - - let data_bytes = self.data.0; - - if data_bytes.is_empty() { - return Err(DataDeserializationError::EmptyBuffer); - } - - let schema_version = data_bytes[0]; - let bytes = &data_bytes[1..]; - - let data = match schema_version { - 0 => postcard::from_bytes::(bytes).map(Into::into), - ver => return Err(Error::UnknownSchemaVersion(ver)), - } - .map_err(Error::from_postcard)?; - - Ok(NodeOperator { id: self.id, data }) - } -} - -// NOTE: The on-chain serialization is non self-describing! Every change to -// the schema should be handled by creating a new version. -#[derive(Debug, Clone, Deserialize, Serialize)] -struct DataV0 { - name: Name, - nodes: Vec, - clients: Vec, -} - -impl From for DataV0 { - fn from(data: Data) -> Self { - Self { - name: data.name, - nodes: data.nodes.into_iter().map(Into::into).collect(), - clients: data.clients.into_iter().map(Into::into).collect(), - } - } -} - -impl From for Data { - fn from(data: DataV0) -> Self { - Self { - name: data.name, - nodes: data.nodes.into_iter().map(Into::into).collect(), - clients: data.clients.into_iter().map(Into::into).collect(), - } - } -} - -#[derive(Debug, thiserror::Error)] -pub enum DataSerializationError { - #[error("Codec: {0}")] - Codec(String), -} - -impl DataSerializationError { - fn from_postcard(err: postcard::Error) -> Self { - Self::Codec(format!("{err:?}")) - } -} - -#[derive(Debug, thiserror::Error)] -pub enum DataDeserializationError { - #[error("Empty data buffer")] - EmptyBuffer, - - #[error("Codec: {0}")] - Codec(String), - - #[error("Unknown schema version: {0}")] - UnknownSchemaVersion(u8), -} - -impl DataDeserializationError { - fn from_postcard(err: postcard::Error) -> Self { - Self::Codec(format!("{err:?}")) - } -} - -impl SerializedData { - /// Validates that [`SerializedData`] size doesn't exceed - /// [`cluster::Settings::max_node_operator_data_bytes`]. - pub(super) fn validate(&self, settings: &cluster::Settings) -> Result<(), DataTooLargeError> { - let value = self.0.len(); - let limit = settings.max_node_operator_data_bytes as usize; - - if value > limit { - return Err(DataTooLargeError { value, limit }); - } - - Ok(()) - } -} - -/// [`SerializedData`] size is too large. -#[derive(Debug, thiserror::Error)] -#[error("Node operator data size is too large (value: {value}, limit: {limit})")] -pub struct DataTooLargeError { - value: usize, - limit: usize, -} - -#[derive(Debug, thiserror::Error)] -#[error("Node operator (id: {0}) is not a member of the cluster")] -pub struct NotFoundError(pub Id); - -#[derive(Debug, thiserror::Error)] -#[error("Node operator (id: {0}) is already a member of the cluster")] -pub struct AlreadyExistsError(pub Id); diff --git a/crates/cluster/src/node_operators.rs b/crates/cluster/src/node_operators.rs deleted file mode 100644 index 922a96e1..00000000 --- a/crates/cluster/src/node_operators.rs +++ /dev/null @@ -1,167 +0,0 @@ -//! Slot map of [`NodeOperator`]s. - -use { - crate::{self as cluster, node_operator, NodeOperator}, - itertools::Itertools as _, - std::collections::HashMap, -}; - -/// Slot map of [`NodeOperator`]s. -#[derive(Debug, Clone)] -pub struct NodeOperators { - id_to_idx: HashMap, - - // TODO: assert length - slots: Vec>>, -} - -/// [`NodeOperators`] with [`node_operator::SerializedData`]. -pub type Serialized = NodeOperators; - -impl NodeOperators { - pub(super) fn new( - slots: impl IntoIterator>>, - ) -> Result { - let slots: Vec<_> = slots.into_iter().collect(); - - if slots.len() > cluster::MAX_OPERATORS { - return Err(CreationError::TooManyOperatorSlots(slots.len())); - } - - let mut id_to_idx = HashMap::with_capacity(slots.len()); - - for (idx, slot) in slots.iter().enumerate() { - if let Some(operator) = &slot { - if id_to_idx.insert(operator.id, idx as u8).is_some() { - return Err(CreationError::OperatorDuplicate(operator.id)); - }; - } - } - - Ok(Self { id_to_idx, slots }) - } - - pub(super) fn into_slots(self) -> Vec>> { - self.slots - } - - pub(super) fn set(&mut self, idx: node_operator::Idx, slot: Option>) { - if let Some(id) = self.get_by_idx(idx).map(|op| op.id) { - self.id_to_idx.remove(&id); - } - - if self.slots.len() >= idx as usize { - self.expand(idx); - } - - if let Some(operator) = &slot { - self.id_to_idx.insert(operator.id, idx); - } - - self.slots[idx as usize] = slot; - } - - fn expand(&mut self, idx: node_operator::Idx) { - let desired_len = (idx as usize) + 1; - let slots_to_add = desired_len.checked_sub(self.slots.len()); - - for _ in 0..slots_to_add.unwrap_or_default() { - self.slots.push(None); - } - } - - /// Returns whether this map contains the [`NodeOperator`] with the provided - /// [`Id`]. - pub(super) fn contains(&self, id: &node_operator::Id) -> bool { - self.get_idx(id).is_some() - } - - /// Returns whether this map contains the [`NodeOperator`] with the provided - /// [`Idx`]. - pub(super) fn contains_idx(&self, idx: node_operator::Idx) -> bool { - self.get_by_idx(idx).is_some() - } - - /// Gets an [`NodeOperator`] by [`Id`]. - pub fn get(&self, id: &node_operator::Id) -> Option<&NodeOperator> { - self.get_by_idx(self.get_idx(id)?) - } - - /// Gets an [`NodeOperator`] by [`Idx`]. - pub(super) fn get_by_idx(&self, idx: node_operator::Idx) -> Option<&NodeOperator> { - self.slots.get(idx as usize)?.as_ref() - } - - /// Gets an [`Idx`] by [`Id`]. - pub(super) fn get_idx(&self, id: &node_operator::Id) -> Option { - self.id_to_idx.get(id).copied() - } - - pub(super) fn occupied_indexes(&self) -> impl Iterator + '_ { - self.slots - .iter() - .enumerate() - .filter_map(|(idx, slot)| slot.is_some().then_some(idx as u8)) - } - - pub(super) fn require_idx( - &self, - id: &node_operator::Id, - ) -> Result { - self.get_idx(id) - .ok_or_else(|| node_operator::NotFoundError(*id)) - } - - pub(super) fn require_not_exists( - &self, - id: &node_operator::Id, - ) -> Result<&Self, node_operator::AlreadyExistsError> { - if self.contains(id) { - return Err(node_operator::AlreadyExistsError(*id)); - } - - Ok(self) - } - - pub(super) fn require_free_slot( - &self, - idx: node_operator::Idx, - ) -> Result<&Self, SlotOccupiedError> { - if self.contains_idx(idx) { - return Err(SlotOccupiedError(idx)); - } - - Ok(self) - } -} - -impl Serialized { - pub(super) fn deserialize( - self, - ) -> Result { - Ok(NodeOperators { - id_to_idx: self.id_to_idx, - slots: self - .slots - .into_iter() - .map(|slot| slot.map(NodeOperator::deserialize).transpose()) - .try_collect()?, - }) - } -} - -#[derive(Debug, thiserror::Error)] -pub enum CreationError { - #[error("Too many operator slots: {_0} > {}", cluster::MAX_OPERATORS)] - TooManyOperatorSlots(usize), - - #[error("Too few operators: {_0} < {}", cluster::MIN_OPERATORS)] - TooFewOperators(usize), - - #[error("Duplicate NodeOperator(id: {_0})")] - OperatorDuplicate(node_operator::Id), -} - -#[derive(Debug, thiserror::Error)] -#[error("Slot {_0} in NodeOperators slot map is already occupied")] -pub struct SlotOccupiedError(pub node_operator::Idx); diff --git a/crates/cluster/src/ownership.rs b/crates/cluster/src/ownership.rs deleted file mode 100644 index 0d1d79d2..00000000 --- a/crates/cluster/src/ownership.rs +++ /dev/null @@ -1,51 +0,0 @@ -//! Ownership of a WCN cluster. - -use crate::{smart_contract, SmartContract, Version as ClusterVersion}; - -/// Ownership of a WCN cluster. -/// -/// Cluster has a single owner, and some [`smart_contract`] methods are -/// resticted to be executed only by the owner. -#[derive(Clone)] -pub struct Ownership { - owner: smart_contract::AccountAddress, -} - -impl Ownership { - pub(super) fn new(owner: smart_contract::AccountAddress) -> Self { - Self { owner } - } - - pub(super) fn is_owner(&self, address: &smart_contract::AccountAddress) -> bool { - address == &self.owner - } - - pub(super) fn require_owner( - &self, - smart_contract: &impl SmartContract, - ) -> Result<(), NotOwnerError> { - if !self.is_owner(smart_contract.signer().address()) { - return Err(NotOwnerError); - } - - Ok(()) - } - - pub(super) fn transfer(&mut self, new_owner: smart_contract::AccountAddress) { - self.owner = new_owner; - } -} - -/// Event of [`Ownership`] being transferred. -#[derive(Debug)] -pub struct Transferred { - /// New owner of the WCN cluster. - pub new_owner: smart_contract::AccountAddress, - - /// Update [`ClusterVersion`]. - pub cluster_version: ClusterVersion, -} - -#[derive(Debug, thiserror::Error)] -#[error("Smart-contract signer is not the owner")] -pub struct NotOwnerError; diff --git a/crates/cluster/src/settings.rs b/crates/cluster/src/settings.rs deleted file mode 100644 index 0f8a6cf4..00000000 --- a/crates/cluster/src/settings.rs +++ /dev/null @@ -1,19 +0,0 @@ -//! WCN cluster settings. -use crate::Version as ClusterVersion; - -/// WCN cluster settings. -#[derive(Clone, Debug, Eq, PartialEq)] -pub struct Settings { - /// Maximum number of on-chain bytes stored for a single [`NodeOperator`]. - pub max_node_operator_data_bytes: u16, -} - -/// Event of [`Settings`] being updated. -#[derive(Debug)] -pub struct Updated { - /// Updated [`Settings`]. - pub settings: Settings, - - /// Updated [`ClusterVersion`]. - pub cluster_version: ClusterVersion, -} diff --git a/crates/cluster/src/smart_contract/evm.rs b/crates/cluster/src/smart_contract/evm.rs deleted file mode 100644 index 1e9db5b7..00000000 --- a/crates/cluster/src/smart_contract/evm.rs +++ /dev/null @@ -1,618 +0,0 @@ -//! EVM implementation of [`SmartContract`](super::SmartContract). - -use { - super::{ - AccountAddress, - ConnectionError, - Connector, - Deployer, - DeploymentError, - ReadError, - ReadResult, - RpcUrl, - Signer, - SignerKind, - WriteError, - WriteResult, - }, - crate::{ - self as cluster, - maintenance, - migration, - node_operator, - ownership, - settings, - smart_contract, - Event, - Keyspace, - Maintenance, - Migration, - NodeOperator, - NodeOperators, - Ownership, - SerializedEvent, - Settings, - }, - alloy::{ - contract::{CallBuilder, CallDecoder}, - network::EthereumWallet, - primitives::Uint, - providers::{DynProvider, Provider, ProviderBuilder, WsConnect}, - rpc::types::{Filter, Log}, - sol_types::SolEvent, - }, - futures::{Stream, StreamExt as _}, - std::{collections::HashSet, fmt, sync::Arc, time::Duration}, -}; - -mod bindings { - alloy::sol!( - #[sol(rpc)] - #[derive(Debug)] - Cluster, - "../../contracts/out/Cluster.sol/Cluster.json", - ); -} - -pub(crate) type Address = alloy::primitives::Address; - -type AlloyContract = bindings::Cluster::ClusterInstance; - -type U256 = Uint<256, 4>; - -/// RPC provider for EVM chains. -pub struct RpcProvider { - signer: S, - alloy: DynProvider, -} - -impl RpcProvider { - /// Creates a new [`RpcProvider`]. - pub async fn new( - url: RpcUrl, - signer: Signer, - ) -> Result, RpcProviderCreationError> { - let wallet: EthereumWallet = match &signer.kind { - SignerKind::PrivateKey(key) => key.clone().into(), - }; - - let provider = ProviderBuilder::new() - .wallet(wallet) - .connect_ws(WsConnect::new(url.0)) - .await?; - - Ok(RpcProvider { - signer, - alloy: DynProvider::new(provider), - }) - } - - /// Creates a new read-only [`RpcProvider`]. - pub async fn new_ro(self, url: RpcUrl) -> Result, RpcProviderCreationError> { - let provider = ProviderBuilder::new() - .connect_ws(WsConnect::new(url.0)) - .await?; - - Ok(RpcProvider { - signer: (), - alloy: DynProvider::new(provider), - }) - } -} - -/// EVM implementation of WCN Cluster smart contract. -#[derive(Clone)] -pub struct SmartContract { - signer: S, - alloy: AlloyContract, -} - -impl Deployer> for RpcProvider { - async fn deploy( - &self, - initial_settings: Settings, - initial_operators: NodeOperators, - ) -> Result, DeploymentError> { - let signer = self.signer.clone(); - - let settings = initial_settings.into(); - let operators = initial_operators - .into_slots() - .into_iter() - .filter_map(|op| op.map(Into::into)) - .collect(); - - bindings::Cluster::deploy(self.alloy.clone(), settings, operators) - .await - .map(|alloy| SmartContract { signer, alloy }) - .map_err(Into::into) - } -} - -impl Connector> for RpcProvider { - async fn connect( - &self, - address: smart_contract::Address, - ) -> Result, ConnectionError> { - let signer = self.signer.clone(); - - let code = self - .alloy - .get_code_at(address.0) - .await - .map_err(|err| ConnectionError::Other(err.to_string()))?; - - if code.is_empty() { - return Err(ConnectionError::UnknownContract); - } - - // TODO: false positive - // if code != bindings::Cluster::BYTECODE { - // return Err(ConnectionError::WrongContract); - // } - - Ok(SmartContract { - signer, - alloy: bindings::Cluster::new(address.0, self.alloy.clone()), - }) - } -} - -impl smart_contract::Write for SmartContract { - fn signer(&self) -> &Signer { - &self.signer - } - - async fn start_migration(&self, new_keyspace: Keyspace) -> WriteResult<()> { - check_receipt(self.alloy.startMigration(new_keyspace.into())).await - } - - async fn complete_migration(&self, id: migration::Id) -> WriteResult<()> { - check_receipt(self.alloy.completeMigration(id)).await - } - - async fn abort_migration(&self, id: migration::Id) -> WriteResult<()> { - check_receipt(self.alloy.abortMigration(id)).await - } - - async fn start_maintenance(&self) -> WriteResult<()> { - check_receipt(self.alloy.startMaintenance()).await - } - - async fn finish_maintenance(&self) -> WriteResult<()> { - check_receipt(self.alloy.finishMaintenance()).await - } - - async fn add_node_operator( - &self, - idx: node_operator::Idx, - operator: NodeOperator, - ) -> WriteResult<()> { - check_receipt(self.alloy.addNodeOperator(idx, operator.into())).await - } - - async fn update_node_operator(&self, operator: node_operator::Serialized) -> WriteResult<()> { - check_receipt(self.alloy.updateNodeOperator(operator.into())).await - } - - async fn remove_node_operator(&self, id: node_operator::Id) -> WriteResult<()> { - check_receipt(self.alloy.removeNodeOperator(id.0)).await - } - - async fn update_settings(&self, new_settings: Settings) -> WriteResult<()> { - check_receipt(self.alloy.updateSettings(new_settings.into())).await - } - - async fn transfer_ownership(&self, new_owner: AccountAddress) -> WriteResult<()> { - check_receipt(self.alloy.transferOwnership(new_owner.0)).await - } -} - -async fn check_receipt(call: CallBuilder<&DynProvider, D>) -> WriteResult<()> -where - D: CallDecoder, -{ - let receipt = call - .send() - .await? - .with_timeout(Some(Duration::from_secs(30))) - .get_receipt() - .await?; - - if !receipt.status() { - return Err(WriteError::Revert(format!("{}", receipt.transaction_hash))); - } - - Ok(()) -} - -impl smart_contract::Read for SmartContract { - fn address(&self) -> smart_contract::Address { - smart_contract::Address(*self.alloy.address()) - } - - async fn cluster_view(&self) -> ReadResult> { - self.alloy.getView().call().await?.try_into() - } - - async fn events( - &self, - ) -> ReadResult> + Send + 'static> { - let filter = Filter::new().address(*self.alloy.address()); - - Ok(self - .alloy - .provider() - .subscribe_logs(&filter) - .await? - .into_stream() - .map(TryFrom::try_from)) - } -} - -impl TryFrom for Event { - type Error = ReadError; - - fn try_from(log: Log) -> Result { - use bindings::Cluster; - - let topics = log.topics(); - let data = &log.data().data; - - Ok(match log.topics().get(0) { - Some(&Cluster::MigrationStarted::SIGNATURE_HASH) => { - Cluster::MigrationStarted::decode_raw_log_validate(topics, data)?.try_into()? - } - Some(&Cluster::MigrationDataPullCompleted::SIGNATURE_HASH) => { - Cluster::MigrationDataPullCompleted::decode_raw_log_validate(topics, data)?.into() - } - Some(&Cluster::MigrationCompleted::SIGNATURE_HASH) => { - Cluster::MigrationCompleted::decode_raw_log_validate(topics, data)?.into() - } - Some(&Cluster::MigrationAborted::SIGNATURE_HASH) => { - Cluster::MigrationAborted::decode_raw_log_validate(topics, data)?.into() - } - - Some(&Cluster::MaintenanceStarted::SIGNATURE_HASH) => { - Cluster::MaintenanceStarted::decode_raw_log_validate(topics, data)?.into() - } - Some(&Cluster::MaintenanceFinished::SIGNATURE_HASH) => { - Cluster::MaintenanceFinished::decode_raw_log_validate(topics, data)?.into() - } - - Some(&Cluster::NodeOperatorAdded::SIGNATURE_HASH) => { - Cluster::NodeOperatorAdded::decode_raw_log_validate(topics, data)?.into() - } - Some(&Cluster::NodeOperatorUpdated::SIGNATURE_HASH) => { - Cluster::NodeOperatorUpdated::decode_raw_log_validate(topics, data)?.into() - } - Some(&Cluster::NodeOperatorRemoved::SIGNATURE_HASH) => { - Cluster::NodeOperatorRemoved::decode_raw_log_validate(topics, data)?.into() - } - - Some(&Cluster::SettingsUpdated::SIGNATURE_HASH) => { - Cluster::SettingsUpdated::decode_raw_log_validate(topics, data)?.into() - } - - Some(&Cluster::OwnershipTransferred::SIGNATURE_HASH) => { - Cluster::OwnershipTransferred::decode_raw_log_validate(topics, data)?.into() - } - - other => { - return Err(ReadError::InvalidData(format!( - "Unexpected event: {other:?}" - ))) - } - }) - } -} - -impl TryFrom for Event { - type Error = ReadError; - - fn try_from(evt: bindings::Cluster::MigrationStarted) -> ReadResult { - Ok(Self::MigrationStarted(migration::Started { - migration_id: evt.id, - new_keyspace: Keyspace::try_from_alloy(&evt.newKeyspace, evt.newKeyspaceVersion)?, - cluster_version: evt.clusterVersion, - })) - } -} - -impl From for Event { - fn from(evt: bindings::Cluster::MigrationDataPullCompleted) -> Self { - Self::MigrationDataPullCompleted(migration::DataPullCompleted { - migration_id: evt.id, - operator_id: evt.operatorAddress.into(), - cluster_version: evt.clusterVersion, - }) - } -} - -impl From for Event { - fn from(evt: bindings::Cluster::MigrationCompleted) -> Self { - Self::MigrationCompleted(migration::Completed { - migration_id: evt.id, - operator_id: evt.operatorAddress.into(), - cluster_version: evt.clusterVersion, - }) - } -} - -impl From for Event { - fn from(evt: bindings::Cluster::MigrationAborted) -> Self { - Self::MigrationAborted(migration::Aborted { - migration_id: evt.id, - cluster_version: evt.clusterVersion, - }) - } -} - -impl From for Event { - fn from(evt: bindings::Cluster::MaintenanceStarted) -> Self { - Self::MaintenanceStarted(maintenance::Started { - operator_id: evt.addr.into(), - cluster_version: evt.clusterVersion, - }) - } -} - -impl From for Event { - fn from(evt: bindings::Cluster::MaintenanceFinished) -> Self { - Self::MaintenanceFinished(maintenance::Finished { - cluster_version: evt.clusterVersion, - }) - } -} - -impl From for Event { - fn from(evt: bindings::Cluster::NodeOperatorAdded) -> Self { - Self::NodeOperatorAdded(node_operator::Added { - idx: evt.idx, - operator: evt.operator.into(), - cluster_version: evt.clusterVersion, - }) - } -} - -impl From for Event { - fn from(evt: bindings::Cluster::NodeOperatorUpdated) -> Self { - Self::NodeOperatorUpdated(node_operator::Updated { - operator: evt.operator.into(), - cluster_version: evt.clusterVersion, - }) - } -} - -impl From for Event { - fn from(evt: bindings::Cluster::NodeOperatorRemoved) -> Self { - Self::NodeOperatorRemoved(node_operator::Removed { - id: evt.operatorAddress.into(), - cluster_version: evt.clusterVersion, - }) - } -} - -impl From for Event { - fn from(evt: bindings::Cluster::SettingsUpdated) -> Self { - Self::SettingsUpdated(settings::Updated { - settings: evt.newSettings.into(), - cluster_version: evt.clusterVersion, - }) - } -} - -impl From for Event { - fn from(evt: bindings::Cluster::OwnershipTransferred) -> Self { - Self::OwnershipTransferred(ownership::Transferred { - new_owner: evt.newOwner.into(), - cluster_version: evt.cluserVersion, - }) - } -} - -impl From for bindings::Cluster::NodeOperator { - fn from(op: node_operator::Serialized) -> Self { - Self { - addr: op.id.0, - data: op.data.0.into(), - } - } -} - -impl From for node_operator::Serialized { - fn from(op: bindings::Cluster::NodeOperator) -> Self { - NodeOperator { - id: smart_contract::AccountAddress(op.addr), - data: node_operator::SerializedData(op.data.into()), - } - } -} - -impl From for bindings::Cluster::Settings { - fn from(settings: Settings) -> Self { - Self { - maxOperatorDataBytes: settings.max_node_operator_data_bytes, - } - } -} - -impl From for Settings { - fn from(settings: bindings::Cluster::Settings) -> Self { - Self { - max_node_operator_data_bytes: settings.maxOperatorDataBytes, - } - } -} - -impl From for bindings::Cluster::Keyspace { - fn from(keyspace: Keyspace) -> Self { - let mut operators_bitmask = U256::ZERO; - - for idx in keyspace.operators() { - operators_bitmask.set_bit(idx as usize, true); - } - - Self { - operatorsBitmask: operators_bitmask, - replicationStrategy: keyspace.replication_strategy() as u8, - } - } -} - -impl Keyspace { - fn try_from_alloy( - keyspace: &bindings::Cluster::Keyspace, - version: u64, - ) -> Result { - let mut operators = HashSet::new(); - - // TODO: do less iterations - for idx in 0..256 { - if keyspace.operatorsBitmask.bit(idx) { - operators.insert(idx as u8); - } - } - - let replication_strategy = keyspace.replicationStrategy.try_into().map_err(|err| { - ReadError::InvalidData(format!("Invalid ReplicationStrategy: {err:?}")) - })?; - - Self::new(operators, replication_strategy, version) - .map_err(|err| ReadError::InvalidData(format!("Invalid Keyspace: {err:?}"))) - } -} - -impl Migration { - fn from_alloy(migration: bindings::Cluster::Migration, keyspace: Keyspace) -> Self { - let mut pulling_operators = HashSet::new(); - - // TODO: do less iterations - for idx in 0..256 { - if migration.pullingOperatorsBitmask.bit(idx) { - pulling_operators.insert(idx as u8); - } - } - - Self::new(migration.id, keyspace, pulling_operators) - } -} - -impl From for Option { - fn from(maintenance: bindings::Cluster::Maintenance) -> Self { - if maintenance.slot.is_zero() { - None - } else { - Some(Maintenance::new(maintenance.slot.into())) - } - } -} - -impl TryFrom for cluster::View<(), node_operator::SerializedData> { - type Error = ReadError; - - fn try_from(view: bindings::Cluster::ClusterView) -> Result { - let node_operators = - NodeOperators::new(view.nodeOperatorSlots.into_iter().map(|operator| { - if operator.addr.is_zero() { - None - } else { - Some(operator.into()) - } - })) - .map_err(|err| ReadError::InvalidData(format!("Invalid NodeOperators: {err:?}")))?; - - // assert array length - let _: &[_; 2] = &view.keyspaces; - - let try_keyspace = - |version| Keyspace::try_from_alloy(&view.keyspaces[version as usize % 2], version); - - let (keyspace, migration) = if view.migration.pullingOperatorsBitmask == U256::ZERO { - // migration is not in progress - - (try_keyspace(view.keyspaceVersion)?, None) - } else { - // migration is in progress - - let prev_keyspace_version = view - .keyspaceVersion - .checked_sub(1) - .ok_or_else(|| ReadError::InvalidData(format!("Invalid keyspace::Version")))?; - - let keyspace = try_keyspace(prev_keyspace_version)?; - let migration_keyspace = try_keyspace(view.keyspaceVersion)?; - let migration = Migration::from_alloy(view.migration, migration_keyspace); - - (keyspace, Some(migration)) - }; - - Ok(Self { - node_operators, - ownership: Ownership::new(view.owner.into()), - settings: view.settings.into(), - keyspace: Arc::new(keyspace), - migration, - maintenance: view.maintenance.into(), - cluster_version: view.version, - }) - } -} - -impl From for DeploymentError { - fn from(err: alloy::contract::Error) -> Self { - Self(format!("{err:?}")) - } -} - -impl From> for WriteError { - fn from(err: alloy::transports::RpcError) -> Self { - WriteError::Transport(format!("{err:?}")) - } -} - -impl From> for ReadError { - fn from(err: alloy::transports::RpcError) -> Self { - ReadError::Transport(format!("{err:?}")) - } -} - -impl From for WriteError { - fn from(err: alloy::providers::PendingTransactionError) -> Self { - Self::Other(format!("{err:?}")) - } -} - -impl From for WriteError { - fn from(err: alloy::contract::Error) -> Self { - match err { - alloy::contract::Error::TransportError(err) => Self::Transport(format!("{err:?}")), - _ => Self::Other(format!("{err:?}")), - } - } -} - -impl From for ReadError { - fn from(err: alloy::contract::Error) -> Self { - match err { - alloy::contract::Error::TransportError(err) => Self::Transport(format!("{err:?}")), - _ => Self::Other(format!("{err:?}")), - } - } -} - -impl From for ReadError { - fn from(err: alloy::sol_types::Error) -> Self { - ReadError::InvalidData(format!("{err:?}")) - } -} - -#[derive(Debug, thiserror::Error)] -#[error("{_0}")] -pub struct RpcProviderCreationError(String); - -impl From for RpcProviderCreationError { - fn from(err: alloy::transports::TransportError) -> Self { - Self(format!("alloy transport: {err:?}")) - } -} diff --git a/crates/cluster/src/smart_contract/mod.rs b/crates/cluster/src/smart_contract/mod.rs deleted file mode 100644 index c7b292c7..00000000 --- a/crates/cluster/src/smart_contract/mod.rs +++ /dev/null @@ -1,298 +0,0 @@ -//! Smart-contract managing the state of a WCN cluster. - -pub mod evm; - -use { - crate::{ - self as cluster, - migration, - node_operator, - Keyspace, - NodeOperators, - SerializedEvent, - Settings, - }, - alloy::{signers::local::PrivateKeySigner, transports::http::reqwest}, - derive_more::derive::{Display, From}, - futures::Stream, - serde::{Deserialize, Serialize}, - std::{future::Future, str::FromStr}, -}; - -/// Deployer of WCN Cluster [`SmartContract`]s. -pub trait Deployer { - /// Deploys a new [`SmartContract`]. - fn deploy( - &self, - initial_settings: Settings, - initial_operators: NodeOperators, - ) -> impl Future>; -} - -/// Connector to WCN Cluster [`SmartContract`]s. -pub trait Connector { - /// Connects to an existing [`SmartContract`]. - fn connect(&self, address: Address) -> impl Future>; -} - -/// Smart-contract managing the state of a WCN cluster. -pub trait SmartContract: Read + Write {} - -/// Write [`SmartContract`] calls. -/// -/// Logic invariants documented on the methods of this trait MUST be -/// implemented inside the on-chain implementation of the smart-contract itself. -// TODO: docs are outdated, revisit -pub trait Write { - /// Returns the [`Signer`] being used to sign transactions. - fn signer(&self) -> &Signer; - - /// Starts a new data [`migration`] process using the provided - /// [`migration::Plan`]. - /// - /// The implementation MUST validate the following invariants: - /// - there's no ongoing data migration - /// - there's no ongoing maintenance - /// - [`signer`](SmartContract::signer) is the owner of the - /// [`SmartContract`] - /// - /// The implementation MUST emit [`migration::Started`] event on success. - fn start_migration(&self, new_keyspace: Keyspace) -> impl Future>; - - /// Marks that the [`signer`](SmartContract::signer) has completed the data - /// pull required for completion of the current [`migration`]. - /// - /// The implementation MUST validate the following invariants: - /// - there's an ongoing data migration - /// - the provided [`migration::Id`] matches the ID of the migration - /// - [`signer`](Smart::signer) is a [`node::Operator`] under the provided - /// [`node::OperatorIdx`] - /// - /// If this [`node::Operator`] is the last remaining one left to complete - /// the data pull then the migration MUST be completed and - /// [`migration::Completed`] event MUST be emitted. - /// Otherwise the data pull MUST be marked as completed for the - /// [`node::Operator`] and [`migration::DataPullCompleted`] MUST be emitted. - /// - /// The implementation MAY be idempotent. In case of an idempotent - /// execution the event MUST not be emitted. - fn complete_migration(&self, id: migration::Id) -> impl Future>; - - /// Aborts the ongoing data [`migration`] process restoring the WCN cluster - /// to the original state it had before the migration had started. - /// - /// The implementation MUST validate the following invariants: - /// - there's an ongoing data migration - /// - [`signer`](SmartContract::signer) is the owner of the - /// [`SmartContract`] - /// - /// The implementation MUST emit [`migration::Aborted`] event on success. - fn abort_migration(&self, id: migration::Id) -> impl Future>; - - /// Starts a [`maintenance`] process for the [`node::Operator`] being the - /// current [`signer`](Manager::signer). - /// - /// The implementation MUST validate the following invariants: - /// - there's no ongoing data migration - /// - there's no ongoing maintenance - /// - [`signer`](SmartContract::signer) is a [`node::Operator`] under the - /// provided [`node::OperatorIdx`] - /// - /// The implementation MUST emit [`maintenance::Started`] event on success. - fn start_maintenance(&self) -> impl Future>; - - /// Completes the ongoing [`maintenance`] process. - /// - /// The implementation MUST validate the following invariants: - /// - there's an ongoing maintenance - /// - [`signer`](SmartContract::signer) is the one who - /// [started](Manager::start_maintenance) the maintenance - /// - /// The implementation MUST emit [`maintenance::Completed`] event on - /// success. - fn finish_maintenance(&self) -> impl Future>; - - fn add_node_operator( - &self, - idx: node_operator::Idx, - operator: node_operator::Serialized, - ) -> impl Future>; - - /// Updates on-chain data of a [`node::Operator`]. - /// - /// The implementation MUST validate the following invariants: - /// - [`signer`](SmartContract::signer) is a [`node::Operator`] under the - /// provided [`node::OperatorIdx`] - /// - /// The implementation MUST emit [`node::OperatorUpdated`] event on success. - fn update_node_operator( - &self, - operator: node_operator::Serialized, - ) -> impl Future>; - - fn remove_node_operator(&self, id: node_operator::Id) -> impl Future>; - - fn update_settings(&self, new_settings: Settings) -> impl Future>; - - fn transfer_ownership( - &self, - new_owner: AccountAddress, - ) -> impl Future>; -} - -/// Read [`SmartContract`] calls. -pub trait Read: Sized + Send + Sync + 'static { - /// Returns [`Address`] of this [`SmartContract`]. - fn address(&self) -> Address; - - /// Returns the current [`cluster::View`]. - fn cluster_view( - &self, - ) -> impl Future>> + Send; - - /// Subscribes to WCN Cluster [`Events`]. - fn events( - &self, - ) -> impl Future< - Output = ReadResult> + Send + 'static>, - > + Send; -} - -/// [`SmartContract`] address. -#[derive(Clone, Copy, Debug, Display, From, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub struct Address(evm::Address); - -/// Account address on the chain hosting WCN cluster [`SmartContract`]. -#[derive(Clone, Copy, Debug, Display, From, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub struct AccountAddress(evm::Address); - -/// Transaction signer. -#[derive(Clone)] -pub struct Signer { - address: AccountAddress, - kind: SignerKind, -} - -/// RPC provider URL. -pub struct RpcUrl(reqwest::Url); - -/// Error of [`Deployer::deploy`]. -#[derive(Debug, thiserror::Error)] -#[error("{_0}")] -pub struct DeploymentError(String); - -/// Error of [`Connector::connect`]. -#[derive(Debug, thiserror::Error)] -pub enum ConnectionError { - #[error("Smart-contract with the provided address doesn't exist")] - UnknownContract, - - #[error("Smart-contract with the provided address is not a WCN cluster")] - WrongContract, - - #[error("Other: {0}")] - Other(String), -} - -/// [`Write`] error. -#[derive(Debug, thiserror::Error)] -pub enum WriteError { - #[error("Transport: {0}")] - Transport(String), - - #[error("Transaction reverted: {0}")] - Revert(String), - - #[error("Other: {0}")] - Other(String), -} - -/// [`Read`] error. -#[derive(Debug, thiserror::Error)] - -pub enum ReadError { - #[error("Transport: {0}")] - Transport(String), - - #[error("Invalid data: {0}")] - InvalidData(String), - - #[error("Other: {0}")] - Other(String), -} - -/// [`Write`] result. -pub type WriteResult = std::result::Result; - -/// [`Read`] result. -pub type ReadResult = std::result::Result; - -impl Signer { - pub fn try_from_private_key(hex: &str) -> Result { - let private_key = PrivateKeySigner::from_str(hex) - .map_err(|err| InvalidPrivateKeyError(err.to_string()))?; - - Ok(Self { - address: AccountAddress(private_key.address()), - kind: SignerKind::PrivateKey(private_key), - }) - } - - /// Returns [`AccountAddress`] of this [`Signer`]. - pub fn address(&self) -> &AccountAddress { - &self.address - } -} - -#[derive(Clone)] -enum SignerKind { - PrivateKey(PrivateKeySigner), -} - -#[derive(Debug, thiserror::Error)] -#[error("Invalid RPC URL: {0:?}")] -pub struct InvalidRpcUrlError(String); - -#[derive(Debug, thiserror::Error)] -#[error("Invalid private key: {0:?}")] -pub struct InvalidPrivateKeyError(String); - -#[derive(Debug, thiserror::Error)] -#[error("Invalid account address: {0:?}")] -pub struct InvalidAccountAddressError(String); - -#[derive(Debug, thiserror::Error)] -#[error("Invalid smart-contract address: {0:?}")] -pub struct InvalidAddressError(String); - -impl FromStr for RpcUrl { - type Err = InvalidRpcUrlError; - - fn from_str(s: &str) -> Result { - reqwest::Url::from_str(s) - .map(Self) - .map_err(|err| InvalidRpcUrlError(err.to_string())) - } -} - -impl FromStr for AccountAddress { - type Err = InvalidAccountAddressError; - - fn from_str(s: &str) -> Result { - alloy::primitives::Address::from_str(s) - .map(AccountAddress) - .map_err(|err| InvalidAccountAddressError(err.to_string())) - } -} - -impl FromStr for Address { - type Err = InvalidAddressError; - - fn from_str(s: &str) -> Result { - alloy::primitives::Address::from_str(s) - .map(Address) - .map_err(|err| InvalidAddressError(err.to_string())) - } -} - -impl SmartContract for SC where SC: Read + Write {} diff --git a/crates/cluster/src/task.rs b/crates/cluster/src/task.rs deleted file mode 100644 index af274025..00000000 --- a/crates/cluster/src/task.rs +++ /dev/null @@ -1,117 +0,0 @@ -use { - crate::{ - keyspace, - node_operator, - smart_contract, - view, - Inner, - Keyspace, - SerializedEvent, - View, - }, - futures::{Stream, StreamExt}, - std::{pin::pin, sync::Arc, time::Duration}, - tokio::sync::watch, -}; - -pub(super) struct Task { - pub initial_events: Option, - pub inner: Arc>, - pub watch: watch::Sender<()>, -} - -pub(super) struct Guard(tokio::task::JoinHandle<()>); - -impl Drop for Guard { - fn drop(&mut self) { - self.0.abort(); - tracing::info!("aborted"); - } -} - -impl Task -where - SC: smart_contract::Read, - Shards: Clone + Send + Sync + 'static, - Events: Stream> + Send + 'static, - Keyspace: keyspace::sealed::Calculate, -{ - pub(super) fn spawn(self) -> Guard { - let guard = Guard(tokio::spawn(self.run())); - tracing::info!("spawned"); - guard - } - - async fn run(mut self) { - loop { - // apply initial events until they finish / first error - if let Some(events) = self.initial_events.take() { - match self.apply_events(events).await { - Ok(()) => tracing::warn!("Initial event stream finished"), - Err(err) => tracing::error!(%err, "Failed to apply initial events"), - } - } - - loop { - // when we fail for whatever reason - subscribe again and refetch the whole - // state - match self.update_view().await { - Ok(()) => tracing::warn!("Event stream finished"), - Err(err) => { - tracing::error!(%err, "Failed to update cluster::View"); - tokio::time::sleep(Duration::from_secs(60)).await; - } - } - } - } - } - - async fn update_view(&mut self) -> Result<()> { - let events = self.inner.smart_contract.events().await?; - - let new_view = View::fetch(&self.inner.smart_contract).await?; - if self.inner.view.load().cluster_version != new_view.cluster_version { - let new_view = Arc::new(new_view.calculate_keyspace().await); - self.inner.view.store(new_view); - let _ = self.watch.send(()); - } - - self.apply_events(events).await - } - - async fn apply_events( - &mut self, - events: impl Stream>, - ) -> Result<()> { - let mut events = pin!(events); - - while let Some(res) = events.next().await { - let event = res?.deserialize()?; - tracing::info!(?event, "received"); - - let view = self.inner.view.load_full(); - let view = Arc::new((*view).clone().apply_event(event).await?); - self.inner.view.store(view); - let _ = self.watch.send(()); - } - - Ok(()) - } -} - -#[derive(Debug, thiserror::Error)] -enum Error { - #[error(transparent)] - ApplyEvent(#[from] view::Error), - - #[error(transparent)] - DataDeserialization(#[from] node_operator::DataDeserializationError), - - #[error(transparent)] - ViewFetch(#[from] view::FetchError), - - #[error(transparent)] - SmartContractRead(#[from] smart_contract::ReadError), -} - -type Result = std::result::Result; diff --git a/crates/cluster/src/view.rs b/crates/cluster/src/view.rs deleted file mode 100644 index 2eaf6fdf..00000000 --- a/crates/cluster/src/view.rs +++ /dev/null @@ -1,350 +0,0 @@ -//! Read-only view of a WCN cluster. - -use { - crate::{ - self as cluster, - keyspace, - maintenance, - migration, - node_operator, - node_operators, - ownership, - settings, - smart_contract, - Event, - Keyspace, - Maintenance, - Migration, - NodeOperators, - Ownership, - Settings, - }, - futures::future::OptionFuture, - std::sync::Arc, -}; - -/// Read-only view of a WCN cluster. -#[derive(Clone)] -pub struct View { - pub(super) node_operators: NodeOperators, - - pub(super) ownership: Ownership, - pub(super) settings: Settings, - - pub(super) keyspace: Arc>, - pub(super) migration: Option>, - pub(super) maintenance: Option, - - pub(super) cluster_version: cluster::Version, -} - -impl View { - pub(super) async fn fetch(contract: &impl smart_contract::Read) -> Result - where - Keyspace: keyspace::sealed::Calculate, - { - Ok(contract.cluster_view().await?.deserialize()?) - } - - /// Returns [`Ownership`] of the WCN cluster. - pub fn ownership(&self) -> &Ownership { - &self.ownership - } - - /// Returns [`Settings`] of the WCN cluster. - pub fn settings(&self) -> &Settings { - &self.settings - } - - /// Returns the primary [`Keyspace`] of the WCN cluster. - pub fn keyspace(&self) -> &Keyspace { - &self.keyspace - } - - /// Returns the ongoing [`Migration`] of the WCN cluster. - pub fn migration(&self) -> Option<&Migration> { - self.migration.as_ref() - } - - /// Returns the ongoing [`Maintenance`] of the WCN cluster. - pub fn maintenance(&self) -> Option<&Maintenance> { - self.maintenance.as_ref() - } - - /// Returns [`NodeOperators`] of the WCN cluster. - pub fn node_operators(&self) -> &NodeOperators { - &self.node_operators - } - - pub(super) fn require_no_migration(&self) -> Result<(), migration::InProgressError> { - if let Some(migration) = self.migration() { - return Err(migration::InProgressError(migration.id())); - } - - Ok(()) - } - - pub(super) fn require_no_maintenance(&self) -> Result<(), maintenance::InProgressError> { - if let Some(maintenance) = self.maintenance() { - return Err(maintenance::InProgressError(*maintenance.slot())); - } - - Ok(()) - } - - pub(super) fn require_migration(&self) -> Result<&Migration, migration::NotFoundError> { - self.migration.as_ref().ok_or(migration::NotFoundError) - } - - pub(super) fn require_maintenance(&self) -> Result<&Maintenance, maintenance::NotFoundError> { - self.maintenance.as_ref().ok_or(maintenance::NotFoundError) - } - - /// Applies the provided [`Event`] to this [`View`]. - pub async fn apply_event(mut self, event: Event) -> Result - where - Keyspace: keyspace::sealed::Calculate, - { - let new_version = event.cluster_version(); - - if new_version != self.cluster_version + 1 { - return Err(Error::ClusterVersionNotMonotonic( - self.cluster_version, - new_version, - )); - } - - match event { - Event::MigrationStarted(evt) => evt.apply(&mut self).await, - Event::MigrationDataPullCompleted(evt) => evt.apply(&mut self), - Event::MigrationCompleted(evt) => evt.apply(&mut self), - Event::MigrationAborted(evt) => evt.apply(&mut self), - Event::MaintenanceStarted(evt) => evt.apply(&mut self), - Event::MaintenanceFinished(evt) => evt.apply(&mut self), - Event::NodeOperatorAdded(evt) => evt.apply(&mut self), - Event::NodeOperatorUpdated(evt) => evt.apply(&mut self), - Event::NodeOperatorRemoved(evt) => evt.apply(&mut self), - Event::SettingsUpdated(evt) => evt.apply(&mut self), - Event::OwnershipTransferred(evt) => evt.apply(&mut self), - }?; - - self.cluster_version = new_version; - - Ok(self) - } -} - -impl View { - pub(super) async fn calculate_keyspace(self) -> View - where - Keyspace: keyspace::sealed::Calculate, - { - let (keyspace, migration) = tokio::join!( - (*self.keyspace).clone().calculate(), - OptionFuture::from(self.migration.map(Migration::calculate_keyspace)) - ); - - View { - node_operators: self.node_operators, - ownership: self.ownership, - settings: self.settings, - keyspace: Arc::new(keyspace), - migration, - maintenance: self.maintenance, - cluster_version: self.cluster_version, - } - } -} - -impl View { - pub(super) fn deserialize( - self, - ) -> Result, node_operator::DataDeserializationError> { - Ok(View { - node_operators: self.node_operators.deserialize()?, - ownership: self.ownership, - settings: self.settings, - keyspace: self.keyspace, - migration: self.migration, - maintenance: self.maintenance, - cluster_version: self.cluster_version, - }) - } -} - -impl migration::Started { - async fn apply(self, view: &mut View) -> Result<()> - where - Keyspace: keyspace::sealed::Calculate, - { - view.require_no_migration()?; - view.require_no_maintenance()?; - view.keyspace().require_diff(&self.new_keyspace)?; - - view.migration = Some(Migration::new( - self.migration_id, - self.new_keyspace.calculate().await, - view.node_operators.occupied_indexes(), - )); - - Ok(()) - } -} - -impl migration::DataPullCompleted { - pub(super) fn apply(self, view: &mut View) -> Result<()> { - let idx = view.node_operators.require_idx(&self.operator_id)?; - view.require_migration()? - .require_id(self.migration_id)? - .require_pulling(idx)?; - - if let Some(migration) = view.migration.as_mut() { - migration.complete_pull(idx); - } - - Ok(()) - } -} - -impl migration::Completed { - pub(super) fn apply(self, view: &mut View) -> Result<()> { - let idx = view.node_operators.require_idx(&self.operator_id)?; - view.require_migration()? - .require_id(self.migration_id)? - .require_pulling(idx)? - .require_pulling_count(1)?; - - view.keyspace = view.migration.take().unwrap().into_keyspace(); - - Ok(()) - } -} - -impl migration::Aborted { - pub(super) fn apply(self, view: &mut View) -> Result<()> { - view.require_migration()?.require_id(self.migration_id)?; - view.migration = None; - - Ok(()) - } -} - -impl maintenance::Started { - pub(super) fn apply(self, view: &mut View) -> Result<()> { - view.require_no_migration()?; - view.require_no_maintenance()?; - - view.maintenance = Some(Maintenance::new(self.operator_id)); - - Ok(()) - } -} - -impl maintenance::Finished { - pub(super) fn apply(self, view: &mut View) -> Result<()> { - view.require_maintenance()?; - view.maintenance = None; - - Ok(()) - } -} - -impl node_operator::Added { - pub(super) fn apply(self, view: &mut View) -> Result<()> { - view.node_operators() - .require_not_exists(&self.operator.id)? - .require_free_slot(self.idx)?; - - view.node_operators.set(self.idx, Some(self.operator)); - - Ok(()) - } -} - -impl node_operator::Updated { - pub(super) fn apply(self, view: &mut View) -> Result<()> { - let idx = view.node_operators.require_idx(&self.operator.id)?; - view.node_operators.set(idx, Some(self.operator)); - - Ok(()) - } -} - -impl node_operator::Removed { - pub(super) fn apply(self, view: &mut View) -> Result<()> { - let idx = view.node_operators.require_idx(&self.id)?; - view.node_operators.set(idx, None); - - Ok(()) - } -} - -impl settings::Updated { - pub(super) fn apply(self, view: &mut View) -> Result<()> { - view.settings = self.settings; - - Ok(()) - } -} - -impl ownership::Transferred { - pub(super) fn apply(self, view: &mut View) -> Result<()> { - view.ownership.transfer(self.new_owner); - - Ok(()) - } -} - -/// Error of [`View::apply_event`] caused by a race condition or by an incorrect -/// implementation of the [`SmartContract`](crate::SmartContract). -#[derive(Debug, thiserror::Error)] -pub enum Error { - #[error("Cluster version change wasn't monotonic: {_0} -> {_1}")] - ClusterVersionNotMonotonic(cluster::Version, cluster::Version), - - #[error(transparent)] - MigrationInProgress(#[from] migration::InProgressError), - - #[error(transparent)] - MaintenanceInProgress(#[from] maintenance::InProgressError), - - #[error(transparent)] - NoMigration(#[from] migration::NotFoundError), - - #[error(transparent)] - NoMaintenance(#[from] maintenance::NotFoundError), - - #[error(transparent)] - WrongMigrationId(#[from] migration::WrongIdError), - - #[error(transparent)] - SameKeyspace(#[from] keyspace::SameKeyspaceError), - - #[error(transparent)] - NotPulling(#[from] migration::OperatorNotPullingError), - - #[error(transparent)] - WrongPullingOperatorsCount(#[from] migration::WrongPullingOperatorsCountError), - - #[error(transparent)] - OperatorNotFound(#[from] node_operator::NotFoundError), - - #[error(transparent)] - OperatorAlreadyExists(#[from] node_operator::AlreadyExistsError), - - #[error(transparent)] - OperatorSlotOccupied(#[from] node_operators::SlotOccupiedError), -} - -/// Result of [`View::apply_event`]. -pub type Result = std::result::Result; - -/// Error of fetching [`View`] from a [`smart_contract`]. -#[derive(Debug, thiserror::Error)] -pub enum FetchError { - #[error(transparent)] - DataDeserialization(#[from] node_operator::DataDeserializationError), - - #[error("Smart-contract: {0}")] - SmartContractRead(#[from] smart_contract::ReadError), -} diff --git a/crates/cluster/tests/integration.rs b/crates/cluster/tests/integration.rs deleted file mode 100644 index da66702f..00000000 --- a/crates/cluster/tests/integration.rs +++ /dev/null @@ -1,159 +0,0 @@ -use { - cluster::{ - keyspace::ReplicationStrategy, - node_operator, - smart_contract::{ - self, - evm::{self, RpcProvider}, - Read, - Signer, - }, - Cluster, - Node, - NodeOperator, - Settings, - }, - libp2p::PeerId, - std::{collections::HashSet, net::SocketAddrV4, time::Duration}, - tracing_subscriber::EnvFilter, -}; - -// Anvil private keys with balances -const PRIVATE_KEYS: [&'static str; 10] = [ - "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", - "0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d", - "0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a", - "0x7c852118294e51e653712a81e05800f419141751be58f605c371e15141b007a6", - "0x47e179ec197488593b187f80a00eb0da91f1b9d0b13f8733639f19c30a34926a", - "0x8b3a350cf5c34c9194ca85829a2df0ec3153be0318b5e2d3348e872092edffba", - "0x92db14e403b83dfe3df233f83dfa3a0d7096f21ca9b0d6d6b8d88b2b4ec1564e", - "0x4bbbf85ce3377467afe5d46f804f221813b2bb87f24d81f60f1fcdbf7cbf4356", - "0xdbda1821b80551c9d65939329250298aa3472ba22feea921c0cf5d620ea67b97", - "0x2a871d0798f97d79848a013d4936a73bf4cc922c825d33c1cf7073dff6d409c6", -]; - -#[tokio::test] -async fn test_suite() { - let subscriber = tracing_subscriber::FmtSubscriber::builder() - .with_max_level(tracing::Level::INFO) - .with_env_filter(EnvFilter::from_default_env()) - .finish(); - tracing::subscriber::set_global_default(subscriber).unwrap(); - - let settings = Settings { - max_node_operator_data_bytes: 4096, - }; - - let signer = Signer::try_from_private_key( - "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", - ) - .unwrap(); - - let provider = provider(signer).await; - - let operators = (1..=5).map(|n| new_node_operator(n)).collect(); - - let cluster = Cluster::>::deploy(&provider, settings, operators) - .await - .unwrap(); - - for idx in 5..=7 { - cluster - .add_node_operator(idx, new_node_operator(idx + 1)) - .await - .unwrap(); - } - - cluster - .start_migration(cluster::migration::Plan { - remove: [operator_id(1)].into_iter().collect(), - add: [operator_id(6), operator_id(7), operator_id(8)] - .into_iter() - .collect(), - replication_strategy: ReplicationStrategy::UniformDistribution, - }) - .await - .unwrap(); - - for idx in 1..=7 { - connect(idx + 1, cluster.smart_contract().address()) - .await - .complete_migration(1) - .await - .unwrap(); - } - - tokio::time::sleep(Duration::from_secs(1)).await; - - cluster - .start_migration(cluster::migration::Plan { - remove: HashSet::default(), - add: [operator_id(1)].into_iter().collect(), - replication_strategy: ReplicationStrategy::UniformDistribution, - }) - .await - .unwrap(); - - cluster.abort_migration(2).await.unwrap(); - - cluster.start_maintenance().await.unwrap(); - cluster.finish_maintenance().await.unwrap(); - - cluster.remove_node_operator(operator_id(1)).await.unwrap(); - - let mut operator2 = new_node_operator(2); - operator2.data.name = node_operator::Name::new("NewName").unwrap(); - cluster.update_node_operator(operator2).await.unwrap(); - - cluster - .update_settings(Settings { - max_node_operator_data_bytes: 10000, - }) - .await - .unwrap(); - - cluster - .transfer_ownership(*new_signer(9).address()) - .await - .unwrap(); -} - -fn new_node_operator(n: u8) -> NodeOperator { - let data = node_operator::Data { - name: node_operator::Name::new(format!("Operator{n}")).unwrap(), - nodes: vec![Node { - peer_id: PeerId::random(), - addr: SocketAddrV4::new([127, 0, 0, 1].into(), 40000 + n as u16), - }], - clients: vec![], - }; - - NodeOperator { - id: operator_id(n), - data, - } -} - -fn operator_id(n: u8) -> node_operator::Id { - *new_signer(n).address() -} - -fn new_signer(n: u8) -> Signer { - Signer::try_from_private_key(PRIVATE_KEYS[n as usize]).unwrap() -} - -async fn provider(signer: Signer) -> RpcProvider { - RpcProvider::new("ws://127.0.0.1:8545".parse().unwrap(), signer) - .await - .unwrap() -} - -async fn connect( - operator: u8, - address: smart_contract::Address, -) -> Cluster> { - let provider = provider(new_signer(operator)).await; - Cluster::>::connect(&provider, address) - .await - .unwrap() -} From 7b1daf261fb9278882992cee7128da238c9ab24e Mon Sep 17 00:00:00 2001 From: Darksome Date: Fri, 6 Jun 2025 13:40:32 +0000 Subject: [PATCH 40/79] fix: axum --- Cargo.lock | 2408 ++---------------------------------- crates/node/Cargo.toml | 6 - crates/node/src/lib.rs | 2 +- crates/node/src/metrics.rs | 10 +- crates/wcn/Cargo.toml | 9 - 5 files changed, 122 insertions(+), 2313 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ecec469a..bd7516db 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,17 +23,6 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" -[[package]] -name = "aes" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" -dependencies = [ - "cfg-if", - "cipher", - "cpufeatures", -] - [[package]] name = "ahash" version = "0.8.11" @@ -97,680 +86,6 @@ version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" -[[package]] -name = "alloy" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca940218f168ba7dd97c22fccd3055e9f2ff463bd5aededf614f1fba71c90648" -dependencies = [ - "alloy-consensus", - "alloy-contract", - "alloy-core", - "alloy-eips", - "alloy-network", - "alloy-node-bindings", - "alloy-provider", - "alloy-pubsub", - "alloy-rpc-client", - "alloy-rpc-types", - "alloy-serde", - "alloy-signer", - "alloy-signer-local", - "alloy-transport", - "alloy-transport-http", - "alloy-transport-ws", -] - -[[package]] -name = "alloy-chains" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "517e5acbd38b6d4c59da380e8bbadc6d365bf001903ce46cf5521c53c647e07b" -dependencies = [ - "alloy-primitives", - "num_enum", - "strum", -] - -[[package]] -name = "alloy-consensus" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78090ff96d0d1b648dbcebc63b5305296b76ad4b5d4810f755d7d1224ced6247" -dependencies = [ - "alloy-eips", - "alloy-primitives", - "alloy-rlp", - "alloy-serde", - "alloy-trie", - "auto_impl", - "c-kzg", - "derive_more 2.0.1", - "either", - "k256", - "once_cell", - "rand 0.8.5", - "secp256k1", - "serde", - "serde_with", - "thiserror 2.0.12", -] - -[[package]] -name = "alloy-consensus-any" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcdfc3b2f202e3c6284685e6d3dcfbb532b39552d9e1021276e68e2389037616" -dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-primitives", - "alloy-rlp", - "alloy-serde", - "serde", -] - -[[package]] -name = "alloy-contract" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f4a5b6c7829e8aa048f5b23defa21706b675e68e612cf88d9f509771fecc806" -dependencies = [ - "alloy-consensus", - "alloy-dyn-abi", - "alloy-json-abi", - "alloy-network", - "alloy-network-primitives", - "alloy-primitives", - "alloy-provider", - "alloy-pubsub", - "alloy-rpc-types-eth", - "alloy-sol-types", - "alloy-transport", - "futures", - "futures-util", - "thiserror 2.0.12", -] - -[[package]] -name = "alloy-core" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3c5a28f166629752f2e7246b813cdea3243cca59aab2d4264b1fd68392c10eb" -dependencies = [ - "alloy-dyn-abi", - "alloy-json-abi", - "alloy-primitives", - "alloy-sol-types", -] - -[[package]] -name = "alloy-dyn-abi" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18cc14d832bc3331ca22a1c7819de1ede99f58f61a7d123952af7dde8de124a6" -dependencies = [ - "alloy-json-abi", - "alloy-primitives", - "alloy-sol-type-parser", - "alloy-sol-types", - "itoa", - "serde", - "serde_json", - "winnow 0.7.10", -] - -[[package]] -name = "alloy-eip2124" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "741bdd7499908b3aa0b159bba11e71c8cddd009a2c2eb7a06e825f1ec87900a5" -dependencies = [ - "alloy-primitives", - "alloy-rlp", - "crc", - "serde", - "thiserror 2.0.12", -] - -[[package]] -name = "alloy-eip2930" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b82752a889170df67bbb36d42ca63c531eb16274f0d7299ae2a680facba17bd" -dependencies = [ - "alloy-primitives", - "alloy-rlp", - "serde", -] - -[[package]] -name = "alloy-eip7702" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d4769c6ffddca380b0070d71c8b7f30bed375543fe76bb2f74ec0acf4b7cd16" -dependencies = [ - "alloy-primitives", - "alloy-rlp", - "serde", - "thiserror 2.0.12", -] - -[[package]] -name = "alloy-eips" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fb7646210355c36b07886c91cac52e4727191e2b0ee1415cce8f953f6019dd2" -dependencies = [ - "alloy-eip2124", - "alloy-eip2930", - "alloy-eip7702", - "alloy-primitives", - "alloy-rlp", - "alloy-serde", - "auto_impl", - "c-kzg", - "derive_more 2.0.1", - "either", - "serde", - "sha2", -] - -[[package]] -name = "alloy-genesis" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b14b506d7a4f739dd57ad5026d65eb64d842f4e971f71da5e9be5067ecbdc9" -dependencies = [ - "alloy-eips", - "alloy-primitives", - "alloy-serde", - "alloy-trie", - "serde", -] - -[[package]] -name = "alloy-hardforks" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbff8445282ec080c2673692062bd4930d7a0d6bda257caf138cfc650c503000" -dependencies = [ - "alloy-chains", - "alloy-eip2124", - "alloy-primitives", - "auto_impl", - "dyn-clone", -] - -[[package]] -name = "alloy-json-abi" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ccaa79753d7bf15f06399ea76922afbfaf8d18bebed9e8fc452984b4a90dcc9" -dependencies = [ - "alloy-primitives", - "alloy-sol-type-parser", - "serde", - "serde_json", -] - -[[package]] -name = "alloy-json-rpc" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a7ed339a633ba1a2af3eb9847dc90936d1b3c380a223cfca7a45be1713d8ab0" -dependencies = [ - "alloy-primitives", - "alloy-sol-types", - "serde", - "serde_json", - "thiserror 2.0.12", - "tracing", -] - -[[package]] -name = "alloy-network" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "691a4825b3d08f031b49aae3c11cb35abf2af376fc11146bf8e5930a432dbf40" -dependencies = [ - "alloy-consensus", - "alloy-consensus-any", - "alloy-eips", - "alloy-json-rpc", - "alloy-network-primitives", - "alloy-primitives", - "alloy-rpc-types-any", - "alloy-rpc-types-eth", - "alloy-serde", - "alloy-signer", - "alloy-sol-types", - "async-trait", - "auto_impl", - "derive_more 2.0.1", - "futures-utils-wasm", - "serde", - "serde_json", - "thiserror 2.0.12", -] - -[[package]] -name = "alloy-network-primitives" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5713f40f9cbe4428292d095e8bbb38af82e63ad4247418b7f6d6fb7ef2d9d68b" -dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-primitives", - "alloy-serde", - "serde", -] - -[[package]] -name = "alloy-node-bindings" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88c4a039f33025c4f4a88c121ce59f0b09a7ec159ac76c843dfb96a663cc48e8" -dependencies = [ - "alloy-genesis", - "alloy-hardforks", - "alloy-network", - "alloy-primitives", - "alloy-signer", - "alloy-signer-local", - "k256", - "rand 0.8.5", - "serde_json", - "tempfile", - "thiserror 2.0.12", - "tracing", - "url", -] - -[[package]] -name = "alloy-primitives" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18c35fc4b03ace65001676358ffbbaefe2a2b27ee50fe777c345082c7c888be8" -dependencies = [ - "alloy-rlp", - "bytes", - "cfg-if", - "const-hex", - "derive_more 2.0.1", - "foldhash", - "hashbrown 0.15.3", - "indexmap 2.9.0", - "itoa", - "k256", - "keccak-asm", - "paste", - "proptest", - "rand 0.9.1", - "ruint", - "rustc-hash 2.1.1", - "serde", - "sha3", - "tiny-keccak", -] - -[[package]] -name = "alloy-provider" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1382ef9e0fa1ab3f5a3dbc0a0fa1193f3794d5c9d75fc22654bb6da1cf7a59cc" -dependencies = [ - "alloy-chains", - "alloy-consensus", - "alloy-eips", - "alloy-json-rpc", - "alloy-network", - "alloy-network-primitives", - "alloy-node-bindings", - "alloy-primitives", - "alloy-pubsub", - "alloy-rpc-client", - "alloy-rpc-types-anvil", - "alloy-rpc-types-eth", - "alloy-signer", - "alloy-sol-types", - "alloy-transport", - "alloy-transport-http", - "alloy-transport-ws", - "async-stream", - "async-trait", - "auto_impl", - "dashmap 6.1.0", - "either", - "futures", - "futures-utils-wasm", - "lru 0.13.0", - "parking_lot", - "pin-project", - "reqwest", - "serde", - "serde_json", - "thiserror 2.0.12", - "tokio", - "tracing", - "url", - "wasmtimer", -] - -[[package]] -name = "alloy-pubsub" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8550f7306e0230fc835eb2ff4af0a96362db4b6fc3f25767d161e0ad0ac765bf" -dependencies = [ - "alloy-json-rpc", - "alloy-primitives", - "alloy-transport", - "bimap", - "futures", - "parking_lot", - "serde", - "serde_json", - "tokio", - "tokio-stream", - "tower 0.5.2", - "tracing", - "wasmtimer", -] - -[[package]] -name = "alloy-rlp" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6c1d995bff8d011f7cd6c81820d51825e6e06d6db73914c1630ecf544d83d6" -dependencies = [ - "alloy-rlp-derive", - "arrayvec", - "bytes", -] - -[[package]] -name = "alloy-rlp-derive" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a40e1ef334153322fd878d07e86af7a529bcb86b2439525920a88eba87bcf943" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.101", -] - -[[package]] -name = "alloy-rpc-client" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "859ec46fb132175969a0101bdd2fe9ecd413c40feeb0383e98710a4a089cee77" -dependencies = [ - "alloy-json-rpc", - "alloy-primitives", - "alloy-pubsub", - "alloy-transport", - "alloy-transport-http", - "alloy-transport-ws", - "async-stream", - "futures", - "pin-project", - "reqwest", - "serde", - "serde_json", - "tokio", - "tokio-stream", - "tower 0.5.2", - "tracing", - "tracing-futures", - "url", - "wasmtimer", -] - -[[package]] -name = "alloy-rpc-types" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f1512ec542339a72c263570644a56d685f20ce77be465fbd3f3f33fb772bcbd" -dependencies = [ - "alloy-primitives", - "alloy-rpc-types-anvil", - "alloy-rpc-types-eth", - "alloy-serde", - "serde", -] - -[[package]] -name = "alloy-rpc-types-anvil" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e284bffcdd934f924c710fdec402b7482f9fa1c6e9923fdfb6069106e832d525" -dependencies = [ - "alloy-primitives", - "alloy-rpc-types-eth", - "alloy-serde", - "serde", -] - -[[package]] -name = "alloy-rpc-types-any" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d87236623aafabbf7196bcde37a4d626c3e56b3b22d787310e6d5ea25239c5d8" -dependencies = [ - "alloy-consensus-any", - "alloy-rpc-types-eth", - "alloy-serde", -] - -[[package]] -name = "alloy-rpc-types-eth" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b8acc64d23e484a0a27375b57caba34569729560a29aa366933f0ae07b7786f" -dependencies = [ - "alloy-consensus", - "alloy-consensus-any", - "alloy-eips", - "alloy-network-primitives", - "alloy-primitives", - "alloy-rlp", - "alloy-serde", - "alloy-sol-types", - "itertools 0.14.0", - "serde", - "serde_json", - "thiserror 2.0.12", -] - -[[package]] -name = "alloy-serde" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "114c287eb4595f1e0844800efb0860dd7228fcf9bc77d52e303fb7a43eb766b2" -dependencies = [ - "alloy-primitives", - "serde", - "serde_json", -] - -[[package]] -name = "alloy-signer" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afebd60fa84d9ce793326941509d8f26ce7b383f2aabd7a42ba215c1b92ea96b" -dependencies = [ - "alloy-primitives", - "async-trait", - "auto_impl", - "either", - "elliptic-curve", - "k256", - "thiserror 2.0.12", -] - -[[package]] -name = "alloy-signer-local" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f551042c11c4fa7cb8194d488250b8dc58035241c418d79f07980c4aee4fa5c9" -dependencies = [ - "alloy-consensus", - "alloy-network", - "alloy-primitives", - "alloy-signer", - "async-trait", - "k256", - "rand 0.8.5", - "thiserror 2.0.12", -] - -[[package]] -name = "alloy-sol-macro" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8612e0658964d616344f199ab251a49d48113992d81b92dab93ed855faa66383" -dependencies = [ - "alloy-sol-macro-expander", - "alloy-sol-macro-input", - "proc-macro-error2", - "proc-macro2", - "quote", - "syn 2.0.101", -] - -[[package]] -name = "alloy-sol-macro-expander" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a384edac7283bc4c010a355fb648082860c04b826bb7a814c45263c8f304c74" -dependencies = [ - "alloy-json-abi", - "alloy-sol-macro-input", - "const-hex", - "heck 0.5.0", - "indexmap 2.9.0", - "proc-macro-error2", - "proc-macro2", - "quote", - "syn 2.0.101", - "syn-solidity", - "tiny-keccak", -] - -[[package]] -name = "alloy-sol-macro-input" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dd588c2d516da7deb421b8c166dc60b7ae31bca5beea29ab6621fcfa53d6ca5" -dependencies = [ - "alloy-json-abi", - "const-hex", - "dunce", - "heck 0.5.0", - "macro-string", - "proc-macro2", - "quote", - "serde_json", - "syn 2.0.101", - "syn-solidity", -] - -[[package]] -name = "alloy-sol-type-parser" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86ddeb70792c7ceaad23e57d52250107ebbb86733e52f4a25d8dc1abc931837" -dependencies = [ - "serde", - "winnow 0.7.10", -] - -[[package]] -name = "alloy-sol-types" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "584cb97bfc5746cb9dcc4def77da11694b5d6d7339be91b7480a6a68dc129387" -dependencies = [ - "alloy-json-abi", - "alloy-primitives", - "alloy-sol-macro", - "serde", -] - -[[package]] -name = "alloy-transport" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46fb766c0bce9f62779a83048ca6d998c2ced4153d694027c66e537629f4fd61" -dependencies = [ - "alloy-json-rpc", - "alloy-primitives", - "base64 0.22.1", - "derive_more 2.0.1", - "futures", - "futures-utils-wasm", - "parking_lot", - "serde", - "serde_json", - "thiserror 2.0.12", - "tokio", - "tower 0.5.2", - "tracing", - "url", - "wasmtimer", -] - -[[package]] -name = "alloy-transport-http" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "254bd59ca1abaf2da3e3201544a41924163b019414cce16f0dc6bc75d20c6612" -dependencies = [ - "alloy-json-rpc", - "alloy-transport", - "reqwest", - "serde_json", - "tower 0.5.2", - "tracing", - "url", -] - -[[package]] -name = "alloy-transport-ws" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0c6f9b37cd8d44aab959613966cc9d4d7a9b429c575cec43b3e5b46ea109a79" -dependencies = [ - "alloy-pubsub", - "alloy-transport", - "futures", - "http 1.1.0", - "rustls", - "serde_json", - "tokio", - "tokio-tungstenite", - "tracing", - "ws_stream_wasm", -] - -[[package]] -name = "alloy-trie" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "983d99aa81f586cef9dae38443245e585840fcf0fc58b09aee0b1f27aed1d500" -dependencies = [ - "alloy-primitives", - "alloy-rlp", - "arrayvec", - "derive_more 2.0.1", - "nybbles", - "serde", - "smallvec", - "tracing", -] - [[package]] name = "android-tzdata" version = "0.1.1" @@ -837,153 +152,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" dependencies = [ "anstyle", - "windows-sys 0.52.0", -] - -[[package]] -name = "anyerror" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcd04a72664a65fb9adeae7ced0c98efd68a2b7a45adda8319b3bb36538404b8" -dependencies = [ - "serde", -] - -[[package]] -name = "anyhow" -version = "1.0.81" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" - -[[package]] -name = "arc-swap" -version = "1.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" - -[[package]] -name = "ark-ff" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b3235cc41ee7a12aaaf2c575a2ad7b46713a8a50bda2fc3b003a04845c05dd6" -dependencies = [ - "ark-ff-asm 0.3.0", - "ark-ff-macros 0.3.0", - "ark-serialize 0.3.0", - "ark-std 0.3.0", - "derivative", - "num-bigint", - "num-traits", - "paste", - "rustc_version 0.3.3", - "zeroize", -] - -[[package]] -name = "ark-ff" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" -dependencies = [ - "ark-ff-asm 0.4.2", - "ark-ff-macros 0.4.2", - "ark-serialize 0.4.2", - "ark-std 0.4.0", - "derivative", - "digest 0.10.7", - "itertools 0.10.5", - "num-bigint", - "num-traits", - "paste", - "rustc_version 0.4.0", - "zeroize", -] - -[[package]] -name = "ark-ff-asm" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db02d390bf6643fb404d3d22d31aee1c4bc4459600aef9113833d17e786c6e44" -dependencies = [ - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ark-ff-asm" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" -dependencies = [ - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ark-ff-macros" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fd794a08ccb318058009eefdf15bcaaaaf6f8161eb3345f907222bac38b20" -dependencies = [ - "num-bigint", - "num-traits", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ark-ff-macros" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" -dependencies = [ - "num-bigint", - "num-traits", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ark-serialize" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6c2b318ee6e10f8c2853e73a83adc0ccb88995aa978d8a3408d492ab2ee671" -dependencies = [ - "ark-std 0.3.0", - "digest 0.9.0", + "windows-sys 0.52.0", ] [[package]] -name = "ark-serialize" -version = "0.4.2" +name = "anyerror" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" +checksum = "bcd04a72664a65fb9adeae7ced0c98efd68a2b7a45adda8319b3bb36538404b8" dependencies = [ - "ark-std 0.4.0", - "digest 0.10.7", - "num-bigint", + "serde", ] [[package]] -name = "ark-std" -version = "0.3.0" +name = "anyhow" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c" -dependencies = [ - "num-traits", - "rand 0.8.5", -] +checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" [[package]] -name = "ark-std" -version = "0.4.0" +name = "arc-swap" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" -dependencies = [ - "num-traits", - "rand 0.8.5", -] +checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" [[package]] name = "arrayref" @@ -991,15 +182,6 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" -[[package]] -name = "arrayvec" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" -dependencies = [ - "serde", -] - [[package]] name = "asn1-rs" version = "0.6.2" @@ -1084,17 +266,6 @@ dependencies = [ "syn 2.0.101", ] -[[package]] -name = "async_io_stream" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6d7b9decdf35d8908a7e3ef02f64c5e9b1695e230154c0e8de3969142d9b94c" -dependencies = [ - "futures", - "pharos", - "rustc_version 0.4.0", -] - [[package]] name = "asynchronous-codec" version = "0.7.0" @@ -1125,46 +296,12 @@ dependencies = [ "winapi", ] -[[package]] -name = "auto_impl" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.101", -] - [[package]] name = "autocfg" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" -[[package]] -name = "aws-lc-rs" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fcc8f365936c834db5514fc45aee5b1202d677e6b40e48468aaaa8183ca8c7" -dependencies = [ - "aws-lc-sys", - "zeroize", -] - -[[package]] -name = "aws-lc-sys" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61b1d86e7705efe1be1b569bab41d4fa1e14e220b60a160f78de2db687add079" -dependencies = [ - "bindgen 0.69.5", - "cc", - "cmake", - "dunce", - "fs_extra", -] - [[package]] name = "axum" version = "0.8.4" @@ -1254,12 +391,6 @@ version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270" -[[package]] -name = "base16ct" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" - [[package]] name = "base64" version = "0.20.0" @@ -1294,12 +425,6 @@ dependencies = [ "console", ] -[[package]] -name = "bimap" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "230c5f1ca6a325a32553f8640d31ac9b49f2411e901e427570154868b46da4f7" - [[package]] name = "bindgen" version = "0.65.1" @@ -1321,60 +446,6 @@ dependencies = [ "syn 2.0.101", ] -[[package]] -name = "bindgen" -version = "0.69.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" -dependencies = [ - "bitflags 2.6.0", - "cexpr", - "clang-sys", - "itertools 0.12.1", - "lazy_static", - "lazycell", - "log", - "prettyplease", - "proc-macro2", - "quote", - "regex", - "rustc-hash 1.1.0", - "shlex", - "syn 2.0.101", - "which", -] - -[[package]] -name = "bit-set" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" -dependencies = [ - "bit-vec", -] - -[[package]] -name = "bit-vec" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" - -[[package]] -name = "bitcoin-io" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b47c4ab7a93edb0c7198c5535ed9b52b63095f4e9b45279c6736cec4b856baf" - -[[package]] -name = "bitcoin_hashes" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb18c03d0db0247e147a21a6faafd5a7eb851c743db062de72018b6b7e8e4d16" -dependencies = [ - "bitcoin-io", - "hex-conservative", -] - [[package]] name = "bitflags" version = "1.3.2" @@ -1390,18 +461,6 @@ dependencies = [ "serde", ] -[[package]] -name = "bitvec" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" -dependencies = [ - "funty", - "radium", - "tap", - "wyz", -] - [[package]] name = "block-buffer" version = "0.10.4" @@ -1411,18 +470,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "blst" -version = "0.3.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47c79a94619fade3c0b887670333513a67ac28a6a7e653eb260bf0d4103db38d" -dependencies = [ - "cc", - "glob", - "threadpool", - "zeroize", -] - [[package]] name = "bs58" version = "0.5.1" @@ -1458,12 +505,6 @@ version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" -[[package]] -name = "byte-slice-cast" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" - [[package]] name = "byte-unit" version = "4.0.19" @@ -1488,9 +529,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.10.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" dependencies = [ "serde", ] @@ -1506,21 +547,6 @@ dependencies = [ "pkg-config", ] -[[package]] -name = "c-kzg" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7318cfa722931cb5fe0838b98d3ce5621e75f6a6408abc21721d80de9223f2e4" -dependencies = [ - "blst", - "cc", - "glob", - "hex", - "libc", - "once_cell", - "serde", -] - [[package]] name = "camino" version = "1.1.6" @@ -1547,7 +573,7 @@ checksum = "4acbb09d9ee8e23699b9634375c72795d095bf268439da88562cf9b501f181fa" dependencies = [ "camino", "cargo-platform", - "semver 1.0.22", + "semver", "serde", "serde_json", ] @@ -1560,7 +586,7 @@ checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" dependencies = [ "camino", "cargo-platform", - "semver 1.0.22", + "semver", "serde", "serde_json", "thiserror 1.0.64", @@ -1578,24 +604,14 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" -[[package]] -name = "cbc" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6" -dependencies = [ - "cipher", -] - [[package]] name = "cc" -version = "1.2.22" +version = "1.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32db95edf998450acc7881c932f94cd9b05c87b4b2599e8bab064753da4acfd1" +checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" dependencies = [ "jobserver", "libc", - "shlex", ] [[package]] @@ -1667,16 +683,6 @@ dependencies = [ "half", ] -[[package]] -name = "cipher" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" -dependencies = [ - "crypto-common", - "inout", -] - [[package]] name = "clang-sys" version = "1.7.0" @@ -1718,7 +724,7 @@ dependencies = [ "anstream", "anstyle", "clap_lex", - "strsim 0.11.1", + "strsim 0.11.0", ] [[package]] @@ -1745,43 +751,6 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8191fa7302e03607ff0e237d4246cc043ff5b3cb9409d995172ba3bea16b807" -[[package]] -name = "cluster" -version = "0.1.0" -dependencies = [ - "aes", - "alloy", - "anyhow", - "arc-swap", - "backoff", - "derivative", - "derive_more 1.0.0", - "fpe", - "futures", - "hex", - "itertools 0.12.1", - "libp2p", - "postcard", - "serde", - "sharding", - "tap", - "thiserror 1.0.64", - "tokio", - "tokio-stream", - "tracing", - "tracing-subscriber", - "xxhash-rust", -] - -[[package]] -name = "cmake" -version = "0.1.54" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0" -dependencies = [ - "cc", -] - [[package]] name = "cobs" version = "0.2.3" @@ -1843,19 +812,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "const-hex" -version = "1.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b0485bab839b018a8f1723fc5391819fea5f8f0f32288ef8a735fd096b6160c" -dependencies = [ - "cfg-if", - "cpufeatures", - "hex", - "proptest", - "serde", -] - [[package]] name = "const-oid" version = "0.9.6" @@ -1887,21 +843,11 @@ dependencies = [ "libc", ] -[[package]] -name = "core-foundation" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "core-foundation-sys" -version = "0.8.7" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "core2" @@ -1921,21 +867,6 @@ dependencies = [ "libc", ] -[[package]] -name = "crc" -version = "3.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9710d3b3739c2e349eb44fe848ad0b7c8cb1e42bd87ee49371df2f7acaf3e675" -dependencies = [ - "crc-catalog", -] - -[[package]] -name = "crc-catalog" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" - [[package]] name = "crc32fast" version = "1.4.2" @@ -2046,18 +977,6 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" -[[package]] -name = "crypto-bigint" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" -dependencies = [ - "generic-array", - "rand_core 0.6.4", - "subtle", - "zeroize", -] - [[package]] name = "crypto-common" version = "0.1.6" @@ -2077,10 +996,10 @@ dependencies = [ "cfg-if", "cpufeatures", "curve25519-dalek-derive", - "digest 0.10.7", + "digest", "fiat-crypto", "platforms", - "rustc_version 0.4.0", + "rustc_version", "subtle", "zeroize", ] @@ -2102,18 +1021,8 @@ version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" dependencies = [ - "darling_core 0.14.4", - "darling_macro 0.14.4", -] - -[[package]] -name = "darling" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" -dependencies = [ - "darling_core 0.20.11", - "darling_macro 0.20.11", + "darling_core", + "darling_macro", ] [[package]] @@ -2130,64 +1039,25 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "darling_core" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim 0.11.1", - "syn 2.0.101", -] - [[package]] name = "darling_macro" version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" -dependencies = [ - "darling_core 0.14.4", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "darling_macro" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" -dependencies = [ - "darling_core 0.20.11", - "quote", - "syn 2.0.101", -] - -[[package]] -name = "dashmap" -version = "5.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" -dependencies = [ - "cfg-if", - "hashbrown 0.14.3", - "lock_api", - "once_cell", - "parking_lot_core", +dependencies = [ + "darling_core", + "quote", + "syn 1.0.109", ] [[package]] name = "dashmap" -version = "6.1.0" +version = "5.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ "cfg-if", - "crossbeam-utils", - "hashbrown 0.14.3", + "hashbrown", "lock_api", "once_cell", "parking_lot_core", @@ -2279,7 +1149,7 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4ec317cc3e7ef0928b0ca6e4a634a4d6c001672ae210438cf114a83e56b018d" dependencies = [ - "darling 0.14.4", + "darling", "proc-macro2", "quote", "syn 1.0.109", @@ -2304,7 +1174,7 @@ dependencies = [ "convert_case 0.4.0", "proc-macro2", "quote", - "rustc_version 0.4.0", + "rustc_version", "syn 1.0.109", ] @@ -2314,16 +1184,7 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" dependencies = [ - "derive_more-impl 1.0.0", -] - -[[package]] -name = "derive_more" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678" -dependencies = [ - "derive_more-impl 2.0.1", + "derive_more-impl", ] [[package]] @@ -2338,18 +1199,6 @@ dependencies = [ "unicode-xid", ] -[[package]] -name = "derive_more-impl" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.101", - "unicode-xid", -] - [[package]] name = "dhat" version = "0.3.2" @@ -2375,15 +1224,6 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" -[[package]] -name = "digest" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" -dependencies = [ - "generic-array", -] - [[package]] name = "digest" version = "0.10.7" @@ -2391,7 +1231,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", - "const-oid", "crypto-common", "subtle", ] @@ -2419,27 +1258,6 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" -[[package]] -name = "dyn-clone" -version = "1.0.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c7a8fb8a9fbf66c1f703fe16184d10ca0ee9d23be5b4436400408ba54a95005" - -[[package]] -name = "ecdsa" -version = "0.16.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" -dependencies = [ - "der", - "digest 0.10.7", - "elliptic-curve", - "rfc6979", - "serdect", - "signature", - "spki", -] - [[package]] name = "ed25519" version = "2.2.3" @@ -2479,32 +1297,9 @@ dependencies = [ [[package]] name = "either" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" -dependencies = [ - "serde", -] - -[[package]] -name = "elliptic-curve" -version = "0.13.8" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" -dependencies = [ - "base16ct", - "crypto-bigint", - "digest 0.10.7", - "ff", - "generic-array", - "group", - "pkcs8", - "rand_core 0.6.4", - "sec1", - "serdect", - "subtle", - "zeroize", -] +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "embedded-io" @@ -2587,9 +1382,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.12" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" dependencies = [ "libc", "windows-sys 0.52.0", @@ -2643,41 +1438,9 @@ checksum = "a2a2b11eda1d40935b26cf18f6833c526845ae8c41e58d09af6adeb6f0269183" [[package]] name = "fastrand" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" - -[[package]] -name = "fastrlp" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "139834ddba373bbdd213dffe02c8d110508dcf1726c2be27e8d1f7d7e1856418" -dependencies = [ - "arrayvec", - "auto_impl", - "bytes", -] - -[[package]] -name = "fastrlp" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce8dba4714ef14b8274c371879b175aa55b16b30f269663f19d576f380018dc4" -dependencies = [ - "arrayvec", - "auto_impl", - "bytes", -] - -[[package]] -name = "ff" -version = "0.13.0" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" -dependencies = [ - "rand_core 0.6.4", - "subtle", -] +checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" [[package]] name = "fiat-crypto" @@ -2697,18 +1460,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "fixed-hash" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" -dependencies = [ - "byteorder", - "rand 0.8.5", - "rustc-hex", - "static_assertions", -] - [[package]] name = "flate2" version = "1.0.33" @@ -2725,12 +1476,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "foldhash" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" - [[package]] name = "foreign-types" version = "0.3.2" @@ -2764,32 +1509,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "fpe" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26c4b37de5ae15812a764c958297cfc50f5c010438f60c6ce75d11b802abd404" -dependencies = [ - "cbc", - "cipher", - "libm", - "num-bigint", - "num-integer", - "num-traits", -] - -[[package]] -name = "fs_extra" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" - -[[package]] -name = "funty" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" - [[package]] name = "future" version = "0.1.0" @@ -2918,12 +1637,6 @@ dependencies = [ "slab", ] -[[package]] -name = "futures-utils-wasm" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42012b0f064e01aa58b545fe3727f90f7dd4020f4a3ea735b50344965f5a57e9" - [[package]] name = "generic-array" version = "0.14.7" @@ -2932,7 +1645,6 @@ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", - "zeroize", ] [[package]] @@ -2957,18 +1669,6 @@ dependencies = [ "wasi 0.11.0+wasi-snapshot-preview1", ] -[[package]] -name = "getrandom" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" -dependencies = [ - "cfg-if", - "libc", - "r-efi", - "wasi 0.14.2+wasi-0.2.4", -] - [[package]] name = "gimli" version = "0.28.1" @@ -3193,7 +1893,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ddf80e16f3c19ac06ce415a38b8591993d3f73aede049cb561becb5b3a8e242" dependencies = [ "gix-hash", - "hashbrown 0.14.3", + "hashbrown", "parking_lot", ] @@ -3217,7 +1917,7 @@ dependencies = [ "itoa", "libc", "memmap2", - "rustix 0.38.32", + "rustix", "smallvec", "thiserror 1.0.64", ] @@ -3499,17 +2199,6 @@ dependencies = [ "spinning_top", ] -[[package]] -name = "group" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" -dependencies = [ - "ff", - "rand_core 0.6.4", - "subtle", -] - [[package]] name = "h2" version = "0.3.26" @@ -3522,7 +2211,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.9.0", + "indexmap", "slab", "tokio", "tokio-util", @@ -3541,7 +2230,7 @@ dependencies = [ "futures-core", "futures-sink", "http 1.1.0", - "indexmap 2.9.0", + "indexmap", "slab", "tokio", "tokio-util", @@ -3558,12 +2247,6 @@ dependencies = [ "crunchy", ] -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - [[package]] name = "hashbrown" version = "0.14.3" @@ -3574,25 +2257,13 @@ dependencies = [ "allocator-api2", ] -[[package]] -name = "hashbrown" -version = "0.15.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3" -dependencies = [ - "allocator-api2", - "equivalent", - "foldhash", - "serde", -] - [[package]] name = "hashlink" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af" dependencies = [ - "hashbrown 0.14.3", + "hashbrown", ] [[package]] @@ -3630,18 +2301,6 @@ name = "hex" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" -dependencies = [ - "serde", -] - -[[package]] -name = "hex-conservative" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5313b072ce3c597065a808dbf612c4c8e8590bdbf8b579508bf7a762c5eae6cd" -dependencies = [ - "arrayvec", -] [[package]] name = "hex_fmt" @@ -3664,7 +2323,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest 0.10.7", + "digest", ] [[package]] @@ -3795,25 +2454,6 @@ dependencies = [ "want", ] -[[package]] -name = "hyper-rustls" -version = "0.27.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2" -dependencies = [ - "futures-util", - "http 1.1.0", - "hyper 1.3.1", - "hyper-util", - "log", - "rustls", - "rustls-native-certs 0.8.1", - "rustls-pki-types", - "tokio", - "tokio-rustls", - "tower-service", -] - [[package]] name = "hyper-tls" version = "0.6.0" @@ -3899,26 +2539,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "impl-codec" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" -dependencies = [ - "parity-scale-codec", -] - -[[package]] -name = "impl-trait-for-tuples" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "indenter" version = "0.3.3" @@ -3927,24 +2547,12 @@ checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" [[package]] name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", - "serde", -] - -[[package]] -name = "indexmap" -version = "2.9.0" +version = "2.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", - "hashbrown 0.15.3", - "serde", + "hashbrown", ] [[package]] @@ -3967,15 +2575,6 @@ dependencies = [ "libc", ] -[[package]] -name = "inout" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" -dependencies = [ - "generic-array", -] - [[package]] name = "instant" version = "0.1.12" @@ -4035,15 +2634,6 @@ dependencies = [ "either", ] -[[package]] -name = "itertools" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" -dependencies = [ - "either", -] - [[package]] name = "itoa" version = "1.0.11" @@ -4072,9 +2662,9 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] name = "jobserver" -version = "0.1.32" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +checksum = "ab46a6e9526ddef3ae7f787c06f0f2600639ba80ea3eade3d8e670a2230f51d6" dependencies = [ "libc", ] @@ -4088,39 +2678,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "k256" -version = "0.13.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" -dependencies = [ - "cfg-if", - "ecdsa", - "elliptic-curve", - "once_cell", - "serdect", - "sha2", -] - -[[package]] -name = "keccak" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" -dependencies = [ - "cpufeatures", -] - -[[package]] -name = "keccak-asm" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47a3633291834c4fbebf8673acbc1b04ec9d151418ff9b8e26dcd79129928758" -dependencies = [ - "digest 0.10.7", - "sha3-asm", -] - [[package]] name = "kqueue" version = "1.0.8" @@ -4169,12 +2726,6 @@ dependencies = [ "windows-targets 0.52.4", ] -[[package]] -name = "libm" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" - [[package]] name = "libp2p" version = "0.55.0" @@ -4350,7 +2901,7 @@ dependencies = [ "smallvec", "thiserror 2.0.12", "tracing", - "uint 0.10.0", + "uint", "web-time", ] @@ -4366,7 +2917,7 @@ dependencies = [ "futures-timer", "libp2p-core 0.43.0", "libp2p-identity", - "lru 0.12.3", + "lru", "multistream-select", "once_cell", "rand 0.8.5", @@ -4400,7 +2951,7 @@ version = "0.11.0+8.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3386f101bcb4bd252d8e9d2fb41ec3b0862a15a62b478c355b2982efa469e3e" dependencies = [ - "bindgen 0.65.1", + "bindgen", "bzip2-sys", "cc", "glob", @@ -4438,12 +2989,6 @@ version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" -[[package]] -name = "linux-raw-sys" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" - [[package]] name = "lock_api" version = "0.4.11" @@ -4466,16 +3011,7 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" dependencies = [ - "hashbrown 0.14.3", -] - -[[package]] -name = "lru" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "227748d55f2f0ab4735d87fd623798cb6b664512fe979705f829c9f81c934465" -dependencies = [ - "hashbrown 0.15.3", + "hashbrown", ] [[package]] @@ -4484,19 +3020,8 @@ version = "1.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57d27b317e207b10f69f5e75494119e391a96f48861ae870d1da6edac98ca900" dependencies = [ - "cc", - "libc", -] - -[[package]] -name = "macro-string" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b27834086c65ec3f9387b096d66e99f221cf081c2b738042aa252bcd41204e3" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.101", + "cc", + "libc", ] [[package]] @@ -4561,16 +3086,16 @@ dependencies = [ [[package]] name = "metrics-exporter-prometheus" -version = "0.15.3" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4f0c8427b39666bf970460908b213ec09b3b350f20c0c2eabcbba51704a08e6" +checksum = "26eb45aff37b45cff885538e1dcbd6c2b462c04fe84ce0155ea469f325672c98" dependencies = [ "base64 0.22.1", "http-body-util", "hyper 1.3.1", - "hyper-rustls", + "hyper-tls", "hyper-util", - "indexmap 2.9.0", + "indexmap", "ipnet", "metrics", "metrics-util", @@ -4588,7 +3113,7 @@ checksum = "4259040465c955f9f2f1a4a8a16dc46726169bca0f88e8fb2dbeced487c3e828" dependencies = [ "crossbeam-epoch", "crossbeam-utils", - "hashbrown 0.14.3", + "hashbrown", "metrics", "num_cpus", "quanta", @@ -4609,7 +3134,7 @@ checksum = "c325dfab65f261f386debee8b0969da215b3fa0037e74c8a1234db7ba986d803" dependencies = [ "crossbeam-channel", "crossbeam-utils", - "dashmap 5.5.3", + "dashmap", "skeptic", "smallvec", "tagptr", @@ -4727,17 +3252,18 @@ dependencies = [ [[package]] name = "native-tls" -version = "0.2.14" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" +checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" dependencies = [ + "lazy_static", "libc", "log", "openssl", "openssl-probe", "openssl-sys", "schannel", - "security-framework 2.11.1", + "security-framework", "security-framework-sys", "tempfile", ] @@ -4845,7 +3371,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" dependencies = [ "autocfg", - "libm", ] [[package]] @@ -4858,26 +3383,6 @@ dependencies = [ "libc", ] -[[package]] -name = "num_enum" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" -dependencies = [ - "num_enum_derive", -] - -[[package]] -name = "num_enum_derive" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.101", -] - [[package]] name = "num_threads" version = "0.1.7" @@ -4887,19 +3392,6 @@ dependencies = [ "libc", ] -[[package]] -name = "nybbles" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8983bb634df7248924ee0c4c3a749609b5abcb082c28fffe3254b3eb3602b307" -dependencies = [ - "alloy-rlp", - "const-hex", - "proptest", - "serde", - "smallvec", -] - [[package]] name = "object" version = "0.32.2" @@ -4920,9 +3412,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.21.3" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "oorandom" @@ -4954,9 +3446,9 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.72" +version = "0.10.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fedfea7d58a1f73118430a55da6a286e7b044961736ce96a16a17068ea25e5da" +checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" dependencies = [ "bitflags 2.6.0", "cfg-if", @@ -4986,9 +3478,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.108" +version = "0.9.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e145e1651e858e820e4860f7b9c5e169bc1d8ce1c86043be79fa7b7634821847" +checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" dependencies = [ "cc", "libc", @@ -5002,32 +3494,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" -[[package]] -name = "parity-scale-codec" -version = "3.6.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" -dependencies = [ - "arrayvec", - "bitvec", - "byte-slice-cast", - "impl-trait-for-tuples", - "parity-scale-codec-derive", - "serde", -] - -[[package]] -name = "parity-scale-codec-derive" -version = "3.6.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "parking" version = "2.2.1" @@ -5100,27 +3566,6 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" -[[package]] -name = "pest" -version = "2.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "560131c633294438da9f7c4b08189194b20946c8274c6b9e38881a7874dc8ee8" -dependencies = [ - "memchr", - "thiserror 1.0.64", - "ucd-trie", -] - -[[package]] -name = "pharos" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9567389417feee6ce15dd6527a8a1ecac205ef62c2932bcf3d9f6fc5b78b414" -dependencies = [ - "futures", - "rustc_version 0.4.0", -] - [[package]] name = "phi-accrual-failure-detector" version = "0.1.0" @@ -5261,26 +3706,6 @@ dependencies = [ "syn 2.0.101", ] -[[package]] -name = "primitive-types" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" -dependencies = [ - "fixed-hash", - "impl-codec", - "uint 0.9.5", -] - -[[package]] -name = "proc-macro-crate" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" -dependencies = [ - "toml_edit 0.21.1", -] - [[package]] name = "proc-macro-error" version = "1.0.4" @@ -5305,28 +3730,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "proc-macro-error-attr2" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" -dependencies = [ - "proc-macro2", - "quote", -] - -[[package]] -name = "proc-macro-error2" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" -dependencies = [ - "proc-macro-error-attr2", - "proc-macro2", - "quote", - "syn 2.0.101", -] - [[package]] name = "proc-macro2" version = "1.0.95" @@ -5374,26 +3777,6 @@ dependencies = [ "syn 2.0.101", ] -[[package]] -name = "proptest" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14cae93065090804185d3b75f0bf93b8eeda30c7a9b4a33d3bdb3988d6229e50" -dependencies = [ - "bit-set", - "bit-vec", - "bitflags 2.6.0", - "lazy_static", - "num-traits", - "rand 0.8.5", - "rand_chacha 0.3.1", - "rand_xorshift", - "regex-syntax 0.8.5", - "rusty-fork", - "tempfile", - "unarray", -] - [[package]] name = "pulldown-cmark" version = "0.9.6" @@ -5439,12 +3822,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "quick-error" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" - [[package]] name = "quick-protobuf" version = "0.8.1" @@ -5477,7 +3854,7 @@ dependencies = [ "pin-project-lite", "quinn-proto", "quinn-udp", - "rustc-hash 2.1.1", + "rustc-hash 2.0.0", "rustls", "socket2", "thiserror 1.0.64", @@ -5494,7 +3871,7 @@ dependencies = [ "bytes", "rand 0.8.5", "ring 0.17.8", - "rustc-hash 2.1.1", + "rustc-hash 2.0.0", "rustls", "rustls-platform-verifier", "slab", @@ -5525,18 +3902,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "r-efi" -version = "5.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" - -[[package]] -name = "radium" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" - [[package]] name = "raft" version = "0.1.0" @@ -5577,18 +3942,6 @@ dependencies = [ "libc", "rand_chacha 0.3.1", "rand_core 0.6.4", - "serde", -] - -[[package]] -name = "rand" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" -dependencies = [ - "rand_chacha 0.9.0", - "rand_core 0.9.3", - "serde", ] [[package]] @@ -5611,16 +3964,6 @@ dependencies = [ "rand_core 0.6.4", ] -[[package]] -name = "rand_chacha" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" -dependencies = [ - "ppv-lite86", - "rand_core 0.9.3", -] - [[package]] name = "rand_core" version = "0.5.1" @@ -5639,16 +3982,6 @@ dependencies = [ "getrandom 0.2.15", ] -[[package]] -name = "rand_core" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" -dependencies = [ - "getrandom 0.3.3", - "serde", -] - [[package]] name = "rand_hc" version = "0.2.0" @@ -5658,15 +3991,6 @@ dependencies = [ "rand_core 0.5.1", ] -[[package]] -name = "rand_xorshift" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" -dependencies = [ - "rand_core 0.6.4", -] - [[package]] name = "raw-cpuid" version = "11.0.2" @@ -5815,23 +4139,19 @@ dependencies = [ "http-body 1.0.0", "http-body-util", "hyper 1.3.1", - "hyper-tls", "hyper-util", "ipnet", "js-sys", "log", "mime", - "native-tls", "once_cell", "percent-encoding", "pin-project-lite", - "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", "sync_wrapper 0.1.2", "tokio", - "tokio-native-tls", "tower-service", "url", "wasm-bindgen", @@ -5840,16 +4160,6 @@ dependencies = [ "winreg", ] -[[package]] -name = "rfc6979" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" -dependencies = [ - "hmac", - "subtle", -] - [[package]] name = "ring" version = "0.16.20" @@ -5880,16 +4190,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "rlp" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" -dependencies = [ - "bytes", - "rustc-hex", -] - [[package]] name = "rmp" version = "0.8.14" @@ -5931,7 +4231,7 @@ dependencies = [ "futures", "futures-timer", "rstest_macros", - "rustc_version 0.4.0", + "rustc_version", ] [[package]] @@ -5946,44 +4246,11 @@ dependencies = [ "quote", "regex", "relative-path", - "rustc_version 0.4.0", + "rustc_version", "syn 2.0.101", "unicode-ident", ] -[[package]] -name = "ruint" -version = "1.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78a46eb779843b2c4f21fac5773e25d6d5b7c8f0922876c91541790d2ca27eef" -dependencies = [ - "alloy-rlp", - "ark-ff 0.3.0", - "ark-ff 0.4.2", - "bytes", - "fastrlp 0.3.1", - "fastrlp 0.4.0", - "num-bigint", - "num-integer", - "num-traits", - "parity-scale-codec", - "primitive-types", - "proptest", - "rand 0.8.5", - "rand 0.9.1", - "rlp", - "ruint-macro", - "serde", - "valuable", - "zeroize", -] - -[[package]] -name = "ruint-macro" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48fd7bd8a6377e15ad9d42a8ec25371b94ddc67abe7c8b9127bec79bebaaae18" - [[package]] name = "rustc-demangle" version = "0.1.23" @@ -5998,24 +4265,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc-hash" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" - -[[package]] -name = "rustc-hex" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" - -[[package]] -name = "rustc_version" -version = "0.3.3" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" -dependencies = [ - "semver 0.11.0", -] +checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" [[package]] name = "rustc_version" @@ -6023,7 +4275,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.22", + "semver", ] [[package]] @@ -6044,31 +4296,16 @@ dependencies = [ "bitflags 2.6.0", "errno", "libc", - "linux-raw-sys 0.4.13", - "windows-sys 0.52.0", -] - -[[package]] -name = "rustix" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" -dependencies = [ - "bitflags 2.6.0", - "errno", - "libc", - "linux-raw-sys 0.9.4", + "linux-raw-sys", "windows-sys 0.52.0", ] [[package]] name = "rustls" -version = "0.23.23" +version = "0.23.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47796c98c480fce5406ef69d1c76378375492c3b0a0de587be0c1d9feb12f395" +checksum = "eee87ff5d9b36712a58574e12e9f0ea80f915a5b0ac518d322b24a465617925e" dependencies = [ - "aws-lc-rs", - "log", "once_cell", "ring 0.17.8", "rustls-pki-types", @@ -6087,19 +4324,7 @@ dependencies = [ "rustls-pemfile", "rustls-pki-types", "schannel", - "security-framework 2.11.1", -] - -[[package]] -name = "rustls-native-certs" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" -dependencies = [ - "openssl-probe", - "rustls-pki-types", - "schannel", - "security-framework 3.2.0", + "security-framework", ] [[package]] @@ -6124,16 +4349,16 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "afbb878bdfdf63a336a5e63561b1835e7a8c91524f51621db870169eac84b490" dependencies = [ - "core-foundation 0.9.4", + "core-foundation", "core-foundation-sys", "jni", "log", "once_cell", "rustls", - "rustls-native-certs 0.7.3", + "rustls-native-certs", "rustls-platform-verifier-android", "rustls-webpki 0.102.8", - "security-framework 2.11.1", + "security-framework", "security-framework-sys", "webpki-roots", "winapi", @@ -6161,7 +4386,6 @@ version = "0.102.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" dependencies = [ - "aws-lc-rs", "ring 0.17.8", "rustls-pki-types", "untrusted 0.9.0", @@ -6173,18 +4397,6 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" -[[package]] -name = "rusty-fork" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" -dependencies = [ - "fnv", - "quick-error", - "tempfile", - "wait-timeout", -] - [[package]] name = "rw-stream-sink" version = "0.4.0" @@ -6222,92 +4434,34 @@ dependencies = [ [[package]] name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "sec1" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" -dependencies = [ - "base16ct", - "der", - "generic-array", - "pkcs8", - "serdect", - "subtle", - "zeroize", -] - -[[package]] -name = "secp256k1" -version = "0.30.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b50c5943d326858130af85e049f2661ba3c78b26589b8ab98e65e80ae44a1252" -dependencies = [ - "bitcoin_hashes", - "rand 0.8.5", - "secp256k1-sys", - "serde", -] - -[[package]] -name = "secp256k1-sys" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4387882333d3aa8cb20530a17c69a3752e97837832f34f6dccc760e715001d9" -dependencies = [ - "cc", -] - -[[package]] -name = "security-framework" -version = "2.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" -dependencies = [ - "bitflags 2.6.0", - "core-foundation 0.9.4", - "core-foundation-sys", - "libc", - "num-bigint", - "security-framework-sys", -] +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "security-framework" -version = "3.2.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271720403f46ca04f7ba6f55d438f8bd878d6b8ca0a1046e8228c4145bcbb316" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ "bitflags 2.6.0", - "core-foundation 0.10.0", + "core-foundation", "core-foundation-sys", "libc", + "num-bigint", "security-framework-sys", ] [[package]] name = "security-framework-sys" -version = "2.14.0" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" +checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" dependencies = [ "core-foundation-sys", "libc", ] -[[package]] -name = "semver" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" -dependencies = [ - "semver-parser", -] - [[package]] name = "semver" version = "1.0.22" @@ -6317,21 +4471,6 @@ dependencies = [ "serde", ] -[[package]] -name = "semver-parser" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" -dependencies = [ - "pest", -] - -[[package]] -name = "send_wrapper" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" - [[package]] name = "serde" version = "1.0.202" @@ -6404,57 +4543,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_with" -version = "3.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6b6f7f2fcb69f747921f79f3926bd1e203fce4fef62c268dd3abfb6d86029aa" -dependencies = [ - "base64 0.22.1", - "chrono", - "hex", - "indexmap 1.9.3", - "indexmap 2.9.0", - "serde", - "serde_derive", - "serde_json", - "serde_with_macros", - "time", -] - -[[package]] -name = "serde_with_macros" -version = "3.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d00caa5193a3c8362ac2b73be6b9e768aa5a4b2f721d8f4b339600c3cb51f8e" -dependencies = [ - "darling 0.20.11", - "proc-macro2", - "quote", - "syn 2.0.101", -] - -[[package]] -name = "serdect" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a84f14a19e9a014bb9f4512488d9829a68e04ecabffb0f9904cd1ace94598177" -dependencies = [ - "base16ct", - "serde", -] - -[[package]] -name = "sha1" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.7", -] - [[package]] name = "sha1_smol" version = "1.0.0" @@ -6469,27 +4557,7 @@ checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", - "digest 0.10.7", -] - -[[package]] -name = "sha3" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" -dependencies = [ - "digest 0.10.7", - "keccak", -] - -[[package]] -name = "sha3-asm" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9b57fd861253bff08bb1919e995f90ba8f4889de2726091c8876f3a4e823b40" -dependencies = [ - "cc", - "cfg-if", + "digest", ] [[package]] @@ -6505,7 +4573,7 @@ dependencies = [ name = "sharding" version = "0.1.0" dependencies = [ - "indexmap 2.9.0", + "indexmap", "rand 0.8.5", "thiserror 1.0.64", ] @@ -6552,7 +4620,6 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ - "digest 0.10.7", "rand_core 0.6.4", ] @@ -6656,9 +4723,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "strsim" -version = "0.11.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" +checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" [[package]] name = "structopt" @@ -6684,28 +4751,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "strum" -version = "0.27.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f64def088c51c9510a8579e3c5d67c65349dcf755e5479ad3d010aa6454e2c32" -dependencies = [ - "strum_macros", -] - -[[package]] -name = "strum_macros" -version = "0.27.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c77a8c5abcaf0f9ce05d62342b7d298c346515365c36b673df4ebe3ced01fde8" -dependencies = [ - "heck 0.5.0", - "proc-macro2", - "quote", - "rustversion", - "syn 2.0.101", -] - [[package]] name = "subtle" version = "2.5.0" @@ -6734,18 +4779,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "syn-solidity" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5d879005cc1b5ba4e18665be9e9501d9da3a9b95f625497c4cb7ee082b532e" -dependencies = [ - "paste", - "proc-macro2", - "quote", - "syn 2.0.101", -] - [[package]] name = "sync_wrapper" version = "0.1.2" @@ -6798,14 +4831,13 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.20.0" +version = "3.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ + "cfg-if", "fastrand", - "getrandom 0.3.3", - "once_cell", - "rustix 1.0.7", + "rustix", "windows-sys 0.52.0", ] @@ -6925,15 +4957,6 @@ dependencies = [ "once_cell", ] -[[package]] -name = "threadpool" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" -dependencies = [ - "num_cpus", -] - [[package]] name = "tikv-jemalloc-ctl" version = "0.5.4" @@ -6998,15 +5021,6 @@ dependencies = [ "time-core", ] -[[package]] -name = "tiny-keccak" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" -dependencies = [ - "crunchy", -] - [[package]] name = "tinytemplate" version = "1.2.1" @@ -7034,9 +5048,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.45.0" +version = "1.45.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2513ca694ef9ede0fb23fe71a4ee4107cb102b9dc1930f6d0fd77aae068ae165" +checksum = "75ef51a33ef1da925cea3e4eb122833cb377c61439ca401b770f54902b806779" dependencies = [ "backtrace", "bytes", @@ -7071,16 +5085,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "tokio-rustls" -version = "0.26.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" -dependencies = [ - "rustls", - "tokio", -] - [[package]] name = "tokio-serde" version = "0.9.0" @@ -7118,22 +5122,6 @@ dependencies = [ "tokio-util", ] -[[package]] -name = "tokio-tungstenite" -version = "0.26.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a9daff607c6d2bf6c16fd681ccb7eecc83e4e2cdc1ca067ffaadfca5de7f084" -dependencies = [ - "futures-util", - "log", - "rustls", - "rustls-pki-types", - "tokio", - "tokio-rustls", - "tungstenite", - "webpki-roots", -] - [[package]] name = "tokio-util" version = "0.7.10" @@ -7158,7 +5146,7 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.22.13", + "toml_edit", ] [[package]] @@ -7170,24 +5158,13 @@ dependencies = [ "serde", ] -[[package]] -name = "toml_edit" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" -dependencies = [ - "indexmap 2.9.0", - "toml_datetime", - "winnow 0.5.40", -] - [[package]] name = "toml_edit" version = "0.22.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c127785850e8c20836d49732ae6abfa47616e60bf9d9f57c43c250361a9db96c" dependencies = [ - "indexmap 2.9.0", + "indexmap", "serde", "serde_spanned", "toml_datetime", @@ -7264,9 +5241,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.28" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" +checksum = "1b1ffbcf9c6f6b99d386e7444eb608ba646ae452a36b39737deb9663b610f662" dependencies = [ "proc-macro2", "quote", @@ -7275,9 +5252,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.33" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" dependencies = [ "once_cell", "valuable", @@ -7289,8 +5266,6 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" dependencies = [ - "futures", - "futures-task", "pin-project", "tracing", ] @@ -7363,49 +5338,12 @@ dependencies = [ "unicode-width", ] -[[package]] -name = "tungstenite" -version = "0.26.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4793cb5e56680ecbb1d843515b23b6de9a75eb04b66643e256a396d43be33c13" -dependencies = [ - "bytes", - "data-encoding", - "http 1.1.0", - "httparse", - "log", - "rand 0.9.1", - "rustls", - "rustls-pki-types", - "sha1", - "thiserror 2.0.12", - "utf-8", -] - [[package]] name = "typenum" version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" -[[package]] -name = "ucd-trie" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" - -[[package]] -name = "uint" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" -dependencies = [ - "byteorder", - "crunchy", - "hex", - "static_assertions", -] - [[package]] name = "uint" version = "0.10.0" @@ -7418,12 +5356,6 @@ dependencies = [ "static_assertions", ] -[[package]] -name = "unarray" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" - [[package]] name = "unicase" version = "2.8.1" @@ -7510,12 +5442,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "utf-8" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" - [[package]] name = "utf8-width" version = "0.1.7" @@ -7560,7 +5486,7 @@ dependencies = [ "cfg-if", "gix", "regex", - "rustc_version 0.4.0", + "rustc_version", "rustversion", "time", ] @@ -7590,15 +5516,6 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -[[package]] -name = "wait-timeout" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" -dependencies = [ - "libc", -] - [[package]] name = "walkdir" version = "2.5.0" @@ -7630,15 +5547,6 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" -[[package]] -name = "wasi" -version = "0.14.2+wasi-0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" -dependencies = [ - "wit-bindgen-rt", -] - [[package]] name = "wasm-bindgen" version = "0.2.92" @@ -7705,20 +5613,6 @@ version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" -[[package]] -name = "wasmtimer" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0048ad49a55b9deb3953841fa1fc5858f0efbcb7a18868c899a360269fac1b23" -dependencies = [ - "futures", - "js-sys", - "parking_lot", - "pin-utils", - "slab", - "wasm-bindgen", -] - [[package]] name = "wc" version = "0.1.0" @@ -7841,7 +5735,7 @@ dependencies = [ "bytes", "chrono", "criterion", - "dashmap 5.5.3", + "dashmap", "derivative", "derive_more 1.0.0", "difference", @@ -8045,7 +5939,7 @@ dependencies = [ "derive_more 1.0.0", "futures", "governor", - "indexmap 2.9.0", + "indexmap", "libp2p", "libp2p-tls", "metrics", @@ -8114,18 +6008,6 @@ dependencies = [ "rustls-pki-types", ] -[[package]] -name = "which" -version = "4.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" -dependencies = [ - "either", - "home", - "once_cell", - "rustix 0.38.32", -] - [[package]] name = "winapi" version = "0.3.9" @@ -8382,15 +6264,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "winnow" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06928c8748d81b05c9be96aad92e1b6ff01833332f281e8cfca3be4b35fc9ec" -dependencies = [ - "memchr", -] - [[package]] name = "winreg" version = "0.52.0" @@ -8401,43 +6274,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "wit-bindgen-rt" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" -dependencies = [ - "bitflags 2.6.0", -] - -[[package]] -name = "ws_stream_wasm" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7999f5f4217fe3818726b66257a4475f71e74ffd190776ad053fa159e50737f5" -dependencies = [ - "async_io_stream", - "futures", - "js-sys", - "log", - "pharos", - "rustc_version 0.4.0", - "send_wrapper", - "thiserror 1.0.64", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - -[[package]] -name = "wyz" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" -dependencies = [ - "tap", -] - [[package]] name = "x509-parser" version = "0.16.0" @@ -8495,17 +6331,3 @@ name = "zeroize" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" -dependencies = [ - "zeroize_derive", -] - -[[package]] -name = "zeroize_derive" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.101", -] diff --git a/crates/node/Cargo.toml b/crates/node/Cargo.toml index db8c2d6d..02e07c18 100644 --- a/crates/node/Cargo.toml +++ b/crates/node/Cargo.toml @@ -88,12 +88,6 @@ xxhash-rust = { version = "0.8", features = ["xxh3", "const_xxh3"] } postcard = { version = "1.0", default-features = false, features = ["alloc"] } anyerror = "0.1" -# alloy = { git = "https://github.com/alloy-rs/alloy", features = [ -# "contract", -# "providers", -# "provider-http", -# "signer-mnemonic", -# ] } reqwest = { version = "0.12", default-features = false } chrono = { version = "0.4", default-features = false } if-addrs = "0.13" diff --git a/crates/node/src/lib.rs b/crates/node/src/lib.rs index 9089a594..1a94c798 100644 --- a/crates/node/src/lib.rs +++ b/crates/node/src/lib.rs @@ -44,7 +44,7 @@ pub enum Error { InvalidMetricsAddress(#[from] std::net::AddrParseError), #[error("Metrics server error: {0}")] - MetricsServer(#[from] hyper::Error), + MetricsServer(io::Error), #[error("Failed to start Client API server: {0:?}")] ClientApiServer(#[from] client_api::server::ServeError), diff --git a/crates/node/src/metrics.rs b/crates/node/src/metrics.rs index 90286a97..4f19549f 100644 --- a/crates/node/src/metrics.rs +++ b/crates/node/src/metrics.rs @@ -210,10 +210,12 @@ pub(crate) fn serve( Ok(async move { tracing::info!(?addr, "starting metrics server"); - let result = axum::Server::bind(&addr) - .serve(svc) - .await - .map_err(Into::into); + let result = async move { + let listener = tokio::net::TcpListener::bind(addr).await?; + axum::serve(listener, svc).await + } + .await + .map_err(Error::MetricsServer); let _ = tx.send(()); diff --git a/crates/wcn/Cargo.toml b/crates/wcn/Cargo.toml index de6fac1c..f3fc2650 100644 --- a/crates/wcn/Cargo.toml +++ b/crates/wcn/Cargo.toml @@ -45,14 +45,5 @@ pidlock = "0.1" nix = { version = "0.28", default-features = false, features = ["signal"] } fork = "0.1" - -# Smart Contract Integration -# alloy = { git = "https://github.com/alloy-rs/alloy", features = [ -# "contract", -# "providers", -# "provider-http", -# "signer-mnemonic", -# ] } - [lints] workspace = true From 0381b776c2479e85b4e76e5320b11142b71518a1 Mon Sep 17 00:00:00 2001 From: Darksome Date: Fri, 6 Jun 2025 13:50:42 +0000 Subject: [PATCH 41/79] fix: axum --- crates/node/src/metrics.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/node/src/metrics.rs b/crates/node/src/metrics.rs index 4f19549f..9a86aada 100644 --- a/crates/node/src/metrics.rs +++ b/crates/node/src/metrics.rs @@ -200,7 +200,7 @@ pub(crate) fn serve( axum::routing::get(move || async move { prometheus.render() }), ) .route( - "/metrics/:peer_id", + "/metrics/{peer_id}", axum::routing::get(move |axum::extract::Path(peer_id)| { scrape_prometheus(prometheus_.clone(), node.clone(), peer_id) }), From e04d3b1fb5eca26d7d06df911c3dfd33bd45b0cc Mon Sep 17 00:00:00 2001 From: Darksome Date: Fri, 6 Jun 2025 15:10:29 +0000 Subject: [PATCH 42/79] fix: dockerfile --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 9a738758..73a2ff87 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,8 +3,8 @@ # Build args # ################################################################################ -ARG BASE="rust:1.79-buster" -ARG RUNTIME="debian:buster-slim" +ARG BASE="1.87-bullseye" +ARG RUNTIME="debian:bullseye-slim" ARG VERSION="unknown" ARG SHA="unknown" ARG MAINTAINER="WalletConnect" From 3cc33d7110a363fd851f660c3c0e6ce7cf632219 Mon Sep 17 00:00:00 2001 From: Darksome Date: Fri, 6 Jun 2025 15:31:19 +0000 Subject: [PATCH 43/79] fix: dockerfile --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 73a2ff87..2659e991 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,7 +3,7 @@ # Build args # ################################################################################ -ARG BASE="1.87-bullseye" +ARG BASE="rust:1.87-bullseye" ARG RUNTIME="debian:bullseye-slim" ARG VERSION="unknown" ARG SHA="unknown" From bbd0f941b8f97cee6b505328258387481ea41ce6 Mon Sep 17 00:00:00 2001 From: Darksome Date: Fri, 6 Jun 2025 15:53:45 +0000 Subject: [PATCH 44/79] feat: 2.0 cluster machinery --- Cargo.lock | 2250 +++++++++++++++++++++- crates/cluster/Cargo.toml | 46 + crates/cluster/src/client.rs | 36 + crates/cluster/src/keyspace.rs | 198 ++ crates/cluster/src/lib.rs | 684 +++++++ crates/cluster/src/maintenance.rs | 46 + crates/cluster/src/migration.rs | 189 ++ crates/cluster/src/node.rs | 56 + crates/cluster/src/node_operator.rs | 276 +++ crates/cluster/src/node_operators.rs | 167 ++ crates/cluster/src/ownership.rs | 51 + crates/cluster/src/settings.rs | 19 + crates/cluster/src/smart_contract/evm.rs | 618 ++++++ crates/cluster/src/smart_contract/mod.rs | 298 +++ crates/cluster/src/task.rs | 117 ++ crates/cluster/src/view.rs | 350 ++++ crates/cluster/tests/integration.rs | 159 ++ 17 files changed, 5460 insertions(+), 100 deletions(-) create mode 100644 crates/cluster/Cargo.toml create mode 100644 crates/cluster/src/client.rs create mode 100644 crates/cluster/src/keyspace.rs create mode 100644 crates/cluster/src/lib.rs create mode 100644 crates/cluster/src/maintenance.rs create mode 100644 crates/cluster/src/migration.rs create mode 100644 crates/cluster/src/node.rs create mode 100644 crates/cluster/src/node_operator.rs create mode 100644 crates/cluster/src/node_operators.rs create mode 100644 crates/cluster/src/ownership.rs create mode 100644 crates/cluster/src/settings.rs create mode 100644 crates/cluster/src/smart_contract/evm.rs create mode 100644 crates/cluster/src/smart_contract/mod.rs create mode 100644 crates/cluster/src/task.rs create mode 100644 crates/cluster/src/view.rs create mode 100644 crates/cluster/tests/integration.rs diff --git a/Cargo.lock b/Cargo.lock index bd7516db..a2bfc73e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,6 +23,17 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + [[package]] name = "ahash" version = "0.8.11" @@ -70,21 +81,695 @@ dependencies = [ ] [[package]] -name = "alloc_counter_macro" -version = "0.0.2" +name = "alloc_counter_macro" +version = "0.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a52f81f9add01deacdc1fcb05ba09523a8faefdec6c3f69cb752b9fa9c22e5a" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "allocator-api2" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" + +[[package]] +name = "alloy" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0093d23bf026b580c1f66ed3a053d8209c104a446c5264d3ad99587f6edef24e" +dependencies = [ + "alloy-consensus", + "alloy-contract", + "alloy-core", + "alloy-eips", + "alloy-network", + "alloy-node-bindings", + "alloy-provider", + "alloy-pubsub", + "alloy-rpc-client", + "alloy-rpc-types", + "alloy-serde", + "alloy-signer", + "alloy-signer-local", + "alloy-transport", + "alloy-transport-http", + "alloy-transport-ws", +] + +[[package]] +name = "alloy-chains" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6967ca1ed656766e471bc323da42fb0db320ca5e1418b408650e98e4757b3d2" +dependencies = [ + "alloy-primitives", + "num_enum", + "strum", +] + +[[package]] +name = "alloy-consensus" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad451f9a70c341d951bca4e811d74dbe1e193897acd17e9dbac1353698cc430b" +dependencies = [ + "alloy-eips", + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "alloy-trie", + "auto_impl", + "c-kzg", + "derive_more 2.0.1", + "either", + "k256", + "once_cell", + "rand 0.8.5", + "secp256k1", + "serde", + "serde_with", + "thiserror 2.0.12", +] + +[[package]] +name = "alloy-consensus-any" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "142daffb15d5be1a2b20d2cd540edbcef03037b55d4ff69dc06beb4d06286dba" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "serde", +] + +[[package]] +name = "alloy-contract" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebf25443920ecb9728cb087fe4dc04a0b290bd6ac85638c58fe94aba70f1a44e" +dependencies = [ + "alloy-consensus", + "alloy-dyn-abi", + "alloy-json-abi", + "alloy-network", + "alloy-network-primitives", + "alloy-primitives", + "alloy-provider", + "alloy-pubsub", + "alloy-rpc-types-eth", + "alloy-sol-types", + "alloy-transport", + "futures", + "futures-util", + "thiserror 2.0.12", +] + +[[package]] +name = "alloy-core" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5968f48d7a62587cd874bd84034831da4f7f577ce5de984828e376766efc0f32" +dependencies = [ + "alloy-dyn-abi", + "alloy-json-abi", + "alloy-primitives", + "alloy-sol-types", +] + +[[package]] +name = "alloy-dyn-abi" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9135eb501feccf7f4cb8a183afd406a65483fdad7bbd7332d0470e5d725c92f" +dependencies = [ + "alloy-json-abi", + "alloy-primitives", + "alloy-sol-type-parser", + "alloy-sol-types", + "itoa", + "serde", + "serde_json", + "winnow 0.7.10", +] + +[[package]] +name = "alloy-eip2124" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "741bdd7499908b3aa0b159bba11e71c8cddd009a2c2eb7a06e825f1ec87900a5" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "crc", + "serde", + "thiserror 2.0.12", +] + +[[package]] +name = "alloy-eip2930" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b82752a889170df67bbb36d42ca63c531eb16274f0d7299ae2a680facba17bd" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "serde", +] + +[[package]] +name = "alloy-eip7702" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d4769c6ffddca380b0070d71c8b7f30bed375543fe76bb2f74ec0acf4b7cd16" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "serde", + "thiserror 2.0.12", +] + +[[package]] +name = "alloy-eips" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3056872f6da48046913e76edb5ddced272861f6032f09461aea1a2497be5ae5d" +dependencies = [ + "alloy-eip2124", + "alloy-eip2930", + "alloy-eip7702", + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "auto_impl", + "c-kzg", + "derive_more 2.0.1", + "either", + "serde", + "sha2", +] + +[[package]] +name = "alloy-genesis" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c98fb40f07997529235cc474de814cd7bd9de561e101716289095696c0e4639d" +dependencies = [ + "alloy-eips", + "alloy-primitives", + "alloy-serde", + "alloy-trie", + "serde", +] + +[[package]] +name = "alloy-hardforks" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "977d2492ce210e34baf7b36afaacea272c96fbe6774c47e23f97d14033c0e94f" +dependencies = [ + "alloy-chains", + "alloy-eip2124", + "alloy-primitives", + "auto_impl", + "dyn-clone", +] + +[[package]] +name = "alloy-json-abi" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b26fdd571915bafe857fccba4ee1a4f352965800e46a53e4a5f50187b7776fa" +dependencies = [ + "alloy-primitives", + "alloy-sol-type-parser", + "serde", + "serde_json", +] + +[[package]] +name = "alloy-json-rpc" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc08b31ebf9273839bd9a01f9333cbb7a3abb4e820c312ade349dd18bdc79581" +dependencies = [ + "alloy-primitives", + "alloy-sol-types", + "serde", + "serde_json", + "thiserror 2.0.12", + "tracing", +] + +[[package]] +name = "alloy-network" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed117b08f0cc190312bf0c38c34cf4f0dabfb4ea8f330071c587cd7160a88cb2" +dependencies = [ + "alloy-consensus", + "alloy-consensus-any", + "alloy-eips", + "alloy-json-rpc", + "alloy-network-primitives", + "alloy-primitives", + "alloy-rpc-types-any", + "alloy-rpc-types-eth", + "alloy-serde", + "alloy-signer", + "alloy-sol-types", + "async-trait", + "auto_impl", + "derive_more 2.0.1", + "futures-utils-wasm", + "serde", + "serde_json", + "thiserror 2.0.12", +] + +[[package]] +name = "alloy-network-primitives" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7162ff7be8649c0c391f4e248d1273e85c62076703a1f3ec7daf76b283d886d" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-primitives", + "alloy-serde", + "serde", +] + +[[package]] +name = "alloy-node-bindings" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eec6d2e7743d2bcb3e7dfc9cb7a7322bc0f808fddd48f4aab5d974260f2ae0cf" +dependencies = [ + "alloy-genesis", + "alloy-hardforks", + "alloy-network", + "alloy-primitives", + "alloy-signer", + "alloy-signer-local", + "k256", + "rand 0.8.5", + "serde_json", + "tempfile", + "thiserror 2.0.12", + "tracing", + "url", +] + +[[package]] +name = "alloy-primitives" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a326d47106039f38b811057215a92139f46eef7983a4b77b10930a0ea5685b1e" +dependencies = [ + "alloy-rlp", + "bytes", + "cfg-if", + "const-hex", + "derive_more 2.0.1", + "foldhash", + "hashbrown 0.15.3", + "indexmap 2.9.0", + "itoa", + "k256", + "keccak-asm", + "paste", + "proptest", + "rand 0.9.1", + "ruint", + "rustc-hash 2.1.1", + "serde", + "sha3", + "tiny-keccak", +] + +[[package]] +name = "alloy-provider" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d84eba1fd8b6fe8b02f2acd5dd7033d0f179e304bd722d11e817db570d1fa6c4" +dependencies = [ + "alloy-chains", + "alloy-consensus", + "alloy-eips", + "alloy-json-rpc", + "alloy-network", + "alloy-network-primitives", + "alloy-node-bindings", + "alloy-primitives", + "alloy-pubsub", + "alloy-rpc-client", + "alloy-rpc-types-anvil", + "alloy-rpc-types-eth", + "alloy-signer", + "alloy-sol-types", + "alloy-transport", + "alloy-transport-http", + "alloy-transport-ws", + "async-stream", + "async-trait", + "auto_impl", + "dashmap 6.1.0", + "either", + "futures", + "futures-utils-wasm", + "lru 0.13.0", + "parking_lot", + "pin-project", + "reqwest", + "serde", + "serde_json", + "thiserror 2.0.12", + "tokio", + "tracing", + "url", + "wasmtimer", +] + +[[package]] +name = "alloy-pubsub" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8550f7306e0230fc835eb2ff4af0a96362db4b6fc3f25767d161e0ad0ac765bf" +dependencies = [ + "alloy-json-rpc", + "alloy-primitives", + "alloy-transport", + "bimap", + "futures", + "parking_lot", + "serde", + "serde_json", + "tokio", + "tokio-stream", + "tower 0.5.2", + "tracing", + "wasmtimer", +] + +[[package]] +name = "alloy-rlp" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f70d83b765fdc080dbcd4f4db70d8d23fe4761f2f02ebfa9146b833900634b4" +dependencies = [ + "alloy-rlp-derive", + "arrayvec", + "bytes", +] + +[[package]] +name = "alloy-rlp-derive" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64b728d511962dda67c1bc7ea7c03736ec275ed2cf4c35d9585298ac9ccf3b73" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "alloy-rpc-client" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "518a699422a3eab800f3dac2130d8f2edba8e4fff267b27a9c7dc6a2b0d313ee" +dependencies = [ + "alloy-json-rpc", + "alloy-primitives", + "alloy-pubsub", + "alloy-transport", + "alloy-transport-http", + "alloy-transport-ws", + "async-stream", + "futures", + "pin-project", + "reqwest", + "serde", + "serde_json", + "tokio", + "tokio-stream", + "tower 0.5.2", + "tracing", + "tracing-futures", + "url", + "wasmtimer", +] + +[[package]] +name = "alloy-rpc-types" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c000cab4ec26a4b3e29d144e999e1c539c2fa0abed871bf90311eb3466187ca8" +dependencies = [ + "alloy-primitives", + "alloy-rpc-types-anvil", + "alloy-rpc-types-eth", + "alloy-serde", + "serde", +] + +[[package]] +name = "alloy-rpc-types-anvil" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8abecc34549a208b5f91bc7f02df3205c36e2aa6586f1d9375c3382da1066b3b" +dependencies = [ + "alloy-primitives", + "alloy-rpc-types-eth", + "alloy-serde", + "serde", +] + +[[package]] +name = "alloy-rpc-types-any" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "508b2fbe66d952089aa694e53802327798806498cd29ff88c75135770ecaabfc" +dependencies = [ + "alloy-consensus-any", + "alloy-rpc-types-eth", + "alloy-serde", +] + +[[package]] +name = "alloy-rpc-types-eth" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcaf7dff0fdd756a714d58014f4f8354a1706ebf9fa2cf73431e0aeec3c9431e" +dependencies = [ + "alloy-consensus", + "alloy-consensus-any", + "alloy-eips", + "alloy-network-primitives", + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "alloy-sol-types", + "itertools 0.14.0", + "serde", + "serde_json", + "thiserror 2.0.12", +] + +[[package]] +name = "alloy-serde" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "730e8f2edf2fc224cabd1c25d090e1655fa6137b2e409f92e5eec735903f1507" +dependencies = [ + "alloy-primitives", + "serde", + "serde_json", +] + +[[package]] +name = "alloy-signer" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b0d2428445ec13edc711909e023d7779618504c4800be055a5b940025dbafe3" +dependencies = [ + "alloy-primitives", + "async-trait", + "auto_impl", + "either", + "elliptic-curve", + "k256", + "thiserror 2.0.12", +] + +[[package]] +name = "alloy-signer-local" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e14fe6fedb7fe6e0dfae47fe020684f1d8e063274ef14bca387ddb7a6efa8ec1" +dependencies = [ + "alloy-consensus", + "alloy-network", + "alloy-primitives", + "alloy-signer", + "async-trait", + "k256", + "rand 0.8.5", + "thiserror 2.0.12", +] + +[[package]] +name = "alloy-sol-macro" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4be1ce1274ddd7fdfac86e5ece1b225e9bba1f2327e20fbb30ee6b9cc1423fe" +dependencies = [ + "alloy-sol-macro-expander", + "alloy-sol-macro-input", + "proc-macro-error2", + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "alloy-sol-macro-expander" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01e92f3708ea4e0d9139001c86c051c538af0146944a2a9c7181753bd944bf57" +dependencies = [ + "alloy-json-abi", + "alloy-sol-macro-input", + "const-hex", + "heck 0.5.0", + "indexmap 2.9.0", + "proc-macro-error2", + "proc-macro2", + "quote", + "syn 2.0.101", + "syn-solidity", + "tiny-keccak", +] + +[[package]] +name = "alloy-sol-macro-input" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afe1bd348a41f8c9b4b54dfb314886786d6201235b0b3f47198b9d910c86bb2" +dependencies = [ + "alloy-json-abi", + "const-hex", + "dunce", + "heck 0.5.0", + "macro-string", + "proc-macro2", + "quote", + "serde_json", + "syn 2.0.101", + "syn-solidity", +] + +[[package]] +name = "alloy-sol-type-parser" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6195df2acd42df92a380a8db6205a5c7b41282d0ce3f4c665ecf7911ac292f1" +dependencies = [ + "serde", + "winnow 0.7.10", +] + +[[package]] +name = "alloy-sol-types" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6185e98a79cf19010722f48a74b5a65d153631d2f038cabd250f4b9e9813b8ad" +dependencies = [ + "alloy-json-abi", + "alloy-primitives", + "alloy-sol-macro", + "serde", +] + +[[package]] +name = "alloy-transport" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a712bdfeff42401a7dd9518f72f617574c36226a9b5414537fedc34350b73bf9" +dependencies = [ + "alloy-json-rpc", + "alloy-primitives", + "base64 0.22.1", + "derive_more 2.0.1", + "futures", + "futures-utils-wasm", + "parking_lot", + "serde", + "serde_json", + "thiserror 2.0.12", + "tokio", + "tower 0.5.2", + "tracing", + "url", + "wasmtimer", +] + +[[package]] +name = "alloy-transport-http" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ea5a76d7f2572174a382aedf36875bedf60bcc41116c9f031cf08040703a2dc" +dependencies = [ + "alloy-json-rpc", + "alloy-transport", + "reqwest", + "serde_json", + "tower 0.5.2", + "tracing", + "url", +] + +[[package]] +name = "alloy-transport-ws" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a52f81f9add01deacdc1fcb05ba09523a8faefdec6c3f69cb752b9fa9c22e5a" +checksum = "e0c6f9b37cd8d44aab959613966cc9d4d7a9b429c575cec43b3e5b46ea109a79" dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", + "alloy-pubsub", + "alloy-transport", + "futures", + "http 1.1.0", + "rustls", + "serde_json", + "tokio", + "tokio-tungstenite", + "tracing", + "ws_stream_wasm", ] [[package]] -name = "allocator-api2" -version = "0.2.18" +name = "alloy-trie" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" +checksum = "983d99aa81f586cef9dae38443245e585840fcf0fc58b09aee0b1f27aed1d500" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "arrayvec", + "derive_more 2.0.1", + "nybbles", + "serde", + "smallvec", + "tracing", +] [[package]] name = "android-tzdata" @@ -176,12 +861,145 @@ version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" +[[package]] +name = "ark-ff" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b3235cc41ee7a12aaaf2c575a2ad7b46713a8a50bda2fc3b003a04845c05dd6" +dependencies = [ + "ark-ff-asm 0.3.0", + "ark-ff-macros 0.3.0", + "ark-serialize 0.3.0", + "ark-std 0.3.0", + "derivative", + "num-bigint", + "num-traits", + "paste", + "rustc_version 0.3.3", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" +dependencies = [ + "ark-ff-asm 0.4.2", + "ark-ff-macros 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", + "derivative", + "digest 0.10.7", + "itertools 0.10.5", + "num-bigint", + "num-traits", + "paste", + "rustc_version 0.4.0", + "zeroize", +] + +[[package]] +name = "ark-ff-asm" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db02d390bf6643fb404d3d22d31aee1c4bc4459600aef9113833d17e786c6e44" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-asm" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fd794a08ccb318058009eefdf15bcaaaaf6f8161eb3345f907222bac38b20" +dependencies = [ + "num-bigint", + "num-traits", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-serialize" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6c2b318ee6e10f8c2853e73a83adc0ccb88995aa978d8a3408d492ab2ee671" +dependencies = [ + "ark-std 0.3.0", + "digest 0.9.0", +] + +[[package]] +name = "ark-serialize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" +dependencies = [ + "ark-std 0.4.0", + "digest 0.10.7", + "num-bigint", +] + +[[package]] +name = "ark-std" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c" +dependencies = [ + "num-traits", + "rand 0.8.5", +] + +[[package]] +name = "ark-std" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" +dependencies = [ + "num-traits", + "rand 0.8.5", +] + [[package]] name = "arrayref" version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +dependencies = [ + "serde", +] + [[package]] name = "asn1-rs" version = "0.6.2" @@ -266,6 +1084,17 @@ dependencies = [ "syn 2.0.101", ] +[[package]] +name = "async_io_stream" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d7b9decdf35d8908a7e3ef02f64c5e9b1695e230154c0e8de3969142d9b94c" +dependencies = [ + "futures", + "pharos", + "rustc_version 0.4.0", +] + [[package]] name = "asynchronous-codec" version = "0.7.0" @@ -296,6 +1125,17 @@ dependencies = [ "winapi", ] +[[package]] +name = "auto_impl" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffdcb70bdbc4d478427380519163274ac86e52916e10f0a8889adf0f96d3fee7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + [[package]] name = "autocfg" version = "1.2.0" @@ -391,6 +1231,12 @@ version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270" +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + [[package]] name = "base64" version = "0.20.0" @@ -425,6 +1271,12 @@ dependencies = [ "console", ] +[[package]] +name = "bimap" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "230c5f1ca6a325a32553f8640d31ac9b49f2411e901e427570154868b46da4f7" + [[package]] name = "bindgen" version = "0.65.1" @@ -446,6 +1298,37 @@ dependencies = [ "syn 2.0.101", ] +[[package]] +name = "bit-set" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" + +[[package]] +name = "bitcoin-io" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b47c4ab7a93edb0c7198c5535ed9b52b63095f4e9b45279c6736cec4b856baf" + +[[package]] +name = "bitcoin_hashes" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb18c03d0db0247e147a21a6faafd5a7eb851c743db062de72018b6b7e8e4d16" +dependencies = [ + "bitcoin-io", + "hex-conservative", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -461,6 +1344,18 @@ dependencies = [ "serde", ] +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + [[package]] name = "block-buffer" version = "0.10.4" @@ -470,6 +1365,18 @@ dependencies = [ "generic-array", ] +[[package]] +name = "blst" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fd49896f12ac9b6dcd7a5998466b9b58263a695a3dd1ecc1aaca2e12a90b080" +dependencies = [ + "cc", + "glob", + "threadpool", + "zeroize", +] + [[package]] name = "bs58" version = "0.5.1" @@ -505,6 +1412,12 @@ version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" +[[package]] +name = "byte-slice-cast" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7575182f7272186991736b70173b0ea045398f984bf5ebbb3804736ce1330c9d" + [[package]] name = "byte-unit" version = "4.0.19" @@ -529,9 +1442,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.6.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" dependencies = [ "serde", ] @@ -547,6 +1460,21 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "c-kzg" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7318cfa722931cb5fe0838b98d3ce5621e75f6a6408abc21721d80de9223f2e4" +dependencies = [ + "blst", + "cc", + "glob", + "hex", + "libc", + "once_cell", + "serde", +] + [[package]] name = "camino" version = "1.1.6" @@ -573,7 +1501,7 @@ checksum = "4acbb09d9ee8e23699b9634375c72795d095bf268439da88562cf9b501f181fa" dependencies = [ "camino", "cargo-platform", - "semver", + "semver 1.0.22", "serde", "serde_json", ] @@ -586,7 +1514,7 @@ checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" dependencies = [ "camino", "cargo-platform", - "semver", + "semver 1.0.22", "serde", "serde_json", "thiserror 1.0.64", @@ -604,14 +1532,24 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" +[[package]] +name = "cbc" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6" +dependencies = [ + "cipher", +] + [[package]] name = "cc" -version = "1.0.90" +version = "1.2.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" +checksum = "956a5e21988b87f372569b66183b78babf23ebc2e744b733e4350a752c4dafac" dependencies = [ "jobserver", "libc", + "shlex", ] [[package]] @@ -683,6 +1621,16 @@ dependencies = [ "half", ] +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + [[package]] name = "clang-sys" version = "1.7.0" @@ -724,7 +1672,7 @@ dependencies = [ "anstream", "anstyle", "clap_lex", - "strsim 0.11.0", + "strsim 0.11.1", ] [[package]] @@ -751,6 +1699,34 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8191fa7302e03607ff0e237d4246cc043ff5b3cb9409d995172ba3bea16b807" +[[package]] +name = "cluster" +version = "0.1.0" +dependencies = [ + "aes", + "alloy", + "anyhow", + "arc-swap", + "backoff", + "derivative", + "derive_more 1.0.0", + "fpe", + "futures", + "hex", + "itertools 0.12.1", + "libp2p", + "postcard", + "serde", + "sharding", + "tap", + "thiserror 1.0.64", + "tokio", + "tokio-stream", + "tracing", + "tracing-subscriber", + "xxhash-rust", +] + [[package]] name = "cobs" version = "0.2.3" @@ -812,6 +1788,19 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "const-hex" +version = "1.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83e22e0ed40b96a48d3db274f72fd365bd78f67af39b6bbd47e8a15e1c6207ff" +dependencies = [ + "cfg-if", + "cpufeatures", + "hex", + "proptest", + "serde", +] + [[package]] name = "const-oid" version = "0.9.6" @@ -855,17 +1844,32 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" dependencies = [ - "memchr", + "memchr", +] + +[[package]] +name = "cpufeatures" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +dependencies = [ + "libc", +] + +[[package]] +name = "crc" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9710d3b3739c2e349eb44fe848ad0b7c8cb1e42bd87ee49371df2f7acaf3e675" +dependencies = [ + "crc-catalog", ] [[package]] -name = "cpufeatures" -version = "0.2.12" +name = "crc-catalog" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" -dependencies = [ - "libc", -] +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" [[package]] name = "crc32fast" @@ -977,6 +1981,18 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + [[package]] name = "crypto-common" version = "0.1.6" @@ -996,10 +2012,10 @@ dependencies = [ "cfg-if", "cpufeatures", "curve25519-dalek-derive", - "digest", + "digest 0.10.7", "fiat-crypto", "platforms", - "rustc_version", + "rustc_version 0.4.0", "subtle", "zeroize", ] @@ -1021,8 +2037,18 @@ version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" dependencies = [ - "darling_core", - "darling_macro", + "darling_core 0.14.4", + "darling_macro 0.14.4", +] + +[[package]] +name = "darling" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" +dependencies = [ + "darling_core 0.20.11", + "darling_macro 0.20.11", ] [[package]] @@ -1039,17 +2065,42 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "darling_core" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.11.1", + "syn 2.0.101", +] + [[package]] name = "darling_macro" version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" dependencies = [ - "darling_core", + "darling_core 0.14.4", "quote", "syn 1.0.109", ] +[[package]] +name = "darling_macro" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" +dependencies = [ + "darling_core 0.20.11", + "quote", + "syn 2.0.101", +] + [[package]] name = "dashmap" version = "5.5.3" @@ -1057,7 +2108,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ "cfg-if", - "hashbrown", + "hashbrown 0.14.3", + "lock_api", + "once_cell", + "parking_lot_core", +] + +[[package]] +name = "dashmap" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" +dependencies = [ + "cfg-if", + "crossbeam-utils", + "hashbrown 0.14.3", "lock_api", "once_cell", "parking_lot_core", @@ -1149,7 +2214,7 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4ec317cc3e7ef0928b0ca6e4a634a4d6c001672ae210438cf114a83e56b018d" dependencies = [ - "darling", + "darling 0.14.4", "proc-macro2", "quote", "syn 1.0.109", @@ -1174,7 +2239,7 @@ dependencies = [ "convert_case 0.4.0", "proc-macro2", "quote", - "rustc_version", + "rustc_version 0.4.0", "syn 1.0.109", ] @@ -1184,7 +2249,16 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" dependencies = [ - "derive_more-impl", + "derive_more-impl 1.0.0", +] + +[[package]] +name = "derive_more" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678" +dependencies = [ + "derive_more-impl 2.0.1", ] [[package]] @@ -1199,6 +2273,18 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "derive_more-impl" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", + "unicode-xid", +] + [[package]] name = "dhat" version = "0.3.2" @@ -1224,6 +2310,15 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + [[package]] name = "digest" version = "0.10.7" @@ -1231,6 +2326,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", + "const-oid", "crypto-common", "subtle", ] @@ -1258,6 +2354,27 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" +[[package]] +name = "dyn-clone" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c7a8fb8a9fbf66c1f703fe16184d10ca0ee9d23be5b4436400408ba54a95005" + +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest 0.10.7", + "elliptic-curve", + "rfc6979", + "serdect", + "signature", + "spki", +] + [[package]] name = "ed25519" version = "2.2.3" @@ -1297,9 +2414,32 @@ dependencies = [ [[package]] name = "either" -version = "1.13.0" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +dependencies = [ + "serde", +] + +[[package]] +name = "elliptic-curve" +version = "0.13.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest 0.10.7", + "ff", + "generic-array", + "group", + "pkcs8", + "rand_core 0.6.4", + "sec1", + "serdect", + "subtle", + "zeroize", +] [[package]] name = "embedded-io" @@ -1382,9 +2522,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.8" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18" dependencies = [ "libc", "windows-sys 0.52.0", @@ -1438,9 +2578,41 @@ checksum = "a2a2b11eda1d40935b26cf18f6833c526845ae8c41e58d09af6adeb6f0269183" [[package]] name = "fastrand" -version = "2.0.2" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "fastrlp" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139834ddba373bbdd213dffe02c8d110508dcf1726c2be27e8d1f7d7e1856418" +dependencies = [ + "arrayvec", + "auto_impl", + "bytes", +] + +[[package]] +name = "fastrlp" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce8dba4714ef14b8274c371879b175aa55b16b30f269663f19d576f380018dc4" +dependencies = [ + "arrayvec", + "auto_impl", + "bytes", +] + +[[package]] +name = "ff" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" +checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] [[package]] name = "fiat-crypto" @@ -1460,6 +2632,18 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "fixed-hash" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" +dependencies = [ + "byteorder", + "rand 0.8.5", + "rustc-hex", + "static_assertions", +] + [[package]] name = "flate2" version = "1.0.33" @@ -1476,6 +2660,12 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + [[package]] name = "foreign-types" version = "0.3.2" @@ -1509,6 +2699,26 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fpe" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26c4b37de5ae15812a764c958297cfc50f5c010438f60c6ce75d11b802abd404" +dependencies = [ + "cbc", + "cipher", + "libm", + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + [[package]] name = "future" version = "0.1.0" @@ -1637,6 +2847,12 @@ dependencies = [ "slab", ] +[[package]] +name = "futures-utils-wasm" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42012b0f064e01aa58b545fe3727f90f7dd4020f4a3ea735b50344965f5a57e9" + [[package]] name = "generic-array" version = "0.14.7" @@ -1645,6 +2861,7 @@ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", + "zeroize", ] [[package]] @@ -1669,6 +2886,18 @@ dependencies = [ "wasi 0.11.0+wasi-snapshot-preview1", ] +[[package]] +name = "getrandom" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", +] + [[package]] name = "gimli" version = "0.28.1" @@ -1893,7 +3122,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ddf80e16f3c19ac06ce415a38b8591993d3f73aede049cb561becb5b3a8e242" dependencies = [ "gix-hash", - "hashbrown", + "hashbrown 0.14.3", "parking_lot", ] @@ -1917,7 +3146,7 @@ dependencies = [ "itoa", "libc", "memmap2", - "rustix", + "rustix 0.38.32", "smallvec", "thiserror 1.0.64", ] @@ -2199,6 +3428,17 @@ dependencies = [ "spinning_top", ] +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core 0.6.4", + "subtle", +] + [[package]] name = "h2" version = "0.3.26" @@ -2211,7 +3451,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap", + "indexmap 2.9.0", "slab", "tokio", "tokio-util", @@ -2230,7 +3470,7 @@ dependencies = [ "futures-core", "futures-sink", "http 1.1.0", - "indexmap", + "indexmap 2.9.0", "slab", "tokio", "tokio-util", @@ -2247,6 +3487,12 @@ dependencies = [ "crunchy", ] +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + [[package]] name = "hashbrown" version = "0.14.3" @@ -2257,13 +3503,25 @@ dependencies = [ "allocator-api2", ] +[[package]] +name = "hashbrown" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash", + "serde", +] + [[package]] name = "hashlink" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af" dependencies = [ - "hashbrown", + "hashbrown 0.14.3", ] [[package]] @@ -2301,6 +3559,18 @@ name = "hex" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +dependencies = [ + "serde", +] + +[[package]] +name = "hex-conservative" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5313b072ce3c597065a808dbf612c4c8e8590bdbf8b579508bf7a762c5eae6cd" +dependencies = [ + "arrayvec", +] [[package]] name = "hex_fmt" @@ -2323,7 +3593,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest", + "digest 0.10.7", ] [[package]] @@ -2539,6 +3809,26 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "impl-codec" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" +dependencies = [ + "parity-scale-codec", +] + +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "indenter" version = "0.3.3" @@ -2547,12 +3837,24 @@ checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" [[package]] name = "indexmap" -version = "2.2.6" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "indexmap" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.15.3", + "serde", ] [[package]] @@ -2575,6 +3877,15 @@ dependencies = [ "libc", ] +[[package]] +name = "inout" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" +dependencies = [ + "generic-array", +] + [[package]] name = "instant" version = "0.1.12" @@ -2634,6 +3945,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.11" @@ -2655,27 +3975,61 @@ dependencies = [ ] [[package]] -name = "jni-sys" -version = "0.3.0" +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + +[[package]] +name = "jobserver" +version = "0.1.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" +dependencies = [ + "getrandom 0.3.3", + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "k256" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" +checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "once_cell", + "serdect", + "sha2", +] [[package]] -name = "jobserver" -version = "0.1.28" +name = "keccak" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab46a6e9526ddef3ae7f787c06f0f2600639ba80ea3eade3d8e670a2230f51d6" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" dependencies = [ - "libc", + "cpufeatures", ] [[package]] -name = "js-sys" -version = "0.3.69" +name = "keccak-asm" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +checksum = "505d1856a39b200489082f90d897c3f07c455563880bc5952e38eabf731c83b6" dependencies = [ - "wasm-bindgen", + "digest 0.10.7", + "sha3-asm", ] [[package]] @@ -2726,6 +4080,12 @@ dependencies = [ "windows-targets 0.52.4", ] +[[package]] +name = "libm" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" + [[package]] name = "libp2p" version = "0.55.0" @@ -2901,7 +4261,7 @@ dependencies = [ "smallvec", "thiserror 2.0.12", "tracing", - "uint", + "uint 0.10.0", "web-time", ] @@ -2917,7 +4277,7 @@ dependencies = [ "futures-timer", "libp2p-core 0.43.0", "libp2p-identity", - "lru", + "lru 0.12.3", "multistream-select", "once_cell", "rand 0.8.5", @@ -2989,6 +4349,12 @@ version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +[[package]] +name = "linux-raw-sys" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" + [[package]] name = "lock_api" version = "0.4.11" @@ -3011,7 +4377,16 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" dependencies = [ - "hashbrown", + "hashbrown 0.14.3", +] + +[[package]] +name = "lru" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "227748d55f2f0ab4735d87fd623798cb6b664512fe979705f829c9f81c934465" +dependencies = [ + "hashbrown 0.15.3", ] [[package]] @@ -3024,6 +4399,17 @@ dependencies = [ "libc", ] +[[package]] +name = "macro-string" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b27834086c65ec3f9387b096d66e99f221cf081c2b738042aa252bcd41204e3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + [[package]] name = "macros" version = "0.9.0" @@ -3095,7 +4481,7 @@ dependencies = [ "hyper 1.3.1", "hyper-tls", "hyper-util", - "indexmap", + "indexmap 2.9.0", "ipnet", "metrics", "metrics-util", @@ -3113,7 +4499,7 @@ checksum = "4259040465c955f9f2f1a4a8a16dc46726169bca0f88e8fb2dbeced487c3e828" dependencies = [ "crossbeam-epoch", "crossbeam-utils", - "hashbrown", + "hashbrown 0.14.3", "metrics", "num_cpus", "quanta", @@ -3134,7 +4520,7 @@ checksum = "c325dfab65f261f386debee8b0969da215b3fa0037e74c8a1234db7ba986d803" dependencies = [ "crossbeam-channel", "crossbeam-utils", - "dashmap", + "dashmap 5.5.3", "skeptic", "smallvec", "tagptr", @@ -3371,6 +4757,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" dependencies = [ "autocfg", + "libm", ] [[package]] @@ -3383,6 +4770,26 @@ dependencies = [ "libc", ] +[[package]] +name = "num_enum" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + [[package]] name = "num_threads" version = "0.1.7" @@ -3392,6 +4799,19 @@ dependencies = [ "libc", ] +[[package]] +name = "nybbles" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8983bb634df7248924ee0c4c3a749609b5abcb082c28fffe3254b3eb3602b307" +dependencies = [ + "alloy-rlp", + "const-hex", + "proptest", + "serde", + "smallvec", +] + [[package]] name = "object" version = "0.32.2" @@ -3412,9 +4832,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.19.0" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "oorandom" @@ -3494,6 +4914,32 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" +[[package]] +name = "parity-scale-codec" +version = "3.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" +dependencies = [ + "arrayvec", + "bitvec", + "byte-slice-cast", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "serde", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "parking" version = "2.2.1" @@ -3566,6 +5012,27 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +[[package]] +name = "pest" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "198db74531d58c70a361c42201efde7e2591e976d518caf7662a47dc5720e7b6" +dependencies = [ + "memchr", + "thiserror 2.0.12", + "ucd-trie", +] + +[[package]] +name = "pharos" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9567389417feee6ce15dd6527a8a1ecac205ef62c2932bcf3d9f6fc5b78b414" +dependencies = [ + "futures", + "rustc_version 0.4.0", +] + [[package]] name = "phi-accrual-failure-detector" version = "0.1.0" @@ -3706,6 +5173,26 @@ dependencies = [ "syn 2.0.101", ] +[[package]] +name = "primitive-types" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" +dependencies = [ + "fixed-hash", + "impl-codec", + "uint 0.9.5", +] + +[[package]] +name = "proc-macro-crate" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" +dependencies = [ + "toml_edit", +] + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -3730,6 +5217,28 @@ dependencies = [ "version_check", ] +[[package]] +name = "proc-macro-error-attr2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "proc-macro-error2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" +dependencies = [ + "proc-macro-error-attr2", + "proc-macro2", + "quote", + "syn 2.0.101", +] + [[package]] name = "proc-macro2" version = "1.0.95" @@ -3777,6 +5286,26 @@ dependencies = [ "syn 2.0.101", ] +[[package]] +name = "proptest" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14cae93065090804185d3b75f0bf93b8eeda30c7a9b4a33d3bdb3988d6229e50" +dependencies = [ + "bit-set", + "bit-vec", + "bitflags 2.6.0", + "lazy_static", + "num-traits", + "rand 0.8.5", + "rand_chacha 0.3.1", + "rand_xorshift", + "regex-syntax 0.8.5", + "rusty-fork", + "tempfile", + "unarray", +] + [[package]] name = "pulldown-cmark" version = "0.9.6" @@ -3822,6 +5351,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + [[package]] name = "quick-protobuf" version = "0.8.1" @@ -3854,7 +5389,7 @@ dependencies = [ "pin-project-lite", "quinn-proto", "quinn-udp", - "rustc-hash 2.0.0", + "rustc-hash 2.1.1", "rustls", "socket2", "thiserror 1.0.64", @@ -3871,7 +5406,7 @@ dependencies = [ "bytes", "rand 0.8.5", "ring 0.17.8", - "rustc-hash 2.0.0", + "rustc-hash 2.1.1", "rustls", "rustls-platform-verifier", "slab", @@ -3902,6 +5437,18 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + [[package]] name = "raft" version = "0.1.0" @@ -3942,6 +5489,18 @@ dependencies = [ "libc", "rand_chacha 0.3.1", "rand_core 0.6.4", + "serde", +] + +[[package]] +name = "rand" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.3", + "serde", ] [[package]] @@ -3964,6 +5523,16 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.3", +] + [[package]] name = "rand_core" version = "0.5.1" @@ -3982,6 +5551,16 @@ dependencies = [ "getrandom 0.2.15", ] +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom 0.3.3", + "serde", +] + [[package]] name = "rand_hc" version = "0.2.0" @@ -3991,6 +5570,15 @@ dependencies = [ "rand_core 0.5.1", ] +[[package]] +name = "rand_xorshift" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" +dependencies = [ + "rand_core 0.6.4", +] + [[package]] name = "raw-cpuid" version = "11.0.2" @@ -4139,19 +5727,23 @@ dependencies = [ "http-body 1.0.0", "http-body-util", "hyper 1.3.1", + "hyper-tls", "hyper-util", "ipnet", "js-sys", "log", "mime", + "native-tls", "once_cell", "percent-encoding", "pin-project-lite", + "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", "sync_wrapper 0.1.2", "tokio", + "tokio-native-tls", "tower-service", "url", "wasm-bindgen", @@ -4160,6 +5752,16 @@ dependencies = [ "winreg", ] +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + [[package]] name = "ring" version = "0.16.20" @@ -4190,6 +5792,16 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rlp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" +dependencies = [ + "bytes", + "rustc-hex", +] + [[package]] name = "rmp" version = "0.8.14" @@ -4231,7 +5843,7 @@ dependencies = [ "futures", "futures-timer", "rstest_macros", - "rustc_version", + "rustc_version 0.4.0", ] [[package]] @@ -4246,11 +5858,44 @@ dependencies = [ "quote", "regex", "relative-path", - "rustc_version", + "rustc_version 0.4.0", "syn 2.0.101", "unicode-ident", ] +[[package]] +name = "ruint" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11256b5fe8c68f56ac6f39ef0720e592f33d2367a4782740d9c9142e889c7fb4" +dependencies = [ + "alloy-rlp", + "ark-ff 0.3.0", + "ark-ff 0.4.2", + "bytes", + "fastrlp 0.3.1", + "fastrlp 0.4.0", + "num-bigint", + "num-integer", + "num-traits", + "parity-scale-codec", + "primitive-types", + "proptest", + "rand 0.8.5", + "rand 0.9.1", + "rlp", + "ruint-macro", + "serde", + "valuable", + "zeroize", +] + +[[package]] +name = "ruint-macro" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48fd7bd8a6377e15ad9d42a8ec25371b94ddc67abe7c8b9127bec79bebaaae18" + [[package]] name = "rustc-demangle" version = "0.1.23" @@ -4265,9 +5910,24 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc-hash" -version = "2.0.0" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" + +[[package]] +name = "rustc-hex" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" + +[[package]] +name = "rustc_version" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" +checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" +dependencies = [ + "semver 0.11.0", +] [[package]] name = "rustc_version" @@ -4275,7 +5935,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver", + "semver 1.0.22", ] [[package]] @@ -4296,20 +5956,33 @@ dependencies = [ "bitflags 2.6.0", "errno", "libc", - "linux-raw-sys", + "linux-raw-sys 0.4.13", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustix" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" +dependencies = [ + "bitflags 2.6.0", + "errno", + "libc", + "linux-raw-sys 0.9.4", "windows-sys 0.52.0", ] [[package]] name = "rustls" -version = "0.23.16" +version = "0.23.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eee87ff5d9b36712a58574e12e9f0ea80f915a5b0ac518d322b24a465617925e" +checksum = "730944ca083c1c233a75c09f199e973ca499344a2b7ba9e755c457e86fb4a321" dependencies = [ "once_cell", "ring 0.17.8", "rustls-pki-types", - "rustls-webpki 0.102.8", + "rustls-webpki 0.103.3", "subtle", "zeroize", ] @@ -4339,9 +6012,12 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.10.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" +checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +dependencies = [ + "zeroize", +] [[package]] name = "rustls-platform-verifier" @@ -4385,6 +6061,16 @@ name = "rustls-webpki" version = "0.102.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" +dependencies = [ + "rustls-pki-types", + "untrusted 0.9.0", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4a72fe2bcf7a6ac6fd7d0b9e5cb68aeb7d4c0a0271730218b3e92d43b4eb435" dependencies = [ "ring 0.17.8", "rustls-pki-types", @@ -4397,6 +6083,18 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" +[[package]] +name = "rusty-fork" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" +dependencies = [ + "fnv", + "quick-error", + "tempfile", + "wait-timeout", +] + [[package]] name = "rw-stream-sink" version = "0.4.0" @@ -4438,6 +6136,42 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "serdect", + "subtle", + "zeroize", +] + +[[package]] +name = "secp256k1" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b50c5943d326858130af85e049f2661ba3c78b26589b8ab98e65e80ae44a1252" +dependencies = [ + "bitcoin_hashes", + "rand 0.8.5", + "secp256k1-sys", + "serde", +] + +[[package]] +name = "secp256k1-sys" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4387882333d3aa8cb20530a17c69a3752e97837832f34f6dccc760e715001d9" +dependencies = [ + "cc", +] + [[package]] name = "security-framework" version = "2.11.1" @@ -4462,6 +6196,15 @@ dependencies = [ "libc", ] +[[package]] +name = "semver" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" +dependencies = [ + "semver-parser", +] + [[package]] name = "semver" version = "1.0.22" @@ -4471,6 +6214,21 @@ dependencies = [ "serde", ] +[[package]] +name = "semver-parser" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9900206b54a3527fdc7b8a938bffd94a568bac4f4aa8113b209df75a09c0dec2" +dependencies = [ + "pest", +] + +[[package]] +name = "send_wrapper" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" + [[package]] name = "serde" version = "1.0.202" @@ -4524,9 +6282,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.6" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" dependencies = [ "serde", ] @@ -4543,6 +6301,57 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_with" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6b6f7f2fcb69f747921f79f3926bd1e203fce4fef62c268dd3abfb6d86029aa" +dependencies = [ + "base64 0.22.1", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.9.0", + "serde", + "serde_derive", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d00caa5193a3c8362ac2b73be6b9e768aa5a4b2f721d8f4b339600c3cb51f8e" +dependencies = [ + "darling 0.20.11", + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "serdect" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a84f14a19e9a014bb9f4512488d9829a68e04ecabffb0f9904cd1ace94598177" +dependencies = [ + "base16ct", + "serde", +] + +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + [[package]] name = "sha1_smol" version = "1.0.0" @@ -4557,7 +6366,27 @@ checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", - "digest", + "digest 0.10.7", +] + +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest 0.10.7", + "keccak", +] + +[[package]] +name = "sha3-asm" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28efc5e327c837aa837c59eae585fc250715ef939ac32881bcc11677cd02d46" +dependencies = [ + "cc", + "cfg-if", ] [[package]] @@ -4573,7 +6402,7 @@ dependencies = [ name = "sharding" version = "0.1.0" dependencies = [ - "indexmap", + "indexmap 2.9.0", "rand 0.8.5", "thiserror 1.0.64", ] @@ -4620,6 +6449,7 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ + "digest 0.10.7", "rand_core 0.6.4", ] @@ -4723,9 +6553,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "strsim" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "structopt" @@ -4751,6 +6581,28 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "strum" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f64def088c51c9510a8579e3c5d67c65349dcf755e5479ad3d010aa6454e2c32" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c77a8c5abcaf0f9ce05d62342b7d298c346515365c36b673df4ebe3ced01fde8" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.101", +] + [[package]] name = "subtle" version = "2.5.0" @@ -4779,6 +6631,18 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn-solidity" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c8c8f496c33dc6343dac05b4be8d9e0bca180a4caa81d7b8416b10cc2273cd" +dependencies = [ + "paste", + "proc-macro2", + "quote", + "syn 2.0.101", +] + [[package]] name = "sync_wrapper" version = "0.1.2" @@ -4831,13 +6695,14 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.10.1" +version = "3.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" dependencies = [ - "cfg-if", "fastrand", - "rustix", + "getrandom 0.3.3", + "once_cell", + "rustix 1.0.7", "windows-sys 0.52.0", ] @@ -4957,6 +6822,15 @@ dependencies = [ "once_cell", ] +[[package]] +name = "threadpool" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +dependencies = [ + "num_cpus", +] + [[package]] name = "tikv-jemalloc-ctl" version = "0.5.4" @@ -5021,6 +6895,15 @@ dependencies = [ "time-core", ] +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + [[package]] name = "tinytemplate" version = "1.2.1" @@ -5085,6 +6968,16 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-rustls" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" +dependencies = [ + "rustls", + "tokio", +] + [[package]] name = "tokio-serde" version = "0.9.0" @@ -5122,6 +7015,22 @@ dependencies = [ "tokio-util", ] +[[package]] +name = "tokio-tungstenite" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a9daff607c6d2bf6c16fd681ccb7eecc83e4e2cdc1ca067ffaadfca5de7f084" +dependencies = [ + "futures-util", + "log", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tungstenite", + "webpki-roots", +] + [[package]] name = "tokio-util" version = "0.7.10" @@ -5151,26 +7060,33 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.6" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.22.13" +version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c127785850e8c20836d49732ae6abfa47616e60bf9d9f57c43c250361a9db96c" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ - "indexmap", + "indexmap 2.9.0", "serde", "serde_spanned", "toml_datetime", - "winnow 0.6.8", + "toml_write", + "winnow 0.7.10", ] +[[package]] +name = "toml_write" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" + [[package]] name = "tower" version = "0.4.13" @@ -5266,6 +7182,8 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" dependencies = [ + "futures", + "futures-task", "pin-project", "tracing", ] @@ -5338,12 +7256,49 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "tungstenite" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4793cb5e56680ecbb1d843515b23b6de9a75eb04b66643e256a396d43be33c13" +dependencies = [ + "bytes", + "data-encoding", + "http 1.1.0", + "httparse", + "log", + "rand 0.9.1", + "rustls", + "rustls-pki-types", + "sha1", + "thiserror 2.0.12", + "utf-8", +] + [[package]] name = "typenum" version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +[[package]] +name = "ucd-trie" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" + +[[package]] +name = "uint" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + [[package]] name = "uint" version = "0.10.0" @@ -5356,6 +7311,12 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + [[package]] name = "unicase" version = "2.8.1" @@ -5442,6 +7403,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + [[package]] name = "utf8-width" version = "0.1.7" @@ -5486,7 +7453,7 @@ dependencies = [ "cfg-if", "gix", "regex", - "rustc_version", + "rustc_version 0.4.0", "rustversion", "time", ] @@ -5516,6 +7483,15 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" +[[package]] +name = "wait-timeout" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11" +dependencies = [ + "libc", +] + [[package]] name = "walkdir" version = "2.5.0" @@ -5547,6 +7523,15 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + [[package]] name = "wasm-bindgen" version = "0.2.92" @@ -5613,6 +7598,20 @@ version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +[[package]] +name = "wasmtimer" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0048ad49a55b9deb3953841fa1fc5858f0efbcb7a18868c899a360269fac1b23" +dependencies = [ + "futures", + "js-sys", + "parking_lot", + "pin-utils", + "slab", + "wasm-bindgen", +] + [[package]] name = "wc" version = "0.1.0" @@ -5735,7 +7734,7 @@ dependencies = [ "bytes", "chrono", "criterion", - "dashmap", + "dashmap 5.5.3", "derivative", "derive_more 1.0.0", "difference", @@ -5939,7 +7938,7 @@ dependencies = [ "derive_more 1.0.0", "futures", "governor", - "indexmap", + "indexmap 2.9.0", "libp2p", "libp2p-tls", "metrics", @@ -6257,9 +8256,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.6.8" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3c52e9c97a68071b23e836c9380edae937f17b9c4667bd021973efc689f618d" +checksum = "c06928c8748d81b05c9be96aad92e1b6ff01833332f281e8cfca3be4b35fc9ec" dependencies = [ "memchr", ] @@ -6274,6 +8273,43 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags 2.6.0", +] + +[[package]] +name = "ws_stream_wasm" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7999f5f4217fe3818726b66257a4475f71e74ffd190776ad053fa159e50737f5" +dependencies = [ + "async_io_stream", + "futures", + "js-sys", + "log", + "pharos", + "rustc_version 0.4.0", + "send_wrapper", + "thiserror 1.0.64", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + [[package]] name = "x509-parser" version = "0.16.0" @@ -6331,3 +8367,17 @@ name = "zeroize" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] diff --git a/crates/cluster/Cargo.toml b/crates/cluster/Cargo.toml new file mode 100644 index 00000000..9622013a --- /dev/null +++ b/crates/cluster/Cargo.toml @@ -0,0 +1,46 @@ +[package] +name = "cluster" +version = "0.1.0" +edition = "2021" + +[lints] +workspace = true + +[dependencies] +derive_more = { workspace = true, features = ["try_from", "into"] } +derivative = { workspace = true } +libp2p = { workspace = true } +itertools = { workspace = true } +futures = { workspace = true } +backoff = { workspace = true } +tracing = { workspace = true } +tokio-stream = { workspace = true } + +sharding = { path = "../sharding" } + +alloy = { version = "1.0", default-features = false, features = ["sol-types", "contract", "signer-local", "network", "reqwest", "provider-ws", "rpc-types"] } + +anyhow = "1" +thiserror = "1" + +tap = "1.0" +serde = { version = "1", features = ["derive"] } +postcard = { version = "1.0", default-features = false, features = ["alloc"] } + +xxhash-rust = { version = "0.8", features = ["xxh3", "const_xxh3"] } +fpe = "0.6" +aes = "0.8" + +tokio = { version = "1", features = ["full"] } +arc-swap = "1.7" + +[dev-dependencies] +alloy = { version = "1.0", default-features = false, features = ["provider-anvil-node"] } +tokio = { version = "1", default-features = false } +hex = "0.4" + +tracing-subscriber = { version = "0.3", features = [ + "env-filter", + "parking_lot", + "json", +] } diff --git a/crates/cluster/src/client.rs b/crates/cluster/src/client.rs new file mode 100644 index 00000000..200939a7 --- /dev/null +++ b/crates/cluster/src/client.rs @@ -0,0 +1,36 @@ +//! Client of a WCN cluster. + +use { + libp2p::identity::PeerId, + serde::{Deserialize, Serialize}, +}; + +/// Client of a WCN cluster. +#[derive(Debug, Clone)] +pub struct Client { + /// [`PeerId`] of the [`Client`]. Used for authentication. + pub peer_id: PeerId, +} + +// NOTE: The on-chain serialization is non self-describing! Every change to +// the schema should be handled by creating a new version. +#[derive(Clone, Copy, Debug, Serialize, Deserialize)] +pub(crate) struct V0 { + pub peer_id: PeerId, +} + +impl From for V0 { + fn from(client: Client) -> Self { + Self { + peer_id: client.peer_id, + } + } +} + +impl From for Client { + fn from(client: V0) -> Self { + Self { + peer_id: client.peer_id, + } + } +} diff --git a/crates/cluster/src/keyspace.rs b/crates/cluster/src/keyspace.rs new file mode 100644 index 00000000..3b041563 --- /dev/null +++ b/crates/cluster/src/keyspace.rs @@ -0,0 +1,198 @@ +use { + crate::node_operator::{self}, + derivative::Derivative, + derive_more::TryFrom, + sharding::ShardId, + std::collections::HashSet, + xxhash_rust::xxh3::Xxh3Builder, +}; + +/// Maximum number of [`node_operator`]s within a [`Keyspace`]. +pub const MAX_OPERATORS: usize = 256; + +/// Number of [`node_operator`]s within a [`ReplicaSet`]. +pub const REPLICATION_FACTOR: usize = 5; + +/// Continuous space of `u64` keys. +/// +/// [`Keyspace`] is being split into a set of equally sized [`Shards`], +/// and each [`Shard`] is being assigned to a set of [`node_operator`]s. +#[derive(Clone, Derivative)] +#[derivative(Debug)] +pub struct Keyspace { + operators: HashSet, + + #[derivative(Debug = "ignore")] + shards: S, + + replication_strategy: ReplicationStrategy, + + version: u64, +} + +/// All [`Shard`]s within a [`Keyspace`]. +pub struct Shards(sharding::Keyspace); + +/// A single [`Shard`] within a [`Keyspace`]. +#[derive(Clone, Copy, Debug)] +pub struct Shard { + replica_set: [node_operator::Idx; REPLICATION_FACTOR], +} + +/// Strategy of distributing [`Shard`]s to [`node_operator`]s. +#[repr(u8)] +#[derive(Clone, Copy, Debug, Default, TryFrom, Eq, PartialEq)] +#[try_from(repr)] +pub enum ReplicationStrategy { + /// [`Shard`]s are being uniformly distributed across [`node_operator`]s. + #[default] + UniformDistribution = 0, +} + +/// Set of [`node_operator`]s assigned to a [`Shard`]. +pub type ReplicaSet = [T; REPLICATION_FACTOR]; + +/// [`Keyspace`] version. +pub type Version = u64; + +impl Keyspace { + /// Creates a new [`Keyspace`]. + pub fn new( + operators: HashSet, + replication_strategy: ReplicationStrategy, + version: u64, + ) -> Result { + if operators.len() < REPLICATION_FACTOR { + return Err(CreationError::TooFewOperators(operators.len())); + } + + if operators.len() > MAX_OPERATORS { + return Err(CreationError::TooManyOperators(operators.len())); + } + + Ok(Keyspace { + operators, + shards: (), + replication_strategy, + version, + }) + } + + pub(crate) async fn calculate(self) -> Keyspace + where + Self: sealed::Calculate, + { + sealed::Calculate::::calculate_shards(self).await + } +} + +impl Keyspace { + /// Returns the [`Shard`] that contains the specified key. + pub fn shard(&self, key: u64) -> Shard { + Shard { + replica_set: *self.shards.0.shard_replicas(ShardId::from_key(key)), + } + } +} + +impl Keyspace { + /// Returns an [`Iterator`] over [`node_operator`]s of this [`Keyspace`]. + pub fn operators(&self) -> impl Iterator + '_ { + self.operators.iter().copied() + } + + /// Returns [`ReplicationStrategy`] of this [`Keyspace`]. + pub fn replication_strategy(&self) -> ReplicationStrategy { + self.replication_strategy + } + + /// Returns [`Version`] of this [`Keyspace`]. + pub fn version(&self) -> Version { + self.version + } + + pub(super) fn contains_operator(&self, idx: node_operator::Idx) -> bool { + self.operators.contains(&idx) + } + + pub(super) fn require_diff(&self, other: &Keyspace) -> Result<(), SameKeyspaceError> { + if self.operators == other.operators + && self.replication_strategy == other.replication_strategy + { + return Err(SameKeyspaceError); + } + + Ok(()) + } +} + +impl Shard { + /// Returns [`ReplicaSet`] assigned to this [`Shard`]. + pub fn replica_set(&self) -> ReplicaSet { + self.replica_set + } +} + +#[derive(Debug, thiserror::Error)] +pub enum CreationError { + #[error("Too few operators within a Keyspace: {_0} < {REPLICATION_FACTOR}")] + TooFewOperators(usize), + + #[error("Too many operators within a Keyspace: {_0} > {MAX_OPERATORS}")] + TooManyOperators(usize), +} + +#[derive(Debug, thiserror::Error)] +#[error("The new Keyspace doesn't differ from the old one")] +pub struct SameKeyspaceError; + +pub(crate) mod sealed { + use std::future::Future; + + #[allow(unused_imports)] + use super::*; + + /// Trait to make `Keyspace<()>` and `Keyspace` polymorphic. + pub trait Calculate { + /// Calculates [`Shards`] of a [`Keyspace`]. + /// + /// It's highly CPU intensive task (order of seconds), so the task is + /// being [spawned](tokio::task::spawn_blocking) to the + /// [`tokio`] threadpool. + fn calculate_shards(self) -> impl Future> + Send; + } +} + +impl sealed::Calculate for Keyspace { + async fn calculate_shards(self) -> Keyspace { + let operators = self.operators.clone(); + let res = tokio::task::spawn_blocking(move || { + sharding::Keyspace::new(operators.into_iter(), &Xxh3Builder::default(), || { + sharding::DefaultReplicationStrategy + }) + }) + .await + .unwrap(); // we don't expect the task to panic + + match res { + Ok(sharding) => Keyspace { + operators: self.operators, + shards: Shards(sharding), + replication_strategy: ReplicationStrategy::UniformDistribution, + version: self.version, + }, + + // we checked this in the `Keyspace` constructor + Err(sharding::Error::InvalidNodesCount(_)) => unreachable!(), + + // impossible with the default replication strategy + Err(sharding::Error::IncompleteReplicaSet) => unreachable!(), + } + } +} + +impl sealed::Calculate<()> for Keyspace { + async fn calculate_shards(self) -> Keyspace { + self + } +} diff --git a/crates/cluster/src/lib.rs b/crates/cluster/src/lib.rs new file mode 100644 index 00000000..b3663a6c --- /dev/null +++ b/crates/cluster/src/lib.rs @@ -0,0 +1,684 @@ +//! WalletConnect Network Cluster. + +use { + arc_swap::ArcSwap, + futures::Stream, + itertools::Itertools, + smart_contract::evm, + std::{collections::HashSet, sync::Arc}, + tokio::sync::watch, +}; + +pub mod smart_contract; +pub use smart_contract::SmartContract; + +pub mod view; +pub use view::View; + +pub mod settings; +pub use settings::Settings; + +pub mod ownership; +pub use ownership::Ownership; + +pub mod client; +pub use client::Client; + +pub mod node; +pub use node::Node; + +pub mod node_operator; +pub use node_operator::NodeOperator; + +pub mod node_operators; +pub use node_operators::NodeOperators; + +pub mod keyspace; +pub use keyspace::Keyspace; + +pub mod migration; +pub use migration::Migration; + +pub mod maintenance; +pub use maintenance::Maintenance; + +mod task; +use task::Task; + +/// Maximum number of [`NodeOperator`]s within a WCN [`Cluster`]. +pub const MAX_OPERATORS: usize = keyspace::MAX_OPERATORS; + +/// Minimum number fo [`NodeOperator`]s within a WCN [`Cluster`]. +pub const MIN_OPERATORS: usize = keyspace::REPLICATION_FACTOR; + +/// WCN cluster. +/// +/// Thin wrapper around the underlying [`SmartContract`] implementation. +/// +/// Performs preliminary invariant validation before calling the actual +/// [`SmartContract`] methods. +pub struct Cluster { + inner: Arc>, + _task_guard: Arc, +} + +struct Inner { + smart_contract: SC, + view: ArcSwap>, + watch: watch::Receiver<()>, +} + +/// Version of a WCN [`Cluster`]. +/// +/// Should only monotonically increase. If you observe a jump backwards it means +/// that a chain reorg has occured on the underlying [`SmartContract`] chain. +/// +/// For each version bump a corresponding [`Event`] should be emitted. +pub type Version = u128; + +/// Events happening within a WCN [`Cluster`]. +#[derive(Debug)] +pub enum Event { + /// [`Migration`] has started. + MigrationStarted(migration::Started), + + /// [`NodeOperator`] has completed the data pull. + MigrationDataPullCompleted(migration::DataPullCompleted), + + /// [`Migration`] has been completed. + MigrationCompleted(migration::Completed), + + /// [`Migration`] has been aborted. + MigrationAborted(migration::Aborted), + + /// [`Maintenance`] has started. + MaintenanceStarted(maintenance::Started), + + /// [`Maintenance`] has been finished. + MaintenanceFinished(maintenance::Finished), + + /// [`NodeOperator`] has been updated. + NodeOperatorAdded(node_operator::Added), + + /// [`NodeOperator`] has been updated. + NodeOperatorUpdated(node_operator::Updated), + + /// [`NodeOperator`] has been removed. + NodeOperatorRemoved(node_operator::Removed), + + /// [`Settings`] have been updated. + SettingsUpdated(settings::Updated), + + /// [`Ownership`] has been transferred. + OwnershipTransferred(ownership::Transferred), +} + +/// [`Event`] with [`node_operator::SerializedData`]. +pub type SerializedEvent = Event; + +impl Cluster +where + SC: smart_contract::Read, + Shards: Clone + Send + Sync + 'static, + Keyspace: keyspace::sealed::Calculate, +{ + /// Deploys a new WCN [`Cluster`]. + pub async fn deploy( + deployer: &impl smart_contract::Deployer, + initial_settings: Settings, + initial_operators: Vec, + ) -> Result { + let operators: Vec<_> = initial_operators + .into_iter() + .map(|op| { + let op = op.serialize()?; + op.data.validate(&initial_settings)?; + Ok::<_, DeploymentError>(op) + }) + .try_collect()?; + + let operators = NodeOperators::new(operators.into_iter().map(Some))?; + + let contract = deployer.deploy(initial_settings, operators).await?; + + Self::new(contract).await.map_err(Into::into) + } + + /// Connects to an existing WCN [`Cluster`]. + pub async fn connect( + connector: &impl smart_contract::Connector, + contract_address: smart_contract::Address, + ) -> Result { + let contract = connector.connect(contract_address).await?; + Self::new(contract).await.map_err(Into::into) + } + + async fn new(contract: SC) -> Result { + let events = contract.events().await?; + let view = View::fetch(&contract).await?.calculate_keyspace().await; + + let (tx, rx) = watch::channel(()); + let inner = Arc::new(Inner { + smart_contract: contract, + view: ArcSwap::new(Arc::new(view)), + watch: rx, + }); + + let guard = Task { + initial_events: Some(events), + inner: inner.clone(), + watch: tx, + } + .spawn(); + + Ok(Self { + inner, + _task_guard: Arc::new(guard), + }) + } +} + +impl Cluster { + /// Passes the current [`cluster::View`] into the provided closure. + /// + /// More efficient than calling [`Cluster::view`]. + pub fn using_view(&self, f: impl FnOnce(&View) -> T) -> T { + f(&self.inner.view.load()) + } + + /// Returns the current [`cluster::View`]. + pub fn view(&self) -> Arc> { + self.inner.view.load_full() + } + + /// Returns a [`Stream`] that emits an item each time a [`Cluster`] update + /// occurs. + /// + /// Caller is expected to use [`Cluster::using_view`] or [`Cluster::view`] + /// to see the updated state. + pub fn updates(&self) -> impl Stream + Send + 'static { + tokio_stream::wrappers::WatchStream::new(self.inner.watch.clone()) + } + + /// Returns reference to the underlying [`SmartContract`]. + pub fn smart_contract(&self) -> &SC { + &self.inner.smart_contract + } +} + +impl Cluster { + /// Builds a new [`Keyspace`] using the provided [`migration::Plan`] and + /// calls [`SmartContract::start_migration`]. + pub async fn start_migration(&self, plan: migration::Plan) -> Result<(), StartMigrationError> { + let new_keyspace = self.using_view(move |view| { + view.ownership().require_owner(&self.inner.smart_contract)?; + view.require_no_migration()?; + view.require_no_maintenance()?; + + let operators = view.node_operators(); + let keyspace = view.keyspace(); + + let mut new_operators: HashSet<_> = view.node_operators().occupied_indexes().collect(); + + for id in plan.remove { + let idx = operators.require_idx(&id)?; + + if !keyspace.contains_operator(idx) { + return Err(StartMigrationError::NotInKeyspace(id)); + } + + new_operators.remove(&idx); + } + + for id in plan.add { + let idx = operators.require_idx(&id)?; + + if keyspace.contains_operator(idx) { + return Err(StartMigrationError::AlreadyInKeyspace(id)); + } + + new_operators.insert(idx); + } + + let new_keyspace = Keyspace::new( + new_operators, + plan.replication_strategy, + keyspace.version() + 1, + )?; + + keyspace.require_diff(&new_keyspace)?; + + Ok(new_keyspace) + })?; + + self.inner + .smart_contract + .start_migration(new_keyspace) + .await?; + + Ok(()) + } + + /// Calls [`SmartContract::complete_migration`]. + pub async fn complete_migration( + &self, + id: migration::Id, + ) -> Result<(), CompleteMigrationError> { + self.using_view(|view| { + let operator_idx = view + .node_operators() + .require_idx(self.inner.smart_contract.signer().address())?; + + view.require_migration()? + .require_id(id)? + .require_pulling(operator_idx)?; + + Ok::<_, CompleteMigrationError>(()) + })?; + + self.inner.smart_contract.complete_migration(id).await?; + + Ok(()) + } + + /// Calls [`SmartContract::abort_migration`]. + pub async fn abort_migration(&self, id: migration::Id) -> Result<(), AbortMigrationError> { + self.using_view(|view| { + view.ownership().require_owner(&self.inner.smart_contract)?; + view.require_migration()?.require_id(id)?; + + Ok::<_, AbortMigrationError>(()) + })?; + + self.inner + .smart_contract + .abort_migration(id) + .await + .map_err(Into::into) + } + + /// Calls [`SmartContract::start_maintenance`]. + pub async fn start_maintenance(&self) -> Result<(), StartMaintenanceError> { + let signer = self.inner.smart_contract.signer().address(); + + self.using_view(move |view| { + if !(view.node_operators().contains(signer) || view.ownership().is_owner(signer)) { + return Err(StartMaintenanceError::Unauthorized); + } + + view.require_no_migration()?; + view.require_no_maintenance()?; + + Ok::<_, StartMaintenanceError>(()) + })?; + + self.inner.smart_contract.start_maintenance().await?; + + Ok(()) + } + + /// Calls [`SmartContract::finish_maintenance`]. + pub async fn finish_maintenance(&self) -> Result<(), FinishMaintenanceError> { + let signer = self.inner.smart_contract.signer().address(); + + self.using_view(|view| { + let maintenance = view.require_maintenance()?; + + if !(signer == maintenance.slot() || view.ownership().is_owner(signer)) { + return Err(FinishMaintenanceError::Unauthorized); + } + + Ok(()) + })?; + + self.inner.smart_contract.finish_maintenance().await?; + + Ok(()) + } + + /// Calls [`SmartContract::add_node_operator`]. + pub async fn add_node_operator( + &self, + idx: node_operator::Idx, + operator: NodeOperator, + ) -> Result<(), AddNodeOperatorError> { + let operator = self.using_view(|view| { + view.ownership().require_owner(&self.inner.smart_contract)?; + view.node_operators().require_not_exists(&operator.id)?; + view.node_operators().require_free_slot(idx)?; + + let operator = operator.serialize()?; + operator.data.validate(view.settings())?; + + Ok::<_, AddNodeOperatorError>(operator) + })?; + + self.inner + .smart_contract + .add_node_operator(idx, operator) + .await?; + + Ok(()) + } + + /// Calls [`SmartContract::update_node_operator`]. + pub async fn update_node_operator( + &self, + operator: NodeOperator, + ) -> Result<(), UpdateNodeOperatorError> { + let signer = self.inner.smart_contract.signer().address(); + + let operator = self.using_view(|view| { + if !(signer == &operator.id || view.ownership().is_owner(signer)) { + return Err(UpdateNodeOperatorError::Unauthorized); + } + + let _idx = view.node_operators().require_idx(&operator.id)?; + + let operator = operator.serialize()?; + operator.data.validate(view.settings())?; + + Ok::<_, UpdateNodeOperatorError>(operator) + })?; + + self.inner + .smart_contract + .update_node_operator(operator) + .await?; + + Ok(()) + } + + /// Calls [`SmartContract::remove_node_operator`]. + pub async fn remove_node_operator( + &self, + id: node_operator::Id, + ) -> Result<(), RemoveNodeOperatorError> { + self.using_view(|view| { + let idx = view.node_operators().require_idx(&id)?; + + if view.keyspace().contains_operator(idx) { + return Err(RemoveNodeOperatorError::InKeyspace); + } + + if let Some(keyspace) = view.migration().map(Migration::keyspace) { + if keyspace.contains_operator(idx) { + return Err(RemoveNodeOperatorError::InKeyspace); + } + } + + Ok::<_, RemoveNodeOperatorError>(()) + })?; + + self.inner.smart_contract.remove_node_operator(id).await?; + + Ok(()) + } + + /// Calls [`SmartContract::update_settings`]. + pub async fn update_settings(&self, new_settings: Settings) -> Result<(), UpdateSettingsError> { + self.using_view(move |view| view.ownership().require_owner(&self.inner.smart_contract))?; + + self.inner + .smart_contract + .update_settings(new_settings) + .await?; + + Ok(()) + } + + /// Calls [`SmartContract::transfer_ownership`]. + pub async fn transfer_ownership( + &self, + new_owner: smart_contract::AccountAddress, + ) -> Result<(), TransferOwnershipError> { + self.using_view(move |view| view.ownership().require_owner(&self.inner.smart_contract))?; + + self.inner + .smart_contract + .transfer_ownership(new_owner) + .await?; + + Ok(()) + } +} + +/// [`Cluster::deploy`] error. +#[derive(Debug, thiserror::Error)] +pub enum DeploymentError { + #[error(transparent)] + NodeOperatorsCreation(#[from] node_operators::CreationError), + + #[error(transparent)] + DataSerialization(#[from] node_operator::DataSerializationError), + + #[error(transparent)] + DataDeserialization(#[from] node_operator::DataDeserializationError), + + #[error(transparent)] + DataTooLarge(#[from] node_operator::DataTooLargeError), + + #[error(transparent)] + FetchView(#[from] view::FetchError), + + #[error("Smart-contract: {0}")] + SmartContract(#[from] smart_contract::DeploymentError), +} + +/// [`Cluster::connect`] error. +#[derive(Debug, thiserror::Error)] +pub enum ConnectionError { + #[error(transparent)] + SmartContract(#[from] smart_contract::ConnectionError), + + #[error(transparent)] + FetchView(#[from] view::FetchError), +} + +/// [`Cluster::start_migration`] error. +#[derive(Debug, thiserror::Error)] +pub enum StartMigrationError { + #[error(transparent)] + NotOwner(#[from] ownership::NotOwnerError), + + #[error(transparent)] + MigrationInProgress(#[from] migration::InProgressError), + + #[error(transparent)] + MaintenanceInProgress(#[from] maintenance::InProgressError), + + #[error(transparent)] + UnknownOperator(#[from] node_operator::NotFoundError), + + #[error("NodeOperator(id: {_0}) is not in the Keyspace")] + NotInKeyspace(node_operator::Id), + + #[error("NodeOperator(id: {_0}) is already in the Keyspace")] + AlreadyInKeyspace(node_operator::Id), + + #[error(transparent)] + KeyspaceCreation(#[from] keyspace::CreationError), + + #[error(transparent)] + SameKeyspace(#[from] keyspace::SameKeyspaceError), + + #[error("Smart-contract: {0}")] + SmartContract(#[from] smart_contract::WriteError), +} + +/// [`Cluster::complete_migration`] error. +#[derive(Debug, thiserror::Error)] +pub enum CompleteMigrationError { + #[error(transparent)] + UnknownOperator(#[from] node_operator::NotFoundError), + + #[error(transparent)] + NoMigration(#[from] migration::NotFoundError), + + #[error(transparent)] + WrongMigrationId(#[from] migration::WrongIdError), + + #[error(transparent)] + OperatorNotPulling(#[from] migration::OperatorNotPullingError), + + #[error("Smart-contract: {0}")] + SmartContract(#[from] smart_contract::WriteError), +} + +/// [`Cluster::abort_migration`] error. +#[derive(Debug, thiserror::Error)] +pub enum AbortMigrationError { + #[error(transparent)] + NotOwner(#[from] ownership::NotOwnerError), + + #[error(transparent)] + NoMigration(#[from] migration::NotFoundError), + + #[error(transparent)] + WrongMigrationId(#[from] migration::WrongIdError), + + #[error("Smart-contract: {0}")] + SmartContract(#[from] smart_contract::WriteError), +} + +/// [`Cluster::start_maintenance`] error. +#[derive(Debug, thiserror::Error)] +pub enum StartMaintenanceError { + #[error("Signer should either be a node operator or the owner")] + Unauthorized, + + #[error(transparent)] + MigrationInProgress(#[from] migration::InProgressError), + + #[error(transparent)] + MaintenanceInProgress(#[from] maintenance::InProgressError), + + #[error("Smart-contract: {0}")] + SmartContract(#[from] smart_contract::WriteError), +} + +/// [`Cluster::finish_maintenance`] error. +#[derive(Debug, thiserror::Error)] +pub enum FinishMaintenanceError { + #[error(transparent)] + NoMaintenance(#[from] maintenance::NotFoundError), + + #[error("Signer should either be a node operator that started the maintenance or the owner")] + Unauthorized, + + #[error("Smart-contract: {0}")] + SmartContract(#[from] smart_contract::WriteError), +} + +/// [`Cluster::add_node_operator`] error. +#[derive(Debug, thiserror::Error)] +pub enum AddNodeOperatorError { + #[error(transparent)] + NotOwner(#[from] ownership::NotOwnerError), + + #[error(transparent)] + AlreadyExists(#[from] node_operator::AlreadyExistsError), + + #[error(transparent)] + SlotOccupied(#[from] node_operators::SlotOccupiedError), + + #[error(transparent)] + DataSerialization(#[from] node_operator::DataSerializationError), + + #[error(transparent)] + DataTooLarge(#[from] node_operator::DataTooLargeError), + + #[error("Smart-contract: {0}")] + SmartContract(#[from] smart_contract::WriteError), +} + +/// [`Cluster::update_node_operator`] error. +#[derive(Debug, thiserror::Error)] +pub enum UpdateNodeOperatorError { + #[error("Signer should either be the NodeOperator being updated or the owner")] + Unauthorized, + + #[error(transparent)] + NotFoundError(#[from] node_operator::NotFoundError), + + #[error(transparent)] + DataSerialization(#[from] node_operator::DataSerializationError), + + #[error(transparent)] + DataTooLarge(#[from] node_operator::DataTooLargeError), + + #[error("Smart-contract: {0}")] + SmartContract(#[from] smart_contract::WriteError), +} + +/// [`Cluster::remove_node_operator`] error. +#[derive(Debug, thiserror::Error)] +pub enum RemoveNodeOperatorError { + #[error(transparent)] + NotOwner(#[from] ownership::NotOwnerError), + + #[error(transparent)] + NotFoundError(#[from] node_operator::NotFoundError), + + #[error("Node operator is still within a Keyspace")] + InKeyspace, + + #[error("Smart-contract: {0}")] + SmartContract(#[from] smart_contract::WriteError), +} + +/// [`Cluster::update_settings`] error. +#[derive(Debug, thiserror::Error)] +pub enum UpdateSettingsError { + #[error(transparent)] + NotOwner(#[from] ownership::NotOwnerError), + + #[error("Smart-contract: {0}")] + SmartContract(#[from] smart_contract::WriteError), +} + +/// [`Cluster::transfer_ownership`] error. +#[derive(Debug, thiserror::Error)] +pub enum TransferOwnershipError { + #[error(transparent)] + NotOwner(#[from] ownership::NotOwnerError), + + #[error("Smart-contract: {0}")] + SmartContract(#[from] smart_contract::WriteError), +} + +impl Event { + fn cluster_version(&self) -> Version { + match self { + Event::MigrationStarted(evt) => evt.cluster_version, + Event::MigrationDataPullCompleted(evt) => evt.cluster_version, + Event::MigrationCompleted(evt) => evt.cluster_version, + Event::MigrationAborted(evt) => evt.cluster_version, + Event::MaintenanceStarted(evt) => evt.cluster_version, + Event::MaintenanceFinished(evt) => evt.cluster_version, + Event::NodeOperatorAdded(evt) => evt.cluster_version, + Event::NodeOperatorUpdated(evt) => evt.cluster_version, + Event::NodeOperatorRemoved(evt) => evt.cluster_version, + Event::SettingsUpdated(evt) => evt.cluster_version, + Event::OwnershipTransferred(evt) => evt.cluster_version, + } + } +} + +impl SerializedEvent { + fn deserialize(self) -> Result { + Ok(match self { + Event::MigrationStarted(evt) => Event::MigrationStarted(evt), + Event::MigrationDataPullCompleted(evt) => Event::MigrationDataPullCompleted(evt), + Event::MigrationCompleted(evt) => Event::MigrationCompleted(evt), + Event::MigrationAborted(evt) => Event::MigrationAborted(evt), + Event::MaintenanceStarted(evt) => Event::MaintenanceStarted(evt), + Event::MaintenanceFinished(evt) => Event::MaintenanceFinished(evt), + Event::NodeOperatorAdded(evt) => Event::NodeOperatorAdded(evt.deserialize()?), + Event::NodeOperatorUpdated(evt) => Event::NodeOperatorUpdated(evt.deserialize()?), + Event::NodeOperatorRemoved(evt) => Event::NodeOperatorRemoved(evt), + Event::SettingsUpdated(evt) => Event::SettingsUpdated(evt), + Event::OwnershipTransferred(evt) => Event::OwnershipTransferred(evt), + }) + } +} diff --git a/crates/cluster/src/maintenance.rs b/crates/cluster/src/maintenance.rs new file mode 100644 index 00000000..63c060c0 --- /dev/null +++ b/crates/cluster/src/maintenance.rs @@ -0,0 +1,46 @@ +use crate::{node_operator, Version as ClusterVersion}; + +/// Maintenance process within a WCN cluster. +/// +/// Only a single [`node_operator`] at a time is allowed to be under +/// maintenance. +#[derive(Clone)] +pub struct Maintenance { + slot: node_operator::Id, +} + +impl Maintenance { + pub fn new(slot: node_operator::Id) -> Self { + Self { slot } + } + + /// Returns [`node_operator::Id`] that occupies the [`Maintenance`] slot. + pub fn slot(&self) -> &node_operator::Id { + &self.slot + } +} + +/// [`Maintenance`] has started. +#[derive(Debug)] +pub struct Started { + /// ID of the [`node_operator`] that started the [`Maintenance`]. + pub operator_id: node_operator::Id, + + /// Updated [`ClusterVersion`]. + pub cluster_version: ClusterVersion, +} + +/// [`Maintenance`] has been finished. +#[derive(Debug)] +pub struct Finished { + /// Updated [`ClusterVersion`]. + pub cluster_version: ClusterVersion, +} + +#[derive(Debug, thiserror::Error)] +#[error("Maintenance(slot: {_0}) in progress")] +pub struct InProgressError(pub node_operator::Id); + +#[derive(Debug, thiserror::Error)] +#[error("No maintenance")] +pub struct NotFoundError; diff --git a/crates/cluster/src/migration.rs b/crates/cluster/src/migration.rs new file mode 100644 index 00000000..f7d6b447 --- /dev/null +++ b/crates/cluster/src/migration.rs @@ -0,0 +1,189 @@ +use { + crate::{ + keyspace::{self, ReplicationStrategy}, + node_operator, + Keyspace, + Version as ClusterVersion, + }, + std::{collections::HashSet, sync::Arc}, +}; + +/// Identifier of a [`Migration`]. +pub type Id = u64; + +/// Data migration process within a WCN cluster. +#[derive(Clone)] +pub struct Migration { + id: Id, + keyspace: Arc>, + pulling_operators: HashSet, +} + +/// [`Migration`] plan. +pub struct Plan { + /// Set of [`node_operator`]s to remove from the current [`Keyspace`]. + pub remove: HashSet, + + /// Set of [`node_operator`]s to add to the current [`Keyspace`]. + pub add: HashSet, + + /// New [`ReplicationStrategy`] to use. + pub replication_strategy: ReplicationStrategy, +} + +impl Migration { + /// Creates a new [`Migration`]. + pub(super) fn new( + id: Id, + keyspace: Keyspace, + pulling_operators: impl IntoIterator, + ) -> Self { + Self { + id, + keyspace: Arc::new(keyspace), + pulling_operators: pulling_operators.into_iter().collect(), + } + } + + /// Returns [`Id`] of this [`Migration`]. + pub fn id(&self) -> Id { + self.id + } + + /// Returns the new [`Keyspace`] this [`Migration`] is migrating to. + pub fn keyspace(&self) -> &Keyspace { + &self.keyspace + } + + // /// Mutable version of [`Migration::keyspace`]. + // pub fn keyspace_mut(&mut self) -> &mut Keyspace { + // &mut self.keyspace + // } + + pub(super) fn into_keyspace(self) -> Arc> { + self.keyspace + } + + /// Indicates whether the specified [`node_operator`] is still in process of + /// pulling the data. + pub fn is_pulling(&self, idx: node_operator::Idx) -> bool { + self.pulling_operators.contains(&idx) + } + + pub(crate) fn complete_pull(&mut self, idx: node_operator::Idx) { + self.pulling_operators.remove(&idx); + } + + pub(crate) fn require_id(&self, id: Id) -> Result<&Migration, WrongIdError> { + if id != self.id { + return Err(WrongIdError(id, self.id)); + } + + Ok(self) + } + + pub(crate) fn require_pulling( + &self, + idx: node_operator::Idx, + ) -> Result<&Migration, OperatorNotPullingError> { + if !self.is_pulling(idx) { + return Err(OperatorNotPullingError(idx)); + } + + Ok(self) + } + + pub(crate) fn require_pulling_count( + &self, + expected: usize, + ) -> Result<&Migration, WrongPullingOperatorsCountError> { + let count = self.pulling_operators.len(); + if count != expected { + return Err(WrongPullingOperatorsCountError(expected, count)); + } + + Ok(self) + } +} + +impl Migration { + pub(crate) async fn calculate_keyspace(self) -> Migration + where + Keyspace: keyspace::sealed::Calculate, + { + Migration { + id: self.id, + keyspace: Arc::new((*self.keyspace).clone().calculate().await), + pulling_operators: self.pulling_operators, + } + } +} + +/// [`Migration`] has started. +#[derive(Debug)] +pub struct Started { + /// [`Id`] of the [`Migration`] being started. + pub migration_id: Id, + + /// New [`Keyspace`] to migrate to. + pub new_keyspace: Keyspace, + + /// Updated [`ClusterVersion`]. + pub cluster_version: ClusterVersion, +} + +/// [`NodeOperator`](crate::NodeOperator) has completed the data pull. +#[derive(Debug)] +pub struct DataPullCompleted { + /// [`Id`] of the [`Migration`]. + pub migration_id: Id, + + /// ID of the [`node_operator`] that completed the pull. + pub operator_id: node_operator::Id, + + /// Updated [`ClusterVersion`]. + pub cluster_version: ClusterVersion, +} + +/// [`Migration`] has been completed. +#[derive(Debug)] +pub struct Completed { + /// [`Id`] of the completed [`Migration`]. + pub migration_id: Id, + + /// ID of the [`node_operator`] that completed the last data pull. + pub operator_id: node_operator::Id, + + /// Updated [`ClusterVersion`]. + pub cluster_version: ClusterVersion, +} + +/// [`Migration`] has been aborted. +#[derive(Debug)] +pub struct Aborted { + /// [`Id`] of the [`Migration`]. + pub migration_id: Id, + + /// Updated [`ClusterVersion`]. + pub cluster_version: ClusterVersion, +} + +#[derive(Debug, thiserror::Error)] +#[error("Migration(id: {_0}) in progress")] +pub struct InProgressError(pub Id); + +#[derive(Debug, thiserror::Error)] +#[error("No migration")] +pub struct NotFoundError; + +#[derive(Debug, thiserror::Error)] +#[error("Wrong migration ID: {_0} != {_1}")] +pub struct WrongIdError(pub Id, pub Id); + +#[derive(Debug, thiserror::Error)] +#[error("NodeOperator(idx: {_0}) is not currently pulling data")] +pub struct OperatorNotPullingError(pub node_operator::Idx); + +#[derive(Debug, thiserror::Error)] +#[error("Wrong pulling operators count: {_0} != {_1}")] +pub struct WrongPullingOperatorsCountError(pub usize, pub usize); diff --git a/crates/cluster/src/node.rs b/crates/cluster/src/node.rs new file mode 100644 index 00000000..85a3c603 --- /dev/null +++ b/crates/cluster/src/node.rs @@ -0,0 +1,56 @@ +//! Node within a WCN cluster. + +use { + libp2p::identity::PeerId, + serde::{Deserialize, Serialize}, + std::net::SocketAddrV4, +}; + +/// Node within a WCN cluster. +/// +/// The IP address is currently being encrypted using a format-preserving +/// encryption algorithm. +// TODO: encrypt +#[derive(Debug, Clone, Copy)] +pub struct Node { + /// [`PeerId`] of the [`Node`]. + /// + /// Used for authentication. Multiple nodes managed by the same + /// node operator are allowed to have the same [`PeerId`]. + pub peer_id: PeerId, + + /// [`SocketAddrV4`] of the [`Node`]. + pub addr: SocketAddrV4, +} + +// NOTE: The on-chain serialization is non self-describing! Every change to +// the schema should be handled by creating a new version. +#[derive(Clone, Copy, Debug, Serialize, Deserialize)] +pub(crate) struct V0 { + /// [`PeerId`] of this [`Node`]. + /// + /// Used for authentication. Multiple nodes managed by the same + /// [`NodeOperator`] are allowed to have the same [`PeerId`]. + pub peer_id: PeerId, + + /// [`SocketAddrV4`] of this [`Node`]. + pub addr: SocketAddrV4, +} + +impl From for V0 { + fn from(node: Node) -> Self { + Self { + peer_id: node.peer_id, + addr: node.addr, + } + } +} + +impl From for Node { + fn from(node: V0) -> Self { + Self { + peer_id: node.peer_id, + addr: node.addr, + } + } +} diff --git a/crates/cluster/src/node_operator.rs b/crates/cluster/src/node_operator.rs new file mode 100644 index 00000000..043f1b38 --- /dev/null +++ b/crates/cluster/src/node_operator.rs @@ -0,0 +1,276 @@ +//! Entity operating a set of nodes within a WCN cluster. + +use { + crate::{ + self as cluster, + client, + node, + smart_contract, + Client, + Node, + Version as ClusterVersion, + }, + derive_more::derive::Into, + serde::{Deserialize, Serialize}, +}; + +/// Globally unique identifier of a [`NodeOperator`]; +pub type Id = smart_contract::AccountAddress; + +/// Locally unique identifier of a [`NodeOperator`] within a WCN cluster. +/// +/// Refers to a position within the [`NodeOperators`] slot map. +pub type Idx = u8; + +/// Name of a [`NodeOperator`]. +/// +/// Used for informational purposes only. +/// Expected to be unique within the cluster, but not enforced to. +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Name(String); + +impl Name { + /// Maximum allowed length of a [`Name`] (in bytes). + pub const MAX_LENGTH: usize = 32; + + /// Tries to create a new [`Name`] out of the provided [`ToString`]. + /// + /// Returns `None` if the string length exceeds [`Self::MAX_LENGTH`]. + pub fn new(s: impl ToString) -> Option { + let s = s.to_string(); + (s.len() <= Self::MAX_LENGTH).then_some(Self(s)) + } + + /// Returns a reference to the underlying string. + pub fn as_str(&self) -> &str { + &self.0 + } +} + +/// On-chain data of a [`NodeOperator`]. +#[derive(Clone, Debug)] +pub struct Data { + /// Name of the [`NodeOperator`]. + pub name: Name, + + /// List of [`Node`]s of the [`NodeOperator`]. + pub nodes: Vec, + + /// List of [`Client`]s authorized to use the WCN cluster on behalf of the + /// [`NodeOperator`]. + pub clients: Vec, +} + +/// [`NodeOperator`] [`Data`] serialized for on-chain storage. +#[derive(Debug, Into)] +pub struct SerializedData(pub(crate) Vec); + +/// [`NodeOperator`] with [`SerializedData`]. +pub type Serialized = NodeOperator; + +/// Entity operating a set of [`Node`]s within a WCN cluster. +#[derive(Clone, Debug)] +pub struct NodeOperator { + /// ID of this [`NodeOperator`]. + pub id: Id, + + /// On-chain data of this [`NodeOperator`]. + pub data: D, +} + +/// Event of a new [`NodeOperator`] being added to a WCN cluster. +#[derive(Debug)] +pub struct Added { + /// [`Idx`] in the [`NodeOperators`] slot map the [`NodeOperator`] is being + /// placed to. + pub idx: Idx, + + /// [`NodeOperator`] being added. + pub operator: NodeOperator, + + /// Updated [`ClusterVersion`]. + pub cluster_version: ClusterVersion, +} + +impl Added { + pub(super) fn deserialize(self) -> Result { + Ok(Added { + idx: self.idx, + operator: self.operator.deserialize()?, + cluster_version: self.cluster_version, + }) + } +} + +/// Event of a [`NodeOperator`] being updated. +#[derive(Debug)] +pub struct Updated { + /// Updated [`NodeOperator`]. + pub operator: NodeOperator, + + /// Updated [`ClusterVersion`]. + pub cluster_version: ClusterVersion, +} + +impl Updated { + pub(super) fn deserialize(self) -> Result { + Ok(Updated { + operator: self.operator.deserialize()?, + cluster_version: self.cluster_version, + }) + } +} + +/// Event of a [`NodeOperator`] being removed from a WCN cluster. +#[derive(Debug)] +pub struct Removed { + /// [`Id`] of the [`NodeOperator`] being removed. + pub id: Id, + + /// Updated [`ClusterVersion`]. + pub cluster_version: ClusterVersion, +} + +impl NodeOperator { + pub(super) fn serialize(self) -> Result, DataSerializationError> { + Ok(NodeOperator { + id: self.id, + data: self.data.serialize()?, + }) + } +} + +impl Data { + pub(super) fn serialize(self) -> Result { + use DataSerializationError as Error; + + // TODO: encrypt + + let data = DataV0 { + name: self.name, + nodes: self.nodes.into_iter().map(Into::into).collect(), + clients: self.clients.into_iter().map(Into::into).collect(), + }; + + let size = postcard::experimental::serialized_size(&data).map_err(Error::from_postcard)?; + + // reserve first byte for versioning + let mut buf = vec![0; size + 1]; + buf[0] = 0; // current schema version + postcard::to_slice(&data, &mut buf[1..]).map_err(Error::from_postcard)?; + Ok(SerializedData(buf)) + } +} + +impl NodeOperator { + pub(super) fn deserialize(self) -> Result { + use DataDeserializationError as Error; + + let data_bytes = self.data.0; + + if data_bytes.is_empty() { + return Err(DataDeserializationError::EmptyBuffer); + } + + let schema_version = data_bytes[0]; + let bytes = &data_bytes[1..]; + + let data = match schema_version { + 0 => postcard::from_bytes::(bytes).map(Into::into), + ver => return Err(Error::UnknownSchemaVersion(ver)), + } + .map_err(Error::from_postcard)?; + + Ok(NodeOperator { id: self.id, data }) + } +} + +// NOTE: The on-chain serialization is non self-describing! Every change to +// the schema should be handled by creating a new version. +#[derive(Debug, Clone, Deserialize, Serialize)] +struct DataV0 { + name: Name, + nodes: Vec, + clients: Vec, +} + +impl From for DataV0 { + fn from(data: Data) -> Self { + Self { + name: data.name, + nodes: data.nodes.into_iter().map(Into::into).collect(), + clients: data.clients.into_iter().map(Into::into).collect(), + } + } +} + +impl From for Data { + fn from(data: DataV0) -> Self { + Self { + name: data.name, + nodes: data.nodes.into_iter().map(Into::into).collect(), + clients: data.clients.into_iter().map(Into::into).collect(), + } + } +} + +#[derive(Debug, thiserror::Error)] +pub enum DataSerializationError { + #[error("Codec: {0}")] + Codec(String), +} + +impl DataSerializationError { + fn from_postcard(err: postcard::Error) -> Self { + Self::Codec(format!("{err:?}")) + } +} + +#[derive(Debug, thiserror::Error)] +pub enum DataDeserializationError { + #[error("Empty data buffer")] + EmptyBuffer, + + #[error("Codec: {0}")] + Codec(String), + + #[error("Unknown schema version: {0}")] + UnknownSchemaVersion(u8), +} + +impl DataDeserializationError { + fn from_postcard(err: postcard::Error) -> Self { + Self::Codec(format!("{err:?}")) + } +} + +impl SerializedData { + /// Validates that [`SerializedData`] size doesn't exceed + /// [`cluster::Settings::max_node_operator_data_bytes`]. + pub(super) fn validate(&self, settings: &cluster::Settings) -> Result<(), DataTooLargeError> { + let value = self.0.len(); + let limit = settings.max_node_operator_data_bytes as usize; + + if value > limit { + return Err(DataTooLargeError { value, limit }); + } + + Ok(()) + } +} + +/// [`SerializedData`] size is too large. +#[derive(Debug, thiserror::Error)] +#[error("Node operator data size is too large (value: {value}, limit: {limit})")] +pub struct DataTooLargeError { + value: usize, + limit: usize, +} + +#[derive(Debug, thiserror::Error)] +#[error("Node operator (id: {0}) is not a member of the cluster")] +pub struct NotFoundError(pub Id); + +#[derive(Debug, thiserror::Error)] +#[error("Node operator (id: {0}) is already a member of the cluster")] +pub struct AlreadyExistsError(pub Id); diff --git a/crates/cluster/src/node_operators.rs b/crates/cluster/src/node_operators.rs new file mode 100644 index 00000000..922a96e1 --- /dev/null +++ b/crates/cluster/src/node_operators.rs @@ -0,0 +1,167 @@ +//! Slot map of [`NodeOperator`]s. + +use { + crate::{self as cluster, node_operator, NodeOperator}, + itertools::Itertools as _, + std::collections::HashMap, +}; + +/// Slot map of [`NodeOperator`]s. +#[derive(Debug, Clone)] +pub struct NodeOperators { + id_to_idx: HashMap, + + // TODO: assert length + slots: Vec>>, +} + +/// [`NodeOperators`] with [`node_operator::SerializedData`]. +pub type Serialized = NodeOperators; + +impl NodeOperators { + pub(super) fn new( + slots: impl IntoIterator>>, + ) -> Result { + let slots: Vec<_> = slots.into_iter().collect(); + + if slots.len() > cluster::MAX_OPERATORS { + return Err(CreationError::TooManyOperatorSlots(slots.len())); + } + + let mut id_to_idx = HashMap::with_capacity(slots.len()); + + for (idx, slot) in slots.iter().enumerate() { + if let Some(operator) = &slot { + if id_to_idx.insert(operator.id, idx as u8).is_some() { + return Err(CreationError::OperatorDuplicate(operator.id)); + }; + } + } + + Ok(Self { id_to_idx, slots }) + } + + pub(super) fn into_slots(self) -> Vec>> { + self.slots + } + + pub(super) fn set(&mut self, idx: node_operator::Idx, slot: Option>) { + if let Some(id) = self.get_by_idx(idx).map(|op| op.id) { + self.id_to_idx.remove(&id); + } + + if self.slots.len() >= idx as usize { + self.expand(idx); + } + + if let Some(operator) = &slot { + self.id_to_idx.insert(operator.id, idx); + } + + self.slots[idx as usize] = slot; + } + + fn expand(&mut self, idx: node_operator::Idx) { + let desired_len = (idx as usize) + 1; + let slots_to_add = desired_len.checked_sub(self.slots.len()); + + for _ in 0..slots_to_add.unwrap_or_default() { + self.slots.push(None); + } + } + + /// Returns whether this map contains the [`NodeOperator`] with the provided + /// [`Id`]. + pub(super) fn contains(&self, id: &node_operator::Id) -> bool { + self.get_idx(id).is_some() + } + + /// Returns whether this map contains the [`NodeOperator`] with the provided + /// [`Idx`]. + pub(super) fn contains_idx(&self, idx: node_operator::Idx) -> bool { + self.get_by_idx(idx).is_some() + } + + /// Gets an [`NodeOperator`] by [`Id`]. + pub fn get(&self, id: &node_operator::Id) -> Option<&NodeOperator> { + self.get_by_idx(self.get_idx(id)?) + } + + /// Gets an [`NodeOperator`] by [`Idx`]. + pub(super) fn get_by_idx(&self, idx: node_operator::Idx) -> Option<&NodeOperator> { + self.slots.get(idx as usize)?.as_ref() + } + + /// Gets an [`Idx`] by [`Id`]. + pub(super) fn get_idx(&self, id: &node_operator::Id) -> Option { + self.id_to_idx.get(id).copied() + } + + pub(super) fn occupied_indexes(&self) -> impl Iterator + '_ { + self.slots + .iter() + .enumerate() + .filter_map(|(idx, slot)| slot.is_some().then_some(idx as u8)) + } + + pub(super) fn require_idx( + &self, + id: &node_operator::Id, + ) -> Result { + self.get_idx(id) + .ok_or_else(|| node_operator::NotFoundError(*id)) + } + + pub(super) fn require_not_exists( + &self, + id: &node_operator::Id, + ) -> Result<&Self, node_operator::AlreadyExistsError> { + if self.contains(id) { + return Err(node_operator::AlreadyExistsError(*id)); + } + + Ok(self) + } + + pub(super) fn require_free_slot( + &self, + idx: node_operator::Idx, + ) -> Result<&Self, SlotOccupiedError> { + if self.contains_idx(idx) { + return Err(SlotOccupiedError(idx)); + } + + Ok(self) + } +} + +impl Serialized { + pub(super) fn deserialize( + self, + ) -> Result { + Ok(NodeOperators { + id_to_idx: self.id_to_idx, + slots: self + .slots + .into_iter() + .map(|slot| slot.map(NodeOperator::deserialize).transpose()) + .try_collect()?, + }) + } +} + +#[derive(Debug, thiserror::Error)] +pub enum CreationError { + #[error("Too many operator slots: {_0} > {}", cluster::MAX_OPERATORS)] + TooManyOperatorSlots(usize), + + #[error("Too few operators: {_0} < {}", cluster::MIN_OPERATORS)] + TooFewOperators(usize), + + #[error("Duplicate NodeOperator(id: {_0})")] + OperatorDuplicate(node_operator::Id), +} + +#[derive(Debug, thiserror::Error)] +#[error("Slot {_0} in NodeOperators slot map is already occupied")] +pub struct SlotOccupiedError(pub node_operator::Idx); diff --git a/crates/cluster/src/ownership.rs b/crates/cluster/src/ownership.rs new file mode 100644 index 00000000..0d1d79d2 --- /dev/null +++ b/crates/cluster/src/ownership.rs @@ -0,0 +1,51 @@ +//! Ownership of a WCN cluster. + +use crate::{smart_contract, SmartContract, Version as ClusterVersion}; + +/// Ownership of a WCN cluster. +/// +/// Cluster has a single owner, and some [`smart_contract`] methods are +/// resticted to be executed only by the owner. +#[derive(Clone)] +pub struct Ownership { + owner: smart_contract::AccountAddress, +} + +impl Ownership { + pub(super) fn new(owner: smart_contract::AccountAddress) -> Self { + Self { owner } + } + + pub(super) fn is_owner(&self, address: &smart_contract::AccountAddress) -> bool { + address == &self.owner + } + + pub(super) fn require_owner( + &self, + smart_contract: &impl SmartContract, + ) -> Result<(), NotOwnerError> { + if !self.is_owner(smart_contract.signer().address()) { + return Err(NotOwnerError); + } + + Ok(()) + } + + pub(super) fn transfer(&mut self, new_owner: smart_contract::AccountAddress) { + self.owner = new_owner; + } +} + +/// Event of [`Ownership`] being transferred. +#[derive(Debug)] +pub struct Transferred { + /// New owner of the WCN cluster. + pub new_owner: smart_contract::AccountAddress, + + /// Update [`ClusterVersion`]. + pub cluster_version: ClusterVersion, +} + +#[derive(Debug, thiserror::Error)] +#[error("Smart-contract signer is not the owner")] +pub struct NotOwnerError; diff --git a/crates/cluster/src/settings.rs b/crates/cluster/src/settings.rs new file mode 100644 index 00000000..0f8a6cf4 --- /dev/null +++ b/crates/cluster/src/settings.rs @@ -0,0 +1,19 @@ +//! WCN cluster settings. +use crate::Version as ClusterVersion; + +/// WCN cluster settings. +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct Settings { + /// Maximum number of on-chain bytes stored for a single [`NodeOperator`]. + pub max_node_operator_data_bytes: u16, +} + +/// Event of [`Settings`] being updated. +#[derive(Debug)] +pub struct Updated { + /// Updated [`Settings`]. + pub settings: Settings, + + /// Updated [`ClusterVersion`]. + pub cluster_version: ClusterVersion, +} diff --git a/crates/cluster/src/smart_contract/evm.rs b/crates/cluster/src/smart_contract/evm.rs new file mode 100644 index 00000000..1e9db5b7 --- /dev/null +++ b/crates/cluster/src/smart_contract/evm.rs @@ -0,0 +1,618 @@ +//! EVM implementation of [`SmartContract`](super::SmartContract). + +use { + super::{ + AccountAddress, + ConnectionError, + Connector, + Deployer, + DeploymentError, + ReadError, + ReadResult, + RpcUrl, + Signer, + SignerKind, + WriteError, + WriteResult, + }, + crate::{ + self as cluster, + maintenance, + migration, + node_operator, + ownership, + settings, + smart_contract, + Event, + Keyspace, + Maintenance, + Migration, + NodeOperator, + NodeOperators, + Ownership, + SerializedEvent, + Settings, + }, + alloy::{ + contract::{CallBuilder, CallDecoder}, + network::EthereumWallet, + primitives::Uint, + providers::{DynProvider, Provider, ProviderBuilder, WsConnect}, + rpc::types::{Filter, Log}, + sol_types::SolEvent, + }, + futures::{Stream, StreamExt as _}, + std::{collections::HashSet, fmt, sync::Arc, time::Duration}, +}; + +mod bindings { + alloy::sol!( + #[sol(rpc)] + #[derive(Debug)] + Cluster, + "../../contracts/out/Cluster.sol/Cluster.json", + ); +} + +pub(crate) type Address = alloy::primitives::Address; + +type AlloyContract = bindings::Cluster::ClusterInstance; + +type U256 = Uint<256, 4>; + +/// RPC provider for EVM chains. +pub struct RpcProvider { + signer: S, + alloy: DynProvider, +} + +impl RpcProvider { + /// Creates a new [`RpcProvider`]. + pub async fn new( + url: RpcUrl, + signer: Signer, + ) -> Result, RpcProviderCreationError> { + let wallet: EthereumWallet = match &signer.kind { + SignerKind::PrivateKey(key) => key.clone().into(), + }; + + let provider = ProviderBuilder::new() + .wallet(wallet) + .connect_ws(WsConnect::new(url.0)) + .await?; + + Ok(RpcProvider { + signer, + alloy: DynProvider::new(provider), + }) + } + + /// Creates a new read-only [`RpcProvider`]. + pub async fn new_ro(self, url: RpcUrl) -> Result, RpcProviderCreationError> { + let provider = ProviderBuilder::new() + .connect_ws(WsConnect::new(url.0)) + .await?; + + Ok(RpcProvider { + signer: (), + alloy: DynProvider::new(provider), + }) + } +} + +/// EVM implementation of WCN Cluster smart contract. +#[derive(Clone)] +pub struct SmartContract { + signer: S, + alloy: AlloyContract, +} + +impl Deployer> for RpcProvider { + async fn deploy( + &self, + initial_settings: Settings, + initial_operators: NodeOperators, + ) -> Result, DeploymentError> { + let signer = self.signer.clone(); + + let settings = initial_settings.into(); + let operators = initial_operators + .into_slots() + .into_iter() + .filter_map(|op| op.map(Into::into)) + .collect(); + + bindings::Cluster::deploy(self.alloy.clone(), settings, operators) + .await + .map(|alloy| SmartContract { signer, alloy }) + .map_err(Into::into) + } +} + +impl Connector> for RpcProvider { + async fn connect( + &self, + address: smart_contract::Address, + ) -> Result, ConnectionError> { + let signer = self.signer.clone(); + + let code = self + .alloy + .get_code_at(address.0) + .await + .map_err(|err| ConnectionError::Other(err.to_string()))?; + + if code.is_empty() { + return Err(ConnectionError::UnknownContract); + } + + // TODO: false positive + // if code != bindings::Cluster::BYTECODE { + // return Err(ConnectionError::WrongContract); + // } + + Ok(SmartContract { + signer, + alloy: bindings::Cluster::new(address.0, self.alloy.clone()), + }) + } +} + +impl smart_contract::Write for SmartContract { + fn signer(&self) -> &Signer { + &self.signer + } + + async fn start_migration(&self, new_keyspace: Keyspace) -> WriteResult<()> { + check_receipt(self.alloy.startMigration(new_keyspace.into())).await + } + + async fn complete_migration(&self, id: migration::Id) -> WriteResult<()> { + check_receipt(self.alloy.completeMigration(id)).await + } + + async fn abort_migration(&self, id: migration::Id) -> WriteResult<()> { + check_receipt(self.alloy.abortMigration(id)).await + } + + async fn start_maintenance(&self) -> WriteResult<()> { + check_receipt(self.alloy.startMaintenance()).await + } + + async fn finish_maintenance(&self) -> WriteResult<()> { + check_receipt(self.alloy.finishMaintenance()).await + } + + async fn add_node_operator( + &self, + idx: node_operator::Idx, + operator: NodeOperator, + ) -> WriteResult<()> { + check_receipt(self.alloy.addNodeOperator(idx, operator.into())).await + } + + async fn update_node_operator(&self, operator: node_operator::Serialized) -> WriteResult<()> { + check_receipt(self.alloy.updateNodeOperator(operator.into())).await + } + + async fn remove_node_operator(&self, id: node_operator::Id) -> WriteResult<()> { + check_receipt(self.alloy.removeNodeOperator(id.0)).await + } + + async fn update_settings(&self, new_settings: Settings) -> WriteResult<()> { + check_receipt(self.alloy.updateSettings(new_settings.into())).await + } + + async fn transfer_ownership(&self, new_owner: AccountAddress) -> WriteResult<()> { + check_receipt(self.alloy.transferOwnership(new_owner.0)).await + } +} + +async fn check_receipt(call: CallBuilder<&DynProvider, D>) -> WriteResult<()> +where + D: CallDecoder, +{ + let receipt = call + .send() + .await? + .with_timeout(Some(Duration::from_secs(30))) + .get_receipt() + .await?; + + if !receipt.status() { + return Err(WriteError::Revert(format!("{}", receipt.transaction_hash))); + } + + Ok(()) +} + +impl smart_contract::Read for SmartContract { + fn address(&self) -> smart_contract::Address { + smart_contract::Address(*self.alloy.address()) + } + + async fn cluster_view(&self) -> ReadResult> { + self.alloy.getView().call().await?.try_into() + } + + async fn events( + &self, + ) -> ReadResult> + Send + 'static> { + let filter = Filter::new().address(*self.alloy.address()); + + Ok(self + .alloy + .provider() + .subscribe_logs(&filter) + .await? + .into_stream() + .map(TryFrom::try_from)) + } +} + +impl TryFrom for Event { + type Error = ReadError; + + fn try_from(log: Log) -> Result { + use bindings::Cluster; + + let topics = log.topics(); + let data = &log.data().data; + + Ok(match log.topics().get(0) { + Some(&Cluster::MigrationStarted::SIGNATURE_HASH) => { + Cluster::MigrationStarted::decode_raw_log_validate(topics, data)?.try_into()? + } + Some(&Cluster::MigrationDataPullCompleted::SIGNATURE_HASH) => { + Cluster::MigrationDataPullCompleted::decode_raw_log_validate(topics, data)?.into() + } + Some(&Cluster::MigrationCompleted::SIGNATURE_HASH) => { + Cluster::MigrationCompleted::decode_raw_log_validate(topics, data)?.into() + } + Some(&Cluster::MigrationAborted::SIGNATURE_HASH) => { + Cluster::MigrationAborted::decode_raw_log_validate(topics, data)?.into() + } + + Some(&Cluster::MaintenanceStarted::SIGNATURE_HASH) => { + Cluster::MaintenanceStarted::decode_raw_log_validate(topics, data)?.into() + } + Some(&Cluster::MaintenanceFinished::SIGNATURE_HASH) => { + Cluster::MaintenanceFinished::decode_raw_log_validate(topics, data)?.into() + } + + Some(&Cluster::NodeOperatorAdded::SIGNATURE_HASH) => { + Cluster::NodeOperatorAdded::decode_raw_log_validate(topics, data)?.into() + } + Some(&Cluster::NodeOperatorUpdated::SIGNATURE_HASH) => { + Cluster::NodeOperatorUpdated::decode_raw_log_validate(topics, data)?.into() + } + Some(&Cluster::NodeOperatorRemoved::SIGNATURE_HASH) => { + Cluster::NodeOperatorRemoved::decode_raw_log_validate(topics, data)?.into() + } + + Some(&Cluster::SettingsUpdated::SIGNATURE_HASH) => { + Cluster::SettingsUpdated::decode_raw_log_validate(topics, data)?.into() + } + + Some(&Cluster::OwnershipTransferred::SIGNATURE_HASH) => { + Cluster::OwnershipTransferred::decode_raw_log_validate(topics, data)?.into() + } + + other => { + return Err(ReadError::InvalidData(format!( + "Unexpected event: {other:?}" + ))) + } + }) + } +} + +impl TryFrom for Event { + type Error = ReadError; + + fn try_from(evt: bindings::Cluster::MigrationStarted) -> ReadResult { + Ok(Self::MigrationStarted(migration::Started { + migration_id: evt.id, + new_keyspace: Keyspace::try_from_alloy(&evt.newKeyspace, evt.newKeyspaceVersion)?, + cluster_version: evt.clusterVersion, + })) + } +} + +impl From for Event { + fn from(evt: bindings::Cluster::MigrationDataPullCompleted) -> Self { + Self::MigrationDataPullCompleted(migration::DataPullCompleted { + migration_id: evt.id, + operator_id: evt.operatorAddress.into(), + cluster_version: evt.clusterVersion, + }) + } +} + +impl From for Event { + fn from(evt: bindings::Cluster::MigrationCompleted) -> Self { + Self::MigrationCompleted(migration::Completed { + migration_id: evt.id, + operator_id: evt.operatorAddress.into(), + cluster_version: evt.clusterVersion, + }) + } +} + +impl From for Event { + fn from(evt: bindings::Cluster::MigrationAborted) -> Self { + Self::MigrationAborted(migration::Aborted { + migration_id: evt.id, + cluster_version: evt.clusterVersion, + }) + } +} + +impl From for Event { + fn from(evt: bindings::Cluster::MaintenanceStarted) -> Self { + Self::MaintenanceStarted(maintenance::Started { + operator_id: evt.addr.into(), + cluster_version: evt.clusterVersion, + }) + } +} + +impl From for Event { + fn from(evt: bindings::Cluster::MaintenanceFinished) -> Self { + Self::MaintenanceFinished(maintenance::Finished { + cluster_version: evt.clusterVersion, + }) + } +} + +impl From for Event { + fn from(evt: bindings::Cluster::NodeOperatorAdded) -> Self { + Self::NodeOperatorAdded(node_operator::Added { + idx: evt.idx, + operator: evt.operator.into(), + cluster_version: evt.clusterVersion, + }) + } +} + +impl From for Event { + fn from(evt: bindings::Cluster::NodeOperatorUpdated) -> Self { + Self::NodeOperatorUpdated(node_operator::Updated { + operator: evt.operator.into(), + cluster_version: evt.clusterVersion, + }) + } +} + +impl From for Event { + fn from(evt: bindings::Cluster::NodeOperatorRemoved) -> Self { + Self::NodeOperatorRemoved(node_operator::Removed { + id: evt.operatorAddress.into(), + cluster_version: evt.clusterVersion, + }) + } +} + +impl From for Event { + fn from(evt: bindings::Cluster::SettingsUpdated) -> Self { + Self::SettingsUpdated(settings::Updated { + settings: evt.newSettings.into(), + cluster_version: evt.clusterVersion, + }) + } +} + +impl From for Event { + fn from(evt: bindings::Cluster::OwnershipTransferred) -> Self { + Self::OwnershipTransferred(ownership::Transferred { + new_owner: evt.newOwner.into(), + cluster_version: evt.cluserVersion, + }) + } +} + +impl From for bindings::Cluster::NodeOperator { + fn from(op: node_operator::Serialized) -> Self { + Self { + addr: op.id.0, + data: op.data.0.into(), + } + } +} + +impl From for node_operator::Serialized { + fn from(op: bindings::Cluster::NodeOperator) -> Self { + NodeOperator { + id: smart_contract::AccountAddress(op.addr), + data: node_operator::SerializedData(op.data.into()), + } + } +} + +impl From for bindings::Cluster::Settings { + fn from(settings: Settings) -> Self { + Self { + maxOperatorDataBytes: settings.max_node_operator_data_bytes, + } + } +} + +impl From for Settings { + fn from(settings: bindings::Cluster::Settings) -> Self { + Self { + max_node_operator_data_bytes: settings.maxOperatorDataBytes, + } + } +} + +impl From for bindings::Cluster::Keyspace { + fn from(keyspace: Keyspace) -> Self { + let mut operators_bitmask = U256::ZERO; + + for idx in keyspace.operators() { + operators_bitmask.set_bit(idx as usize, true); + } + + Self { + operatorsBitmask: operators_bitmask, + replicationStrategy: keyspace.replication_strategy() as u8, + } + } +} + +impl Keyspace { + fn try_from_alloy( + keyspace: &bindings::Cluster::Keyspace, + version: u64, + ) -> Result { + let mut operators = HashSet::new(); + + // TODO: do less iterations + for idx in 0..256 { + if keyspace.operatorsBitmask.bit(idx) { + operators.insert(idx as u8); + } + } + + let replication_strategy = keyspace.replicationStrategy.try_into().map_err(|err| { + ReadError::InvalidData(format!("Invalid ReplicationStrategy: {err:?}")) + })?; + + Self::new(operators, replication_strategy, version) + .map_err(|err| ReadError::InvalidData(format!("Invalid Keyspace: {err:?}"))) + } +} + +impl Migration { + fn from_alloy(migration: bindings::Cluster::Migration, keyspace: Keyspace) -> Self { + let mut pulling_operators = HashSet::new(); + + // TODO: do less iterations + for idx in 0..256 { + if migration.pullingOperatorsBitmask.bit(idx) { + pulling_operators.insert(idx as u8); + } + } + + Self::new(migration.id, keyspace, pulling_operators) + } +} + +impl From for Option { + fn from(maintenance: bindings::Cluster::Maintenance) -> Self { + if maintenance.slot.is_zero() { + None + } else { + Some(Maintenance::new(maintenance.slot.into())) + } + } +} + +impl TryFrom for cluster::View<(), node_operator::SerializedData> { + type Error = ReadError; + + fn try_from(view: bindings::Cluster::ClusterView) -> Result { + let node_operators = + NodeOperators::new(view.nodeOperatorSlots.into_iter().map(|operator| { + if operator.addr.is_zero() { + None + } else { + Some(operator.into()) + } + })) + .map_err(|err| ReadError::InvalidData(format!("Invalid NodeOperators: {err:?}")))?; + + // assert array length + let _: &[_; 2] = &view.keyspaces; + + let try_keyspace = + |version| Keyspace::try_from_alloy(&view.keyspaces[version as usize % 2], version); + + let (keyspace, migration) = if view.migration.pullingOperatorsBitmask == U256::ZERO { + // migration is not in progress + + (try_keyspace(view.keyspaceVersion)?, None) + } else { + // migration is in progress + + let prev_keyspace_version = view + .keyspaceVersion + .checked_sub(1) + .ok_or_else(|| ReadError::InvalidData(format!("Invalid keyspace::Version")))?; + + let keyspace = try_keyspace(prev_keyspace_version)?; + let migration_keyspace = try_keyspace(view.keyspaceVersion)?; + let migration = Migration::from_alloy(view.migration, migration_keyspace); + + (keyspace, Some(migration)) + }; + + Ok(Self { + node_operators, + ownership: Ownership::new(view.owner.into()), + settings: view.settings.into(), + keyspace: Arc::new(keyspace), + migration, + maintenance: view.maintenance.into(), + cluster_version: view.version, + }) + } +} + +impl From for DeploymentError { + fn from(err: alloy::contract::Error) -> Self { + Self(format!("{err:?}")) + } +} + +impl From> for WriteError { + fn from(err: alloy::transports::RpcError) -> Self { + WriteError::Transport(format!("{err:?}")) + } +} + +impl From> for ReadError { + fn from(err: alloy::transports::RpcError) -> Self { + ReadError::Transport(format!("{err:?}")) + } +} + +impl From for WriteError { + fn from(err: alloy::providers::PendingTransactionError) -> Self { + Self::Other(format!("{err:?}")) + } +} + +impl From for WriteError { + fn from(err: alloy::contract::Error) -> Self { + match err { + alloy::contract::Error::TransportError(err) => Self::Transport(format!("{err:?}")), + _ => Self::Other(format!("{err:?}")), + } + } +} + +impl From for ReadError { + fn from(err: alloy::contract::Error) -> Self { + match err { + alloy::contract::Error::TransportError(err) => Self::Transport(format!("{err:?}")), + _ => Self::Other(format!("{err:?}")), + } + } +} + +impl From for ReadError { + fn from(err: alloy::sol_types::Error) -> Self { + ReadError::InvalidData(format!("{err:?}")) + } +} + +#[derive(Debug, thiserror::Error)] +#[error("{_0}")] +pub struct RpcProviderCreationError(String); + +impl From for RpcProviderCreationError { + fn from(err: alloy::transports::TransportError) -> Self { + Self(format!("alloy transport: {err:?}")) + } +} diff --git a/crates/cluster/src/smart_contract/mod.rs b/crates/cluster/src/smart_contract/mod.rs new file mode 100644 index 00000000..c7b292c7 --- /dev/null +++ b/crates/cluster/src/smart_contract/mod.rs @@ -0,0 +1,298 @@ +//! Smart-contract managing the state of a WCN cluster. + +pub mod evm; + +use { + crate::{ + self as cluster, + migration, + node_operator, + Keyspace, + NodeOperators, + SerializedEvent, + Settings, + }, + alloy::{signers::local::PrivateKeySigner, transports::http::reqwest}, + derive_more::derive::{Display, From}, + futures::Stream, + serde::{Deserialize, Serialize}, + std::{future::Future, str::FromStr}, +}; + +/// Deployer of WCN Cluster [`SmartContract`]s. +pub trait Deployer { + /// Deploys a new [`SmartContract`]. + fn deploy( + &self, + initial_settings: Settings, + initial_operators: NodeOperators, + ) -> impl Future>; +} + +/// Connector to WCN Cluster [`SmartContract`]s. +pub trait Connector { + /// Connects to an existing [`SmartContract`]. + fn connect(&self, address: Address) -> impl Future>; +} + +/// Smart-contract managing the state of a WCN cluster. +pub trait SmartContract: Read + Write {} + +/// Write [`SmartContract`] calls. +/// +/// Logic invariants documented on the methods of this trait MUST be +/// implemented inside the on-chain implementation of the smart-contract itself. +// TODO: docs are outdated, revisit +pub trait Write { + /// Returns the [`Signer`] being used to sign transactions. + fn signer(&self) -> &Signer; + + /// Starts a new data [`migration`] process using the provided + /// [`migration::Plan`]. + /// + /// The implementation MUST validate the following invariants: + /// - there's no ongoing data migration + /// - there's no ongoing maintenance + /// - [`signer`](SmartContract::signer) is the owner of the + /// [`SmartContract`] + /// + /// The implementation MUST emit [`migration::Started`] event on success. + fn start_migration(&self, new_keyspace: Keyspace) -> impl Future>; + + /// Marks that the [`signer`](SmartContract::signer) has completed the data + /// pull required for completion of the current [`migration`]. + /// + /// The implementation MUST validate the following invariants: + /// - there's an ongoing data migration + /// - the provided [`migration::Id`] matches the ID of the migration + /// - [`signer`](Smart::signer) is a [`node::Operator`] under the provided + /// [`node::OperatorIdx`] + /// + /// If this [`node::Operator`] is the last remaining one left to complete + /// the data pull then the migration MUST be completed and + /// [`migration::Completed`] event MUST be emitted. + /// Otherwise the data pull MUST be marked as completed for the + /// [`node::Operator`] and [`migration::DataPullCompleted`] MUST be emitted. + /// + /// The implementation MAY be idempotent. In case of an idempotent + /// execution the event MUST not be emitted. + fn complete_migration(&self, id: migration::Id) -> impl Future>; + + /// Aborts the ongoing data [`migration`] process restoring the WCN cluster + /// to the original state it had before the migration had started. + /// + /// The implementation MUST validate the following invariants: + /// - there's an ongoing data migration + /// - [`signer`](SmartContract::signer) is the owner of the + /// [`SmartContract`] + /// + /// The implementation MUST emit [`migration::Aborted`] event on success. + fn abort_migration(&self, id: migration::Id) -> impl Future>; + + /// Starts a [`maintenance`] process for the [`node::Operator`] being the + /// current [`signer`](Manager::signer). + /// + /// The implementation MUST validate the following invariants: + /// - there's no ongoing data migration + /// - there's no ongoing maintenance + /// - [`signer`](SmartContract::signer) is a [`node::Operator`] under the + /// provided [`node::OperatorIdx`] + /// + /// The implementation MUST emit [`maintenance::Started`] event on success. + fn start_maintenance(&self) -> impl Future>; + + /// Completes the ongoing [`maintenance`] process. + /// + /// The implementation MUST validate the following invariants: + /// - there's an ongoing maintenance + /// - [`signer`](SmartContract::signer) is the one who + /// [started](Manager::start_maintenance) the maintenance + /// + /// The implementation MUST emit [`maintenance::Completed`] event on + /// success. + fn finish_maintenance(&self) -> impl Future>; + + fn add_node_operator( + &self, + idx: node_operator::Idx, + operator: node_operator::Serialized, + ) -> impl Future>; + + /// Updates on-chain data of a [`node::Operator`]. + /// + /// The implementation MUST validate the following invariants: + /// - [`signer`](SmartContract::signer) is a [`node::Operator`] under the + /// provided [`node::OperatorIdx`] + /// + /// The implementation MUST emit [`node::OperatorUpdated`] event on success. + fn update_node_operator( + &self, + operator: node_operator::Serialized, + ) -> impl Future>; + + fn remove_node_operator(&self, id: node_operator::Id) -> impl Future>; + + fn update_settings(&self, new_settings: Settings) -> impl Future>; + + fn transfer_ownership( + &self, + new_owner: AccountAddress, + ) -> impl Future>; +} + +/// Read [`SmartContract`] calls. +pub trait Read: Sized + Send + Sync + 'static { + /// Returns [`Address`] of this [`SmartContract`]. + fn address(&self) -> Address; + + /// Returns the current [`cluster::View`]. + fn cluster_view( + &self, + ) -> impl Future>> + Send; + + /// Subscribes to WCN Cluster [`Events`]. + fn events( + &self, + ) -> impl Future< + Output = ReadResult> + Send + 'static>, + > + Send; +} + +/// [`SmartContract`] address. +#[derive(Clone, Copy, Debug, Display, From, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub struct Address(evm::Address); + +/// Account address on the chain hosting WCN cluster [`SmartContract`]. +#[derive(Clone, Copy, Debug, Display, From, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub struct AccountAddress(evm::Address); + +/// Transaction signer. +#[derive(Clone)] +pub struct Signer { + address: AccountAddress, + kind: SignerKind, +} + +/// RPC provider URL. +pub struct RpcUrl(reqwest::Url); + +/// Error of [`Deployer::deploy`]. +#[derive(Debug, thiserror::Error)] +#[error("{_0}")] +pub struct DeploymentError(String); + +/// Error of [`Connector::connect`]. +#[derive(Debug, thiserror::Error)] +pub enum ConnectionError { + #[error("Smart-contract with the provided address doesn't exist")] + UnknownContract, + + #[error("Smart-contract with the provided address is not a WCN cluster")] + WrongContract, + + #[error("Other: {0}")] + Other(String), +} + +/// [`Write`] error. +#[derive(Debug, thiserror::Error)] +pub enum WriteError { + #[error("Transport: {0}")] + Transport(String), + + #[error("Transaction reverted: {0}")] + Revert(String), + + #[error("Other: {0}")] + Other(String), +} + +/// [`Read`] error. +#[derive(Debug, thiserror::Error)] + +pub enum ReadError { + #[error("Transport: {0}")] + Transport(String), + + #[error("Invalid data: {0}")] + InvalidData(String), + + #[error("Other: {0}")] + Other(String), +} + +/// [`Write`] result. +pub type WriteResult = std::result::Result; + +/// [`Read`] result. +pub type ReadResult = std::result::Result; + +impl Signer { + pub fn try_from_private_key(hex: &str) -> Result { + let private_key = PrivateKeySigner::from_str(hex) + .map_err(|err| InvalidPrivateKeyError(err.to_string()))?; + + Ok(Self { + address: AccountAddress(private_key.address()), + kind: SignerKind::PrivateKey(private_key), + }) + } + + /// Returns [`AccountAddress`] of this [`Signer`]. + pub fn address(&self) -> &AccountAddress { + &self.address + } +} + +#[derive(Clone)] +enum SignerKind { + PrivateKey(PrivateKeySigner), +} + +#[derive(Debug, thiserror::Error)] +#[error("Invalid RPC URL: {0:?}")] +pub struct InvalidRpcUrlError(String); + +#[derive(Debug, thiserror::Error)] +#[error("Invalid private key: {0:?}")] +pub struct InvalidPrivateKeyError(String); + +#[derive(Debug, thiserror::Error)] +#[error("Invalid account address: {0:?}")] +pub struct InvalidAccountAddressError(String); + +#[derive(Debug, thiserror::Error)] +#[error("Invalid smart-contract address: {0:?}")] +pub struct InvalidAddressError(String); + +impl FromStr for RpcUrl { + type Err = InvalidRpcUrlError; + + fn from_str(s: &str) -> Result { + reqwest::Url::from_str(s) + .map(Self) + .map_err(|err| InvalidRpcUrlError(err.to_string())) + } +} + +impl FromStr for AccountAddress { + type Err = InvalidAccountAddressError; + + fn from_str(s: &str) -> Result { + alloy::primitives::Address::from_str(s) + .map(AccountAddress) + .map_err(|err| InvalidAccountAddressError(err.to_string())) + } +} + +impl FromStr for Address { + type Err = InvalidAddressError; + + fn from_str(s: &str) -> Result { + alloy::primitives::Address::from_str(s) + .map(Address) + .map_err(|err| InvalidAddressError(err.to_string())) + } +} + +impl SmartContract for SC where SC: Read + Write {} diff --git a/crates/cluster/src/task.rs b/crates/cluster/src/task.rs new file mode 100644 index 00000000..af274025 --- /dev/null +++ b/crates/cluster/src/task.rs @@ -0,0 +1,117 @@ +use { + crate::{ + keyspace, + node_operator, + smart_contract, + view, + Inner, + Keyspace, + SerializedEvent, + View, + }, + futures::{Stream, StreamExt}, + std::{pin::pin, sync::Arc, time::Duration}, + tokio::sync::watch, +}; + +pub(super) struct Task { + pub initial_events: Option, + pub inner: Arc>, + pub watch: watch::Sender<()>, +} + +pub(super) struct Guard(tokio::task::JoinHandle<()>); + +impl Drop for Guard { + fn drop(&mut self) { + self.0.abort(); + tracing::info!("aborted"); + } +} + +impl Task +where + SC: smart_contract::Read, + Shards: Clone + Send + Sync + 'static, + Events: Stream> + Send + 'static, + Keyspace: keyspace::sealed::Calculate, +{ + pub(super) fn spawn(self) -> Guard { + let guard = Guard(tokio::spawn(self.run())); + tracing::info!("spawned"); + guard + } + + async fn run(mut self) { + loop { + // apply initial events until they finish / first error + if let Some(events) = self.initial_events.take() { + match self.apply_events(events).await { + Ok(()) => tracing::warn!("Initial event stream finished"), + Err(err) => tracing::error!(%err, "Failed to apply initial events"), + } + } + + loop { + // when we fail for whatever reason - subscribe again and refetch the whole + // state + match self.update_view().await { + Ok(()) => tracing::warn!("Event stream finished"), + Err(err) => { + tracing::error!(%err, "Failed to update cluster::View"); + tokio::time::sleep(Duration::from_secs(60)).await; + } + } + } + } + } + + async fn update_view(&mut self) -> Result<()> { + let events = self.inner.smart_contract.events().await?; + + let new_view = View::fetch(&self.inner.smart_contract).await?; + if self.inner.view.load().cluster_version != new_view.cluster_version { + let new_view = Arc::new(new_view.calculate_keyspace().await); + self.inner.view.store(new_view); + let _ = self.watch.send(()); + } + + self.apply_events(events).await + } + + async fn apply_events( + &mut self, + events: impl Stream>, + ) -> Result<()> { + let mut events = pin!(events); + + while let Some(res) = events.next().await { + let event = res?.deserialize()?; + tracing::info!(?event, "received"); + + let view = self.inner.view.load_full(); + let view = Arc::new((*view).clone().apply_event(event).await?); + self.inner.view.store(view); + let _ = self.watch.send(()); + } + + Ok(()) + } +} + +#[derive(Debug, thiserror::Error)] +enum Error { + #[error(transparent)] + ApplyEvent(#[from] view::Error), + + #[error(transparent)] + DataDeserialization(#[from] node_operator::DataDeserializationError), + + #[error(transparent)] + ViewFetch(#[from] view::FetchError), + + #[error(transparent)] + SmartContractRead(#[from] smart_contract::ReadError), +} + +type Result = std::result::Result; diff --git a/crates/cluster/src/view.rs b/crates/cluster/src/view.rs new file mode 100644 index 00000000..2eaf6fdf --- /dev/null +++ b/crates/cluster/src/view.rs @@ -0,0 +1,350 @@ +//! Read-only view of a WCN cluster. + +use { + crate::{ + self as cluster, + keyspace, + maintenance, + migration, + node_operator, + node_operators, + ownership, + settings, + smart_contract, + Event, + Keyspace, + Maintenance, + Migration, + NodeOperators, + Ownership, + Settings, + }, + futures::future::OptionFuture, + std::sync::Arc, +}; + +/// Read-only view of a WCN cluster. +#[derive(Clone)] +pub struct View { + pub(super) node_operators: NodeOperators, + + pub(super) ownership: Ownership, + pub(super) settings: Settings, + + pub(super) keyspace: Arc>, + pub(super) migration: Option>, + pub(super) maintenance: Option, + + pub(super) cluster_version: cluster::Version, +} + +impl View { + pub(super) async fn fetch(contract: &impl smart_contract::Read) -> Result + where + Keyspace: keyspace::sealed::Calculate, + { + Ok(contract.cluster_view().await?.deserialize()?) + } + + /// Returns [`Ownership`] of the WCN cluster. + pub fn ownership(&self) -> &Ownership { + &self.ownership + } + + /// Returns [`Settings`] of the WCN cluster. + pub fn settings(&self) -> &Settings { + &self.settings + } + + /// Returns the primary [`Keyspace`] of the WCN cluster. + pub fn keyspace(&self) -> &Keyspace { + &self.keyspace + } + + /// Returns the ongoing [`Migration`] of the WCN cluster. + pub fn migration(&self) -> Option<&Migration> { + self.migration.as_ref() + } + + /// Returns the ongoing [`Maintenance`] of the WCN cluster. + pub fn maintenance(&self) -> Option<&Maintenance> { + self.maintenance.as_ref() + } + + /// Returns [`NodeOperators`] of the WCN cluster. + pub fn node_operators(&self) -> &NodeOperators { + &self.node_operators + } + + pub(super) fn require_no_migration(&self) -> Result<(), migration::InProgressError> { + if let Some(migration) = self.migration() { + return Err(migration::InProgressError(migration.id())); + } + + Ok(()) + } + + pub(super) fn require_no_maintenance(&self) -> Result<(), maintenance::InProgressError> { + if let Some(maintenance) = self.maintenance() { + return Err(maintenance::InProgressError(*maintenance.slot())); + } + + Ok(()) + } + + pub(super) fn require_migration(&self) -> Result<&Migration, migration::NotFoundError> { + self.migration.as_ref().ok_or(migration::NotFoundError) + } + + pub(super) fn require_maintenance(&self) -> Result<&Maintenance, maintenance::NotFoundError> { + self.maintenance.as_ref().ok_or(maintenance::NotFoundError) + } + + /// Applies the provided [`Event`] to this [`View`]. + pub async fn apply_event(mut self, event: Event) -> Result + where + Keyspace: keyspace::sealed::Calculate, + { + let new_version = event.cluster_version(); + + if new_version != self.cluster_version + 1 { + return Err(Error::ClusterVersionNotMonotonic( + self.cluster_version, + new_version, + )); + } + + match event { + Event::MigrationStarted(evt) => evt.apply(&mut self).await, + Event::MigrationDataPullCompleted(evt) => evt.apply(&mut self), + Event::MigrationCompleted(evt) => evt.apply(&mut self), + Event::MigrationAborted(evt) => evt.apply(&mut self), + Event::MaintenanceStarted(evt) => evt.apply(&mut self), + Event::MaintenanceFinished(evt) => evt.apply(&mut self), + Event::NodeOperatorAdded(evt) => evt.apply(&mut self), + Event::NodeOperatorUpdated(evt) => evt.apply(&mut self), + Event::NodeOperatorRemoved(evt) => evt.apply(&mut self), + Event::SettingsUpdated(evt) => evt.apply(&mut self), + Event::OwnershipTransferred(evt) => evt.apply(&mut self), + }?; + + self.cluster_version = new_version; + + Ok(self) + } +} + +impl View { + pub(super) async fn calculate_keyspace(self) -> View + where + Keyspace: keyspace::sealed::Calculate, + { + let (keyspace, migration) = tokio::join!( + (*self.keyspace).clone().calculate(), + OptionFuture::from(self.migration.map(Migration::calculate_keyspace)) + ); + + View { + node_operators: self.node_operators, + ownership: self.ownership, + settings: self.settings, + keyspace: Arc::new(keyspace), + migration, + maintenance: self.maintenance, + cluster_version: self.cluster_version, + } + } +} + +impl View { + pub(super) fn deserialize( + self, + ) -> Result, node_operator::DataDeserializationError> { + Ok(View { + node_operators: self.node_operators.deserialize()?, + ownership: self.ownership, + settings: self.settings, + keyspace: self.keyspace, + migration: self.migration, + maintenance: self.maintenance, + cluster_version: self.cluster_version, + }) + } +} + +impl migration::Started { + async fn apply(self, view: &mut View) -> Result<()> + where + Keyspace: keyspace::sealed::Calculate, + { + view.require_no_migration()?; + view.require_no_maintenance()?; + view.keyspace().require_diff(&self.new_keyspace)?; + + view.migration = Some(Migration::new( + self.migration_id, + self.new_keyspace.calculate().await, + view.node_operators.occupied_indexes(), + )); + + Ok(()) + } +} + +impl migration::DataPullCompleted { + pub(super) fn apply(self, view: &mut View) -> Result<()> { + let idx = view.node_operators.require_idx(&self.operator_id)?; + view.require_migration()? + .require_id(self.migration_id)? + .require_pulling(idx)?; + + if let Some(migration) = view.migration.as_mut() { + migration.complete_pull(idx); + } + + Ok(()) + } +} + +impl migration::Completed { + pub(super) fn apply(self, view: &mut View) -> Result<()> { + let idx = view.node_operators.require_idx(&self.operator_id)?; + view.require_migration()? + .require_id(self.migration_id)? + .require_pulling(idx)? + .require_pulling_count(1)?; + + view.keyspace = view.migration.take().unwrap().into_keyspace(); + + Ok(()) + } +} + +impl migration::Aborted { + pub(super) fn apply(self, view: &mut View) -> Result<()> { + view.require_migration()?.require_id(self.migration_id)?; + view.migration = None; + + Ok(()) + } +} + +impl maintenance::Started { + pub(super) fn apply(self, view: &mut View) -> Result<()> { + view.require_no_migration()?; + view.require_no_maintenance()?; + + view.maintenance = Some(Maintenance::new(self.operator_id)); + + Ok(()) + } +} + +impl maintenance::Finished { + pub(super) fn apply(self, view: &mut View) -> Result<()> { + view.require_maintenance()?; + view.maintenance = None; + + Ok(()) + } +} + +impl node_operator::Added { + pub(super) fn apply(self, view: &mut View) -> Result<()> { + view.node_operators() + .require_not_exists(&self.operator.id)? + .require_free_slot(self.idx)?; + + view.node_operators.set(self.idx, Some(self.operator)); + + Ok(()) + } +} + +impl node_operator::Updated { + pub(super) fn apply(self, view: &mut View) -> Result<()> { + let idx = view.node_operators.require_idx(&self.operator.id)?; + view.node_operators.set(idx, Some(self.operator)); + + Ok(()) + } +} + +impl node_operator::Removed { + pub(super) fn apply(self, view: &mut View) -> Result<()> { + let idx = view.node_operators.require_idx(&self.id)?; + view.node_operators.set(idx, None); + + Ok(()) + } +} + +impl settings::Updated { + pub(super) fn apply(self, view: &mut View) -> Result<()> { + view.settings = self.settings; + + Ok(()) + } +} + +impl ownership::Transferred { + pub(super) fn apply(self, view: &mut View) -> Result<()> { + view.ownership.transfer(self.new_owner); + + Ok(()) + } +} + +/// Error of [`View::apply_event`] caused by a race condition or by an incorrect +/// implementation of the [`SmartContract`](crate::SmartContract). +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("Cluster version change wasn't monotonic: {_0} -> {_1}")] + ClusterVersionNotMonotonic(cluster::Version, cluster::Version), + + #[error(transparent)] + MigrationInProgress(#[from] migration::InProgressError), + + #[error(transparent)] + MaintenanceInProgress(#[from] maintenance::InProgressError), + + #[error(transparent)] + NoMigration(#[from] migration::NotFoundError), + + #[error(transparent)] + NoMaintenance(#[from] maintenance::NotFoundError), + + #[error(transparent)] + WrongMigrationId(#[from] migration::WrongIdError), + + #[error(transparent)] + SameKeyspace(#[from] keyspace::SameKeyspaceError), + + #[error(transparent)] + NotPulling(#[from] migration::OperatorNotPullingError), + + #[error(transparent)] + WrongPullingOperatorsCount(#[from] migration::WrongPullingOperatorsCountError), + + #[error(transparent)] + OperatorNotFound(#[from] node_operator::NotFoundError), + + #[error(transparent)] + OperatorAlreadyExists(#[from] node_operator::AlreadyExistsError), + + #[error(transparent)] + OperatorSlotOccupied(#[from] node_operators::SlotOccupiedError), +} + +/// Result of [`View::apply_event`]. +pub type Result = std::result::Result; + +/// Error of fetching [`View`] from a [`smart_contract`]. +#[derive(Debug, thiserror::Error)] +pub enum FetchError { + #[error(transparent)] + DataDeserialization(#[from] node_operator::DataDeserializationError), + + #[error("Smart-contract: {0}")] + SmartContractRead(#[from] smart_contract::ReadError), +} diff --git a/crates/cluster/tests/integration.rs b/crates/cluster/tests/integration.rs new file mode 100644 index 00000000..da66702f --- /dev/null +++ b/crates/cluster/tests/integration.rs @@ -0,0 +1,159 @@ +use { + cluster::{ + keyspace::ReplicationStrategy, + node_operator, + smart_contract::{ + self, + evm::{self, RpcProvider}, + Read, + Signer, + }, + Cluster, + Node, + NodeOperator, + Settings, + }, + libp2p::PeerId, + std::{collections::HashSet, net::SocketAddrV4, time::Duration}, + tracing_subscriber::EnvFilter, +}; + +// Anvil private keys with balances +const PRIVATE_KEYS: [&'static str; 10] = [ + "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", + "0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d", + "0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a", + "0x7c852118294e51e653712a81e05800f419141751be58f605c371e15141b007a6", + "0x47e179ec197488593b187f80a00eb0da91f1b9d0b13f8733639f19c30a34926a", + "0x8b3a350cf5c34c9194ca85829a2df0ec3153be0318b5e2d3348e872092edffba", + "0x92db14e403b83dfe3df233f83dfa3a0d7096f21ca9b0d6d6b8d88b2b4ec1564e", + "0x4bbbf85ce3377467afe5d46f804f221813b2bb87f24d81f60f1fcdbf7cbf4356", + "0xdbda1821b80551c9d65939329250298aa3472ba22feea921c0cf5d620ea67b97", + "0x2a871d0798f97d79848a013d4936a73bf4cc922c825d33c1cf7073dff6d409c6", +]; + +#[tokio::test] +async fn test_suite() { + let subscriber = tracing_subscriber::FmtSubscriber::builder() + .with_max_level(tracing::Level::INFO) + .with_env_filter(EnvFilter::from_default_env()) + .finish(); + tracing::subscriber::set_global_default(subscriber).unwrap(); + + let settings = Settings { + max_node_operator_data_bytes: 4096, + }; + + let signer = Signer::try_from_private_key( + "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", + ) + .unwrap(); + + let provider = provider(signer).await; + + let operators = (1..=5).map(|n| new_node_operator(n)).collect(); + + let cluster = Cluster::>::deploy(&provider, settings, operators) + .await + .unwrap(); + + for idx in 5..=7 { + cluster + .add_node_operator(idx, new_node_operator(idx + 1)) + .await + .unwrap(); + } + + cluster + .start_migration(cluster::migration::Plan { + remove: [operator_id(1)].into_iter().collect(), + add: [operator_id(6), operator_id(7), operator_id(8)] + .into_iter() + .collect(), + replication_strategy: ReplicationStrategy::UniformDistribution, + }) + .await + .unwrap(); + + for idx in 1..=7 { + connect(idx + 1, cluster.smart_contract().address()) + .await + .complete_migration(1) + .await + .unwrap(); + } + + tokio::time::sleep(Duration::from_secs(1)).await; + + cluster + .start_migration(cluster::migration::Plan { + remove: HashSet::default(), + add: [operator_id(1)].into_iter().collect(), + replication_strategy: ReplicationStrategy::UniformDistribution, + }) + .await + .unwrap(); + + cluster.abort_migration(2).await.unwrap(); + + cluster.start_maintenance().await.unwrap(); + cluster.finish_maintenance().await.unwrap(); + + cluster.remove_node_operator(operator_id(1)).await.unwrap(); + + let mut operator2 = new_node_operator(2); + operator2.data.name = node_operator::Name::new("NewName").unwrap(); + cluster.update_node_operator(operator2).await.unwrap(); + + cluster + .update_settings(Settings { + max_node_operator_data_bytes: 10000, + }) + .await + .unwrap(); + + cluster + .transfer_ownership(*new_signer(9).address()) + .await + .unwrap(); +} + +fn new_node_operator(n: u8) -> NodeOperator { + let data = node_operator::Data { + name: node_operator::Name::new(format!("Operator{n}")).unwrap(), + nodes: vec![Node { + peer_id: PeerId::random(), + addr: SocketAddrV4::new([127, 0, 0, 1].into(), 40000 + n as u16), + }], + clients: vec![], + }; + + NodeOperator { + id: operator_id(n), + data, + } +} + +fn operator_id(n: u8) -> node_operator::Id { + *new_signer(n).address() +} + +fn new_signer(n: u8) -> Signer { + Signer::try_from_private_key(PRIVATE_KEYS[n as usize]).unwrap() +} + +async fn provider(signer: Signer) -> RpcProvider { + RpcProvider::new("ws://127.0.0.1:8545".parse().unwrap(), signer) + .await + .unwrap() +} + +async fn connect( + operator: u8, + address: smart_contract::Address, +) -> Cluster> { + let provider = provider(new_signer(operator)).await; + Cluster::>::connect(&provider, address) + .await + .unwrap() +} From 48a4bc00305ad52f69d4467d63df6ec7c715fbaf Mon Sep 17 00:00:00 2001 From: Darksome Date: Fri, 6 Jun 2025 16:22:28 +0000 Subject: [PATCH 45/79] fix: deps --- Cargo.lock | 215 ++++++++++++++++++++++++++++++------------ crates/rpc/Cargo.toml | 2 +- crates/wcn/Cargo.toml | 2 +- 3 files changed, 157 insertions(+), 62 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a2bfc73e..66d3f769 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1434,6 +1434,12 @@ version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ce89b21cab1437276d2650d57e971f9d548a2d9037cc231abdc0562b97498ce" +[[package]] +name = "bytemuck" +version = "1.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9134a6ef01ce4b366b50689c94f82c14bc72bc5d0386829828a2e2752ef7958c" + [[package]] name = "byteorder" version = "1.5.0" @@ -1579,6 +1585,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "chrono" version = "0.4.39" @@ -1765,15 +1777,14 @@ dependencies = [ [[package]] name = "config" -version = "0.14.0" +version = "0.15.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7328b20597b53c2454f0b1919720c25c7339051c02b72b7e05409e00b14132be" +checksum = "595aae20e65c3be792d05818e8c63025294ac3cb7e200f11459063a352a6ef80" dependencies = [ - "lazy_static", - "nom", "pathdiff", "serde", "toml", + "winnow 0.7.10", ] [[package]] @@ -1832,6 +1843,16 @@ dependencies = [ "libc", ] +[[package]] +name = "core-foundation" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.6" @@ -2570,6 +2591,18 @@ dependencies = [ "once_cell", ] +[[package]] +name = "fastbloom" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27cea6e7f512d43b098939ff4d5a5d6fe3db07971e1d05176fe26c642d33f5b8" +dependencies = [ + "getrandom 0.3.3", + "rand 0.9.1", + "siphasher", + "wide", +] + [[package]] name = "faster-hex" version = "0.9.0" @@ -2882,8 +2915,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi 0.11.0+wasi-snapshot-preview1", + "wasm-bindgen", ] [[package]] @@ -2893,9 +2928,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ "cfg-if", + "js-sys", "libc", "r-efi", "wasi 0.14.2+wasi-0.2.4", + "wasm-bindgen", ] [[package]] @@ -3962,16 +3999,18 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jni" -version = "0.19.0" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6df18c2e3db7e453d3c6ac5b3e9d5182664d28788126d39b91f2d1e22b017ec" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" dependencies = [ "cesu8", + "cfg-if", "combine", "jni-sys", "log", "thiserror 1.0.64", "walkdir", + "windows-sys 0.45.0", ] [[package]] @@ -3992,10 +4031,11 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.69" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" dependencies = [ + "once_cell", "wasm-bindgen", ] @@ -4389,6 +4429,12 @@ dependencies = [ "hashbrown 0.15.3", ] +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + [[package]] name = "lz4-sys" version = "1.9.4" @@ -4649,7 +4695,7 @@ dependencies = [ "openssl-probe", "openssl-sys", "schannel", - "security-framework", + "security-framework 2.11.1", "security-framework-sys", "tempfile", ] @@ -4662,7 +4708,7 @@ checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" dependencies = [ "bitflags 2.6.0", "cfg-if", - "cfg_aliases", + "cfg_aliases 0.1.1", "libc", "memoffset", ] @@ -5381,38 +5427,45 @@ dependencies = [ [[package]] name = "quinn" -version = "0.11.5" +version = "0.11.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c7c5fdde3cdae7203427dc4f0a68fe0ed09833edc525a03456b153b79828684" +checksum = "626214629cda6781b6dc1d316ba307189c85ba657213ce642d9c77670f8202c8" dependencies = [ "bytes", + "cfg_aliases 0.2.1", "pin-project-lite", "quinn-proto", "quinn-udp", "rustc-hash 2.1.1", "rustls", "socket2", - "thiserror 1.0.64", + "thiserror 2.0.12", "tokio", "tracing", + "web-time", ] [[package]] name = "quinn-proto" -version = "0.11.8" +version = "0.11.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fadfaed2cd7f389d0161bb73eeb07b7b78f8691047a6f3e73caaeae55310a4a6" +checksum = "49df843a9161c85bb8aae55f101bc0bac8bcafd637a620d9122fd7e0b2f7422e" dependencies = [ "bytes", - "rand 0.8.5", + "fastbloom", + "getrandom 0.3.3", + "lru-slab", + "rand 0.9.1", "ring 0.17.8", "rustc-hash 2.1.1", "rustls", + "rustls-pki-types", "rustls-platform-verifier", "slab", - "thiserror 1.0.64", + "thiserror 2.0.12", "tinyvec", "tracing", + "web-time", ] [[package]] @@ -5989,15 +6042,14 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.7.3" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5" +checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" dependencies = [ "openssl-probe", - "rustls-pemfile", "rustls-pki-types", "schannel", - "security-framework", + "security-framework 3.2.0", ] [[package]] @@ -6016,16 +6068,17 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" dependencies = [ + "web-time", "zeroize", ] [[package]] name = "rustls-platform-verifier" -version = "0.3.4" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afbb878bdfdf63a336a5e63561b1835e7a8c91524f51621db870169eac84b490" +checksum = "19787cda76408ec5404443dc8b31795c87cd8fec49762dc75fa727740d34acc1" dependencies = [ - "core-foundation", + "core-foundation 0.10.1", "core-foundation-sys", "jni", "log", @@ -6033,11 +6086,11 @@ dependencies = [ "rustls", "rustls-native-certs", "rustls-platform-verifier-android", - "rustls-webpki 0.102.8", - "security-framework", + "rustls-webpki 0.103.3", + "security-framework 3.2.0", "security-framework-sys", - "webpki-roots", - "winapi", + "webpki-root-certs 0.26.11", + "windows-sys 0.52.0", ] [[package]] @@ -6056,16 +6109,6 @@ dependencies = [ "untrusted 0.9.0", ] -[[package]] -name = "rustls-webpki" -version = "0.102.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" -dependencies = [ - "rustls-pki-types", - "untrusted 0.9.0", -] - [[package]] name = "rustls-webpki" version = "0.103.3" @@ -6112,6 +6155,15 @@ version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" +[[package]] +name = "safe_arch" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96b02de82ddbe1b636e6170c21be622223aea188ef2e139be0a5b219ec215323" +dependencies = [ + "bytemuck", +] + [[package]] name = "same-file" version = "1.0.6" @@ -6179,18 +6231,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ "bitflags 2.6.0", - "core-foundation", + "core-foundation 0.9.4", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271720403f46ca04f7ba6f55d438f8bd878d6b8ca0a1046e8228c4145bcbb316" +dependencies = [ + "bitflags 2.6.0", + "core-foundation 0.10.1", "core-foundation-sys", "libc", - "num-bigint", "security-framework-sys", ] [[package]] name = "security-framework-sys" -version = "2.12.0" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" +checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" dependencies = [ "core-foundation-sys", "libc", @@ -6453,6 +6517,12 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "siphasher" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" + [[package]] name = "skeptic" version = "0.13.7" @@ -7077,16 +7147,9 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_write", "winnow 0.7.10", ] -[[package]] -name = "toml_write" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" - [[package]] name = "tower" version = "0.4.13" @@ -7534,23 +7597,24 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.92" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ "cfg-if", + "once_cell", + "rustversion", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.92" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" dependencies = [ "bumpalo", "log", - "once_cell", "proc-macro2", "quote", "syn 2.0.101", @@ -7571,9 +7635,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.92" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -7581,9 +7645,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.92" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", @@ -7594,9 +7658,12 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.92" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] [[package]] name = "wasmtimer" @@ -7998,6 +8065,24 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki-root-certs" +version = "0.26.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75c7f0ef91146ebfb530314f5f1d24528d7f0767efbfd31dce919275413e393e" +dependencies = [ + "webpki-root-certs 1.0.0", +] + +[[package]] +name = "webpki-root-certs" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01a83f7e1a9f8712695c03eabe9ed3fbca0feff0152f33f12593e5a6303cb1a4" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "webpki-roots" version = "0.26.6" @@ -8007,6 +8092,16 @@ dependencies = [ "rustls-pki-types", ] +[[package]] +name = "wide" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41b5576b9a81633f3e8df296ce0063042a73507636cbe956c61133dd7034ab22" +dependencies = [ + "bytemuck", + "safe_arch", +] + [[package]] name = "winapi" version = "0.3.9" diff --git a/crates/rpc/Cargo.toml b/crates/rpc/Cargo.toml index c1403785..c0887893 100644 --- a/crates/rpc/Cargo.toml +++ b/crates/rpc/Cargo.toml @@ -35,7 +35,7 @@ thiserror = "1.0" wc = { workspace = true, features = ["collections", "future", "metrics"] } metrics = { workspace = true } -quinn = "0.11" +quinn = "0.11.8" quinn-proto = "0.11" libp2p-tls = "0.5" backoff = { version = "0.4", features = ["tokio"] } diff --git a/crates/wcn/Cargo.toml b/crates/wcn/Cargo.toml index f3fc2650..7e892e51 100644 --- a/crates/wcn/Cargo.toml +++ b/crates/wcn/Cargo.toml @@ -27,7 +27,7 @@ thiserror = "1.0" tokio = "1.37" serde = { version = "1.0", features = ["derive"] } serde_json = "1" -config = { version = "0.14", default-features = false, features = ["toml"] } +config = { version = "0.15", default-features = false, features = ["toml"] } tap = "1.0" metrics-exporter-prometheus = "0.15" From 36a61d9447d8ca29dc3673dde0d572078dab9aa1 Mon Sep 17 00:00:00 2001 From: Darksome Date: Mon, 9 Jun 2025 09:48:34 +0000 Subject: [PATCH 46/79] fixes --- clippy.toml | 4 +-- crates/cluster/src/node_operators.rs | 3 +-- crates/cluster/src/smart_contract/evm.rs | 4 +-- crates/cluster/src/task.rs | 31 ++++++++++++------------ crates/cluster/tests/integration.rs | 2 ++ deny.toml | 3 ++- 6 files changed, 24 insertions(+), 23 deletions(-) diff --git a/clippy.toml b/clippy.toml index 62fa634f..48125e01 100644 --- a/clippy.toml +++ b/clippy.toml @@ -1,5 +1,5 @@ await-holding-invalid-types = [ - "tracing::trace::Entered", - "tracing::trace::EnteredSpan", + "tracing::span::Entered", + "tracing::span::EnteredSpan", ] absolute-paths-max-segments = 4 diff --git a/crates/cluster/src/node_operators.rs b/crates/cluster/src/node_operators.rs index 922a96e1..60804d82 100644 --- a/crates/cluster/src/node_operators.rs +++ b/crates/cluster/src/node_operators.rs @@ -108,8 +108,7 @@ impl NodeOperators { &self, id: &node_operator::Id, ) -> Result { - self.get_idx(id) - .ok_or_else(|| node_operator::NotFoundError(*id)) + self.get_idx(id).ok_or(node_operator::NotFoundError(*id)) } pub(super) fn require_not_exists( diff --git a/crates/cluster/src/smart_contract/evm.rs b/crates/cluster/src/smart_contract/evm.rs index 1e9db5b7..776e884c 100644 --- a/crates/cluster/src/smart_contract/evm.rs +++ b/crates/cluster/src/smart_contract/evm.rs @@ -259,7 +259,7 @@ impl TryFrom for Event { let topics = log.topics(); let data = &log.data().data; - Ok(match log.topics().get(0) { + Ok(match log.topics().first() { Some(&Cluster::MigrationStarted::SIGNATURE_HASH) => { Cluster::MigrationStarted::decode_raw_log_validate(topics, data)?.try_into()? } @@ -538,7 +538,7 @@ impl TryFrom for cluster::View<(), node_operator let prev_keyspace_version = view .keyspaceVersion .checked_sub(1) - .ok_or_else(|| ReadError::InvalidData(format!("Invalid keyspace::Version")))?; + .ok_or_else(|| ReadError::InvalidData("Invalid keyspace::Version".into()))?; let keyspace = try_keyspace(prev_keyspace_version)?; let migration_keyspace = try_keyspace(view.keyspaceVersion)?; diff --git a/crates/cluster/src/task.rs b/crates/cluster/src/task.rs index af274025..e1be9e5e 100644 --- a/crates/cluster/src/task.rs +++ b/crates/cluster/src/task.rs @@ -43,24 +43,22 @@ where } async fn run(mut self) { - loop { - // apply initial events until they finish / first error - if let Some(events) = self.initial_events.take() { - match self.apply_events(events).await { - Ok(()) => tracing::warn!("Initial event stream finished"), - Err(err) => tracing::error!(%err, "Failed to apply initial events"), - } + // apply initial events until they finish / first error + if let Some(events) = self.initial_events.take() { + match self.apply_events(events).await { + Ok(()) => tracing::warn!("Initial event stream finished"), + Err(err) => tracing::error!(%err, "Failed to apply initial events"), } + } - loop { - // when we fail for whatever reason - subscribe again and refetch the whole - // state - match self.update_view().await { - Ok(()) => tracing::warn!("Event stream finished"), - Err(err) => { - tracing::error!(%err, "Failed to update cluster::View"); - tokio::time::sleep(Duration::from_secs(60)).await; - } + loop { + // when we fail for whatever reason - subscribe again and refetch the whole + // state + match self.update_view().await { + Ok(()) => tracing::warn!("Event stream finished"), + Err(err) => { + tracing::error!(%err, "Failed to update cluster::View"); + tokio::time::sleep(Duration::from_secs(60)).await; } } } @@ -79,6 +77,7 @@ where self.apply_events(events).await } + #[allow(clippy::needless_pass_by_ref_mut)] // otherwise `Steam` is required to be `Sync` async fn apply_events( &mut self, events: impl Stream>, diff --git a/crates/cluster/tests/integration.rs b/crates/cluster/tests/integration.rs index da66702f..201eaba9 100644 --- a/crates/cluster/tests/integration.rs +++ b/crates/cluster/tests/integration.rs @@ -32,6 +32,8 @@ const PRIVATE_KEYS: [&'static str; 10] = [ "0x2a871d0798f97d79848a013d4936a73bf4cc922c825d33c1cf7073dff6d409c6", ]; +// TODO: Setup Anvil on CI +#[ignore] #[tokio::test] async fn test_suite() { let subscriber = tracing_subscriber::FmtSubscriber::builder() diff --git a/deny.toml b/deny.toml index a59afad3..d340b4a9 100644 --- a/deny.toml +++ b/deny.toml @@ -12,7 +12,8 @@ allow = [ "ISC", "BSL-1.0", "MPL-2.0", - "Zlib" + "Zlib", + "CDLA-Permissive-2.0" ] exceptions = [{ name = "unicode-ident", allow = ["Unicode-DFS-2016"] }] From 6382773cdb1ee12381e0c7fb332ba3a104517f79 Mon Sep 17 00:00:00 2001 From: Github Bot Date: Mon, 9 Jun 2025 09:49:04 +0000 Subject: [PATCH 47/79] Bump VERSION to 250609.0 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 0d1280d9..8ab48a06 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -250606.0 +250609.0 From f1a5e199f45784db9858d6ae3dfa6e92e4d96940 Mon Sep 17 00:00:00 2001 From: Darksome Date: Mon, 9 Jun 2025 09:59:49 +0000 Subject: [PATCH 48/79] fixes --- crates/cluster/Cargo.toml | 1 + crates/cluster/tests/integration.rs | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/cluster/Cargo.toml b/crates/cluster/Cargo.toml index 9622013a..dac5604c 100644 --- a/crates/cluster/Cargo.toml +++ b/crates/cluster/Cargo.toml @@ -2,6 +2,7 @@ name = "cluster" version = "0.1.0" edition = "2021" +publish = false [lints] workspace = true diff --git a/crates/cluster/tests/integration.rs b/crates/cluster/tests/integration.rs index 201eaba9..617ba201 100644 --- a/crates/cluster/tests/integration.rs +++ b/crates/cluster/tests/integration.rs @@ -19,7 +19,7 @@ use { }; // Anvil private keys with balances -const PRIVATE_KEYS: [&'static str; 10] = [ +const PRIVATE_KEYS: [&str; 10] = [ "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", "0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d", "0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a", @@ -53,7 +53,7 @@ async fn test_suite() { let provider = provider(signer).await; - let operators = (1..=5).map(|n| new_node_operator(n)).collect(); + let operators = (1..=5).map(new_node_operator).collect(); let cluster = Cluster::>::deploy(&provider, settings, operators) .await From 1b035919a642a6fe48d21c08ef8b90bae491cef3 Mon Sep 17 00:00:00 2001 From: Darksome Date: Mon, 9 Jun 2025 10:34:34 +0000 Subject: [PATCH 49/79] fix: dockerignore --- .dockerignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.dockerignore b/.dockerignore index b2b1a8aa..cd93afe5 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,4 +1,5 @@ * +!contracts !crates/** !src !Cargo.toml From f084b876ef0edc81176257e3219d38581b4dcb4e Mon Sep 17 00:00:00 2001 From: Darksome Date: Thu, 12 Jun 2025 10:36:40 +0000 Subject: [PATCH 50/79] WIP --- Cargo.lock | 8 +- Cargo.toml | 1 + crates/storage_api2/Cargo.toml | 13 +- crates/storage_api2/src/lib.rs | 672 +++++++++++--------- crates/storage_api2/src/operation.rs | 392 ++++++++++++ crates/storage_api2/src/{ => rpc}/client.rs | 94 +-- crates/storage_api2/src/rpc/mod.rs | 235 +++++++ crates/storage_api2/src/{ => rpc}/server.rs | 146 ++--- 8 files changed, 1086 insertions(+), 475 deletions(-) create mode 100644 crates/storage_api2/src/operation.rs rename crates/storage_api2/src/{ => rpc}/client.rs (82%) create mode 100644 crates/storage_api2/src/rpc/mod.rs rename crates/storage_api2/src/{ => rpc}/server.rs (75%) diff --git a/Cargo.lock b/Cargo.lock index f91e2fdf..c85006c3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8004,7 +8004,7 @@ dependencies = [ "futures", "smallvec", "tap", - "thiserror", + "thiserror 1.0.64", "tokio", "tracing", "wc", @@ -8067,10 +8067,12 @@ dependencies = [ name = "wcn_storage_api2" version = "0.1.0" dependencies = [ - "arc-swap", + "const-hex", + "derive_more 1.0.0", "futures", "serde", - "thiserror", + "strum", + "thiserror 1.0.64", "time", "tracing", "wc", diff --git a/Cargo.toml b/Cargo.toml index ae2fcead..b101ad08 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -55,6 +55,7 @@ futures = "0.3" backoff = { version = "0.4", features = ["tokio"] } tracing = "0.1" tokio-stream = "0.1" +strum = "0.27" [workspace.lints.clippy] all = { level = "deny", priority = -1 } diff --git a/crates/storage_api2/Cargo.toml b/crates/storage_api2/Cargo.toml index 4b687423..fe419c01 100644 --- a/crates/storage_api2/Cargo.toml +++ b/crates/storage_api2/Cargo.toml @@ -8,12 +8,15 @@ publish = false workspace = true [features] -client = ["wcn_rpc/client", "arc-swap"] -server = ["wcn_rpc/server"] +default = ["rpc_client", "rpc_server"] +rpc_client = ["wcn_rpc/client"] +rpc_server = ["wcn_rpc/server"] [dependencies] -wc = { workspace = true, features = ["future"] } +wc = { workspace = true, features = ["future", "metrics"] } auth = { workspace = true } +derive_more = { workspace = true, features = ["from", "try_into"] } +strum = { workspace = true , features = ["derive"] } wcn_rpc = { workspace = true } serde = "1" @@ -21,6 +24,4 @@ thiserror = "1" tracing = "0.1" futures = "0.3" time = "0.3" - -# client -arc-swap = { version = "1.7", optional = true } +const-hex = "1.14" diff --git a/crates/storage_api2/src/lib.rs b/crates/storage_api2/src/lib.rs index 76d34778..96b10a5d 100644 --- a/crates/storage_api2/src/lib.rs +++ b/crates/storage_api2/src/lib.rs @@ -5,112 +5,383 @@ pub use { wcn_rpc::{identity, Multiaddr, PeerAddr, PeerId}, }; use { - serde::{Deserialize, Serialize}, - std::{io, time::Duration}, + derive_more::AsRef, + futures::{FutureExt as _, TryFutureExt as _}, + std::{future::Future, marker::PhantomData, str::FromStr, time::Duration}, time::OffsetDateTime as DateTime, - wcn_rpc::{self as rpc, transport}, }; -#[cfg(feature = "client")] -pub mod client; -#[cfg(feature = "client")] -pub use client::Client; -#[cfg(feature = "server")] -pub mod server; -#[cfg(feature = "server")] -pub use server::Server; +pub mod operation; +pub use operation::Operation; + +#[cfg(any(feature = "rpc_client", feature = "rpc_server"))] +pub mod rpc; + +/// Namespace within WCN network. +/// +/// Namespaces are isolated and every [`StorageApi`] [`Operation`] gets executed +/// on a specific [`Namespace`]. +#[derive(Clone, Copy, Debug)] +pub struct Namespace { + /// ID of the node operator to which this namespace belongs. + /// + /// Currentry an Ethereum address. + node_operator_id: [u8; 20], + + /// ID of this [`Namespace`] within the node operator scope. + id: u8, +} + +/// WCN Storage API. +/// +/// Lingua franka of the WCN network: +/// - Clients use it to execute storage operations on the network via sending +/// them to Replication Coordinators (WCN nodes hosting coordinator RPC +/// servers). +/// - Replication Coordinators use it to replicate storage operations across the +/// network via sending them to Replicas (WCN nodes hosting replica RPC +/// servers). +/// - Replicas use it to finally execute the operations on their local WCN +/// Database instances. +pub trait StorageApi { + type Error: From; + + /// Executes the provided [`operation::Get`]. + fn get( + &self, + get: operation::Get, + ) -> impl Future, Self::Error>> + Send { + self.execute(get).map(operation::Output::downcast_result) + } + + /// Executes the provided [`operation::Set`]. + fn set(&self, set: operation::Set) -> impl Future> + Send { + self.execute(set).map(operation::Output::downcast_result) + } + + /// Executes the provided [`operation::Del`]. + fn del(&self, del: operation::Del) -> impl Future> + Send { + self.execute(del).map(operation::Output::downcast_result) + } + + /// Executes the provided [`operation::GetExp`]. + fn get_exp( + &self, + get_exp: operation::GetExp, + ) -> impl Future, Self::Error>> + Send { + self.execute(get_exp) + .map(operation::Output::downcast_result) + } + + /// Executes the provided [`operation::SetExp`]. + fn set_exp( + &self, + set_exp: operation::SetExp, + ) -> impl Future> + Send { + self.execute(set_exp) + .map(operation::Output::downcast_result) + } + + /// Executes the provided [`operation::HGet`]. + fn hget( + &self, + hget: operation::HGet, + ) -> impl Future, Self::Error>> + Send { + self.execute(hget).map(operation::Output::downcast_result) + } + + /// Executes the provided [`operation::HSet`]. + fn hset(&self, hset: operation::HSet) -> impl Future> + Send { + self.execute(hset).map(operation::Output::downcast_result) + } + + /// Executes the provided [`operation::HDel`]. + fn hdel(&self, hdel: operation::HDel) -> impl Future> + Send { + self.execute(hdel).map(operation::Output::downcast_result) + } + + /// Executes the provided [`operation::HGetExp`]. + fn hget_exp( + &self, + hget_exp: operation::HGetExp, + ) -> impl Future, Self::Error>> + Send { + self.execute(hget_exp) + .map(operation::Output::downcast_result) + } + + /// Executes the provided [`operation::HSetExp`]. + fn hset_exp( + &self, + hset_exp: operation::HSetExp, + ) -> impl Future> + Send { + self.execute(hset_exp) + .map(operation::Output::downcast_result) + } -const RPC_SERVER_NAME: rpc::ServerName = rpc::ServerName::new("storage_api"); + /// Executes the provided [`operation::HCard`]. + fn hcard( + &self, + hcard: operation::HCard, + ) -> impl Future> + Send { + self.execute(hcard).map(operation::Output::downcast_result) + } -/// RPC error codes produced by this module. -mod error_code { - /// Client is not authorized to perform the operation. - pub const UNAUTHORIZED: &str = "unauthorized"; + /// Executes the provided [`operation::HScan`]. + fn hscan( + &self, + hscan: operation::HScan, + ) -> impl Future> + Send { + self.execute(hscan).map(operation::Output::downcast_result) + } - /// Keyspace versions of the client and the server don't match. - pub const KEYSPACE_VERSION_MISMATCH: &str = "keyspace_version_mismatch"; + /// Executes the provided [`StorageApi`] [`Operation`]. + fn execute( + &self, + operation: impl Into + Send, + ) -> impl Future> + Send; + + /// Makes this [`StorageApi`] [`Namespaced`]. + fn namespaced(self, namespace: impl Into) -> Namespaced + where + Self: Sized, + { + Namespaced { + namespace: namespace.into(), + storage_api: self, + _marker: PhantomData, + } + } - /// Provided key was invalid. - pub const INVALID_KEY: &str = "invalid_key"; + /// Makes this [`StorageApi`] [`Namespaced`] using references instead of + /// owned values. + fn namespaced_ref>(&self, namespace: N) -> Namespaced + where + Self: Sized, + { + Namespaced { + namespace, + storage_api: self, + _marker: PhantomData, + } + } } -/// Key in a KV storage. +/// A convienience wrapper around a [`StorageApi`] for client usage. +/// +/// Each function on this wrapper has the same arguments as the respective +/// [`Operation`] constructor with [`Namespace`] being automatically specified. #[derive(Clone, Debug)] -pub struct Key(Vec); +pub struct Namespaced> { + namespace: N, + storage_api: T, + _marker: PhantomData, +} + +/// Owned [`StorageApi`]. +/// +/// Required to make [`Namespaced`] generic over ownership. +pub struct Owned(S); + +impl Namespaced +where + N: AsRef, + T: AsRef, + S: StorageApi, +{ + /// Returns reference to the underlying [`Namespace`]. + pub fn namespace(&self) -> &Namespace { + self.namespace.as_ref() + } -impl Key { - /// Length of a [`Key`] namespace (prefix). - pub const NAMESPACE_LEN: usize = auth::PUBLIC_KEY_LEN; + /// Returns reference to the underlying [`StorageApi`]. + pub fn storage_api(&self) -> &S { + self.storage_api.as_ref() + } - const KIND_SHARED: u8 = 0; - const KIND_PRIVATE: u8 = 1; + /// Gets a [`Record`] by the provided [`Key`]. + pub async fn get(&self, key: Key>) -> Result, S::Error> { + self.storage_api() + .get(operation::Get::new(*self.namespace(), key)) + .await + } - /// Creates a new shared [`Key`] using the global namespace. - pub fn shared(bytes: impl AsRef<[u8]>) -> Self { - Self::new(bytes, None) + /// Sets a new [`Entry`]. + async fn set( + &self, + key: Key>, + value: Value>, + expiration: impl Into, + ) -> Result<(), S::Error> { + let namespace = *self.namespace(); + self.storage_api() + .set(operation::Set::new(namespace, key, value, expiration)) + .await } - /// Creates a new private [`Key`] using the provided `namespace`. - pub fn private(namespace: &auth::PublicKey, bytes: impl AsRef<[u8]>) -> Self { - Self::new(bytes, Some(namespace)) + /// Deletes an [`Entry`] by the provided [`Key`]. + async fn del(&self, key: Key>) -> Result<(), S::Error> { + self.storage_api() + .del(operation::Del::new(*self.namespace(), key)) + .await } - /// Returns namespace of this [`Key`]. - pub fn namespace(&self) -> Option<&[u8; Self::NAMESPACE_LEN]> { - match *self.0.first()? { - Self::KIND_PRIVATE => Some(self.0[1..][..Self::NAMESPACE_LEN].try_into().ok()?), - _ => None, - } + /// Gets an [`EntryExpiration`] by the provided [`Key`]. + async fn get_exp( + &self, + key: Key>, + ) -> Result, S::Error> { + self.storage_api() + .get_exp(operation::GetExp::new(*self.namespace(), key)) + .await } - /// Returns the full byte representation of this [`Key`] (including - /// namespace). - pub fn as_bytes(&self) -> &[u8] { - &self.0 + /// Sets [`EntryExpiration`] on the [`Entry`] with the provided [`Key`]. + async fn set_exp( + &self, + key: Key>, + expiration: impl Into, + ) -> Result<(), S::Error> { + self.storage_api() + .set_exp(operation::SetExp::new(*self.namespace(), key, expiration)) + .await } - /// Converts this [`Key`] into bytes. - pub fn into_bytes(self) -> Vec { - self.0 + /// Gets a map [`Record`] by the provided [`Key`] and [`Field`]. + async fn hget( + &self, + key: Key>, + field: Field>, + ) -> Result, S::Error> { + self.storage_api() + .hget(operation::HGet::new(*self.namespace(), key, field)) + .await } - #[cfg(feature = "server")] - fn from_raw_bytes(bytes: Vec) -> Option { - match *bytes.first()? { - Self::KIND_SHARED => Some(Self(bytes)), - Self::KIND_PRIVATE if bytes.len() > Self::NAMESPACE_LEN + 1 => Some(Self(bytes)), - _ => None, - } + /// Sets a new [`MapEntry`]. + async fn hset( + &self, + key: Key>, + field: Field>, + value: Value>, + expiration: impl Into, + ) -> Result<(), S::Error> { + let namespace = *self.namespace(); + self.storage_api() + .hset(operation::HSet::new( + namespace, key, value, field, expiration, + )) + .await + } + + /// Deletes a [`MapEntry`] by the provided [`Key`] and [`Field`]. + async fn hdel( + &self, + key: Key>, + field: Field>, + ) -> Result<(), S::Error> { + self.storage_api() + .hdel(operation::HDel::new(*self.namespace(), key, field)) + .await + } + + /// Gets a [`EntryExpiration`] by the provided [`Key`] and [`Field`]. + async fn hget_exp( + &self, + key: Key>, + field: Field>, + ) -> Result, S::Error> { + self.storage_api() + .hget_exp(operation::HGetExp::new(*self.namespace(), key, field)) + .await } - fn new(bytes: impl AsRef<[u8]>, namespace: Option<&auth::PublicKey>) -> Self { - let bytes = bytes.as_ref(); + /// Sets [`Expiration`] on the [`MapEntry`] with the provided [`Key`] and + /// [`Field`]. + async fn hset_exp( + &self, + key: Key>, + field: Field>, + expiration: impl Into, + ) -> Result<(), S::Error> { + let namespace = *self.namespace(); + self.storage_api() + .hset_exp(operation::HSetExp::new(namespace, key, field, expiration)) + .await + } + + /// Returns cardinality of the map with the provided [`Key`]. + async fn hcard(&self, key: Key>) -> Result { + self.storage_api() + .hcard(operation::HCard::new(*self.namespace(), key)) + .await + } - let prefix_len = if namespace.is_some() { - Self::NAMESPACE_LEN - } else { - 0 - }; + /// Returns a [`MapPage`] by iterating over the [`Field`]s of the map with + /// the provided [`Key`]. + async fn hscan( + &self, + key: Key>, + count: impl Into, + cursor: Option>>, + ) -> Result { + self.storage_api() + .hscan(operation::HScan::new(*self.namespace(), key, count, cursor)) + .await + } - let mut data = Vec::with_capacity(1 + prefix_len + bytes.len()); + /// Returns [`Value`]s of the map with the provided [`Key`]. + async fn hvals(&self, key: Key>) -> Result, S::Error> { + // `1000` is generous, relay has ~100 limit for these small maps + self.hscan(key, 1000u32, None::) + .map_ok(|page| page.records.into_iter().map(|rec| rec.value).collect()) + .await + } +} - if let Some(namespace) = namespace { - data.push(Self::KIND_PRIVATE); - data.extend_from_slice(namespace.as_ref()); - } else { - data.push(Self::KIND_SHARED); - }; +/// Raw bytes. +pub type Bytes = Vec; - data.extend_from_slice(bytes); - Self(data) +/// Key in a KV storage. +#[derive(Clone, Debug)] +pub struct Key(pub T); + +impl Key { + /// Converts `Self` into `Key`. + pub fn into(self) -> Key + where + T: Into, + { + Self(self.into()) } } /// Value in a KV storage. -pub type Value = Vec; +#[derive(Clone, Debug)] +pub struct Value(pub T); + +impl Value { + /// Converts `Self` into `Value`. + pub fn into(self) -> Value + where + T: Into, + { + Self(self.into()) + } +} /// Subkey of a [`MapEntry`]. -pub type Field = Vec; +#[derive(Clone, Debug)] +pub struct Field(pub T); + +impl Field { + /// Converts `Self` into `Field`. + pub fn into(self) -> Value + where + T: Into, + { + Self(self.into()) + } +} /// Basic KV storage entry. #[derive(Clone, Debug)] @@ -131,8 +402,8 @@ pub struct Entry { impl Entry { /// Creates a new [`Entry`]. pub fn new( - key: impl Into, - value: impl Into, + key: Key>, + value: Value>, expiration: impl Into, ) -> Self { Self { @@ -167,9 +438,9 @@ pub struct MapEntry { impl MapEntry { /// Creates a new [`MapEntry`]. pub fn new( - key: impl Into, - field: impl Into, - value: impl Into, + key: Key>, + field: Field>, + value: Value>, expiration: impl Into, ) -> Self { Self { @@ -195,6 +466,21 @@ pub struct Record { pub version: EntryVersion, } +impl Record { + /// Creates a new [`Record`]. + pub fn new( + value: impl Into, + expiration: impl Into, + version: impl Into, + ) -> Self { + Self { + value: value.into(), + expiration: expiration.into(), + version: version.into(), + } + } +} + /// [`MapEntry`] without the associated [`Key`]. #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct MapRecord { @@ -217,14 +503,6 @@ pub struct EntryExpiration { unix_timestamp_secs: u64, } -impl From for EntryExpiration { - fn from(timestamp: UnixTimestampSecs) -> Self { - Self { - unix_timestamp_secs: timestamp.0, - } - } -} - impl From for EntryExpiration { fn from(dur: Duration) -> Self { Self { @@ -260,10 +538,6 @@ impl EntryExpiration { .try_into() .unwrap_or_default() } - - fn timestamp(&self) -> UnixTimestampSecs { - UnixTimestampSecs(self.unix_timestamp_secs) - } } /// [`Entry`]/[`MapEntry`] version. @@ -272,14 +546,6 @@ pub struct EntryVersion { unix_timestamp_micros: u64, } -impl From for EntryVersion { - fn from(timestamp: UnixTimestampMicros) -> Self { - Self { - unix_timestamp_micros: timestamp.0, - } - } -} - impl EntryVersion { #[allow(clippy::new_without_default)] pub fn new() -> EntryVersion { @@ -300,10 +566,6 @@ impl EntryVersion { pub fn unix_timestamp_micros(&self) -> u64 { self.unix_timestamp_micros } - - fn timestamp(&self) -> UnixTimestampMicros { - UnixTimestampMicros(self.unix_timestamp_micros) - } } /// Page of [`MapRecord`]s. @@ -325,206 +587,30 @@ impl MapPage { } } -#[cfg(feature = "client")] -impl Record { - fn new(value: Value, expiration: UnixTimestampSecs, version: UnixTimestampMicros) -> Self { - Self { - value, - expiration: expiration.into(), - version: version.into(), - } +impl AsRef for Owned { + fn as_ref(&self) -> &S { + &self.0 } } -#[derive(Clone, Copy, Debug, Serialize, Deserialize)] -struct UnixTimestampSecs(u64); - -#[derive(Clone, Copy, Debug, Serialize, Deserialize)] -struct UnixTimestampMicros(u64); - -#[derive(Clone, Debug, Serialize, Deserialize)] -struct ExtendedKey { - inner: Vec, - keyspace_version: Option, -} - -type Get = rpc::Unary<{ rpc::id(b"get") }, GetRequest, Option>; - -#[derive(Clone, Debug, Serialize, Deserialize)] -struct GetRequest { - key: ExtendedKey, -} - -#[derive(Clone, Debug, Serialize, Deserialize)] -struct GetResponse { - value: Value, - expiration: UnixTimestampSecs, - version: UnixTimestampMicros, -} - -type Set = rpc::Unary<{ rpc::id(b"set") }, SetRequest, ()>; - -#[derive(Clone, Debug, Serialize, Deserialize)] -struct SetRequest { - key: ExtendedKey, - value: Value, - expiration: UnixTimestampSecs, - version: UnixTimestampMicros, -} - -type Del = rpc::Unary<{ rpc::id(b"del") }, DelRequest, ()>; - -#[derive(Clone, Debug, Serialize, Deserialize)] -struct DelRequest { - key: ExtendedKey, - version: UnixTimestampMicros, -} - -type GetExp = rpc::Unary<{ rpc::id(b"get_exp") }, GetExpRequest, Option>; - -#[derive(Clone, Debug, Serialize, Deserialize)] -struct GetExpRequest { - key: ExtendedKey, -} - -#[derive(Clone, Debug, Serialize, Deserialize)] -struct GetExpResponse { - expiration: UnixTimestampSecs, -} - -type SetExp = rpc::Unary<{ rpc::id(b"set_exp") }, SetExpRequest, ()>; - -#[derive(Clone, Debug, Serialize, Deserialize)] -struct SetExpRequest { - key: ExtendedKey, - expiration: UnixTimestampSecs, - version: UnixTimestampMicros, -} - -type HGet = rpc::Unary<{ rpc::id(b"hget") }, HGetRequest, Option>; - -#[derive(Clone, Debug, Serialize, Deserialize)] -struct HGetRequest { - key: ExtendedKey, - field: Field, -} - -#[derive(Clone, Debug, Serialize, Deserialize)] -struct HGetResponse { - value: Value, - expiration: UnixTimestampSecs, - version: UnixTimestampMicros, -} - -type HSet = rpc::Unary<{ rpc::id(b"hset") }, HSetRequest, ()>; - -#[derive(Clone, Debug, Serialize, Deserialize)] -struct HSetRequest { - key: ExtendedKey, - field: Field, - value: Value, - expiration: UnixTimestampSecs, - version: UnixTimestampMicros, -} - -type HDel = rpc::Unary<{ rpc::id(b"hdel") }, HDelRequest, ()>; - -#[derive(Clone, Debug, Serialize, Deserialize)] -struct HDelRequest { - key: ExtendedKey, - field: Field, - version: UnixTimestampMicros, -} - -type HGetExp = rpc::Unary<{ rpc::id(b"hget_exp") }, HGetExpRequest, Option>; - -#[derive(Clone, Debug, Serialize, Deserialize)] -struct HGetExpRequest { - key: ExtendedKey, - field: Field, -} - -#[derive(Clone, Debug, Serialize, Deserialize)] -struct HGetExpResponse { - expiration: UnixTimestampSecs, -} - -type HSetExp = rpc::Unary<{ rpc::id(b"hset_exp") }, HSetExpRequest, ()>; - -#[derive(Clone, Debug, Serialize, Deserialize)] -struct HSetExpRequest { - key: ExtendedKey, - field: Field, - expiration: UnixTimestampSecs, - version: UnixTimestampMicros, -} - -type HCard = rpc::Unary<{ rpc::id(b"hcard") }, HCardRequest, HCardResponse>; - -#[derive(Clone, Debug, Serialize, Deserialize)] -struct HCardRequest { - key: ExtendedKey, -} - -#[derive(Clone, Debug, Serialize, Deserialize)] -struct HCardResponse { - cardinality: u64, -} - -type HScan = rpc::Unary<{ rpc::id(b"hscan") }, HScanRequest, HScanResponse>; - -#[derive(Clone, Debug, Serialize, Deserialize)] -struct HScanRequest { - key: ExtendedKey, - count: u32, - cursor: Option, -} - -#[derive(Clone, Debug, Serialize, Deserialize)] -struct HScanResponse { - records: Vec, - has_more: bool, -} - -#[derive(Clone, Debug, Serialize, Deserialize)] -struct HScanResponseRecord { - field: Field, - value: Value, - expiration: UnixTimestampSecs, - version: UnixTimestampMicros, -} - -#[derive(Debug, Serialize, Deserialize)] -struct HandshakeRequest { - access_token: auth::Token, -} - -#[derive(Clone, Debug, Serialize, Deserialize)] -enum HandshakeErrorResponse { - InvalidToken(String), +impl AsRef for Namespace { + fn as_ref(&self) -> &Namespace { + self + } } -type HandshakeResponse = Result<(), HandshakeErrorResponse>; +impl FromStr for Namespace { + type Err = InvalidNamespaceError; -#[derive(Clone, Debug, thiserror::Error)] -pub enum HandshakeError { - #[error(transparent)] - Transport(#[from] transport::Error), + fn from_str(s: &str) -> Result { + let mut parts = s.split('/'); + let addr = parts.next()?; - #[error("Invalid token: {_0}")] - InvalidToken(String), -} - -impl From for HandshakeError { - fn from(err: HandshakeErrorResponse) -> Self { - match err { - HandshakeErrorResponse::InvalidToken(err) => Self::InvalidToken(err), - } + // const_hex::decode_to_array(input) + todo!() } } -impl From for HandshakeError { - fn from(err: io::Error) -> Self { - Self::Transport(err.into()) - } -} +#[derive(Debug, thiserror::Error)] +#[error("Invalid namespace: {_0}")] +pub struct InvalidNamespaceError(String); diff --git a/crates/storage_api2/src/operation.rs b/crates/storage_api2/src/operation.rs new file mode 100644 index 00000000..e36fc014 --- /dev/null +++ b/crates/storage_api2/src/operation.rs @@ -0,0 +1,392 @@ +use { + crate::{ + Bytes, + Entry, + EntryExpiration, + EntryVersion, + Field, + Key, + MapEntry, + MapPage, + MapRecord, + Namespace, + Record, + Value, + }, + derive_more::derive::{From, TryInto}, + std::any::type_name, + strum::{EnumDiscriminants, IntoDiscriminant}, + wc::metrics::{self, enum_ordinalize::Ordinalize}, +}; + +#[derive(Clone, Debug, From, EnumDiscriminants)] +#[strum_discriminants(name(Name))] +#[strum_discriminants(derive(Ordinalize))] +pub enum Operation { + Get(Get), + Set(Set), + Del(Del), + GetExp(GetExp), + SetExp(SetExp), + + HGet(HGet), + HSet(HSet), + HDel(HDel), + HGetExp(HGetExp), + HSetExp(HSetExp), + HCard(HCard), + HScan(HScan), +} + +impl metrics::Enum for Name { + fn as_str(&self) -> &'static str { + match self { + Self::Get => "get", + Self::Set => "set", + Self::Del => "del", + Self::GetExp => "get_exp", + Self::SetExp => "set_exp", + Self::HGet => "hget", + Self::HSet => "hset", + Self::HDel => "hdel", + Self::HGetExp => "hget_exp", + Self::HSetExp => "hset_exp", + Self::HCard => "hcard", + Self::HScan => "hscan", + } + } +} + +impl Operation { + /// Returns [`Name`] of this [`Operation`]. + pub fn name(&self) -> Name { + self.discriminant() + } + + /// Returns [`Key`] of this [`Operation`]. + pub fn key(&self) -> &Key { + match self { + Self::Get(get) => &get.key, + Self::Set(set) => &set.entry.key, + Self::Del(del) => &del.key, + Self::GetExp(get_exp) => &get_exp.key, + Self::SetExp(set_exp) => &set_exp.key, + Self::HGet(hget) => &hget.key, + Self::HSet(hset) => &hset.entry.key, + Self::HDel(hdel) => &hdel.key, + Self::HGetExp(hget_exp) => &hget_exp.key, + Self::HSetExp(hset_exp) => &hset_exp.key, + Self::HCard(hcard) => &hcard.key, + Self::HScan(hscan) => &hscan.key, + } + } +} + +/// Gets a [`Record`] by the provided [`Key`]. +#[derive(Clone, Debug)] +pub struct Get { + pub namespace: Namespace, + pub key: Key, +} + +impl Get { + /// Creates a new [`Get`] operation. + pub fn new(namespace: impl Into, key: Key>) -> Self { + Self { + namespace: namespace.into(), + key: key.into(), + } + } +} + +/// Sets a new [`Entry`]. +#[derive(Clone, Debug)] +pub struct Set { + pub namespace: Namespace, + pub entry: Entry, +} + +impl Set { + /// Creates a new [`Set`] operation. + pub fn new( + namespace: impl Into, + key: Key>, + value: Value>, + expiration: impl Into, + ) -> Self { + Self { + namespace: namespace.into(), + entry: Entry::new(key, value, expiration), + } + } +} + +/// Deletes an [`Entry`] by the provided [`Key`]. +#[derive(Clone, Debug)] +pub struct Del { + pub namespace: Namespace, + pub key: Key, + pub version: EntryVersion, +} + +impl Del { + /// Creates a new [`Del`] operation. + pub fn new(namespace: impl Into, key: Key>) -> Self { + Self { + namespace: namespace.into(), + key: key.into(), + version: EntryVersion::new(), + } + } +} + +/// Gets an [`EntryExpiration`] by the provided [`Key`]. +#[derive(Clone, Debug)] +pub struct GetExp { + pub namespace: Namespace, + pub key: Key, +} + +impl GetExp { + /// Creates a new [`GetExp`] operation. + pub fn new(namespace: impl Into, key: Key>) -> Self { + Self { + namespace: namespace.into(), + key: key.into(), + } + } +} + +/// Sets [`EntryExpiration`] on the [`Entry`] with the provided [`Key`]. +#[derive(Clone, Debug)] +pub struct SetExp { + pub namespace: Namespace, + pub key: Key, + pub expiration: EntryExpiration, + pub version: EntryVersion, +} + +impl SetExp { + /// Creates a new [`SetExp`] operation. + pub fn new( + namespace: impl Into, + key: Key>, + expiration: impl Into, + ) -> Self { + Self { + namespace: namespace.into(), + key: key.into(), + expiration: expiration.into(), + version: EntryVersion::new(), + } + } +} + +/// Gets a map [`Record`] by the provided [`Key`] and [`Field`]. +#[derive(Clone, Debug)] +pub struct HGet { + pub namespace: Namespace, + pub key: Key, + pub field: Field, +} + +impl HGet { + /// Creates a new [`HGet`] operation. + pub fn new( + namespace: impl Into, + key: Key>, + field: Field>, + ) -> Self { + Self { + namespace: namespace.into(), + key: key.into(), + field: field.into(), + } + } +} + +/// Sets a new [`MapEntry`]. +#[derive(Clone, Debug)] +pub struct HSet { + pub namespace: Namespace, + pub entry: MapEntry, +} + +impl HSet { + /// Creates a new [`HSet`] operation. + pub fn new( + namespace: impl Into, + key: Key>, + value: Value>, + field: Field>, + expiration: impl Into, + ) -> Self { + Self { + namespace: namespace.into(), + entry: MapEntry::new(key, field, value, expiration), + } + } +} + +/// Deletes a [`MapEntry`] by the provided [`Key`] and [`Field`]. +#[derive(Clone, Debug)] +pub struct HDel { + pub namespace: Namespace, + pub key: Key, + pub field: Field, + pub version: EntryVersion, +} + +impl HDel { + /// Creates a new [`HDel`] operation. + pub fn new( + namespace: impl Into, + key: Key>, + field: Field>, + ) -> Self { + Self { + namespace: namespace.into(), + key: key.into(), + field: field.into(), + version: EntryVersion::new(), + } + } +} + +/// Gets a [`EntryExpiration`] by the provided [`Key`] and [`Field`]. +#[derive(Clone, Debug)] +pub struct HGetExp { + pub namespace: Namespace, + pub key: Key, + pub field: Field, +} + +impl HGetExp { + /// Creates a new [`HGetExp`] operation. + pub fn new( + namespace: impl Into, + key: Key>, + field: Field>, + ) -> Self { + Self { + namespace: namespace.into(), + key: key.into(), + field: field.into(), + } + } +} + +/// Sets [`Expiration`] on the [`MapEntry`] with the provided [`Key`] and +/// [`Field`]. +#[derive(Clone, Debug)] +pub struct HSetExp { + pub namespace: Namespace, + pub key: Key, + pub field: Field, + pub expiration: EntryExpiration, + pub version: EntryVersion, +} + +impl HSetExp { + /// Creates a new [`HSetExp`] operation. + pub fn new( + namespace: impl Into, + key: Key>, + field: Field>, + expiration: impl Into, + ) -> Self { + Self { + namespace: namespace.into(), + key: key.into(), + field: field.into(), + expiration: expiration.into(), + version: EntryVersion::new(), + } + } +} + +/// Returns cardinality of the map with the provided [`Key`]. +#[derive(Clone, Debug)] +pub struct HCard { + pub namespace: Namespace, + pub key: Key, +} + +impl HCard { + /// Creates a new [`HCard`] operation. + pub fn new(namespace: impl Into, key: Key>) -> Self { + Self { + namespace: namespace.into(), + key: key.into(), + } + } +} + +/// Returns a [`MapPage`] by iterating over the [`Field`]s of the map with +/// the provided [`Key`]. +#[derive(Clone, Debug)] +pub struct HScan { + pub namespace: Namespace, + pub key: Key, + pub count: u32, + pub cursor: Option, +} + +impl HScan { + /// Creates a new [`HCard`] operation. + pub fn new( + namespace: impl Into, + key: Key>, + count: impl Into, + cursor: Option>>, + ) -> Self { + Self { + namespace: namespace.into(), + key: key.into(), + count: count.into(), + cursor: cursor.map(Field::into), + } + } +} + +/// [`Operation`] output. +#[derive(Clone, Debug, From, PartialEq, Eq, EnumDiscriminants, TryInto)] +#[strum_discriminants(name(OutputName))] +#[strum_discriminants(derive(strum::Display))] +pub enum Output { + Record(Option), + Expiration(Option), + MapRecord(Option), + MapPage(MapPage), + Cardinality(u64), + None, +} + +impl From<()> for Output { + fn from(_: ()) -> Self { + Self::None + } +} + +impl Output { + pub fn downcast_result(operation_result: Result) -> Result + where + Self: TryInto>, + WrongOutput: Into, + { + operation_result? + .try_into() + .map_err(|err| WrongOutput { + expected: type_name::(), + got: err.input.discriminant(), + }) + .map_err(Into::into) + } +} + +#[derive(Clone, Debug, thiserror::Error)] +#[error("Wrong operation output (expected: {expected}, got: {got})")] +pub struct WrongOutput { + expected: &'static str, + got: OutputName, +} diff --git a/crates/storage_api2/src/client.rs b/crates/storage_api2/src/rpc/client.rs similarity index 82% rename from crates/storage_api2/src/client.rs rename to crates/storage_api2/src/rpc/client.rs index 38f08b9f..32fce4a0 100644 --- a/crates/storage_api2/src/client.rs +++ b/crates/storage_api2/src/rpc/client.rs @@ -1,6 +1,5 @@ use { super::*, - arc_swap::ArcSwap, futures::SinkExt, std::{ collections::HashSet, @@ -21,22 +20,18 @@ use { }, identity::Keypair, middleware::Metered, - transport::{self, PendingConnection}, + transport::{self, NoHandshake, PendingConnection}, PeerAddr, }, }; -/// Storage API client. +/// Storage API RPC client. #[derive(Clone)] pub struct Client { - rpc: RpcClient, + inner: Inner, } -type RpcClient = - WithRetries>>, RetryStrategy>; - -/// Storage API access token. -pub type AccessToken = Arc>; +type Inner = Metered>; /// [`Client`] config. #[derive(Clone, Debug)] @@ -47,27 +42,19 @@ pub struct Config { /// Timeout of establishing a network connection. pub connection_timeout: Duration, - /// Timeout of a [`Client`] operation. - pub operation_timeout: Duration, - - /// Storage API access token. - pub access_token: AccessToken, - - /// Maximum number of attempts to try before failing an operation. - pub max_attempts: usize, + /// Timeout of a [`Client`] RPC call. + pub rpc_timeout: Duration, /// Additional label to be used for all metrics of the [`Server`]. pub metrics_tag: &'static str, } impl Config { - pub fn new(access_token: AccessToken) -> Self { + pub fn new() -> Self { Self { keypair: Keypair::generate_ed25519(), connection_timeout: Duration::from_secs(5), - operation_timeout: Duration::from_secs(10), - access_token, - max_attempts: 3, + rpc_timeout: Duration::from_secs(10), metrics_tag: "default", } } @@ -86,7 +73,7 @@ impl Config { /// Overwrites [`Config::operation_timeout`]. pub fn with_operation_timeout(mut self, timeout: Duration) -> Self { - self.operation_timeout = timeout; + self.rpc_timeout = timeout; self } @@ -105,28 +92,23 @@ impl Config { impl Client { /// Creates a new [`Client`]. pub fn new(config: Config) -> StdResult { - let handshake = Handshake { - access_token: config.access_token, - }; - let rpc_client_config = wcn_rpc::client::Config { keypair: config.keypair, known_peers: HashSet::new(), - handshake, + handshake: NoHandshake, connection_timeout: config.connection_timeout, - server_name: crate::RPC_SERVER_NAME, + server_name: super::COORDINATOR_SERVER_NAME, priority: transport::Priority::High, }; - let timeouts = Timeouts::new().with_default(config.operation_timeout); + let timeouts = Timeouts::new().with_default(config.rpc_timeout); let rpc_client = wcn_rpc::quic::Client::new(rpc_client_config) .map_err(|err| CreationError(err.to_string()))? .with_timeouts(timeouts) - .metered_with_tag(config.metrics_tag) - .with_retries(RetryStrategy::new(config.max_attempts)); + .metered_with_tag(config.metrics_tag); - Ok(Self { rpc: rpc_client }) + Ok(Self { inner: rpc_client }) } pub fn remote_storage<'a>(&'a self, server_addr: &'a PeerAddr) -> RemoteStorage<'a> { @@ -138,50 +120,6 @@ impl Client { } } -#[derive(Clone, Debug)] -struct RetryStrategy { - max_attempts: usize, -} - -impl RetryStrategy { - fn new(max_attempts: usize) -> Self { - Self { max_attempts } - } -} - -impl middleware::RetryStrategy for RetryStrategy { - fn requires_retry( - &self, - _rpc_id: wcn_rpc::Id, - error: &wcn_rpc::client::Error, - attempt: usize, - ) -> Option { - use crate::error_code; - - if attempt >= self.max_attempts { - return None; - } - - let rpc_error = match error { - wcn_rpc::client::Error::Transport(_) => return Some(Duration::from_millis(50)), - wcn_rpc::client::Error::Rpc { error, .. } => error, - }; - - Some(match rpc_error.code.as_ref() { - // These errors are non-retryable - wcn_rpc::error_code::THROTTLED - | error_code::INVALID_KEY - | error_code::KEYSPACE_VERSION_MISMATCH - | error_code::UNAUTHORIZED => return None, - - // On the first attempt retry immediately. - _ if attempt == 1 => Duration::ZERO, - - _ => Duration::from_millis(100), - }) - } -} - /// Handle to a remote Storage API (Server). #[derive(Clone, Copy)] pub struct RemoteStorage<'a> { @@ -198,8 +136,8 @@ impl RemoteStorage<'_> { } } - fn rpc_client(&self) -> &RpcClient { - &self.client.rpc + fn rpc_client(&self) -> &Inner { + &self.client.inner } /// Specifies the expected version of the keyspace of the [`RemoteStorage`]. diff --git a/crates/storage_api2/src/rpc/mod.rs b/crates/storage_api2/src/rpc/mod.rs new file mode 100644 index 00000000..d2e54c67 --- /dev/null +++ b/crates/storage_api2/src/rpc/mod.rs @@ -0,0 +1,235 @@ +use { + crate::{EntryExpiration, EntryVersion, Field, Value}, + serde::{Deserialize, Serialize}, + std::io, + wcn_rpc::{self as rpc, transport}, +}; + +#[cfg(feature = "rpc_client")] +pub mod client; +#[cfg(feature = "rpc_client")] +pub use client::Client; +#[cfg(feature = "rpc_server")] +pub mod server; +#[cfg(feature = "rpc_server")] +pub use server::Server; + +/// Kind of a Storage API server. +pub enum ServerKind { + /// Replication Coordinator server. + Coordinator, + + /// Replica server. + Replica, + + /// Database server. + Database, +} + +impl ServerKind { + fn server_name(&self) -> rpc::ServerName { + match self { + Self::Coordinator => "StorageApiCoordinator", + Self::Replica => "StorageApiReplica", + Self::Database => "StorageApiDatabase", + } + } +} + +/// RPC error codes produced by this module. +mod error_code { + /// Client is not authorized to perform the operation. + pub const UNAUTHORIZED: &str = "unauthorized"; + + /// Keyspace versions of the client and the server don't match. + pub const KEYSPACE_VERSION_MISMATCH: &str = "keyspace_version_mismatch"; + + /// Provided key was invalid. + pub const INVALID_KEY: &str = "invalid_key"; +} + +type Get = rpc::Unary<{ rpc::id(b"Get") }, GetRequest, Option>; + +#[derive(Clone, Debug, Serialize, Deserialize)] +struct GetRequest { + key: ExtendedKey, +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +struct GetResponse { + value: Value, + expiration: UnixTimestampSecs, + version: UnixTimestampMicros, +} + +type Set = rpc::Unary<{ rpc::id(b"Set") }, SetRequest, ()>; + +#[derive(Clone, Debug, Serialize, Deserialize)] +struct SetRequest { + key: ExtendedKey, + value: Value, + expiration: UnixTimestampSecs, + version: UnixTimestampMicros, +} + +type Del = rpc::Unary<{ rpc::id(b"Del") }, DelRequest, ()>; + +#[derive(Clone, Debug, Serialize, Deserialize)] +struct DelRequest { + key: ExtendedKey, + version: UnixTimestampMicros, +} + +type GetExp = rpc::Unary<{ rpc::id(b"GetExp") }, GetExpRequest, Option>; + +#[derive(Clone, Debug, Serialize, Deserialize)] +struct GetExpRequest { + key: ExtendedKey, +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +struct GetExpResponse { + expiration: UnixTimestampSecs, +} + +type SetExp = rpc::Unary<{ rpc::id(b"SetExp") }, SetExpRequest, ()>; + +#[derive(Clone, Debug, Serialize, Deserialize)] +struct SetExpRequest { + key: ExtendedKey, + expiration: UnixTimestampSecs, + version: UnixTimestampMicros, +} + +type HGet = rpc::Unary<{ rpc::id(b"HGet") }, HGetRequest, Option>; + +#[derive(Clone, Debug, Serialize, Deserialize)] +struct HGetRequest { + key: ExtendedKey, + field: Field, +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +struct HGetResponse { + value: Value, + expiration: UnixTimestampSecs, + version: UnixTimestampMicros, +} + +type HSet = rpc::Unary<{ rpc::id(b"HSet") }, HSetRequest, ()>; + +#[derive(Clone, Debug, Serialize, Deserialize)] +struct HSetRequest { + key: ExtendedKey, + field: Field, + value: Value, + expiration: UnixTimestampSecs, + version: UnixTimestampMicros, +} + +type HDel = rpc::Unary<{ rpc::id(b"HDel") }, HDelRequest, ()>; + +#[derive(Clone, Debug, Serialize, Deserialize)] +struct HDelRequest { + key: ExtendedKey, + field: Field, + version: UnixTimestampMicros, +} + +type HGetExp = rpc::Unary<{ rpc::id(b"HGetExp") }, HGetExpRequest, Option>; + +#[derive(Clone, Debug, Serialize, Deserialize)] +struct HGetExpRequest { + key: ExtendedKey, + field: Field, +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +struct HGetExpResponse { + expiration: UnixTimestampSecs, +} + +type HSetExp = rpc::Unary<{ rpc::id(b"HSetExp") }, HSetExpRequest, ()>; + +#[derive(Clone, Debug, Serialize, Deserialize)] +struct HSetExpRequest { + key: ExtendedKey, + field: Field, + expiration: UnixTimestampSecs, + version: UnixTimestampMicros, +} + +type HCard = rpc::Unary<{ rpc::id(b"HCard") }, HCardRequest, HCardResponse>; + +#[derive(Clone, Debug, Serialize, Deserialize)] +struct HCardRequest { + key: ExtendedKey, +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +struct HCardResponse { + cardinality: u64, +} + +type HScan = rpc::Unary<{ rpc::id(b"HScan") }, HScanRequest, HScanResponse>; + +#[derive(Clone, Debug, Serialize, Deserialize)] +struct HScanRequest { + key: ExtendedKey, + count: u32, + cursor: Option, +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +struct HScanResponse { + records: Vec, + has_more: bool, +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +struct HScanResponseRecord { + field: Field, + value: Value, + expiration: UnixTimestampSecs, + version: UnixTimestampMicros, +} + +#[derive(Clone, Copy, Debug, Serialize, Deserialize)] +struct UnixTimestampSecs(u64); + +impl From for UnixTimestampSecs { + fn from(exp: EntryExpiration) -> Self { + Self(exp.unix_timestamp_secs) + } +} + +impl From for EntryExpiration { + fn from(timestamp: UnixTimestampSecs) -> Self { + Self { + unix_timestamp_secs: timestamp.0, + } + } +} + +#[derive(Clone, Copy, Debug, Serialize, Deserialize)] +struct UnixTimestampMicros(u64); + +impl From for UnixTimestampMicros { + fn from(version: EntryVersion) -> Self { + Self(version.unix_timestamp_micros) + } +} + +impl From for EntryVersion { + fn from(timestamp: UnixTimestampMicros) -> Self { + Self { + unix_timestamp_micros: timestamp.0, + } + } +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +struct ExtendedKey { + inner: Vec, + keyspace_version: Option, +} diff --git a/crates/storage_api2/src/server.rs b/crates/storage_api2/src/rpc/server.rs similarity index 75% rename from crates/storage_api2/src/server.rs rename to crates/storage_api2/src/rpc/server.rs index a48bfddd..818768e1 100644 --- a/crates/storage_api2/src/server.rs +++ b/crates/storage_api2/src/rpc/server.rs @@ -26,79 +26,10 @@ pub struct Config { } /// Storage API server. -pub trait Server: Clone + Send + Sync + 'static { +pub trait Server: StorageApi + Clone + Send + Sync + 'static { /// Returns the current keyspace version of this [`Server`]. fn keyspace_version(&self) -> u64; - /// Gets a [`Record`] by the provided [`Key`]. - fn get(&self, key: Key) -> impl Future>> + Send; - - /// Sets the provided [`Entry`] only if the version of the existing - /// [`Entry`] is < than the new one. - fn set(&self, entry: Entry) -> impl Future> + Send; - - /// Deletes an [`Entry`] by the provided [`Key`] only if the version of the - /// [`Entry`] is < than the provided `version`. - fn del(&self, key: Key, version: EntryVersion) -> impl Future> + Send; - - /// Gets an [`EntryExpiration`] by the provided [`Key`]. - fn get_exp(&self, key: Key) -> impl Future>> + Send; - - /// Sets [`Expiration`] on the [`Entry`] with the provided [`Key`] only if - /// the version of the [`Entry`] is < than the provided `version`. - fn set_exp( - &self, - key: Key, - expiration: impl Into, - version: EntryVersion, - ) -> impl Future> + Send; - - /// Gets a map [`Record`] by the provided [`Key`] and [`Field`]. - fn hget(&self, key: Key, field: Field) -> impl Future>> + Send; - - /// Sets the provided [`MapEntry`] only if the version of the existing - /// [`MapEntry`] is < than the new one. - fn hset(&self, entry: MapEntry) -> impl Future> + Send; - - /// Deletes a [`MapEntry`] by the provided [`Key`] only if the version of - /// the [`MapEntry`] is < than the provided `version`. - fn hdel( - &self, - key: Key, - field: Field, - version: EntryVersion, - ) -> impl Future> + Send; - - /// Gets an [`EntryExpiration`] by the provided [`Key`] and [`Field`]. - fn hget_exp( - &self, - key: Key, - field: Field, - ) -> impl Future>> + Send; - - /// Sets [`Expiration`] on the [`MapEntry`] with the provided [`Key`] and - /// [`Field`] only if the version of the [`MapEntry`] is < than the - /// provided `version`. - fn hset_exp( - &self, - key: Key, - field: Field, - expiration: impl Into, - version: EntryVersion, - ) -> impl Future> + Send; - - /// Returns cardinality of the map with the provided [`Key`]. - fn hcard(&self, key: Key) -> impl Future> + Send; - - /// Returns a [`MapPage`] by iterating over the [`Field`]s of the map with - /// the provided [`Key`]. - fn hscan( - &self, - key: Key, - count: u32, - cursor: Option, - ) -> impl Future> + Send; - /// Converts this Storage API [`Server`] into an [`rpc::Server`]. fn into_rpc_server(self, cfg: Config) -> impl rpc::Server { let timeouts = Timeouts::new().with_default(cfg.operation_timeout); @@ -152,7 +83,9 @@ impl RpcHandler<'_, S> { async fn get(&self, req: GetRequest) -> wcn_rpc::Result> { let record = self .api_server - .get(self.prepare_key(req.key)?) + .execute_get(operation::Get { + key: self.prepare_key(req.key)?, + }) .await .map_err(Error::into_rpc_error)?; @@ -172,14 +105,17 @@ impl RpcHandler<'_, S> { }; self.api_server - .set(entry) + .execute_set(operation::Set { entry }) .await .map_err(Error::into_rpc_error) } async fn del(&self, req: DelRequest) -> wcn_rpc::Result<()> { self.api_server - .del(self.prepare_key(req.key)?, EntryVersion::from(req.version)) + .execute_del(operation::Del { + key: self.prepare_key(req.key)?, + version: EntryVersion::from(req.version), + }) .await .map_err(Error::into_rpc_error) } @@ -187,7 +123,9 @@ impl RpcHandler<'_, S> { async fn get_exp(&self, req: GetExpRequest) -> wcn_rpc::Result> { let expiration = self .api_server - .get_exp(self.prepare_key(req.key)?) + .execute_get_exp(operation::GetExp { + key: self.prepare_key(req.key)?, + }) .await .map_err(Error::into_rpc_error)?; @@ -198,11 +136,11 @@ impl RpcHandler<'_, S> { async fn set_exp(&self, req: SetExpRequest) -> wcn_rpc::Result<()> { self.api_server - .set_exp( - self.prepare_key(req.key)?, - EntryExpiration::from(req.expiration), - EntryVersion::from(req.version), - ) + .execute_set_exp(operation::SetExp { + key: self.prepare_key(req.key)?, + expiration: EntryExpiration::from(req.expiration), + version: EntryVersion::from(req.version), + }) .await .map_err(Error::into_rpc_error) } @@ -210,7 +148,10 @@ impl RpcHandler<'_, S> { async fn hget(&self, req: HGetRequest) -> wcn_rpc::Result> { let record = self .api_server - .hget(self.prepare_key(req.key)?, req.field) + .execute_hget(operation::HGet { + key: self.prepare_key(req.key)?, + field: req.field, + }) .await .map_err(Error::into_rpc_error)?; @@ -231,18 +172,18 @@ impl RpcHandler<'_, S> { }; self.api_server - .hset(entry) + .execute_hset(operation::HSet { entry }) .await .map_err(Error::into_rpc_error) } async fn hdel(&self, req: HDelRequest) -> wcn_rpc::Result<()> { self.api_server - .hdel( - self.prepare_key(req.key)?, - req.field, - EntryVersion::from(req.version), - ) + .execute_hdel(operation::HDel { + key: self.prepare_key(req.key)?, + field: req.field, + version: EntryVersion::from(req.version), + }) .await .map_err(Error::into_rpc_error) } @@ -250,7 +191,10 @@ impl RpcHandler<'_, S> { async fn hget_exp(&self, req: HGetExpRequest) -> wcn_rpc::Result> { let expiration = self .api_server - .hget_exp(self.prepare_key(req.key)?, req.field) + .execute_hget_exp(operation::HGetExp { + key: self.prepare_key(req.key)?, + field: req.field, + }) .await .map_err(Error::into_rpc_error)?; @@ -261,19 +205,21 @@ impl RpcHandler<'_, S> { async fn hset_exp(&self, req: HSetExpRequest) -> wcn_rpc::Result<()> { self.api_server - .hset_exp( - self.prepare_key(req.key)?, - req.field, - EntryExpiration::from(req.expiration), - EntryVersion::from(req.version), - ) + .execute_hset_exp(operation::HSetExp { + key: self.prepare_key(req.key)?, + field: req.field, + expiration: EntryExpiration::from(req.expiration), + version: EntryVersion::from(req.version), + }) .await .map_err(Error::into_rpc_error) } async fn hcard(&self, req: HCardRequest) -> wcn_rpc::Result { self.api_server - .hcard(self.prepare_key(req.key)?) + .execute_hcard(operation::HCard { + key: self.prepare_key(req.key)?, + }) .await .map(|cardinality| HCardResponse { cardinality }) .map_err(Error::into_rpc_error) @@ -282,7 +228,11 @@ impl RpcHandler<'_, S> { async fn hscan(&self, req: HScanRequest) -> wcn_rpc::Result { let page = self .api_server - .hscan(self.prepare_key(req.key)?, req.count, req.cursor) + .execute_hscan(operation::HScan { + key: self.prepare_key(req.key)?, + count: req.count, + cursor: req.cursor, + }) .await .map_err(Error::into_rpc_error)?; @@ -468,3 +418,9 @@ pub trait Authenticator: Clone + Send + Sync + 'static { Ok(claims) } } + +impl From for Error { + fn from(err: operation::WrongOutput) -> Self { + Self(err.to_string()) + } +} From 1db787ef51f4093bd05689ca83e812ff0274ec7a Mon Sep 17 00:00:00 2001 From: Github Bot Date: Thu, 12 Jun 2025 11:49:47 +0000 Subject: [PATCH 51/79] Bump VERSION to 250612.0 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index b8b7012c..57c1ba4f 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -250610.0 +250612.0 From d32eb9fbc134916e7c04ed39e550c64be0916af8 Mon Sep 17 00:00:00 2001 From: Darksome Date: Mon, 16 Jun 2025 09:20:51 +0000 Subject: [PATCH 52/79] WIP --- crates/rpc/src/client2.rs | 187 +++++++++++ crates/rpc/src/lib.rs | 62 +++- crates/rpc/src/quic/client.rs | 45 ++- crates/rpc/src/quic/mod.rs | 32 +- crates/rpc/src/quic/server.rs | 13 +- crates/rpc/src/quic/server/filter.rs | 8 +- crates/rpc/src/server2.rs | 450 ++++++++++++++++++++++++++ crates/rpc/src/transport.rs | 10 +- crates/storage_api2/src/lib.rs | 31 +- crates/storage_api2/src/operation.rs | 15 +- crates/storage_api2/src/rpc/client.rs | 268 ++++++++------- crates/storage_api2/src/rpc/mod.rs | 133 +++++--- crates/storage_api2/src/rpc/server.rs | 156 ++------- 13 files changed, 1048 insertions(+), 362 deletions(-) create mode 100644 crates/rpc/src/client2.rs create mode 100644 crates/rpc/src/server2.rs diff --git a/crates/rpc/src/client2.rs b/crates/rpc/src/client2.rs new file mode 100644 index 00000000..db7f1703 --- /dev/null +++ b/crates/rpc/src/client2.rs @@ -0,0 +1,187 @@ +use { + crate::{ + self as rpc, + quic, + transport::{self, BiDirectionalStream, NoHandshake, RecvStream, SendStream}, + Message, + ServerName, + }, + futures::{Sink, SinkExt, Stream, TryStreamExt as _}, + libp2p::{identity, PeerId}, + std::{ + future::Future, + io, + marker::PhantomData, + net::{SocketAddr, SocketAddrV4}, + sync::Arc, + time::Duration, + }, + tokio::io::AsyncWriteExt, +}; + +pub trait RpcSender: Send + Sync + 'static { + type Output; + + fn send<'a>( + &'a self, + args: Args, + ) -> impl Future> + Send + 'a + where + Args: 'a; +} + +pub struct Config { + /// [`identity::Keypair`] of the client. + pub keypair: identity::Keypair, + + /// Connection timeout. + pub connection_timeout: Duration, + + /// [`transport::Priority`] of the client. + pub priority: transport::Priority, +} + +pub struct Client { + config: Arc, + quic: quinn::Endpoint, +} + +impl Client { + pub fn new(cfg: Config) -> Result { + let transport_config = quic::new_quinn_transport_config(64u32 * 1024); + let socket_addr = SocketAddr::new(std::net::Ipv4Addr::new(0, 0, 0, 0).into(), 0); + let endpoint = quic::new_quinn_endpoint( + socket_addr, + &cfg.keypair, + transport_config, + None, + cfg.priority, + ) + .map_err(|err| Error::Transport(err.to_string()))?; + + Ok(Client { + config: Arc::new(cfg), + quic: endpoint, + }) + } + + pub fn connect( + &self, + addr: SocketAddrV4, + peer_id: PeerId, + ) -> OutboundConnection { + OutboundConnection { + quic: quic::client::ConnectionHandler::new( + peer_id, + addr.into(), + API::NAME, + self.quic.clone(), + NoHandshake, + self.config.connection_timeout, + ), + _marker: PhantomData, + } + } +} + +pub struct OutboundConnection { + quic: quic::client::ConnectionHandler, + _marker: PhantomData, +} + +impl + RpcSender, F> for OutboundConnection +where + API: rpc::Api, + Request: Message, + Response: Message, + Codec: transport::Codec, + F: FnOnce(&mut SendStream, &mut RecvStream) -> Fut + Send, + Fut: Future> + Send, +{ + type Output = T; + + fn send<'a>(&'a self, f: F) -> impl Future> + Send + 'a + where + F: 'a, + { + async move { + let (mut tx, rx) = self + .quic + .open_bi() + .await + .map_err(|err| RpcSenderError::Transport(format!("open bi: {err:?}")))?; + + tx.write_u8(ID) + .await + .map_err(|err| RpcSenderError::Transport(format!("write rpc id: {err:?}")))?; + + let (mut rx, mut tx) = + BiDirectionalStream::new(tx, rx).upgrade::(); + + f(&mut tx, &mut rx) + .await + .map_err(|err| RpcSenderError::Transport(err.to_string())) + } + } +} + +impl + rpc::StreamingV2 +where + Request: Message, + Response: Message, + Codec: transport::Codec, +{ + pub async fn send<'a, S, F, Fut, T>(sender: &'a S, f: F) -> RpcSenderResult + where + S: RpcSender, + F: FnOnce(&'a mut SendStream, &'a mut RecvStream) -> Fut + + 'a, + Fut: Future>, + { + RpcSender::::send(sender, f).await + } +} + +impl + RpcSender, Request> for OutboundConnection +where + API: rpc::Api, + Request: Message, + Response: Message, + Codec: transport::Codec, +{ + type Output = Response; + + fn send<'a>( + &'a self, + request: Request, + ) -> impl Future> + Send + 'a { + RpcSender::, _>::send( + self, + |tx, rx| async { + tx.send(request).await?; + rx.recv_message().await + }, + ) + } +} + +pub struct OutboundRpc { + stream: BiDirectionalStream, +} + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("Transport: {_0}")] + Transport(String), +} + +#[derive(Debug, thiserror::Error)] +pub enum RpcSenderError { + #[error("Transport: {0}")] + Transport(String), +} + +pub type RpcSenderResult = Result; diff --git a/crates/rpc/src/lib.rs b/crates/rpc/src/lib.rs index 46b3e1ee..a98a6d3c 100644 --- a/crates/rpc/src/lib.rs +++ b/crates/rpc/src/lib.rs @@ -5,18 +5,23 @@ pub use libp2p::{identity, Multiaddr, PeerId}; use { derive_more::Display, serde::{Deserialize, Serialize}, - std::{borrow::Cow, fmt::Debug, marker::PhantomData, net::SocketAddr, str::FromStr}, + std::{borrow::Cow, fmt::Debug, marker::PhantomData, net::SocketAddr, str::FromStr, sync::Arc}, + tokio::sync::OwnedSemaphorePermit, transport::Codec, }; #[cfg(feature = "client")] pub mod client; #[cfg(feature = "client")] +pub mod client2; +#[cfg(feature = "client")] pub use client::Client; #[cfg(feature = "server")] pub mod server; #[cfg(feature = "server")] +pub mod server2; +#[cfg(feature = "server")] pub use server::{IntoServer, Server}; pub mod middleware; @@ -60,6 +65,40 @@ pub trait Rpc { type Codec: Codec; } +pub struct StreamingV2 +where + Rx: Message, + Tx: Message, + Codec: transport::Codec, +{ + recv: transport::RecvStream, + send: transport::SendStream, + _marker: PhantomData, +} + +pub struct UnaryV2 +where + Request: Message, + Response: Message, + Codec: transport::Codec, +{ + streaming: StreamingV2, +} + +pub trait RpcV2 { + /// ID of this [`Rpc`]. + const ID: u8; + + /// Request type of this [`Rpc`]. + type Request: Message; + + /// Response type of this [`Rpc`]. + type Response: Message; + + /// Serialization codec of this [`Rpc`]. + type Codec: Codec; +} + /// [`Rpc`] kinds. pub mod kind { /// Unary (request-response) RPC. @@ -119,6 +158,13 @@ impl Name { } } +pub trait Api: Send + Sync + 'static { + const NAME: ApiName; + type RpcId; +} + +pub type ApiName = ServerName; + /// RPC server name. #[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)] pub struct ServerName([u8; 16]); @@ -224,11 +270,25 @@ impl Error { description: None, } } + + // pub fn with_description(mut self, description: impl Display) -> Self { + // self.description = Some(description.to_string().into()); + // self + // } } /// RPC result. pub type Result = std::result::Result; +/// RPC error. +pub struct Error2 { + /// Error code. + pub code: u8, + + /// Error description. + pub description: Option, +} + // Workaround for this compliler bug: https://github.com/rust-lang/rust/issues/100013 // https://github.com/rust-lang/rust/issues/100013#issuecomment-2210995259 // TODO: remove when fixed diff --git a/crates/rpc/src/quic/client.rs b/crates/rpc/src/quic/client.rs index 0a7d19bd..3d69fbef 100644 --- a/crates/rpc/src/quic/client.rs +++ b/crates/rpc/src/quic/client.rs @@ -1,6 +1,7 @@ use { super::{ConnectionHeader, ExtractPeerIdError, InvalidMultiaddrError, PROTOCOL_VERSION}, crate::{ + self as rpc, client::{self, AnyPeer, Config, Result}, transport::{self, BiDirectionalStream, Handshake, NoHandshake, PendingConnection}, Id as RpcId, @@ -141,7 +142,7 @@ impl Client { } #[derive(Clone, Debug)] -pub(super) struct ConnectionHandler { +pub(crate) struct ConnectionHandler { inner: Arc>, handshake: H, } @@ -234,7 +235,7 @@ fn new_connection( } impl ConnectionHandler { - pub(super) fn new( + pub(crate) fn new( peer_id: PeerId, addr: SocketAddr, server_name: ServerName, @@ -264,22 +265,28 @@ impl ConnectionHandler { } } - async fn establish_stream( + pub(crate) async fn open_bi( &self, - rpc_id: RpcId, - ) -> Result { + ) -> Result<(quinn::SendStream, quinn::RecvStream), EstablishStreamError> { let fut = self.inner.write()?.connection.clone(); let conn = fut.await; - let (mut tx, rx) = match conn.open_bi().await { - Ok(bi) => bi, + match conn.open_bi().await { + Ok(bi) => Ok(bi), Err(_) => self .reconnect(conn.stable_id())? .await .open_bi() .await - .map_err(|err| EstablishStreamError::Connection(err.into()))?, - }; + .map_err(|err| EstablishStreamError::Connection(err.into())), + } + } + + pub(crate) async fn establish_stream( + &self, + rpc_id: RpcId, + ) -> Result { + let (mut tx, rx) = self.open_bi().await?; tx.write_u128(rpc_id) .await @@ -381,6 +388,12 @@ impl ConnectionError { } } +impl From for rpc::Error { + fn from(err: ConnectionError) -> Self { + err.as_metrics_label().into() + } +} + #[derive(Debug, From, thiserror::Error)] pub enum EstablishStreamError { #[error("Invalid Multiaddr")] @@ -402,6 +415,20 @@ pub enum EstablishStreamError { Lock, } +impl From for rpc::Error { + fn from(err: EstablishStreamError) -> Self { + match err { + EstablishStreamError::InvalidMultiaddr(_) => "quic_client_invalid_multiaddr", + EstablishStreamError::NoAvailablePeers => "quic_client_no_available_peers", + EstablishStreamError::Connection(err) => return err.into(), + EstablishStreamError::Timeout => "quic_client_establish_stream_timeout", + EstablishStreamError::Rng => todo!(), + EstablishStreamError::Lock => todo!(), + } + .into() + } +} + impl From> for EstablishStreamError { fn from(_: PoisonError) -> Self { Self::Lock diff --git a/crates/rpc/src/quic/mod.rs b/crates/rpc/src/quic/mod.rs index 3fae7f25..4199e11d 100644 --- a/crates/rpc/src/quic/mod.rs +++ b/crates/rpc/src/quic/mod.rs @@ -2,6 +2,7 @@ use nix::sys::socket::{setsockopt, sockopt}; use { crate::{ + self as rpc, transport::{self, Priority}, ServerName, }, @@ -30,15 +31,17 @@ mod metrics; const PROTOCOL_VERSION: u32 = 1; #[derive(Default)] -struct ConnectionHeader { - server_name: Option, +pub(crate) struct ConnectionHeader { + pub server_name: ServerName, } #[derive(Clone, Debug, thiserror::Error, Eq, PartialEq)] #[error("{0}: invalid QUIC Multiaddr")] pub struct InvalidMultiaddrError(Multiaddr); -fn new_quinn_transport_config(max_concurrent_streams: u32) -> Arc { +pub(crate) fn new_quinn_transport_config( + max_concurrent_streams: u32, +) -> Arc { const STREAM_WINDOW: u32 = 4 * 1024 * 1024; // 4 MiB // Our tests are too slow and connections get dropped because of missing keep @@ -61,7 +64,7 @@ fn new_quinn_transport_config(max_concurrent_streams: u32) -> Arc, @@ -222,3 +225,24 @@ enum IpTosDscp { /// Lower-Effort, RFC8622 Le = 0b0000_0100, } + +impl From for rpc::Error { + fn from(err: quinn::ConnectionError) -> Self { + use quinn::ConnectionError as Error; + + match err { + Error::VersionMismatch => "quinn_quic_version_mismatch".into(), + Error::TransportError(err) => rpc::Error::new("quinn_transport").with_description(err), + Error::ConnectionClosed(err) => { + rpc::Error::new("quinn_connection_closed").with_description(err) + } + Error::ApplicationClosed(err) => { + rpc::Error::new("quinn_application_closed").with_description(err) + } + Error::Reset => "quinn_conection_reset".into(), + Error::TimedOut => "quinn_connection_timeout".into(), + Error::LocallyClosed => "quinn_connection_locally_closed".into(), + Error::CidsExhausted => "quinn_connectino_cids_exhausted".into(), + } + } +} diff --git a/crates/rpc/src/quic/server.rs b/crates/rpc/src/quic/server.rs index 64bb2987..e3bcdb12 100644 --- a/crates/rpc/src/quic/server.rs +++ b/crates/rpc/src/quic/server.rs @@ -24,7 +24,7 @@ use { }, }; -mod filter; +pub(crate) mod filter; /// QUIC RPC server config. pub struct Config { @@ -66,7 +66,11 @@ where S: Send + Sync + 'static, Server: Multiplexer, { - let filter = Filter::new(&cfg)?; + let filter = Filter::new(&filter::Config { + max_connections: cfg.max_connections, + max_connections_per_ip: cfg.max_connections_per_ip, + max_connection_rate_per_ip: cfg.max_connection_rate_per_ip, + })?; let server = Server::new(rpc_servers, cfg)?; Ok(server.serve(filter)) } @@ -263,7 +267,7 @@ where } } -async fn read_connection_header( +pub(crate) async fn read_connection_header( conn: &quinn::Connection, ) -> Result { let mut rx = conn.accept_uni().await?; @@ -271,11 +275,10 @@ async fn read_connection_header( let protocol_version = rx.read_u32().await?; let server_name = match protocol_version { - 0 => None, super::PROTOCOL_VERSION => { let mut buf = [0; 16]; rx.read_exact(&mut buf).await?; - Some(ServerName(buf)) + ServerName(buf) } ver => return Err(ConnectionError::UnsupportedProtocolVersion(ver)), }; diff --git a/crates/rpc/src/quic/server/filter.rs b/crates/rpc/src/quic/server/filter.rs index 5d893c6d..82078cf1 100644 --- a/crates/rpc/src/quic/server/filter.rs +++ b/crates/rpc/src/quic/server/filter.rs @@ -21,8 +21,14 @@ pub struct Filter { max_connections_per_ip: u32, } +pub(crate) struct Config { + pub max_connections: u32, + pub max_connections_per_ip: u32, + pub max_connection_rate_per_ip: u32, +} + impl Filter { - pub fn new(cfg: &super::Config) -> Result { + pub fn new(cfg: &Config) -> Result { let max_connection_rate: NonZeroU32 = cfg .max_connection_rate_per_ip .try_into() diff --git a/crates/rpc/src/server2.rs b/crates/rpc/src/server2.rs new file mode 100644 index 00000000..f5cbb1a1 --- /dev/null +++ b/crates/rpc/src/server2.rs @@ -0,0 +1,450 @@ +use { + crate::{ + self as rpc, + quic::{ + self, + server::{ + filter::{self, Filter, RejectionReason}, + read_connection_header, + }, + }, + transport::{self, BiDirectionalStream}, + ApiName, + }, + futures::{Sink, Stream, TryFutureExt as _}, + libp2p::{identity::Keypair, PeerId}, + quinn::crypto::rustls::QuicServerConfig, + sealed::ConnectionRouter, + std::{future::Future, io, marker::PhantomData, sync::Arc, time::Duration}, + tokio::sync::{OwnedSemaphorePermit, Semaphore}, + wc::{ + future::FutureExt as _, + metrics::{self, future_metrics, Enum as _, EnumLabel, StringLabel}, + }, +}; + +// pub trait InboundRpc: RpcV2 + Stream + +// Sink {} + +pub trait ApiHandler: Clone + Send + Sync + 'static { + type Api: rpc::Api; + + fn handle_connection( + &self, + connection: &mut InboundConnection, + ) -> impl Future + Send; + + // /// Converts this [`ConnectionHandler`] into [`ApiConnectionHandler`]. + // fn into_api(self, name: ApiName) -> ApiConnectionHandler; +} + +// /// [`ConnectionHandler`] of a specific RPC API. +// pub struct ApiConnectionHandler { +// api_name: ApiName, +// connection_handler: H, +// } + +pub trait RpcHandler { + fn handle(&self, rpc: &mut RPC) -> impl Future + Send; +} + +pub struct Config { + /// Name of the server. For metrics purposes only. + pub name: &'static str, + + /// [`Multiaddr`] to bind the server to. + pub port: u16, + + /// [`Keypair`] of the server. + pub keypair: Keypair, + + /// Maximum global number of concurrent connections. + pub max_connections: u32, + + /// Maximum number of concurrent connections per client IP address. + pub max_connections_per_ip: u32, + + /// Maximum number of connections accepted per client IP address per second. + pub max_connection_rate_per_ip: u32, + + /// Maximum number of concurrent RPCs. + pub max_concurrent_rpcs: u32, + + /// [`transport::Priority`] of the server. + pub priority: transport::Priority, +} + +/// Serves a single RPC API on the specified. +pub fn serve( + cfg: Config, + api_name: ApiName, + connection_handler: impl ApiHandler, +) -> Result, Error> { + multiplex(cfg, (connection_handler,)) +} + +/// Serves multiple RPC APIs on the specified port. +/// +/// `connection_handlers` is expected to be a tuple of [`ConnectionHandler`]s. +pub fn multiplex(cfg: Config, connection_handlers: H) -> Result, Error> +where + H: sealed::ConnectionRouter, +{ + let transport_config = quic::new_quinn_transport_config(cfg.max_concurrent_rpcs); + let server_tls_config = libp2p_tls::make_server_config(&cfg.keypair) + .map_err(|err| Error::Crypto(err.to_string()))?; + let server_tls_config = QuicServerConfig::try_from(server_tls_config) + .map_err(|err| Error::Crypto(err.to_string()))?; + let mut server_config = quinn::ServerConfig::with_crypto(Arc::new(server_tls_config)); + server_config.transport = transport_config.clone(); + server_config.migration(false); + + let endpoint = quic::new_quinn_endpoint( + ([0, 0, 0, 0], cfg.port).into(), + &cfg.keypair, + transport_config, + Some(server_config), + cfg.priority, + ) + .map_err(|err| Error::Transport(err.to_string()))?; + + let connection_filter = Filter::new(&filter::Config { + max_connections: cfg.max_connections, + max_connections_per_ip: cfg.max_connections_per_ip, + max_connection_rate_per_ip: cfg.max_connection_rate_per_ip, + }) + .map_err(|err| Error::Config(err.to_string()))?; + + let rpc_semaphore = Arc::new(Semaphore::new(cfg.max_concurrent_rpcs as usize)); + + Ok(accept_connections( + cfg, + endpoint, + connection_filter, + rpc_semaphore, + connection_handlers, + )) +} + +async fn accept_connections( + config: Config, + endpoint: quinn::Endpoint, + connection_filter: Filter, + rpc_semaphore: Arc, + handlers: H, +) { + while let Some(incoming) = endpoint.accept().await { + match connection_filter.try_acquire_permit(&incoming) { + Ok(permit) => match incoming.accept() { + Ok(connecting) => accept_connection( + config.name, + connecting, + permit, + rpc_semaphore.clone(), + handlers.clone(), + ), + + Err(err) => tracing::warn!(?err, "failed to accept incoming connection"), + }, + + Err(err) => { + if err == filter::RejectionReason::AddressNotValidated { + // Signal the client to retry with validated address. + let _ = incoming.retry(); + } else { + tracing::debug!( + server_name = config.name, + reason = err.as_str(), + remote_addr = ?incoming.remote_address().ip(), + "inbound connection dropped" + ); + + metrics::counter!( + "wcn_rpc_quic_server_connections_dropped", + EnumLabel<"reason", RejectionReason> => err, + StringLabel<"server_name"> => config.name + ) + .increment(1); + + // Calling `ignore()` instead of dropping avoids sending a response. + incoming.ignore(); + } + } + }; + } +} + +fn accept_connection( + server_name: &'static str, + connecting: quinn::Connecting, + permit: filter::Permit, + rpc_semaphore: Arc, + router: R, +) { + async move { + let conn = connecting + .with_timeout(Duration::from_millis(1000)) + .await + .map_err(|_| ApiHandlerError::ConnectionTimeout)??; + + let header = read_connection_header(&conn) + .with_timeout(Duration::from_millis(500)) + .await + .map_err(|_| ApiHandlerError::ReadConnectionHeaderTimeout)??; + + let conn = InboundConnection { + server_name, + permit, + rpc_semaphore, + inner: conn, + _marker: PhantomData, + }; + + router.route_connection(header.server_name, conn).await + } + .map_err(|err| tracing::debug!(?err, "Inbound connection handler failed")) + .with_metrics(future_metrics!("wcn_rpc_quic_server_inbound_connection")) + .pipe(tokio::spawn); +} + +pub struct InboundConnection { + server_name: &'static str, + + permit: filter::Permit, + rpc_semaphore: Arc, + + inner: quinn::Connection, + + _marker: PhantomData, +} + +impl InboundConnection { + fn set_api(self) -> InboundConnection { + InboundConnection { + server_name: self.server_name, + permit: self.permit, + rpc_semaphore: self.rpc_semaphore, + inner: self.inner, + _marker: (), + } + } +} + +impl InboundConnection { + pub fn peer_id(&self) -> PeerId { + todo!() + } + + pub async fn handle>( + &self, + rpc_handler: impl Fn(InboundRpc) -> F, + ) -> ApiHandlerResult { + loop { + match self.handle_rpc(rpc_handler).await { + Ok(fut) => tokio::spawn(fut), + Err(RpcHandlerError::TooManyRpc) => continue, + Err(err) => return Err(err), + }; + } + } + + pub async fn handle_rpc>( + &self, + rpc_handler: impl Fn(InboundRpc) -> F, + ) -> ApiHandlerResult> { + let (tx, mut rx) = self.inner.accept_bi().await?; + + let Some(permit) = self.acquire_stream_permit() else { + metrics::counter!( + "wcn_rpc_quic_server_streams_dropped", + StringLabel<"server_name"> => self.server_name + ) + .increment(1); + return Err(RpcHandlerError::TooManyRpc); + }; + + async move { + let _permit = permit; + + let rpc = InboundRpc { + id: None, + stream: BiDirectionalStream::new(tx, rx), + }; + + rpc_handler.handle(&mut rpc).await + } + .with_metrics(future_metrics!("wcn_rpc_quic_server_inbound_stream")) + } + + fn acquire_stream_permit(&self) -> Option { + metrics::gauge!("wcn_rpc_quic_server_available_stream_permits", StringLabel<"server_name"> => self.server_name) + .set(self.stream_semaphore.available_permits() as f64); + + self.rpc_semaphore + .clone() + .try_acquire_owned() + .ok() + .tap_none(|| { + metrics::counter!("wcn_rpc_quic_server_throttled_streams", StringLabel<"server_name"> => self.server_name) + .increment(1); + }) + } +} + +pub struct InboundRpc { + id: ID, + stream: BiDirectionalStream, +} + +impl InboundRpc { + pub fn id(&self) -> ID { + self.id + } +} + +// impl InboundRpc { +// fn upgrade(&mut self) -> (impl Stream, impl +// Sink) { self.stream.upgrade() +// } +// } + +async fn read_rpc_id(stream: &mut BiDirectionalStream) -> Result { + stream + .rx + .read_u8() + .with_timeout(Duration::from_millis(500)) + .await + .map_err(|err| err.to_string())? + .map_err(|err| format!("{err:?}")) +} + +mod sealed { + use super::*; + + pub trait ConnectionRouter: Clone { + fn route_connection( + &self, + api_name: ApiName, + connection: InboundConnection, + ) -> impl Future>; + } +} + +impl ConnectionRouter for (A,) +where + A: ApiHandler, +{ + async fn route_connection( + &self, + api_name: ApiName, + conn: InboundConnection, + ) -> Result<(), ApiHandlerError> { + async move { + match &api_name { + A::Api::NAME => self.0.handle_connection(&mut conn.set_api()), + _ => Err(ApiHandlerError::UnknownApi(api_name)), + } + } + } +} + +impl ConnectionRouter for (A, B) +where + A: ApiHandler, + B: ApiHandler, +{ + async fn route_connection( + &self, + api_name: ApiName, + conn: InboundConnection, + ) -> Result<(), ApiHandlerError> { + async move { + match &api_name { + A::Api::NAME => self.0.handle_connection(&mut conn.set_api()), + B::Api::NAME => self.1.handle_connection(&mut conn.set_api()), + _ => Err(ApiHandlerError::UnknownApi(api_name)), + } + } + } +} + +impl ConnectionRouter for (A, B, C) +where + A: ApiHandler, + B: ApiHandler, + C: ApiHandler, +{ + async fn route_connection( + &self, + api_name: ApiName, + conn: InboundConnection, + ) -> Result<(), ApiHandlerError> { + async move { + match &api_name { + A::Api::NAME => self.0.handle_connection(&mut conn.set_api()), + B::Api::NAME => self.1.handle_connection(&mut conn.set_api()), + C::Api::NAME => self.1.handle_connection(&mut conn.set_api()), + _ => Err(ApiHandlerError::UnknownApi(api_name)), + } + } + } +} + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("Transport: {0}")] + Transport(String), + + #[error("Crypto: {0}")] + Crypto(String), + + #[error("Config: {0}")] + Config(String), +} + +#[derive(Debug, thiserror::Error)] +pub enum ApiHandlerError { + #[error("Transport: {0}")] + Transport(String), + + #[error("Timeout establishing inbound connection")] + ConnectionTimeout, + + #[error("Timeout reading inbound connection header")] + ReadConnectionHeaderTimeout, + + #[error("Unknown API: {0}")] + UnknownApi(rpc::ApiName), +} + +pub type ApiHandlerResult = Result; + +#[derive(Debug, thiserror::Error)] +pub enum RpcHandlerError { + #[error("Too many concurrent RPCs")] + TooManyRpc, + + #[error("Read RPC ID: {0}")] + ReadRpcId(#[from] ReadRpcIdError), + + #[error(transparent)] + UnknownRpc(#[from] UnknownRpcError), + + #[error("Transport: {0}")] + Transport(String), +} + +pub type RpcHandlerResult = Result; + +#[derive(Debug, thiserror::Error)] +pub enum ReadRpcIdError { + #[error("IO: {0:?}")] + IO(io::Error), + + #[error("Timeout")] + Timeout, +} + +#[derive(Debug, thiserror::Error)] +#[error("Unknown RPC (ID: {0})")] +pub struct UnknownRpcError(pub u8); diff --git a/crates/rpc/src/transport.rs b/crates/rpc/src/transport.rs index 2cf665e8..16730277 100644 --- a/crates/rpc/src/transport.rs +++ b/crates/rpc/src/transport.rs @@ -56,8 +56,8 @@ impl Codec for JsonCodec { /// Untyped bi-directional stream. pub struct BiDirectionalStream { - rx: RawRecvStream, - tx: RawSendStream, + pub(crate) rx: RawRecvStream, + pub(crate) tx: RawSendStream, } type RawSendStream = FramedWrite; @@ -83,6 +83,12 @@ impl BiDirectionalStream { }, ) } + + pub(crate) fn upgrate_ref( + &mut self, + ) -> (impl Stream, impl Sink) { + () + } } /// [`Stream`] of outbound [`Message`]s. diff --git a/crates/storage_api2/src/lib.rs b/crates/storage_api2/src/lib.rs index 96b10a5d..a385407c 100644 --- a/crates/storage_api2/src/lib.rs +++ b/crates/storage_api2/src/lib.rs @@ -347,7 +347,7 @@ pub struct Key(pub T); impl Key { /// Converts `Self` into `Key`. - pub fn into(self) -> Key + pub fn convert(self) -> Key where T: Into, { @@ -361,7 +361,7 @@ pub struct Value(pub T); impl Value { /// Converts `Self` into `Value`. - pub fn into(self) -> Value + pub fn convert(self) -> Value where T: Into, { @@ -375,7 +375,7 @@ pub struct Field(pub T); impl Field { /// Converts `Self` into `Field`. - pub fn into(self) -> Value + pub fn convert(self) -> Value where T: Into, { @@ -407,8 +407,8 @@ impl Entry { expiration: impl Into, ) -> Self { Self { - key: key.into(), - value: value.into(), + key: key.convert(), + value: value.convert(), expiration: expiration.into(), version: EntryVersion::new(), } @@ -444,9 +444,9 @@ impl MapEntry { expiration: impl Into, ) -> Self { Self { - key: key.into(), - field: field.into(), - value: value.into(), + key: key.convert(), + field: field.convert(), + value: value.convert(), expiration: expiration.into(), version: EntryVersion::new(), } @@ -466,21 +466,6 @@ pub struct Record { pub version: EntryVersion, } -impl Record { - /// Creates a new [`Record`]. - pub fn new( - value: impl Into, - expiration: impl Into, - version: impl Into, - ) -> Self { - Self { - value: value.into(), - expiration: expiration.into(), - version: version.into(), - } - } -} - /// [`MapEntry`] without the associated [`Key`]. #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct MapRecord { diff --git a/crates/storage_api2/src/operation.rs b/crates/storage_api2/src/operation.rs index e36fc014..e69aac90 100644 --- a/crates/storage_api2/src/operation.rs +++ b/crates/storage_api2/src/operation.rs @@ -1,3 +1,5 @@ +//! Storage API operations. + use { crate::{ Bytes, @@ -19,6 +21,7 @@ use { wc::metrics::{self, enum_ordinalize::Ordinalize}, }; +/// Sum type of all Storage API operations. #[derive(Clone, Debug, From, EnumDiscriminants)] #[strum_discriminants(name(Name))] #[strum_discriminants(derive(Ordinalize))] @@ -200,7 +203,7 @@ impl HGet { Self { namespace: namespace.into(), key: key.into(), - field: field.into(), + field: field.convert(), } } } @@ -247,7 +250,7 @@ impl HDel { Self { namespace: namespace.into(), key: key.into(), - field: field.into(), + field: field.convert(), version: EntryVersion::new(), } } @@ -271,7 +274,7 @@ impl HGetExp { Self { namespace: namespace.into(), key: key.into(), - field: field.into(), + field: field.convert(), } } } @@ -298,7 +301,7 @@ impl HSetExp { Self { namespace: namespace.into(), key: key.into(), - field: field.into(), + field: field.convert(), expiration: expiration.into(), version: EntryVersion::new(), } @@ -344,7 +347,7 @@ impl HScan { namespace: namespace.into(), key: key.into(), count: count.into(), - cursor: cursor.map(Field::into), + cursor: cursor.map(Field::convert), } } } @@ -369,6 +372,8 @@ impl From<()> for Output { } impl Output { + /// Tries to downcast an [`Output`] within a [`Result`] into a concrete + /// output type. pub fn downcast_result(operation_result: Result) -> Result where Self: TryInto>, diff --git a/crates/storage_api2/src/rpc/client.rs b/crates/storage_api2/src/rpc/client.rs index 32fce4a0..c1912cdf 100644 --- a/crates/storage_api2/src/rpc/client.rs +++ b/crates/storage_api2/src/rpc/client.rs @@ -1,26 +1,13 @@ use { super::*, + crate::{operation, MapPage, MapRecord, Operation, Record, StorageApi}, futures::SinkExt, - std::{ - collections::HashSet, - future::Future, - result::Result as StdResult, - sync::Arc, - time::Duration, - }, + std::{collections::HashSet, result::Result as StdResult, time::Duration}, wcn_rpc::{ - client::middleware::{ - self, - MeteredExt, - Timeouts, - WithRetries, - WithRetriesExt, - WithTimeouts, - WithTimeoutsExt as _, - }, + client::middleware::{MeteredExt, Timeouts, WithTimeouts, WithTimeoutsExt as _}, identity::Keypair, middleware::Metered, - transport::{self, NoHandshake, PendingConnection}, + transport::{self, NoHandshake}, PeerAddr, }, }; @@ -39,6 +26,9 @@ pub struct Config { /// [`Keypair`] of the [`Client`]. pub keypair: Keypair, + /// Name of the RPC server the [`Client`] is supposed to connect to. + pub server_name: rpc::ServerName, + /// Timeout of establishing a network connection. pub connection_timeout: Duration, @@ -50,9 +40,10 @@ pub struct Config { } impl Config { - pub fn new() -> Self { + pub fn new(server_name: rpc::ServerName) -> Self { Self { keypair: Keypair::generate_ed25519(), + server_name, connection_timeout: Duration::from_secs(5), rpc_timeout: Duration::from_secs(10), metrics_tag: "default", @@ -65,6 +56,12 @@ impl Config { self } + /// Overwrites [`Config::keypair`]. + pub fn with_keypair(mut self, keypair: Keypair) -> Self { + self.keypair = keypair; + self + } + /// Overwrites [`Config::connection_timeout`]. pub fn with_connection_timeout(mut self, timeout: Duration) -> Self { self.connection_timeout = timeout; @@ -97,7 +94,7 @@ impl Client { known_peers: HashSet::new(), handshake: NoHandshake, connection_timeout: config.connection_timeout, - server_name: super::COORDINATOR_SERVER_NAME, + server_name: config.server_name, priority: transport::Priority::High, }; @@ -129,169 +126,169 @@ pub struct RemoteStorage<'a> { } impl RemoteStorage<'_> { - fn extended_key(&self, key: Key) -> ExtendedKey { - ExtendedKey { - inner: key.0, - keyspace_version: self.expected_keyspace_version, - } - } - fn rpc_client(&self) -> &Inner { &self.client.inner } + fn context(&self, namespace: &Namespace) -> Context { + Context { + namespace_node_operator_id: namespace.node_operator_id, + namespace_id: namespace.id, + keyspace_version: self.expected_keyspace_version, + } + } + /// Specifies the expected version of the keyspace of the [`RemoteStorage`]. pub fn expecting_keyspace_version(mut self, version: u64) -> Self { self.expected_keyspace_version = Some(version); self } +} + +impl<'a> StorageApi for RemoteStorage<'a> { + type Error = Error; - /// Gets a [`Record`] by the provided [`Key`]. - pub async fn get(self, key: Key) -> Result> { + async fn get(&self, get: operation::Get) -> Result> { Get::send(self.rpc_client(), self.server_addr, &GetRequest { - key: self.extended_key(key), + context: self.context(&get.namespace), + key: get.key.into(), }) .await - .map(|opt| opt.map(|resp| Record::new(resp.value, resp.expiration, resp.version))) + .map(|opt| { + opt.map(|resp| Record { + value: resp.value.into(), + expiration: resp.expiration.into(), + version: resp.version.into(), + }) + }) .map_err(Into::into) } - /// Sets the provided [`Entry`] only if the version of the existing - /// [`Entry`] is < than the new one. - pub async fn set(self, entry: Entry) -> Result<()> { + async fn set(&self, set: operation::Set) -> Result<()> { Set::send(self.rpc_client(), self.server_addr, &SetRequest { - key: self.extended_key(entry.key), - value: entry.value, - expiration: entry.expiration.timestamp(), - version: entry.version.timestamp(), + context: self.context(&set.namespace), + key: set.entry.key.into(), + value: set.entry.value.into(), + expiration: set.entry.expiration.into(), + version: set.entry.version.into(), }) .await .map_err(Into::into) } - /// Deletes an [`Entry`] by the provided [`Key`] only if the version of the - /// [`Entry`] is < than the provided `version`. - pub async fn del(self, key: Key, version: EntryVersion) -> Result<()> { - Del::send(self.rpc_client(), self.server_addr, &DelRequest { - key: self.extended_key(key), - version: version.timestamp(), + async fn set_exp(&self, set_exp: operation::SetExp) -> Result<()> { + SetExp::send(self.rpc_client(), self.server_addr, &SetExpRequest { + context: self.context(&set_exp.namespace), + key: set_exp.key.into(), + expiration: set_exp.expiration.into(), + version: set_exp.version.into(), }) .await .map_err(Into::into) } - /// Gets an [`EntryExpiration`] by the provided [`Key`]. - pub async fn get_exp(self, key: Key) -> Result> { - GetExp::send(self.rpc_client(), self.server_addr, &GetExpRequest { - key: self.extended_key(key), + async fn del(&self, del: operation::Del) -> Result<()> { + Del::send(self.rpc_client(), self.server_addr, &DelRequest { + context: self.context(&del.namespace), + key: del.key.into(), + version: del.version.into(), }) .await - .map(|opt| opt.map(|resp| EntryExpiration::from(resp.expiration))) .map_err(Into::into) } - /// Sets [`Expiration`] on the [`Entry`] with the provided [`Key`] only if - /// the version of the [`Entry`] is < than the provided `version`. - pub async fn set_exp( - self, - key: Key, - expiration: impl Into, - version: EntryVersion, - ) -> Result<()> { - SetExp::send(self.rpc_client(), self.server_addr, &SetExpRequest { - key: self.extended_key(key), - expiration: expiration.into().timestamp(), - version: version.timestamp(), + async fn get_exp(&self, get_exp: operation::GetExp) -> Result> { + GetExp::send(self.rpc_client(), self.server_addr, &GetExpRequest { + context: self.context(&get_exp.namespace), + key: get_exp.key.into(), }) .await + .map(|opt| opt.map(|resp| EntryExpiration::from(resp.expiration))) .map_err(Into::into) } - /// Gets a map [`Record`] by the provided [`Key`] and [`Field`]. - pub async fn hget(self, key: Key, field: Field) -> Result> { + async fn hget(&self, hget: operation::HGet) -> Result> { HGet::send(self.rpc_client(), self.server_addr, &HGetRequest { - key: self.extended_key(key), - field, + context: self.context(&hget.namespace), + key: hget.key.into(), + field: hget.field.into(), }) .await - .map(|opt| opt.map(|resp| Record::new(resp.value, resp.expiration, resp.version))) + .map(|opt| { + opt.map(|resp| Record { + value: resp.value.into(), + expiration: resp.expiration.into(), + version: resp.version.into(), + }) + }) .map_err(Into::into) } - /// Sets the provided [`MapEntry`] only if the version of the existing - /// [`MapEntry`] is < than the new one. - pub async fn hset(self, entry: MapEntry) -> Result<()> { + async fn hset(&self, hset: operation::HSet) -> Result<()> { HSet::send(self.rpc_client(), self.server_addr, &HSetRequest { - key: self.extended_key(entry.key), - field: entry.field, - value: entry.value, - expiration: entry.expiration.timestamp(), - version: entry.version.timestamp(), + context: self.context(&hset.namespace), + key: hset.entry.key.into(), + field: hset.entry.field.into(), + value: hset.entry.value.into(), + expiration: hset.entry.expiration.into(), + version: hset.entry.version.into(), }) .await .map_err(Into::into) } - /// Deletes a [`MapEntry`] by the provided [`Key`] only if the version of - /// the [`MapEntry`] is < than the provided `version`. - pub async fn hdel(self, key: Key, field: Field, version: EntryVersion) -> Result<()> { + async fn hdel(&self, hdel: operation::HDel) -> Result<()> { HDel::send(self.rpc_client(), self.server_addr, &HDelRequest { - key: self.extended_key(key), - field, - version: version.timestamp(), + context: self.context(&hdel.namespace), + key: hdel.key.into(), + field: hdel.field.into(), + version: hdel.version.into(), }) .await .map_err(Into::into) } - /// Gets an [`EntryExpiration`] by the provided [`Key`] and [`Field`]. - pub async fn hget_exp(self, key: Key, field: Field) -> Result> { + async fn hget_exp(&self, hget_exp: operation::HGetExp) -> Result> { HGetExp::send(self.rpc_client(), self.server_addr, &HGetExpRequest { - key: self.extended_key(key), - field, + context: self.context(&hget_exp.namespace), + key: hget_exp.key.into(), + field: hget_exp.field.into(), }) .await .map(|opt| opt.map(|resp| EntryExpiration::from(resp.expiration))) .map_err(Into::into) } - /// Sets [`Expiration`] on the [`MapEntry`] with the provided [`Key`] and - /// [`Field`] only if the version of the [`MapEntry`] is < than the - /// provided `version`. - pub async fn hset_exp( - self, - key: Key, - field: Field, - expiration: impl Into, - version: EntryVersion, - ) -> Result<()> { + async fn hset_exp(&self, hset_exp: operation::HSetExp) -> Result<()> { HSetExp::send(self.rpc_client(), self.server_addr, &HSetExpRequest { - key: self.extended_key(key), - field, - expiration: expiration.into().timestamp(), - version: version.timestamp(), + context: self.context(&hset_exp.namespace), + key: hset_exp.key.into(), + field: hset_exp.field.into(), + expiration: hset_exp.expiration.into(), + version: hset_exp.version.into(), }) .await .map_err(Into::into) } - /// Returns cardinality of the map with the provided [`Key`]. - pub async fn hcard(self, key: Key) -> Result { + async fn hcard(&self, hcard: operation::HCard) -> Result { HCard::send(self.rpc_client(), self.server_addr, &HCardRequest { - key: self.extended_key(key), + context: self.context(&hcard.namespace), + key: hcard.key.into(), }) .await .map(|resp| resp.cardinality) .map_err(Into::into) } - /// Returns a [`MapPage`] by iterating over the [`Field`]s of the map with - /// the provided [`Key`]. - pub async fn hscan(self, key: Key, count: u32, cursor: Option) -> Result { + async fn hscan(&self, hscan: operation::HScan) -> Result { + let count = hscan.count; + let resp = HScan::send(self.rpc_client(), self.server_addr, &HScanRequest { - key: self.extended_key(key), - count, - cursor, + context: self.context(&hscan.namespace), + key: hscan.key.into(), + count: hscan.count, + cursor: hscan.cursor.map(Into::into), }) .await .map_err(Error::from)?; @@ -302,14 +299,34 @@ impl RemoteStorage<'_> { .records .into_iter() .map(|record| MapRecord { - field: record.field, - value: record.value, + field: record.field.into(), + value: record.value.into(), expiration: EntryExpiration::from(record.expiration), version: EntryVersion::from(record.version), }) .collect(), }) } + + async fn execute( + &self, + operation: impl Into + Send, + ) -> Result { + match operation.into() { + Operation::Get(get) => self.get(get).await.map(Into::into), + Operation::Set(set) => self.set(set).await.map(Into::into), + Operation::Del(del) => self.del(del).await.map(Into::into), + Operation::GetExp(get_exp) => self.get_exp(get_exp).await.map(Into::into), + Operation::SetExp(set_exp) => self.set_exp(set_exp).await.map(Into::into), + Operation::HGet(hget) => self.hget(hget).await.map(Into::into), + Operation::HSet(hset) => self.hset(hset).await.map(Into::into), + Operation::HDel(hdel) => self.hdel(hdel).await.map(Into::into), + Operation::HGetExp(hget_exp) => self.hget_exp(hget_exp).await.map(Into::into), + Operation::HSetExp(hset_exp) => self.hset_exp(hset_exp).await.map(Into::into), + Operation::HCard(hcard) => self.hcard(hcard).await.map(Into::into), + Operation::HScan(hscan) => self.hscan(hscan).await.map(Into::into), + } + } } /// Error of [`Client::new`]. @@ -354,8 +371,8 @@ impl From for Error { match rpc_err.code.as_ref() { wcn_rpc::error_code::TIMEOUT => Self::Timeout, - crate::error_code::KEYSPACE_VERSION_MISMATCH => Self::KeyspaceVersionMismatch, - crate::error_code::UNAUTHORIZED => Self::Unauthorized, + error_code::KEYSPACE_VERSION_MISMATCH => Self::KeyspaceVersionMismatch, + error_code::UNAUTHORIZED => Self::Unauthorized, _ => Self::Other(format!("{rpc_err:?}")), } } @@ -364,33 +381,8 @@ impl From for Error { /// [`Client`] operation [`Result`]. pub type Result = std::result::Result; -/// Client part of the [`network::Handshake`]. -#[derive(Clone)] -struct Handshake { - access_token: AccessToken, -} - -impl transport::Handshake for Handshake { - type Ok = (); - type Err = HandshakeError; - - fn handle( - &self, - _peer_id: PeerId, - conn: PendingConnection, - ) -> impl Future> + Send { - async move { - let (mut rx, mut tx) = conn - .initiate_handshake::() - .await?; - - let req = HandshakeRequest { - access_token: self.access_token.load().as_ref().to_owned(), - }; - - tx.send(req).await.map_err(HandshakeError::Transport)?; - - rx.recv_message().await?.map_err(Into::into) - } +impl From for Error { + fn from(err: operation::WrongOutput) -> Self { + Self::Other(err.to_string()) } } diff --git a/crates/storage_api2/src/rpc/mod.rs b/crates/storage_api2/src/rpc/mod.rs index d2e54c67..83d8ec2c 100644 --- a/crates/storage_api2/src/rpc/mod.rs +++ b/crates/storage_api2/src/rpc/mod.rs @@ -1,8 +1,7 @@ use { - crate::{EntryExpiration, EntryVersion, Field, Value}, + crate::{EntryExpiration, EntryVersion, Namespace}, serde::{Deserialize, Serialize}, - std::io, - wcn_rpc::{self as rpc, transport}, + wcn_rpc::{self as rpc}, }; #[cfg(feature = "rpc_client")] @@ -14,27 +13,15 @@ pub mod server; #[cfg(feature = "rpc_server")] pub use server::Server; -/// Kind of a Storage API server. -pub enum ServerKind { - /// Replication Coordinator server. - Coordinator, +/// Storage API RPC server hosted by a WCN Replication Coordinator. +pub const COORDINATOR_RPC_SERVER_NAME: rpc::ServerName = + rpc::ServerName::new("StorageApiCoordinator"); - /// Replica server. - Replica, +/// Storage API RPC server hosted by a WCN Replica. +pub const REPLICA_RPC_SERVER_NAME: rpc::ServerName = rpc::ServerName::new("StorageApiReplica"); - /// Database server. - Database, -} - -impl ServerKind { - fn server_name(&self) -> rpc::ServerName { - match self { - Self::Coordinator => "StorageApiCoordinator", - Self::Replica => "StorageApiReplica", - Self::Database => "StorageApiDatabase", - } - } -} +/// Storage API RPC server hosted by a WCN Database. +pub const DATABASE_RPC_SERVER_NAME: rpc::ServerName = rpc::ServerName::new("StorageApiDatabase"); /// RPC error codes produced by this module. mod error_code { @@ -48,15 +35,35 @@ mod error_code { pub const INVALID_KEY: &str = "invalid_key"; } +#[derive(Clone, Debug, Serialize, Deserialize)] +struct Context { + namespace_node_operator_id: [u8; 20], + namespace_id: u8, + keyspace_version: Option, +} + +impl + +#[derive(Debug, Serialize, Deserialize)] +struct Key(Vec); + +#[derive(Debug, Serialize, Deserialize)] +struct Value(Vec); + +#[derive(Debug, Serialize, Deserialize)] +struct Field(Vec); + type Get = rpc::Unary<{ rpc::id(b"Get") }, GetRequest, Option>; #[derive(Clone, Debug, Serialize, Deserialize)] struct GetRequest { - key: ExtendedKey, + context: Context, + key: Key, } #[derive(Clone, Debug, Serialize, Deserialize)] struct GetResponse { + context: Context, value: Value, expiration: UnixTimestampSecs, version: UnixTimestampMicros, @@ -66,7 +73,8 @@ type Set = rpc::Unary<{ rpc::id(b"Set") }, SetRequest, ()>; #[derive(Clone, Debug, Serialize, Deserialize)] struct SetRequest { - key: ExtendedKey, + context: Context, + key: Key, value: Value, expiration: UnixTimestampSecs, version: UnixTimestampMicros, @@ -76,7 +84,8 @@ type Del = rpc::Unary<{ rpc::id(b"Del") }, DelRequest, ()>; #[derive(Clone, Debug, Serialize, Deserialize)] struct DelRequest { - key: ExtendedKey, + context: Context, + key: Key, version: UnixTimestampMicros, } @@ -84,7 +93,8 @@ type GetExp = rpc::Unary<{ rpc::id(b"GetExp") }, GetExpRequest, Option; #[derive(Clone, Debug, Serialize, Deserialize)] struct SetExpRequest { - key: ExtendedKey, + context: Context, + key: Key, expiration: UnixTimestampSecs, version: UnixTimestampMicros, } @@ -105,7 +116,8 @@ type HGet = rpc::Unary<{ rpc::id(b"HGet") }, HGetRequest, Option>; #[derive(Clone, Debug, Serialize, Deserialize)] struct HGetRequest { - key: ExtendedKey, + context: Context, + key: Key, field: Field, } @@ -120,7 +132,8 @@ type HSet = rpc::Unary<{ rpc::id(b"HSet") }, HSetRequest, ()>; #[derive(Clone, Debug, Serialize, Deserialize)] struct HSetRequest { - key: ExtendedKey, + context: Context, + key: Key, field: Field, value: Value, expiration: UnixTimestampSecs, @@ -131,7 +144,8 @@ type HDel = rpc::Unary<{ rpc::id(b"HDel") }, HDelRequest, ()>; #[derive(Clone, Debug, Serialize, Deserialize)] struct HDelRequest { - key: ExtendedKey, + context: Context, + key: Key, field: Field, version: UnixTimestampMicros, } @@ -140,7 +154,8 @@ type HGetExp = rpc::Unary<{ rpc::id(b"HGetExp") }, HGetExpRequest, Option; #[derive(Clone, Debug, Serialize, Deserialize)] struct HSetExpRequest { - key: ExtendedKey, + context: Context, + key: Key, field: Field, expiration: UnixTimestampSecs, version: UnixTimestampMicros, @@ -163,7 +179,8 @@ type HCard = rpc::Unary<{ rpc::id(b"HCard") }, HCardRequest, HCardResponse>; #[derive(Clone, Debug, Serialize, Deserialize)] struct HCardRequest { - key: ExtendedKey, + context: Context, + key: Key, } #[derive(Clone, Debug, Serialize, Deserialize)] @@ -175,7 +192,8 @@ type HScan = rpc::Unary<{ rpc::id(b"HScan") }, HScanRequest, HScanResponse>; #[derive(Clone, Debug, Serialize, Deserialize)] struct HScanRequest { - key: ExtendedKey, + context: Context, + key: Key, count: u32, cursor: Option, } @@ -228,8 +246,47 @@ impl From for EntryVersion { } } -#[derive(Clone, Debug, Serialize, Deserialize)] -struct ExtendedKey { - inner: Vec, - keyspace_version: Option, +impl From for Namespace { + fn from(ctx: Context) -> Self { + Self { + node_operator_id: ctx.namespace_node_operator_id, + id: ctx.namespace_id, + } + } +} + +impl From for crate::Key { + fn from(key: Key) -> Self { + Self(key.0) + } +} + +impl From for Key { + fn from(key: crate::Key) -> Self { + Self(key.0) + } +} + +impl From for crate::Value { + fn from(value: Value) -> Self { + Self(value.0) + } +} + +impl From for Value { + fn from(value: crate::Value) -> Self { + Self(value.0) + } +} + +impl From for crate::Field { + fn from(field: Field) -> Self { + Self(field.0) + } +} + +impl From for Field { + fn from(field: crate::Field) -> Self { + Self(field.0) + } } diff --git a/crates/storage_api2/src/rpc/server.rs b/crates/storage_api2/src/rpc/server.rs index 818768e1..13bc9ae8 100644 --- a/crates/storage_api2/src/rpc/server.rs +++ b/crates/storage_api2/src/rpc/server.rs @@ -1,7 +1,8 @@ use { super::*, + crate::{operation, StorageApi}, futures::SinkExt as _, - std::{collections::HashSet, future::Future, sync::Arc}, + std::{collections::HashSet, future::Future, sync::Arc, time::Duration}, wcn_rpc::{ middleware::Timeouts, server::{ @@ -9,7 +10,7 @@ use { ClientConnectionInfo, ConnectionInfo, }, - transport::{self, BiDirectionalStream, PendingConnection, PostcardCodec}, + transport::{self, BiDirectionalStream, NoHandshake, PendingConnection, PostcardCodec}, }, }; @@ -17,28 +18,26 @@ use { pub type Namespace = Vec; /// Storage API [`Server`] config. -pub struct Config { +pub struct Config { + /// Name of the [`Server`]. + pub name: rpc::ServerName, + /// Timeout of a [`Server`] operation. pub operation_timeout: Duration, - - /// Inbound connection [`Authenticator`]. - pub authenticator: A, } /// Storage API server. pub trait Server: StorageApi + Clone + Send + Sync + 'static { - /// Returns the current keyspace version of this [`Server`]. - fn keyspace_version(&self) -> u64; + /// Checks whether the provided keyspace version matches the one of the [`Server`]. + fn validate_keyspace_version(&self, version: u64) -> bool; /// Converts this Storage API [`Server`] into an [`rpc::Server`]. - fn into_rpc_server(self, cfg: Config) -> impl rpc::Server { + fn into_rpc_server(self, cfg: Config) -> impl rpc::Server { let timeouts = Timeouts::new().with_default(cfg.operation_timeout); let rpc_server_config = wcn_rpc::server::Config { - name: crate::RPC_SERVER_NAME, - handshake: Handshake { - authenticator: cfg.authenticator, - }, + name: cfg.name, + handshake: NoHandshake, }; RpcServer { @@ -52,38 +51,16 @@ pub trait Server: StorageApi + Clone + Send + Sync + 'static { struct RpcHandler<'a, S> { api_server: &'a S, - conn_info: &'a ConnectionInfo, + conn_info: &'a ConnectionInfo<(), ()>, } impl RpcHandler<'_, S> { - fn prepare_key(&self, key: ExtendedKey) -> wcn_rpc::Result { - if let Some(keyspace_version) = key.keyspace_version { - if keyspace_version != self.api_server.keyspace_version() { - return Err(wcn_rpc::Error::new(error_code::KEYSPACE_VERSION_MISMATCH)); - } - } - - let key = Key::from_raw_bytes(key.inner) - .ok_or_else(|| wcn_rpc::Error::new(error_code::INVALID_KEY))?; - - if let Some(namespace) = key.namespace() { - if !self - .conn_info - .handshake_data - .namespaces - .contains(namespace.as_slice()) - { - return Err(wcn_rpc::Error::new(error_code::UNAUTHORIZED)); - } - } - - Ok(key) - } async fn get(&self, req: GetRequest) -> wcn_rpc::Result> { let record = self .api_server - .execute_get(operation::Get { + .get(operation::Get { + namespace: key: self.prepare_key(req.key)?, }) .await @@ -112,7 +89,7 @@ impl RpcHandler<'_, S> { async fn del(&self, req: DelRequest) -> wcn_rpc::Result<()> { self.api_server - .execute_del(operation::Del { + .del(operation::Del { key: self.prepare_key(req.key)?, version: EntryVersion::from(req.version), }) @@ -253,17 +230,16 @@ impl RpcHandler<'_, S> { } #[derive(Clone, Debug)] -struct RpcServer { +struct RpcServer { api_server: S, - config: rpc::server::Config>, + config: rpc::server::Config, } -impl rpc::Server for RpcServer +impl rpc::Server for RpcServer where S: Server, - V: Authenticator, { - type Handshake = Handshake; + type Handshake = NoHandshake; type ConnectionData = (); type Codec = PostcardCodec; @@ -327,98 +303,6 @@ impl Error { /// [`Server`] operation [`Result`]. pub type Result = std::result::Result; -/// Server part of the [`network::Handshake`]. -#[derive(Clone, Debug)] -pub struct Handshake { - authenticator: V, -} - -#[derive(Clone, Debug)] -pub struct HandshakeData { - pub namespaces: Arc>, -} - -impl transport::Handshake for Handshake { - type Ok = HandshakeData; - type Err = HandshakeError; - - fn handle( - &self, - peer_id: PeerId, - conn: PendingConnection, - ) -> impl Future> + Send { - async move { - let (mut rx, mut tx) = conn - .accept_handshake::() - .await?; - - let req = rx.recv_message().await?; - - let err_resp = match self - .authenticator - .validate_access_token(&req.access_token, peer_id) - { - Ok(data) => { - tx.send(Ok(())).await?; - return Ok(HandshakeData { - namespaces: Arc::new( - data.namespaces() - .into_iter() - .map(|ns| ns.as_bytes().to_vec()) - .collect(), - ), - }); - } - Err(err) => HandshakeErrorResponse::InvalidToken(err), - }; - - tx.send(Err(err_resp.clone())).await?; - Err(err_resp.into()) - } - } -} - -/// Inbound connection authenticator. -pub trait Authenticator: Clone + Send + Sync + 'static { - /// Indicates whether the specified peer is an authorized access token - /// issuer. - fn is_authorized_token_issuer(&self, peer_id: PeerId) -> bool; - - /// Network id of the local Storage API server. - fn network_id(&self) -> &str; - - /// Validates the provided access token. - fn validate_access_token( - &self, - token: &auth::Token, - client_peer_id: PeerId, - ) -> Result { - let claims = token.decode().map_err(|err| err.to_string())?; - - if claims.is_expired() { - return Err("Token expired".to_string()); - } - - match claims.purpose() { - auth::token::Purpose::Storage => {} - }; - - if self.network_id() != claims.network_id() { - return Err("Wrong network".to_string()); - } - - if !self.is_authorized_token_issuer(claims.issuer_peer_id()) { - return Err("Unauthorized token issuer".to_string()); - } - - if claims.client_peer_id() != client_peer_id { - return Err("Wrong PeerId".to_string()); - } - - Ok(claims) - } -} - impl From for Error { fn from(err: operation::WrongOutput) -> Self { Self(err.to_string()) From b5180a8ba0f1678107d86897a407a27c8f7365ca Mon Sep 17 00:00:00 2001 From: Darksome Date: Wed, 18 Jun 2025 10:43:26 +0000 Subject: [PATCH 53/79] WIP --- Cargo.lock | 1 + crates/rpc/Cargo.toml | 1 + crates/rpc/src/client2.rs | 120 ++++++++++++++++++++++++-------------- crates/rpc/src/lib.rs | 26 +++++++-- crates/rpc/src/server2.rs | 71 ++++++++++------------ 5 files changed, 129 insertions(+), 90 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c85006c3..7a504441 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8018,6 +8018,7 @@ dependencies = [ name = "wcn_rpc" version = "0.1.0" dependencies = [ + "arc-swap", "backoff", "derivative", "derive_more 1.0.0", diff --git a/crates/rpc/Cargo.toml b/crates/rpc/Cargo.toml index c0887893..dc356256 100644 --- a/crates/rpc/Cargo.toml +++ b/crates/rpc/Cargo.toml @@ -44,6 +44,7 @@ socket2 = "0.5.5" nix = { version = "0.28", default-features = false, features = ["socket", "net"] } governor = { version = "0.8", default-features = false, features = ["std"] } mini-moka = { version = "0.10", default-features = false, features = ["sync"] } +arc-swap = "1.7" [dev-dependencies] tracing-subscriber = "0.3" diff --git a/crates/rpc/src/client2.rs b/crates/rpc/src/client2.rs index db7f1703..f7232d59 100644 --- a/crates/rpc/src/client2.rs +++ b/crates/rpc/src/client2.rs @@ -3,31 +3,38 @@ use { self as rpc, quic, transport::{self, BiDirectionalStream, NoHandshake, RecvStream, SendStream}, + ConnectionHandler, Message, + RpcV2, ServerName, }, - futures::{Sink, SinkExt, Stream, TryStreamExt as _}, + arc_swap::ArcSwap, + futures::{future::Shared, Sink, SinkExt, Stream, TryStreamExt as _}, libp2p::{identity, PeerId}, std::{ future::Future, io, marker::PhantomData, net::{SocketAddr, SocketAddrV4}, + pin::Pin, sync::Arc, time::Duration, }, tokio::io::AsyncWriteExt, }; -pub trait RpcSender: Send + Sync + 'static { - type Output; +pub trait Api: super::Api { + type OutboundConnectionHandler: OutboundConnectionHandler; + type OutboundRpcHandler; +} - fn send<'a>( - &'a self, - args: Args, - ) -> impl Future> + Send + 'a - where - Args: 'a; +pub trait OutboundConnectionHandler: Clone + Send + Sync + 'static { + type Api; + + fn handle( + &self, + conn: &mut OutboundConnection, + ) -> impl Future + Send; } pub struct Config { @@ -41,13 +48,19 @@ pub struct Config { pub priority: transport::Priority, } -pub struct Client { +pub struct Client { config: Arc, quic: quinn::Endpoint, + connection_handler: API::OutboundConnectionHandler, + rpc_handler: API::OutboundRpcHandler, } -impl Client { - pub fn new(cfg: Config) -> Result { +impl Client { + pub fn new( + connection_handler: API::OutboundConnectionHandler, + rpc_handler: API::OutboundRpcHandler, + cfg: Config, + ) -> Result { let transport_config = quic::new_quinn_transport_config(64u32 * 1024); let socket_addr = SocketAddr::new(std::net::Ipv4Addr::new(0, 0, 0, 0).into(), 0); let endpoint = quic::new_quinn_endpoint( @@ -62,49 +75,64 @@ impl Client { Ok(Client { config: Arc::new(cfg), quic: endpoint, + connection_handler, + rpc_handler, }) } - pub fn connect( - &self, - addr: SocketAddrV4, - peer_id: PeerId, - ) -> OutboundConnection { - OutboundConnection { - quic: quic::client::ConnectionHandler::new( - peer_id, - addr.into(), - API::NAME, - self.quic.clone(), - NoHandshake, - self.config.connection_timeout, - ), - _marker: PhantomData, - } + pub fn connect(&self, addr: SocketAddrV4, peer_id: PeerId) -> OutboundConnection { + todo!() } } -pub struct OutboundConnection { - quic: quic::client::ConnectionHandler, - _marker: PhantomData, +pub struct Outbound { + send: transport::SendStream, + recv: transport::RecvStream, +} + +pub struct OutboundConnection { + inner: Arc>, +} + +struct OutboundConnectionInner { + quic: Arc>>, + + mutex: Arc>, + connect_fut: tokio::task::JoinHandle<()>, + + rpc_handler: API::OutboundRpcHandler, +} + +impl OutboundConnection { + fn new(addr: SocketAddrV4, peer_id: PeerId) -> Self { + let quic = Arc::new(ArcSwap::new(Arc::new(None))); + let mutex = Arc::new(tokio::sync::Mutex::new(())); + + let quic_clone = quic.clone(); + let mutex_guard = mutex.lock_owned(); + let connect_fut = tokio::spawn(async move { + let _mutex_guard = mutex_guard; + + }); + } + + pub fn send(&self) -> Outbound { + ArcSwap:: + } } -impl - RpcSender, F> for OutboundConnection +impl + RpcSender, H> for OutboundConnection where API: rpc::Api, Request: Message, Response: Message, Codec: transport::Codec, - F: FnOnce(&mut SendStream, &mut RecvStream) -> Fut + Send, - Fut: Future> + Send, + H: RpcHandler, { - type Output = T; + type Output = H::Output; - fn send<'a>(&'a self, f: F) -> impl Future> + Send + 'a - where - F: 'a, - { + fn send(&self, handler: H) -> impl Future> + Send + '_ { async move { let (mut tx, rx) = self .quic @@ -119,7 +147,11 @@ where let (mut rx, mut tx) = BiDirectionalStream::new(tx, rx).upgrade::(); - f(&mut tx, &mut rx) + // we use &mut here instead of passing owned values to force the implementor not + // to move the values outside of the `RpcSender`, otherwise some + // middleware implementations may work incorrectly. + handler + .handle(&mut tx, &mut rx) .await .map_err(|err| RpcSenderError::Transport(err.to_string())) } @@ -168,8 +200,10 @@ where } } -pub struct OutboundRpc { - stream: BiDirectionalStream, +#[derive(Debug, thiserror::Error)] +pub enum OutboundConnectionError { + #[error("Transport: {_0}")] + Transport(String), } #[derive(Debug, thiserror::Error)] diff --git a/crates/rpc/src/lib.rs b/crates/rpc/src/lib.rs index a98a6d3c..ec7fdf54 100644 --- a/crates/rpc/src/lib.rs +++ b/crates/rpc/src/lib.rs @@ -5,7 +5,15 @@ pub use libp2p::{identity, Multiaddr, PeerId}; use { derive_more::Display, serde::{Deserialize, Serialize}, - std::{borrow::Cow, fmt::Debug, marker::PhantomData, net::SocketAddr, str::FromStr, sync::Arc}, + std::{ + borrow::Cow, + fmt::Debug, + future::Future, + marker::PhantomData, + net::SocketAddr, + str::FromStr, + sync::Arc, + }, tokio::sync::OwnedSemaphorePermit, transport::Codec, }; @@ -32,6 +40,17 @@ pub mod transport; #[cfg(test)] mod test; +pub trait Api: Send + Sync + 'static { + const NAME: ApiName; + type RpcId; +} + +pub trait Handler { + type Result; + + fn handle_rpc(&self, rpc: &mut RPC) -> impl Future + Send; +} + /// Error codes produced by this module. pub mod error_code { #[allow(unused_imports)] @@ -158,11 +177,6 @@ impl Name { } } -pub trait Api: Send + Sync + 'static { - const NAME: ApiName; - type RpcId; -} - pub type ApiName = ServerName; /// RPC server name. diff --git a/crates/rpc/src/server2.rs b/crates/rpc/src/server2.rs index f5cbb1a1..55192e2d 100644 --- a/crates/rpc/src/server2.rs +++ b/crates/rpc/src/server2.rs @@ -11,6 +11,7 @@ use { transport::{self, BiDirectionalStream}, ApiName, }, + ::metrics::CounterFn, futures::{Sink, Stream, TryFutureExt as _}, libp2p::{identity::Keypair, PeerId}, quinn::crypto::rustls::QuicServerConfig, @@ -23,29 +24,18 @@ use { }, }; -// pub trait InboundRpc: RpcV2 + Stream + -// Sink {} - -pub trait ApiHandler: Clone + Send + Sync + 'static { - type Api: rpc::Api; - - fn handle_connection( - &self, - connection: &mut InboundConnection, - ) -> impl Future + Send; - - // /// Converts this [`ConnectionHandler`] into [`ApiConnectionHandler`]. - // fn into_api(self, name: ApiName) -> ApiConnectionHandler; +/// Server-specific part of an RPC [`Api`](super::Api). +pub trait Api: super::Api { + type InboundConnectionHandler: InboundConnectionHandler; } -// /// [`ConnectionHandler`] of a specific RPC API. -// pub struct ApiConnectionHandler { -// api_name: ApiName, -// connection_handler: H, -// } +pub trait InboundConnectionHandler: Clone + Send + Sync + 'static { + type Api; -pub trait RpcHandler { - fn handle(&self, rpc: &mut RPC) -> impl Future + Send; + fn handle( + &self, + conn: &mut InboundConnection, + ) -> impl Future + Send; } pub struct Config { @@ -77,8 +67,7 @@ pub struct Config { /// Serves a single RPC API on the specified. pub fn serve( cfg: Config, - api_name: ApiName, - connection_handler: impl ApiHandler, + connection_handler: impl InboundConnectionHandler, ) -> Result, Error> { multiplex(cfg, (connection_handler,)) } @@ -185,12 +174,12 @@ fn accept_connection( let conn = connecting .with_timeout(Duration::from_millis(1000)) .await - .map_err(|_| ApiHandlerError::ConnectionTimeout)??; + .map_err(|_| InboundConnectionHandlerError::ConnectionTimeout)??; let header = read_connection_header(&conn) .with_timeout(Duration::from_millis(500)) .await - .map_err(|_| ApiHandlerError::ReadConnectionHeaderTimeout)??; + .map_err(|_| InboundConnectionHandlerError::ReadConnectionHeaderTimeout)??; let conn = InboundConnection { server_name, @@ -238,7 +227,7 @@ impl InboundConnection { pub async fn handle>( &self, rpc_handler: impl Fn(InboundRpc) -> F, - ) -> ApiHandlerResult { + ) -> InboundConnectionHandlerResult { loop { match self.handle_rpc(rpc_handler).await { Ok(fut) => tokio::spawn(fut), @@ -251,7 +240,7 @@ impl InboundConnection { pub async fn handle_rpc>( &self, rpc_handler: impl Fn(InboundRpc) -> F, - ) -> ApiHandlerResult> { + ) -> InboundConnectionHandlerResult> { let (tx, mut rx) = self.inner.accept_bi().await?; let Some(permit) = self.acquire_stream_permit() else { @@ -326,23 +315,23 @@ mod sealed { &self, api_name: ApiName, connection: InboundConnection, - ) -> impl Future>; + ) -> impl Future>; } } impl ConnectionRouter for (A,) where - A: ApiHandler, + A: InboundConnectionHandler, { async fn route_connection( &self, api_name: ApiName, conn: InboundConnection, - ) -> Result<(), ApiHandlerError> { + ) -> Result<(), InboundConnectionHandlerError> { async move { match &api_name { A::Api::NAME => self.0.handle_connection(&mut conn.set_api()), - _ => Err(ApiHandlerError::UnknownApi(api_name)), + _ => Err(InboundConnectionHandlerError::UnknownApi(api_name)), } } } @@ -350,19 +339,19 @@ where impl ConnectionRouter for (A, B) where - A: ApiHandler, - B: ApiHandler, + A: InboundConnectionHandler, + B: InboundConnectionHandler, { async fn route_connection( &self, api_name: ApiName, conn: InboundConnection, - ) -> Result<(), ApiHandlerError> { + ) -> Result<(), InboundConnectionHandlerError> { async move { match &api_name { A::Api::NAME => self.0.handle_connection(&mut conn.set_api()), B::Api::NAME => self.1.handle_connection(&mut conn.set_api()), - _ => Err(ApiHandlerError::UnknownApi(api_name)), + _ => Err(InboundConnectionHandlerError::UnknownApi(api_name)), } } } @@ -370,21 +359,21 @@ where impl ConnectionRouter for (A, B, C) where - A: ApiHandler, - B: ApiHandler, - C: ApiHandler, + A: InboundConnectionHandler, + B: InboundConnectionHandler, + C: InboundConnectionHandler, { async fn route_connection( &self, api_name: ApiName, conn: InboundConnection, - ) -> Result<(), ApiHandlerError> { + ) -> Result<(), InboundConnectionHandlerError> { async move { match &api_name { A::Api::NAME => self.0.handle_connection(&mut conn.set_api()), B::Api::NAME => self.1.handle_connection(&mut conn.set_api()), C::Api::NAME => self.1.handle_connection(&mut conn.set_api()), - _ => Err(ApiHandlerError::UnknownApi(api_name)), + _ => Err(InboundConnectionHandlerError::UnknownApi(api_name)), } } } @@ -403,7 +392,7 @@ pub enum Error { } #[derive(Debug, thiserror::Error)] -pub enum ApiHandlerError { +pub enum InboundConnectionHandlerError { #[error("Transport: {0}")] Transport(String), @@ -417,7 +406,7 @@ pub enum ApiHandlerError { UnknownApi(rpc::ApiName), } -pub type ApiHandlerResult = Result; +pub type InboundConnectionHandlerResult = Result; #[derive(Debug, thiserror::Error)] pub enum RpcHandlerError { From 4344eb919823b33be3f2892d9164792173b08939 Mon Sep 17 00:00:00 2001 From: Darksome Date: Thu, 19 Jun 2025 08:54:21 +0000 Subject: [PATCH 54/79] WIP --- Cargo.lock | 12 + Cargo.toml | 1 + crates/rpc/Cargo.toml | 1 + crates/rpc/src/client2.rs | 403 +++++++++++++++++++++++++--------- crates/rpc/src/lib.rs | 149 ++++++++----- crates/rpc/src/quic/client.rs | 7 +- crates/rpc/src/quic/mod.rs | 2 +- crates/rpc/src/server2.rs | 6 + 8 files changed, 415 insertions(+), 166 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7a504441..9c0e2892 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2220,6 +2220,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "derive-where" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "510c292c8cf384b1a340b816a9a6cf2599eb8f566a44949024af88418000c50b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + [[package]] name = "derive_builder" version = "0.13.1" @@ -8021,6 +8032,7 @@ dependencies = [ "arc-swap", "backoff", "derivative", + "derive-where", "derive_more 1.0.0", "futures", "governor", diff --git a/Cargo.toml b/Cargo.toml index b101ad08..ed976d9a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,7 @@ derive_more = { version = "1.0.0", features = [ "deref", ] } derivative = "2" +derive-where = "1.5" core = { package = "wcn_core", path = "crates/core" } auth = { package = "wcn_auth", path = "crates/auth" } domain = { package = "wcn_domain", path = "crates/domain" } diff --git a/crates/rpc/Cargo.toml b/crates/rpc/Cargo.toml index dc356256..085cee74 100644 --- a/crates/rpc/Cargo.toml +++ b/crates/rpc/Cargo.toml @@ -13,6 +13,7 @@ server = [] [dependencies] derive_more = { workspace = true } +derive-where = { workspace = true } derivative = "2.2" futures = "0.3" indexmap = "2" diff --git a/crates/rpc/src/client2.rs b/crates/rpc/src/client2.rs index f7232d59..636e30fa 100644 --- a/crates/rpc/src/client2.rs +++ b/crates/rpc/src/client2.rs @@ -1,42 +1,73 @@ use { crate::{ self as rpc, - quic, - transport::{self, BiDirectionalStream, NoHandshake, RecvStream, SendStream}, - ConnectionHandler, + quic::{self}, + transport::{self, BiDirectionalStream, Codec}, Message, + RpcImpl, RpcV2, - ServerName, }, arc_swap::ArcSwap, - futures::{future::Shared, Sink, SinkExt, Stream, TryStreamExt as _}, + derive_where::derive_where, + futures::{FutureExt, Sink, SinkExt, Stream, StreamExt as _}, libp2p::{identity, PeerId}, std::{ future::Future, io, marker::PhantomData, net::{SocketAddr, SocketAddrV4}, - pin::Pin, sync::Arc, time::Duration, }, tokio::io::AsyncWriteExt, + wc::future::FutureExt as _, }; +/// Client-specific part of an RPC [`Api`](super::Api). pub trait Api: super::Api { + /// [`OutboundConnectionHandler`] of this [`Api`]. type OutboundConnectionHandler: OutboundConnectionHandler; - type OutboundRpcHandler; + + /// [`OutboundRpcHandler`] of this [`Api`]. + type OutboundRpcHandler: Clone + Send + Sync + 'static; } +/// Handler of newly established [`OutboundConnection`]s. +/// +/// Every time a new [`OutboundConnection`] gets established it's being passed +/// into an [`OutboundConnectionHandler`]. pub trait OutboundConnectionHandler: Clone + Send + Sync + 'static { - type Api; + /// [`Api`] that uses this [`OutboundConnectionHandler`]. + type Api: Api; + + /// Error of this [`OutboundConnectionHandler`]. + type Error; - fn handle( + /// Handles the provided [`OutboundConnection`]. + fn handle_connection( &self, conn: &mut OutboundConnection, - ) -> impl Future + Send; + ) -> impl Future> + Send; +} + +/// Handler of a specific type of [`Outbound`] RPCs. +pub trait OutboundRpcHandler: Clone + Send + Sync + 'static +where + RPC: RpcV2, +{ + /// [`Result`] of this [`OutboundRpcHandler`]. + type Result; + + /// Handles the provided [`Outbound`] RPC. + fn handle_rpc( + &self, + rpc: &mut Outbound, + args: Args, + ) -> impl Future + Send; } +/// [`Client`] config. +#[derive(Clone, Debug)] pub struct Config { /// [`identity::Keypair`] of the client. pub keypair: identity::Keypair, @@ -44,24 +75,34 @@ pub struct Config { /// Connection timeout. pub connection_timeout: Duration, + /// Highest allowed frequency of connection retries. + pub reconnect_interval: Duration, + + /// Maximum number of concurrent RPCs. + pub max_concurrent_rpcs: u32, + /// [`transport::Priority`] of the client. pub priority: transport::Priority, } +/// RPC client responsible for establishing [`OutboundConnection`]s to remote +/// peers. +#[derive(Clone)] pub struct Client { config: Arc, - quic: quinn::Endpoint, + endpoint: quinn::Endpoint, connection_handler: API::OutboundConnectionHandler, rpc_handler: API::OutboundRpcHandler, } impl Client { + /// Creates a new RPC [`Client`]. pub fn new( connection_handler: API::OutboundConnectionHandler, rpc_handler: API::OutboundRpcHandler, cfg: Config, ) -> Result { - let transport_config = quic::new_quinn_transport_config(64u32 * 1024); + let transport_config = quic::new_quinn_transport_config(cfg.max_concurrent_rpcs); let socket_addr = SocketAddr::new(std::net::Ipv4Addr::new(0, 0, 0, 0).into(), 0); let endpoint = quic::new_quinn_endpoint( socket_addr, @@ -74,148 +115,300 @@ impl Client { Ok(Client { config: Arc::new(cfg), - quic: endpoint, + endpoint, connection_handler, rpc_handler, }) } + /// Establishes a new [`OutboundConnection`]. pub fn connect(&self, addr: SocketAddrV4, peer_id: PeerId) -> OutboundConnection { - todo!() + let conn = OutboundConnection { + inner: Arc::new(OutboundConnectionInner { + client: self.clone(), + remote_addr: addr, + remote_peer_id: peer_id, + quinn: Arc::new(ArcSwap::new(Arc::new(None))), + mutex: Arc::new(tokio::sync::Mutex::new(())), + }), + }; + + conn.reconnect(); + conn } } +/// Error of [`Client::new`]. +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("Transport: {_0}")] + Transport(String), +} + +/// Outboud RPC of a specific type. pub struct Outbound { send: transport::SendStream, recv: transport::RecvStream, } +impl Outbound { + /// Returns [`Sink`] of outbound requests. + pub fn sink(&mut self) -> &mut impl Sink { + &mut self.send + } + + /// Returns [`Stream`] of inbound responses. + pub fn stream(&mut self) -> &mut impl Stream> { + &mut self.recv + } +} + +/// Outbound connection. +/// +/// Existence of an instance of this type doesn't guarantee that the actual +/// network connection is already established (or will ever be established). +/// +/// Reconnects are being handled automatically in the background. +#[derive(Clone)] pub struct OutboundConnection { inner: Arc>, } -struct OutboundConnectionInner { - quic: Arc>>, +struct OutboundConnectionInner { + client: Client, + + remote_addr: SocketAddrV4, + remote_peer_id: PeerId, + + quinn: Arc>>, mutex: Arc>, - connect_fut: tokio::task::JoinHandle<()>, - - rpc_handler: API::OutboundRpcHandler, } impl OutboundConnection { - fn new(addr: SocketAddrV4, peer_id: PeerId) -> Self { - let quic = Arc::new(ArcSwap::new(Arc::new(None))); - let mutex = Arc::new(tokio::sync::Mutex::new(())); + /// Returns [`SocketAddrV4`] of the remote peer. + pub fn peer_addr(&self) -> &SocketAddrV4 { + &self.inner.remote_addr + } + + /// Returns [`PeerId`] of the remote peer. + pub fn peer_id(&self) -> &PeerId { + &self.inner.remote_peer_id + } + + /// Indicates whether this [`OutboundConnection`] is currently open. + pub fn is_open(&self) -> bool { + (**self.inner.quinn.load()) + .as_ref() + .map(|conn| conn.close_reason().is_some()) + .unwrap_or_default() + } - let quic_clone = quic.clone(); - let mutex_guard = mutex.lock_owned(); - let connect_fut = tokio::spawn(async move { + /// Sends a new [`Outbound`] RPC over this [`OutboundConnection`]. + pub fn send(&self) -> SendRpcResult> { + let inner = self.inner.quinn.load(); + let Some(conn) = inner.as_ref() else { + return Err(SendRpcError::ConnectionClosed); + }; + + // `open_bi` only blocks if there are too many outbound streams. + let (mut tx, rx) = match conn.open_bi().now_or_never() { + Some(Ok(stream)) => stream, + Some(Err(_)) => return Err(SendRpcError::ConnectionClosed), + None => return Err(SendRpcError::TooManyConcurrentRpcs), + }; + + // Stream buffer is large enough to fit `u8` without blocking. + tx.write_u8(RPC::ID) + .now_or_never() + .unwrap() + .map_err(|_| SendRpcError::ConnectionClosed)?; + + let (recv, send) = + BiDirectionalStream::new(tx, rx).upgrade::(); + + Ok(Outbound { send, recv }) + } + + fn reconnect(&self) { + // If we can't acquire the lock then reconnection is already in progress. + let Ok(mutex_guard) = self.inner.mutex.clone().try_lock_owned() else { + return; + }; + + let this = self.inner.clone(); + + tokio::spawn(async move { let _mutex_guard = mutex_guard; - + + let mut interval = tokio::time::interval(this.client.config.reconnect_interval); + interval.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip); + + loop { + interval.tick().await; + + match this.clone().new_quic_connection().await { + Ok(conn) => { + this.quinn.store(Arc::new(Some(conn))); + return; + } + Err(err @ ConnectionError::WrongPeerId(_)) => { + tracing::warn!("outbound connection failed: {err}") + } + Err(err) => { + tracing::debug!("outbound connection failed: {err}") + } + } + } }); } - - pub fn send(&self) -> Outbound { - ArcSwap:: - } } -impl - RpcSender, H> for OutboundConnection -where - API: rpc::Api, - Request: Message, - Response: Message, - Codec: transport::Codec, - H: RpcHandler, -{ - type Output = H::Output; +impl OutboundConnectionInner { + async fn new_quic_connection(self: Arc) -> Result { + let timeout = self.client.config.connection_timeout; - fn send(&self, handler: H) -> impl Future> + Send + '_ { async move { - let (mut tx, rx) = self - .quic - .open_bi() - .await - .map_err(|err| RpcSenderError::Transport(format!("open bi: {err:?}")))?; - - tx.write_u8(ID) - .await - .map_err(|err| RpcSenderError::Transport(format!("write rpc id: {err:?}")))?; - - let (mut rx, mut tx) = - BiDirectionalStream::new(tx, rx).upgrade::(); - - // we use &mut here instead of passing owned values to force the implementor not - // to move the values outside of the `RpcSender`, otherwise some - // middleware implementations may work incorrectly. - handler - .handle(&mut tx, &mut rx) - .await - .map_err(|err| RpcSenderError::Transport(err.to_string())) + // `libp2p_tls` uses this "l" placeholder as server_name. + let conn = self + .client + .endpoint + .connect(self.remote_addr.into(), "l")? + .await?; + + let peer_id = quic::connection_peer_id(&conn) + .map_err(|err| ConnectionError::ExtractPeerId(err.to_string()))?; + + if peer_id != self.remote_peer_id { + return Err(ConnectionError::WrongPeerId(peer_id)); + } + + // write connection header + let mut tx = conn.open_uni().await?; + tx.write_u32(super::PROTOCOL_VERSION).await?; + tx.write_all(&API::NAME.0).await?; + + Ok(conn) } + .with_timeout(timeout) + .await + .map_err(|_| ConnectionError::Timeout)? } } -impl - rpc::StreamingV2 +/// Error of sending an [`Outbound`] RPC. +#[derive(Debug, thiserror::Error)] +pub enum SendRpcError { + #[error("Connection closed")] + ConnectionClosed, + + #[error("Too many concurrent RPCs")] + TooManyConcurrentRpcs, +} + +/// Result of sending an [`Outbound`] RPC. +pub type SendRpcResult = Result; + +#[derive(Debug, thiserror::Error)] +enum ConnectionError { + #[error("Failed to extract PeerId")] + ExtractPeerId(String), + + #[error("Wrong PeerId: {0}")] + WrongPeerId(PeerId), + + #[error("Connect: {0:?}")] + Connect(#[from] quinn::ConnectError), + + #[error("Connection: {0:?}")] + Connection(#[from] quinn::ConnectionError), + + #[error("IO: {0:?}")] + Io(#[from] io::Error), + + #[error("Write: {0:?}")] + Write(#[from] quinn::WriteError), + + #[error("Timeout")] + Timeout, +} + +impl RpcImpl where - Request: Message, - Response: Message, - Codec: transport::Codec, + K: Send + Sync + 'static, + API: Api, + Req: Message, + Resp: Message, + C: Codec, { - pub async fn send<'a, S, F, Fut, T>(sender: &'a S, f: F) -> RpcSenderResult + /// Sends this RPC over the provided [`OutboundConnection`]. + pub fn send( + conn: &OutboundConnection, + args: Args, + ) -> SendRpcResult + '_> where - S: RpcSender, - F: FnOnce(&'a mut SendStream, &'a mut RecvStream) -> Fut - + 'a, - Fut: Future>, + API::OutboundRpcHandler: OutboundRpcHandler, + Args: 'static, { - RpcSender::::send(sender, f).await + let mut rpc = conn.send::()?; + let handler = &conn.inner.client.rpc_handler; + Ok(async move { handler.handle_rpc(&mut rpc, args).await }) } } -impl - RpcSender, Request> for OutboundConnection +impl Outbound> where - API: rpc::Api, - Request: Message, - Response: Message, - Codec: transport::Codec, + API: Api, + Req: Message, + Resp: Message, + C: Codec, { - type Output = Response; - - fn send<'a>( - &'a self, - request: Request, - ) -> impl Future> + Send + 'a { - RpcSender::, _>::send( - self, - |tx, rx| async { - tx.send(request).await?; - rx.recv_message().await - }, - ) + /// Handles this [`Outbound`] [`rpc::UnaryV2`]. + pub async fn handle(&mut self, req: Req) -> transport::Result { + self.sink().send(req).await?; + self.stream() + .next() + .await + .ok_or_else(|| transport::Error::StreamFinished)? } } -#[derive(Debug, thiserror::Error)] -pub enum OutboundConnectionError { - #[error("Transport: {_0}")] - Transport(String), +/// Default implementation of [`OutboundRpcHandler`]. +#[derive_where(Clone, Debug, Default; S)] +pub struct DefaultOutboundRpcHandler { + state: S, + _marker: PhantomData, } -#[derive(Debug, thiserror::Error)] -pub enum Error { - #[error("Transport: {_0}")] - Transport(String), +impl DefaultOutboundRpcHandler { + /// Creates a new [`DefaultOutboundRpcHandler`]. + pub fn new(state: S) -> Self { + Self { + state, + _marker: PhantomData, + } + } } -#[derive(Debug, thiserror::Error)] -pub enum RpcSenderError { - #[error("Transport: {0}")] - Transport(String), -} +impl + OutboundRpcHandler, Req> + for DefaultOutboundRpcHandler +where + API: Api, + Req: Message, + Resp: Message, + C: Codec, + Err: Send + Sync + 'static, + S: Clone + Send + Sync + 'static, + transport::Error: Into, +{ + type Result = Result; -pub type RpcSenderResult = Result; + async fn handle_rpc( + &self, + rpc: &mut Outbound>, + req: Req, + ) -> Self::Result { + rpc.handle(req).await.map_err(Into::into) + } +} diff --git a/crates/rpc/src/lib.rs b/crates/rpc/src/lib.rs index ec7fdf54..80837af1 100644 --- a/crates/rpc/src/lib.rs +++ b/crates/rpc/src/lib.rs @@ -5,16 +5,7 @@ pub use libp2p::{identity, Multiaddr, PeerId}; use { derive_more::Display, serde::{Deserialize, Serialize}, - std::{ - borrow::Cow, - fmt::Debug, - future::Future, - marker::PhantomData, - net::SocketAddr, - str::FromStr, - sync::Arc, - }, - tokio::sync::OwnedSemaphorePermit, + std::{borrow::Cow, fmt::Debug, marker::PhantomData, net::SocketAddr, str::FromStr}, transport::Codec, }; @@ -40,17 +31,106 @@ pub mod transport; #[cfg(test)] mod test; -pub trait Api: Send + Sync + 'static { +const PROTOCOL_VERSION: u32 = 0; + +/// RPC API specification. +/// +/// Expected to be implemented on unit types and should not contain data. +/// +/// # Example +/// +/// ``` +/// use wcn_rpc::ApiName; +/// +/// struct MyApi; +/// +/// enum RpcId { +/// CreateUser = 0, +/// UpdateUser = 1, +/// DeleteUser = 2, +/// } +/// +/// impl wcn_rpc::Api for MyApi { +/// const NAME: ApiName = ApiName::new("myApi"); +/// type RpcId = RpcId; +/// } +/// ``` +pub trait Api: Clone + Send + Sync + 'static { + /// [`ApiName`] of this [`Api`]. + /// + /// [`ApiName`] used const NAME: ApiName; + + /// `enum` representation of all RPC IDs of this [`Api`]. + /// + /// Should be convertible from/into `u8`. type RpcId; } -pub trait Handler { - type Result; +/// [`Api`] name. +pub type ApiName = ServerName; + +/// Specification of a remote procedure call. +/// +/// Expected to be implemented on unit types and should not contain any data. +/// +/// See [`StreamingV2`] RPC and [`UnaryV2`] RPC. +pub trait RpcV2 { + /// ID of this [`Rpc`]. + const ID: u8; + + /// [`Api`] this [`Rpc`] belongs to. + type Api: Api; + + /// Request type of this [`Rpc`]. + type Request: Message; + + /// Response type of this [`Rpc`]. + type Response: Message; + + /// Serialization codec of this [`Rpc`]. + type Codec: Codec; +} + +/// Generic [`RpcV2`] implementation. +/// +/// Not intended to be used directly by the users of this crate. +/// +/// Use [`StreamingV2`] or [`UnaryV2`] instead. +pub struct RpcImpl { + _marker: PhantomData<(K, API, Req, Resp, C)>, +} - fn handle_rpc(&self, rpc: &mut RPC) -> impl Future + Send; +impl RpcV2 for RpcImpl +where + API: Api, + Req: Message, + Resp: Message, + C: Codec, +{ + const ID: u8 = ID; + type Api = API; + type Request = Req; + type Response = Resp; + type Codec = C; } +/// Bi-directional streaming [`RpcV2`]. +/// +/// Client sends a stream of requests and server responds with a stream of +/// responses. +/// +/// Use type aliases to conviniently define RPCs of this kind. +pub type StreamingV2 = + RpcImpl; + +/// Unary (request-response) [`RpcV2`]. +/// +/// Client sends a single request and server responds with a single response. +/// +/// Use type aliases to conviniently define RPCs of this kind. +pub type UnaryV2 = RpcImpl; + /// Error codes produced by this module. pub mod error_code { #[allow(unused_imports)] @@ -84,40 +164,6 @@ pub trait Rpc { type Codec: Codec; } -pub struct StreamingV2 -where - Rx: Message, - Tx: Message, - Codec: transport::Codec, -{ - recv: transport::RecvStream, - send: transport::SendStream, - _marker: PhantomData, -} - -pub struct UnaryV2 -where - Request: Message, - Response: Message, - Codec: transport::Codec, -{ - streaming: StreamingV2, -} - -pub trait RpcV2 { - /// ID of this [`Rpc`]. - const ID: u8; - - /// Request type of this [`Rpc`]. - type Request: Message; - - /// Response type of this [`Rpc`]. - type Response: Message; - - /// Serialization codec of this [`Rpc`]. - type Codec: Codec; -} - /// [`Rpc`] kinds. pub mod kind { /// Unary (request-response) RPC. @@ -177,8 +223,6 @@ impl Name { } } -pub type ApiName = ServerName; - /// RPC server name. #[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)] pub struct ServerName([u8; 16]); @@ -284,11 +328,6 @@ impl Error { description: None, } } - - // pub fn with_description(mut self, description: impl Display) -> Self { - // self.description = Some(description.to_string().into()); - // self - // } } /// RPC result. diff --git a/crates/rpc/src/quic/client.rs b/crates/rpc/src/quic/client.rs index 3d69fbef..3615a3f4 100644 --- a/crates/rpc/src/quic/client.rs +++ b/crates/rpc/src/quic/client.rs @@ -201,10 +201,7 @@ fn new_connection( ))); } - write_connection_header(&conn, ConnectionHeader { - server_name: Some(server_name), - }) - .await?; + write_connection_header(&conn, ConnectionHeader { server_name }).await?; handshake .handle(peer_id, PendingConnection(conn.clone())) @@ -514,7 +511,7 @@ impl Client { } } -async fn write_connection_header( +pub(crate) async fn write_connection_header( conn: &quinn::Connection, header: ConnectionHeader, ) -> Result<(), ConnectionError> { diff --git a/crates/rpc/src/quic/mod.rs b/crates/rpc/src/quic/mod.rs index 4199e11d..f037fa5e 100644 --- a/crates/rpc/src/quic/mod.rs +++ b/crates/rpc/src/quic/mod.rs @@ -180,7 +180,7 @@ pub enum Error { InvalidConnectionRate, } -fn connection_peer_id(conn: &quinn::Connection) -> Result { +pub(crate) fn connection_peer_id(conn: &quinn::Connection) -> Result { use ExtractPeerIdError as Error; let identity = conn.peer_identity().ok_or(Error::MissingPeerIdentity)?; diff --git a/crates/rpc/src/server2.rs b/crates/rpc/src/server2.rs index 55192e2d..4a2344a4 100644 --- a/crates/rpc/src/server2.rs +++ b/crates/rpc/src/server2.rs @@ -38,6 +38,12 @@ pub trait InboundConnectionHandler: Clone + Send + Sync + 'static { ) -> impl Future + Send; } +pub trait InboundRpcHandler { + type Result; + + fn handle_rpc(&self, rpc: &mut RPC) -> impl Future + Send; +} + pub struct Config { /// Name of the server. For metrics purposes only. pub name: &'static str, From 873375e4f78ad6b8e2330c4b813d515c0b027bfa Mon Sep 17 00:00:00 2001 From: Darksome Date: Fri, 20 Jun 2025 09:29:05 +0000 Subject: [PATCH 55/79] WIP --- crates/rpc/src/client2.rs | 283 +++++++++++++++++++++++------------- crates/rpc/src/server2.rs | 40 ++--- crates/rpc/src/transport.rs | 6 - 3 files changed, 201 insertions(+), 128 deletions(-) diff --git a/crates/rpc/src/client2.rs b/crates/rpc/src/client2.rs index 636e30fa..2c3995c2 100644 --- a/crates/rpc/src/client2.rs +++ b/crates/rpc/src/client2.rs @@ -2,14 +2,22 @@ use { crate::{ self as rpc, quic::{self}, - transport::{self, BiDirectionalStream, Codec}, + transport::{self, BiDirectionalStream, Codec, RecvStream, SendStream}, Message, RpcImpl, RpcV2, }, - arc_swap::ArcSwap, derive_where::derive_where, - futures::{FutureExt, Sink, SinkExt, Stream, StreamExt as _}, + futures::{ + sink::SinkMapErr, + stream::MapErr, + FutureExt, + Sink, + SinkExt, + Stream, + StreamExt as _, + TryStreamExt, + }, libp2p::{identity, PeerId}, std::{ future::Future, @@ -19,7 +27,11 @@ use { sync::Arc, time::Duration, }, - tokio::io::AsyncWriteExt, + tap::TapFallible, + tokio::{ + io::AsyncWriteExt, + sync::{watch, Mutex}, + }, wc::future::FutureExt as _, }; @@ -111,7 +123,7 @@ impl Client { None, cfg.priority, ) - .map_err(|err| Error::Transport(err.to_string()))?; + .map_err(Error::new)?; Ok(Client { config: Arc::new(cfg), @@ -123,13 +135,15 @@ impl Client { /// Establishes a new [`OutboundConnection`]. pub fn connect(&self, addr: SocketAddrV4, peer_id: PeerId) -> OutboundConnection { + let (tx, rx) = watch::channel(None); + let conn = OutboundConnection { inner: Arc::new(OutboundConnectionInner { client: self.clone(), remote_addr: addr, remote_peer_id: peer_id, - quinn: Arc::new(ArcSwap::new(Arc::new(None))), - mutex: Arc::new(tokio::sync::Mutex::new(())), + watch_rx: rx, + watch_tx: Arc::new(tokio::sync::Mutex::new(tx)), }), }; @@ -138,27 +152,20 @@ impl Client { } } -/// Error of [`Client::new`]. -#[derive(Debug, thiserror::Error)] -pub enum Error { - #[error("Transport: {_0}")] - Transport(String), -} - /// Outboud RPC of a specific type. pub struct Outbound { - send: transport::SendStream, - recv: transport::RecvStream, + send: SinkMapErr, fn(transport::Error) -> Error>, + recv: MapErr, fn(transport::Error) -> Error>, } impl Outbound { /// Returns [`Sink`] of outbound requests. - pub fn sink(&mut self) -> &mut impl Sink { + pub fn sink(&mut self) -> &mut impl Sink { &mut self.send } /// Returns [`Stream`] of inbound responses. - pub fn stream(&mut self) -> &mut impl Stream> { + pub fn stream(&mut self) -> &mut impl Stream> { &mut self.recv } } @@ -180,9 +187,8 @@ struct OutboundConnectionInner { remote_addr: SocketAddrV4, remote_peer_id: PeerId, - quinn: Arc>>, - - mutex: Arc>, + watch_rx: watch::Receiver>, + watch_tx: Arc>>>, } impl OutboundConnection { @@ -198,66 +204,84 @@ impl OutboundConnection { /// Indicates whether this [`OutboundConnection`] is currently open. pub fn is_open(&self) -> bool { - (**self.inner.quinn.load()) + self.inner + .watch_rx + .borrow() .as_ref() .map(|conn| conn.close_reason().is_some()) .unwrap_or_default() } - /// Sends a new [`Outbound`] RPC over this [`OutboundConnection`]. - pub fn send(&self) -> SendRpcResult> { - let inner = self.inner.quinn.load(); - let Some(conn) = inner.as_ref() else { - return Err(SendRpcError::ConnectionClosed); - }; - - // `open_bi` only blocks if there are too many outbound streams. - let (mut tx, rx) = match conn.open_bi().now_or_never() { - Some(Ok(stream)) => stream, - Some(Err(_)) => return Err(SendRpcError::ConnectionClosed), - None => return Err(SendRpcError::TooManyConcurrentRpcs), - }; - - // Stream buffer is large enough to fit `u8` without blocking. - tx.write_u8(RPC::ID) - .now_or_never() - .unwrap() - .map_err(|_| SendRpcError::ConnectionClosed)?; + /// Waits for this [`OutboundConnection`] to become open. + /// + /// IMPORTANT: This future may never resolve! Make sure that you use a + /// timeout. + pub async fn wait_open(&self) { + let mut watch_rx = self.inner.watch_rx.clone(); + match watch_rx.borrow_and_update().as_ref() { + Some(conn) if conn.close_reason().is_none() => return, + _ => {} + } - let (recv, send) = - BiDirectionalStream::new(tx, rx).upgrade::(); + drop(watch_rx.changed().await) + } - Ok(Outbound { send, recv }) + /// Sends a new [`Outbound`] RPC over this [`OutboundConnection`]. + pub fn send(&self) -> Result> { + (|| { + let opt = self.inner.watch_rx.borrow(); + let Some(conn) = opt.as_ref() else { + return Err(ErrorInner::NotConnected); + }; + + // `open_bi` only blocks if there are too many outbound streams. + let (mut tx, rx) = match conn.open_bi().now_or_never() { + Some(Ok(stream)) => stream, + Some(Err(err)) => return Err(err.into()), + None => return Err(ErrorInner::TooManyConcurrentRpcs), + }; + + // This can only block if send buffer is full. + tx.write_u8(RPC::ID) + .now_or_never() + .ok_or_else(|| ErrorInner::SendBufferFull)?; + + let (recv, send) = BiDirectionalStream::new(tx, rx) + .upgrade::(); + + Ok(Outbound { + send: SinkExt::<&RPC::Request>::sink_map_err(send, |err: transport::Error| { + Error::new(err) + }), + recv: recv.map_err(Error::new), + }) + })() + .map_err(Error::new) + .tap_err(|err| { + if err.is_connection_error() { + self.reconnect(); + } + }) } fn reconnect(&self) { // If we can't acquire the lock then reconnection is already in progress. - let Ok(mutex_guard) = self.inner.mutex.clone().try_lock_owned() else { + let Ok(watch_tx) = self.inner.watch_tx.clone().try_lock_owned() else { return; }; let this = self.inner.clone(); tokio::spawn(async move { - let _mutex_guard = mutex_guard; - let mut interval = tokio::time::interval(this.client.config.reconnect_interval); interval.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip); loop { interval.tick().await; - match this.clone().new_quic_connection().await { - Ok(conn) => { - this.quinn.store(Arc::new(Some(conn))); - return; - } - Err(err @ ConnectionError::WrongPeerId(_)) => { - tracing::warn!("outbound connection failed: {err}") - } - Err(err) => { - tracing::debug!("outbound connection failed: {err}") - } + if let Ok(conn) = this.clone().new_quic_connection().await { + watch_tx.send(Some(conn)); + return; } } }); @@ -265,7 +289,7 @@ impl OutboundConnection { } impl OutboundConnectionInner { - async fn new_quic_connection(self: Arc) -> Result { + async fn new_quic_connection(self: Arc) -> Result { let timeout = self.client.config.connection_timeout; async move { @@ -277,10 +301,17 @@ impl OutboundConnectionInner { .await?; let peer_id = quic::connection_peer_id(&conn) - .map_err(|err| ConnectionError::ExtractPeerId(err.to_string()))?; + .map_err(|err| ErrorInner::ExtractPeerId(err.to_string()))?; if peer_id != self.remote_peer_id { - return Err(ConnectionError::WrongPeerId(peer_id)); + tracing::warn!( + expected = ?self.remote_peer_id, + got = ?peer_id, + addr = ?self.remote_addr, + "Wrong PeerId" + ); + + return Err(ErrorInner::WrongPeerId(peer_id)); } // write connection header @@ -292,47 +323,11 @@ impl OutboundConnectionInner { } .with_timeout(timeout) .await - .map_err(|_| ConnectionError::Timeout)? + .map_err(|_| ErrorInner::Timeout)? + .map_err(Error::new) } } -/// Error of sending an [`Outbound`] RPC. -#[derive(Debug, thiserror::Error)] -pub enum SendRpcError { - #[error("Connection closed")] - ConnectionClosed, - - #[error("Too many concurrent RPCs")] - TooManyConcurrentRpcs, -} - -/// Result of sending an [`Outbound`] RPC. -pub type SendRpcResult = Result; - -#[derive(Debug, thiserror::Error)] -enum ConnectionError { - #[error("Failed to extract PeerId")] - ExtractPeerId(String), - - #[error("Wrong PeerId: {0}")] - WrongPeerId(PeerId), - - #[error("Connect: {0:?}")] - Connect(#[from] quinn::ConnectError), - - #[error("Connection: {0:?}")] - Connection(#[from] quinn::ConnectionError), - - #[error("IO: {0:?}")] - Io(#[from] io::Error), - - #[error("Write: {0:?}")] - Write(#[from] quinn::WriteError), - - #[error("Timeout")] - Timeout, -} - impl RpcImpl where K: Send + Sync + 'static, @@ -345,7 +340,7 @@ where pub fn send( conn: &OutboundConnection, args: Args, - ) -> SendRpcResult + '_> + ) -> Result + '_> where API::OutboundRpcHandler: OutboundRpcHandler, Args: 'static, @@ -364,12 +359,12 @@ where C: Codec, { /// Handles this [`Outbound`] [`rpc::UnaryV2`]. - pub async fn handle(&mut self, req: Req) -> transport::Result { + pub async fn handle(&mut self, req: Req) -> Result { self.sink().send(req).await?; self.stream() .next() .await - .ok_or_else(|| transport::Error::StreamFinished)? + .ok_or_else(|| Error::new(transport::Error::StreamFinished))? } } @@ -400,7 +395,7 @@ where C: Codec, Err: Send + Sync + 'static, S: Clone + Send + Sync + 'static, - transport::Error: Into, + Error: Into, { type Result = Result; @@ -412,3 +407,85 @@ where rpc.handle(req).await.map_err(Into::into) } } + +/// RPC [`Client`] error. +#[derive(Debug, thiserror::Error)] +#[error(transparent)] +pub struct Error(ErrorInner); + +/// RPC [`Client`] result. +pub type Result = std::result::Result; + +impl Error { + fn new(err: impl Into) -> Self { + Self(err.into()) + } + + /// Indicates whether this [`Error`] is caused by the + /// [`OutboundConnection`] being closed / broken. + /// + /// Such errors may be fixed by a reconnect. Consider + /// (waiting)[OutboundConnection::wait_open] for the [`OutboundConnection`] + /// to become open again. + pub fn is_connection_error(&self) -> bool { + match &self.0 { + ErrorInner::NotConnected + | ErrorInner::Quic(_) + | ErrorInner::ExtractPeerId(_) + | ErrorInner::WrongPeerId(_) + | ErrorInner::Connect(_) + | ErrorInner::Connection(_) + | ErrorInner::Io(_) + | ErrorInner::Write(_) + | ErrorInner::Timeout + | ErrorInner::Transport(_) => true, + + ErrorInner::TooManyConcurrentRpcs | ErrorInner::SendBufferFull => false, + } + } +} + +impl From for Error { + fn from(err: ErrorInner) -> Self { + Self::new(err) + } +} + +#[derive(Debug, thiserror::Error)] +enum ErrorInner { + #[error("Not connected")] + NotConnected, + + #[error("QUIC: {0}")] + Quic(#[from] quic::Error), + + #[error("Failed to extract PeerId")] + ExtractPeerId(String), + + #[error("Wrong PeerId: {0}")] + WrongPeerId(PeerId), + + #[error("Connect: {0:?}")] + Connect(#[from] quinn::ConnectError), + + #[error("Connection: {0:?}")] + Connection(#[from] quinn::ConnectionError), + + #[error("IO: {0:?}")] + Io(#[from] io::Error), + + #[error("Write: {0:?}")] + Write(#[from] quinn::WriteError), + + #[error("Too many concurrent RPCs")] + TooManyConcurrentRpcs, + + #[error("Send buffer is full")] + SendBufferFull, + + #[error("Timeout")] + Timeout, + + #[error("Transport: {0}")] + Transport(#[from] transport::Error), +} diff --git a/crates/rpc/src/server2.rs b/crates/rpc/src/server2.rs index 4a2344a4..603007a5 100644 --- a/crates/rpc/src/server2.rs +++ b/crates/rpc/src/server2.rs @@ -8,11 +8,12 @@ use { read_connection_header, }, }, - transport::{self, BiDirectionalStream}, + transport::{self, BiDirectionalStream, RecvStream, SendStream}, ApiName, + RpcV2, }, ::metrics::CounterFn, - futures::{Sink, Stream, TryFutureExt as _}, + futures::{future::MapErr, sink::SinkMapErr, Sink, Stream, TryFutureExt as _}, libp2p::{identity::Keypair, PeerId}, quinn::crypto::rustls::QuicServerConfig, sealed::ConnectionRouter, @@ -213,6 +214,24 @@ pub struct InboundConnection { _marker: PhantomData, } +/// Inbound RPC of a specific type. +pub struct Inbound { + recv: MapErr, fn(transport::Error) -> Error>, + send: SinkMapErr, fn(transport::Error) -> Error>, +} + +impl Inbound { + /// Returns [`Stream`] of inbound requests. + pub fn stream(&mut self) -> &mut impl Stream> { + &mut self.recv + } + + /// Returns [`Sink`] of outbound responses. + pub fn sink(&mut self) -> &mut impl Sink { + &mut self.send + } +} + impl InboundConnection { fn set_api(self) -> InboundConnection { InboundConnection { @@ -286,23 +305,6 @@ impl InboundConnection { } } -pub struct InboundRpc { - id: ID, - stream: BiDirectionalStream, -} - -impl InboundRpc { - pub fn id(&self) -> ID { - self.id - } -} - -// impl InboundRpc { -// fn upgrade(&mut self) -> (impl Stream, impl -// Sink) { self.stream.upgrade() -// } -// } - async fn read_rpc_id(stream: &mut BiDirectionalStream) -> Result { stream .rx diff --git a/crates/rpc/src/transport.rs b/crates/rpc/src/transport.rs index 16730277..cc9ba8d9 100644 --- a/crates/rpc/src/transport.rs +++ b/crates/rpc/src/transport.rs @@ -83,12 +83,6 @@ impl BiDirectionalStream { }, ) } - - pub(crate) fn upgrate_ref( - &mut self, - ) -> (impl Stream, impl Sink) { - () - } } /// [`Stream`] of outbound [`Message`]s. From 5dfe8f15c52b1223d0934cf01ca73d07b105754b Mon Sep 17 00:00:00 2001 From: Darksome Date: Fri, 20 Jun 2025 13:37:09 +0000 Subject: [PATCH 56/79] WIP --- crates/rpc/Cargo.toml | 2 +- crates/rpc/src/client2.rs | 81 ++++++++++++----------- crates/rpc/src/lib.rs | 3 +- crates/rpc/src/server2.rs | 131 ++++++++++++++++++++++++++++++-------- 4 files changed, 146 insertions(+), 71 deletions(-) diff --git a/crates/rpc/Cargo.toml b/crates/rpc/Cargo.toml index 085cee74..972953dc 100644 --- a/crates/rpc/Cargo.toml +++ b/crates/rpc/Cargo.toml @@ -12,7 +12,7 @@ client = [] server = [] [dependencies] -derive_more = { workspace = true } +derive_more = { workspace = true, features = ["display"] } derive-where = { workspace = true } derivative = "2.2" futures = "0.3" diff --git a/crates/rpc/src/client2.rs b/crates/rpc/src/client2.rs index 2c3995c2..fb899d24 100644 --- a/crates/rpc/src/client2.rs +++ b/crates/rpc/src/client2.rs @@ -37,37 +37,37 @@ use { /// Client-specific part of an RPC [`Api`](super::Api). pub trait Api: super::Api { - /// [`OutboundConnectionHandler`] of this [`Api`]. - type OutboundConnectionHandler: OutboundConnectionHandler; + /// [`ConnectionHandler`] of this [`Api`]. + type ConnectionHandler: ConnectionHandler; - /// [`OutboundRpcHandler`] of this [`Api`]. - type OutboundRpcHandler: Clone + Send + Sync + 'static; + /// [`RpcHandler`] of this [`Api`]. + type RpcHandler: Clone + Send + Sync + 'static; } -/// Handler of newly established [`OutboundConnection`]s. +/// Handler of newly established outbound [`Connection`]s. /// -/// Every time a new [`OutboundConnection`] gets established it's being passed -/// into an [`OutboundConnectionHandler`]. -pub trait OutboundConnectionHandler: Clone + Send + Sync + 'static { - /// [`Api`] that uses this [`OutboundConnectionHandler`]. +/// Every time a new outbound [`Connection`] gets established it's being +/// passed into a [`ConnectionHandler`]. +pub trait ConnectionHandler: Clone + Send + Sync + 'static { + /// [`Api`] that uses this [`ConnectionHandler`]. type Api: Api; - /// Error of this [`OutboundConnectionHandler`]. + /// Error of this [`ConnectionHandler`]. type Error; - /// Handles the provided [`OutboundConnection`]. + /// Handles the provided outbound [`Connection`]. fn handle_connection( &self, - conn: &mut OutboundConnection, + conn: &mut Connection, ) -> impl Future> + Send; } /// Handler of a specific type of [`Outbound`] RPCs. -pub trait OutboundRpcHandler: Clone + Send + Sync + 'static +pub trait RpcHandler: Clone + Send + Sync + 'static where RPC: RpcV2, { - /// [`Result`] of this [`OutboundRpcHandler`]. + /// [`Result`] of this [`RpcHandler`]. type Result; /// Handles the provided [`Outbound`] RPC. @@ -97,21 +97,21 @@ pub struct Config { pub priority: transport::Priority, } -/// RPC client responsible for establishing [`OutboundConnection`]s to remote +/// RPC client responsible for establishing outbound [`Connection`]s to remote /// peers. #[derive(Clone)] pub struct Client { config: Arc, endpoint: quinn::Endpoint, - connection_handler: API::OutboundConnectionHandler, - rpc_handler: API::OutboundRpcHandler, + connection_handler: API::ConnectionHandler, + rpc_handler: API::RpcHandler, } impl Client { /// Creates a new RPC [`Client`]. pub fn new( - connection_handler: API::OutboundConnectionHandler, - rpc_handler: API::OutboundRpcHandler, + connection_handler: API::ConnectionHandler, + rpc_handler: API::RpcHandler, cfg: Config, ) -> Result { let transport_config = quic::new_quinn_transport_config(cfg.max_concurrent_rpcs); @@ -133,12 +133,12 @@ impl Client { }) } - /// Establishes a new [`OutboundConnection`]. - pub fn connect(&self, addr: SocketAddrV4, peer_id: PeerId) -> OutboundConnection { + /// Establishes a new outbound [`Connection`]. + pub fn connect(&self, addr: SocketAddrV4, peer_id: PeerId) -> Connection { let (tx, rx) = watch::channel(None); - let conn = OutboundConnection { - inner: Arc::new(OutboundConnectionInner { + let conn = Connection { + inner: Arc::new(ConnectionInner { client: self.clone(), remote_addr: addr, remote_peer_id: peer_id, @@ -177,11 +177,11 @@ impl Outbound { /// /// Reconnects are being handled automatically in the background. #[derive(Clone)] -pub struct OutboundConnection { - inner: Arc>, +pub struct Connection { + inner: Arc>, } -struct OutboundConnectionInner { +struct ConnectionInner { client: Client, remote_addr: SocketAddrV4, @@ -191,7 +191,7 @@ struct OutboundConnectionInner { watch_tx: Arc>>>, } -impl OutboundConnection { +impl Connection { /// Returns [`SocketAddrV4`] of the remote peer. pub fn peer_addr(&self) -> &SocketAddrV4 { &self.inner.remote_addr @@ -202,7 +202,7 @@ impl OutboundConnection { &self.inner.remote_peer_id } - /// Indicates whether this [`OutboundConnection`] is currently open. + /// Indicates whether this [`Connection`] is currently open. pub fn is_open(&self) -> bool { self.inner .watch_rx @@ -212,7 +212,7 @@ impl OutboundConnection { .unwrap_or_default() } - /// Waits for this [`OutboundConnection`] to become open. + /// Waits for this [`Connection`] to become open. /// /// IMPORTANT: This future may never resolve! Make sure that you use a /// timeout. @@ -226,7 +226,7 @@ impl OutboundConnection { drop(watch_rx.changed().await) } - /// Sends a new [`Outbound`] RPC over this [`OutboundConnection`]. + /// Sends a new [`Outbound`] RPC over this [`Connection`]. pub fn send(&self) -> Result> { (|| { let opt = self.inner.watch_rx.borrow(); @@ -288,7 +288,7 @@ impl OutboundConnection { } } -impl OutboundConnectionInner { +impl ConnectionInner { async fn new_quic_connection(self: Arc) -> Result { let timeout = self.client.config.connection_timeout; @@ -336,13 +336,13 @@ where Resp: Message, C: Codec, { - /// Sends this RPC over the provided [`OutboundConnection`]. + /// Sends this RPC over the provided [`Connection`]. pub fn send( - conn: &OutboundConnection, + conn: &Connection, args: Args, ) -> Result + '_> where - API::OutboundRpcHandler: OutboundRpcHandler, + API::RpcHandler: RpcHandler, Args: 'static, { let mut rpc = conn.send::()?; @@ -368,15 +368,15 @@ where } } -/// Default implementation of [`OutboundRpcHandler`]. +/// Default implementation of [`RpcHandler`]. #[derive_where(Clone, Debug, Default; S)] -pub struct DefaultOutboundRpcHandler { +pub struct DefaultRpcHandler { state: S, _marker: PhantomData, } -impl DefaultOutboundRpcHandler { - /// Creates a new [`DefaultOutboundRpcHandler`]. +impl DefaultRpcHandler { + /// Creates a new [`DefaultRpcHandler`]. pub fn new(state: S) -> Self { Self { state, @@ -385,9 +385,8 @@ impl DefaultOutboundRpcHandler { } } -impl - OutboundRpcHandler, Req> - for DefaultOutboundRpcHandler +impl RpcHandler, Req> + for DefaultRpcHandler where API: Api, Req: Message, diff --git a/crates/rpc/src/lib.rs b/crates/rpc/src/lib.rs index 80837af1..3a18ccf9 100644 --- a/crates/rpc/src/lib.rs +++ b/crates/rpc/src/lib.rs @@ -224,7 +224,8 @@ impl Name { } /// RPC server name. -#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)] +#[derive(Debug, Display, Clone, Copy, Hash, PartialEq, Eq)] +#[display("{}", self.as_str())] pub struct ServerName([u8; 16]); impl ServerName { diff --git a/crates/rpc/src/server2.rs b/crates/rpc/src/server2.rs index 603007a5..874d5e7b 100644 --- a/crates/rpc/src/server2.rs +++ b/crates/rpc/src/server2.rs @@ -12,10 +12,9 @@ use { ApiName, RpcV2, }, - ::metrics::CounterFn, futures::{future::MapErr, sink::SinkMapErr, Sink, Stream, TryFutureExt as _}, libp2p::{identity::Keypair, PeerId}, - quinn::crypto::rustls::QuicServerConfig, + quinn::crypto::rustls::{self, QuicServerConfig}, sealed::ConnectionRouter, std::{future::Future, io, marker::PhantomData, sync::Arc, time::Duration}, tokio::sync::{OwnedSemaphorePermit, Semaphore}, @@ -27,9 +26,14 @@ use { /// Server-specific part of an RPC [`Api`](super::Api). pub trait Api: super::Api { + /// [`InboundConnectionHandler`] of this [`Api`]. type InboundConnectionHandler: InboundConnectionHandler; } +/// Handler of newly established [`InboundConnection`]s. +/// +/// Every time a new [`InboundConnection`] gets established it's being passed +/// into an [`InboundConnectionHandler`]. pub trait InboundConnectionHandler: Clone + Send + Sync + 'static { type Api; @@ -39,10 +43,13 @@ pub trait InboundConnectionHandler: Clone + Send + Sync + 'static { ) -> impl Future + Send; } -pub trait InboundRpcHandler { - type Result; - - fn handle_rpc(&self, rpc: &mut RPC) -> impl Future + Send; +/// Handler of a specific type of [`Inbound`] RPCs. +pub trait InboundRpcHandler +where + RPC: RpcV2, +{ + /// Handles the provided [`Outbound`] RPC. + fn handle_rpc(&self, rpc: &mut Inbound) -> impl Future> + Send; } pub struct Config { @@ -71,26 +78,25 @@ pub struct Config { pub priority: transport::Priority, } -/// Serves a single RPC API on the specified. +/// Serves a single RPC API on the specified port. pub fn serve( cfg: Config, connection_handler: impl InboundConnectionHandler, -) -> Result, Error> { +) -> Result> { multiplex(cfg, (connection_handler,)) } /// Serves multiple RPC APIs on the specified port. /// -/// `connection_handlers` is expected to be a tuple of [`ConnectionHandler`]s. -pub fn multiplex(cfg: Config, connection_handlers: H) -> Result, Error> +/// `connection_handlers` is expected to be a tuple of +/// [`InboundConnectionHandler`]s. +pub fn multiplex(cfg: Config, connection_handlers: H) -> Result> where H: sealed::ConnectionRouter, { let transport_config = quic::new_quinn_transport_config(cfg.max_concurrent_rpcs); - let server_tls_config = libp2p_tls::make_server_config(&cfg.keypair) - .map_err(|err| Error::Crypto(err.to_string()))?; - let server_tls_config = QuicServerConfig::try_from(server_tls_config) - .map_err(|err| Error::Crypto(err.to_string()))?; + let server_tls_config = libp2p_tls::make_server_config(&cfg.keypair).map_err(Error::new)?; + let server_tls_config = QuicServerConfig::try_from(server_tls_config).map_err(Error::new)?; let mut server_config = quinn::ServerConfig::with_crypto(Arc::new(server_tls_config)); server_config.transport = transport_config.clone(); server_config.migration(false); @@ -102,14 +108,14 @@ where Some(server_config), cfg.priority, ) - .map_err(|err| Error::Transport(err.to_string()))?; + .map_err(Error::new)?; let connection_filter = Filter::new(&filter::Config { max_connections: cfg.max_connections, max_connections_per_ip: cfg.max_connections_per_ip, max_connection_rate_per_ip: cfg.max_connection_rate_per_ip, }) - .map_err(|err| Error::Config(err.to_string()))?; + .map_err(Error::new)?; let rpc_semaphore = Arc::new(Semaphore::new(cfg.max_concurrent_rpcs as usize)); @@ -122,6 +128,14 @@ where )) } +struct Server { + config: Config, + endpoint: quinn::Endpoint, + + connection_filter: Filter, + rpc_semaphore: Arc, +} + async fn accept_connections( config: Config, endpoint: quinn::Endpoint, @@ -181,12 +195,26 @@ fn accept_connection( let conn = connecting .with_timeout(Duration::from_millis(1000)) .await - .map_err(|_| InboundConnectionHandlerError::ConnectionTimeout)??; + .map_err(|_| ErrorInner::ConnectionTimeout)? + .map_err(Error::new)?; + + conn.accept_uni().await.map_err(Error::new)?; + + let protocol_version = rx.read_u32().await?; + + let server_name = match protocol_version { + super::PROTOCOL_VERSION => { + let mut buf = [0; 16]; + rx.read_exact(&mut buf).await?; + ServerName(buf) + } + ver => return Err(ConnectionError::UnsupportedProtocolVersion(ver)), + }; let header = read_connection_header(&conn) .with_timeout(Duration::from_millis(500)) .await - .map_err(|_| InboundConnectionHandlerError::ReadConnectionHeaderTimeout)??; + .map_err(|_| ErrorInner::ReadConnectionHeaderTimeout)??; let conn = InboundConnection { server_name, @@ -323,7 +351,7 @@ mod sealed { &self, api_name: ApiName, connection: InboundConnection, - ) -> impl Future>; + ) -> impl Future>; } } @@ -387,17 +415,17 @@ where } } -#[derive(Debug, thiserror::Error)] -pub enum Error { - #[error("Transport: {0}")] - Transport(String), +// #[derive(Debug, thiserror::Error)] +// pub enum Error { +// #[error("Transport: {0}")] +// Transport(String), - #[error("Crypto: {0}")] - Crypto(String), +// #[error("Crypto: {0}")] +// Crypto(String), - #[error("Config: {0}")] - Config(String), -} +// #[error("Config: {0}")] +// Config(String), +// } #[derive(Debug, thiserror::Error)] pub enum InboundConnectionHandlerError { @@ -445,3 +473,50 @@ pub enum ReadRpcIdError { #[derive(Debug, thiserror::Error)] #[error("Unknown RPC (ID: {0})")] pub struct UnknownRpcError(pub u8); + +/// RPC [`Client`] error. +#[derive(Debug, thiserror::Error)] +#[error(transparent)] +pub struct Error(ErrorInner); + +/// RPC [`Client`] result. +pub type Result = std::result::Result; + +impl Error { + fn new(err: impl Into) -> Self { + Self(err.into()) + } +} + +impl From for Error { + fn from(err: ErrorInner) -> Self { + Self::new(err) + } +} + +#[derive(Debug, thiserror::Error)] +enum ErrorInner { + #[error("Failed to generate TLS certificate: {0:?}")] + GenCertificate(#[from] libp2p_tls::certificate::GenError), + + #[error("quinn::rustls: {0}")] + Rustls(#[from] rustls::NoInitialCipherSuite), + + #[error("QUIC: {0}")] + Quic(#[from] quic::Error), + + #[error("Connection: {0:?}")] + Connection(#[from] quinn::ConnectionError), + + #[error("Timeout establishing inbound connection")] + ConnectionTimeout, + + #[error("Timeout reading inbound connection header")] + ReadConnectionHeaderTimeout, + + #[error("Unknown API: {0}")] + UnknownApi(rpc::ApiName), + + #[error("Transport: {0}")] + Transport(#[from] transport::Error), +} From 8c31c95d4f28835d4224e3b96ed6c304bba188a6 Mon Sep 17 00:00:00 2001 From: Darksome Date: Wed, 25 Jun 2025 15:19:00 +0000 Subject: [PATCH 57/79] WIP --- Cargo.lock | 3 + Cargo.toml | 1 + crates/rpc/Cargo.toml | 5 +- crates/rpc/src/client2.rs | 572 ++++++++++++---------- crates/rpc/src/lib.rs | 104 +++- crates/rpc/src/quic/client.rs | 26 +- crates/rpc/src/quic/mod.rs | 25 +- crates/rpc/src/quic/server.rs | 5 +- crates/rpc/src/server2.rs | 652 +++++++++++++------------- crates/rpc/src/transport.rs | 4 +- crates/rpc/src/transport2.rs | 195 ++++++++ crates/storage_api2/src/lib.rs | 497 ++++++-------------- crates/storage_api2/src/operation.rs | 291 +++--------- crates/storage_api2/src/rpc/client.rs | 593 ++++++++++------------- crates/storage_api2/src/rpc/mod.rs | 407 +++++++++++----- crates/storage_api2/src/rpc/server.rs | 522 ++++++++++----------- 16 files changed, 1973 insertions(+), 1929 deletions(-) create mode 100644 crates/rpc/src/transport2.rs diff --git a/Cargo.lock b/Cargo.lock index 9c0e2892..d4cd6d59 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8031,6 +8031,7 @@ version = "0.1.0" dependencies = [ "arc-swap", "backoff", + "bytes", "derivative", "derive-where", "derive_more 1.0.0", @@ -8043,12 +8044,14 @@ dependencies = [ "mini-moka", "nix", "pin-project", + "postcard", "quinn", "quinn-proto", "rand 0.8.5", "serde", "serde_json", "socket2", + "strum", "tap", "thiserror 1.0.64", "tokio", diff --git a/Cargo.toml b/Cargo.toml index ed976d9a..573a68ad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -51,6 +51,7 @@ time = "0.3" libp2p = { version = "0.55", default-features = false, features = ["serde"] } tokio-serde = { git = "https://github.com/xDarksome/tokio-serde.git", rev = "6df9ff9" } tokio-serde-postcard = { git = "https://github.com/xDarksome/tokio-serde-postcard.git", rev = "5e1b77a" } +postcard = { version = "1.0", default-features = false } itertools = "0.12" futures = "0.3" backoff = { version = "0.4", features = ["tokio"] } diff --git a/crates/rpc/Cargo.toml b/crates/rpc/Cargo.toml index 972953dc..8f0e03e7 100644 --- a/crates/rpc/Cargo.toml +++ b/crates/rpc/Cargo.toml @@ -12,8 +12,9 @@ client = [] server = [] [dependencies] -derive_more = { workspace = true, features = ["display"] } +derive_more = { workspace = true, features = ["display", "try_from"] } derive-where = { workspace = true } +strum = { workspace = true , features = ["derive"] } derivative = "2.2" futures = "0.3" indexmap = "2" @@ -27,6 +28,8 @@ tokio-stream = "0.1" tokio-util = { version = "0.7", features = ["compat", "codec"] } tokio-serde = { workspace = true, features = ["json"] } tokio-serde-postcard = { workspace = true } +postcard = { workspace = true, features = ["alloc"] } +bytes = "1" serde_json = "1" rand = { version = "0.8", features = ["small_rng"] } libp2p = { workspace = true } diff --git a/crates/rpc/src/client2.rs b/crates/rpc/src/client2.rs index fb899d24..d658f72a 100644 --- a/crates/rpc/src/client2.rs +++ b/crates/rpc/src/client2.rs @@ -1,9 +1,11 @@ use { crate::{ - self as rpc, quic::{self}, - transport::{self, BiDirectionalStream, Codec, RecvStream, SendStream}, - Message, + sealed, + transport, + transport2::{self, BiDirectionalStream, Codec, RecvStream, SendStream}, + ConnectionStatusCode, + MessageV2, RpcImpl, RpcV2, }, @@ -22,69 +24,64 @@ use { std::{ future::Future, io, - marker::PhantomData, net::{SocketAddr, SocketAddrV4}, sync::Arc, time::Duration, }, - tap::TapFallible, + strum::{EnumDiscriminants, IntoDiscriminant, IntoStaticStr}, + tap::TapFallible as _, tokio::{ - io::AsyncWriteExt, + io::{AsyncReadExt as _, AsyncWriteExt}, sync::{watch, Mutex}, }, - wc::future::FutureExt as _, + wc::{ + future::FutureExt as _, + metrics::{self, enum_ordinalize::Ordinalize, EnumLabel, StringLabel}, + }, }; -/// Client-specific part of an RPC [`Api`](super::Api). -pub trait Api: super::Api { - /// [`ConnectionHandler`] of this [`Api`]. - type ConnectionHandler: ConnectionHandler; +// TODO: metrics, timeouts +/// Client-specific part of an RPC [Api][`super::Api`]. +pub trait Api: super::Api + Sized { + /// Outbound [`Connection`] parameters. + type ConnectionParameters: Clone + Send + Sync + 'static; + + /// Implementor of [`HandleConnection`] of this RPC [`Api`]. + type ConnectionHandler: HandleConnection; - /// [`RpcHandler`] of this [`Api`]. - type RpcHandler: Clone + Send + Sync + 'static; + //// Implementor of [`HandleRpc`] for the RPCs of this RPC [`Api`]. + // type RpcHandler: Send + Sync + 'static; } /// Handler of newly established outbound [`Connection`]s. -/// -/// Every time a new outbound [`Connection`] gets established it's being -/// passed into a [`ConnectionHandler`]. -pub trait ConnectionHandler: Clone + Send + Sync + 'static { - /// [`Api`] that uses this [`ConnectionHandler`]. - type Api: Api; - - /// Error of this [`ConnectionHandler`]. - type Error; +pub trait HandleConnection: Clone + Send + Sync + 'static { + /// Creates a new instance of [`Api::RpcHandler`]. + /// + /// Each outbound [`Connection`] gets a separate RPC handler. + // fn new_rpc_handler(&self, args: Args) -> API::RpcHandler; /// Handles the provided outbound [`Connection`]. fn handle_connection( &self, - conn: &mut Connection, - ) -> impl Future> + Send; + conn: &Connection, + params: &API::ConnectionParameters, + ) -> impl Future> + Send; } -/// Handler of a specific type of [`Outbound`] RPCs. -pub trait RpcHandler: Clone + Send + Sync + 'static -where - RPC: RpcV2, -{ - /// [`Result`] of this [`RpcHandler`]. - type Result; +/// Handler of [`Outbound`] RPCs. +pub trait HandleRpc: Send + Sync { + type Output; - /// Handles the provided [`Outbound`] RPC. - fn handle_rpc( - &self, - rpc: &mut Outbound, - args: Args, - ) -> impl Future + Send; + fn handle_rpc(self, rpc: Outbound) -> impl Future> + Send; } -/// [`Client`] config. +/// RPC [`Client`] config. #[derive(Clone, Debug)] pub struct Config { /// [`identity::Keypair`] of the client. pub keypair: identity::Keypair, - /// Connection timeout. + /// Timeout of establishing an outbound connection. pub connection_timeout: Duration, /// Highest allowed frequency of connection retries. @@ -97,23 +94,25 @@ pub struct Config { pub priority: transport::Priority, } +impl AsRef for Config { + fn as_ref(&self) -> &Config { + self + } +} + /// RPC client responsible for establishing outbound [`Connection`]s to remote /// peers. -#[derive(Clone)] +#[derive_where(Clone)] pub struct Client { config: Arc, endpoint: quinn::Endpoint, + connection_handler: API::ConnectionHandler, - rpc_handler: API::RpcHandler, } impl Client { /// Creates a new RPC [`Client`]. - pub fn new( - connection_handler: API::ConnectionHandler, - rpc_handler: API::RpcHandler, - cfg: Config, - ) -> Result { + pub fn new(cfg: Config, connection_handler: API::ConnectionHandler) -> Result { let transport_config = quic::new_quinn_transport_config(cfg.max_concurrent_rpcs); let socket_addr = SocketAddr::new(std::net::Ipv4Addr::new(0, 0, 0, 0).into(), 0); let endpoint = quic::new_quinn_endpoint( @@ -129,38 +128,125 @@ impl Client { config: Arc::new(cfg), endpoint, connection_handler, - rpc_handler, }) } /// Establishes a new outbound [`Connection`]. - pub fn connect(&self, addr: SocketAddrV4, peer_id: PeerId) -> Connection { - let (tx, rx) = watch::channel(None); + pub async fn connect( + &self, + addr: SocketAddrV4, + peer_id: &PeerId, + params: API::ConnectionParameters, + ) -> Result> { + async { + // `libp2p_tls` uses this "l" placeholder as server_name. + let conn = self.endpoint.connect(addr.into(), "l")?.await?; + + let remote_peer_id = quic::connection_peer_id(&conn)?; - let conn = Connection { + if *peer_id != remote_peer_id { + tracing::warn!( + expected = ?peer_id, + got = ?&remote_peer_id, + addr = ?addr, + "Wrong PeerId" + ); + + return Err(ErrorInner::WrongPeerId(remote_peer_id)); + } + + // handshake + let (mut tx, mut rx) = conn.open_bi().await?; + tx.write_u32(super::PROTOCOL_VERSION).await?; + tx.write_all(&API::NAME.0).await?; + check_connection_status(rx.read_i32().await?)?; + + let conn = self.new_connection_inner(addr, peer_id, params, Some(conn)); + + // we just created the `Connection`, the lock can't be locked + // NOTE: by holding this guard here we are also making sure that + // `ConnectionHandler::handle_connection` won't get into infinite recursion by + // trying to reconnect + let guard = conn.inner.watch_tx.try_lock().unwrap(); + let params = &guard.1; + + self.connection_handler + .handle_connection(&conn, params) + .await + .map_err(|err| err.0)?; + + drop(guard); + + Ok(conn) + } + .with_timeout((*self.config).as_ref().connection_timeout) + .await + .map_err(|_| ErrorInner::Timeout)? + .map_err(Error::new) + } + + /// Creates a new outbound [`Connection`] without waiting for it to be + /// established. + pub fn new_connection( + &self, + addr: SocketAddrV4, + peer_id: &PeerId, + params: API::ConnectionParameters, + ) -> Connection { + let conn = self.new_connection_inner(addr, peer_id, params, None); + conn.reconnect(); + conn + } + + fn new_connection_inner( + &self, + addr: SocketAddrV4, + peer_id: &PeerId, + params: API::ConnectionParameters, + quic: Option, + ) -> Connection { + let (tx, rx) = watch::channel(quic); + + Connection { inner: Arc::new(ConnectionInner { client: self.clone(), remote_addr: addr, - remote_peer_id: peer_id, + remote_peer_id: *peer_id, watch_rx: rx, - watch_tx: Arc::new(tokio::sync::Mutex::new(tx)), + watch_tx: Arc::new(tokio::sync::Mutex::new((tx, params))), }), - }; + } + } +} - conn.reconnect(); - conn +/// Default implementation of [`ConnectionHandler`]. +/// +/// No-op, doesn't do anything with the [`Connection`]. +#[derive(Clone, Copy, Debug, Default)] +pub struct DefaultConnectionHandler; + +impl HandleConnection for DefaultConnectionHandler +where + API: Api, +{ + // fn new_rpc_handler(&self) -> ::RpcHandler { + // DefaultRpcHandler + // } + + async fn handle_connection(&self, _conn: &Connection, _params: &()) -> Result<()> { + Ok(()) } } -/// Outboud RPC of a specific type. +/// Outbound RPC of a specific type. pub struct Outbound { - send: SinkMapErr, fn(transport::Error) -> Error>, - recv: MapErr, fn(transport::Error) -> Error>, + send: SinkMapErr, fn(transport2::Error) -> Error>, + recv: MapErr, fn(transport2::Error) -> Error>, } impl Outbound { /// Returns [`Sink`] of outbound requests. - pub fn sink(&mut self) -> &mut impl Sink { + pub fn sink(&mut self) -> &mut (impl for<'a> Sink<&'a RPC::Request, Error = Error> + 'static) { &mut self.send } @@ -168,19 +254,31 @@ impl Outbound { pub fn stream(&mut self) -> &mut impl Stream> { &mut self.recv } + + /// Handles this [`Outbound`] unary RPC. + pub async fn handle_unary(&mut self, req: &RPC::Request) -> Result + where + RPC: sealed::UnaryRpc, + { + self.sink().send(req).await?; + self.stream() + .next() + .await + .ok_or_else(|| Error::new(transport2::Error::StreamFinished))? + } } /// Outbound connection. /// /// Existence of an instance of this type doesn't guarantee that the actual -/// network connection is already established (or will ever be established). -/// -/// Reconnects are being handled automatically in the background. -#[derive(Clone)] +/// network [`Connection`] is already established (or will ever be established). +#[derive_where(Clone)] pub struct Connection { inner: Arc>, } +type ConnectionMutex = Mutex<(watch::Sender>, Params)>; + struct ConnectionInner { client: Client, @@ -188,28 +286,28 @@ struct ConnectionInner { remote_peer_id: PeerId, watch_rx: watch::Receiver>, - watch_tx: Arc>>>, + watch_tx: Arc>, } impl Connection { /// Returns [`SocketAddrV4`] of the remote peer. - pub fn peer_addr(&self) -> &SocketAddrV4 { + pub fn remote_peer_addr(&self) -> &SocketAddrV4 { &self.inner.remote_addr } /// Returns [`PeerId`] of the remote peer. - pub fn peer_id(&self) -> &PeerId { + pub fn remote_peer_id(&self) -> &PeerId { &self.inner.remote_peer_id } - /// Indicates whether this [`Connection`] is currently open. - pub fn is_open(&self) -> bool { + /// Indicates whether this [`Connection`] is closed. + pub fn is_closed(&self) -> bool { self.inner .watch_rx .borrow() .as_ref() .map(|conn| conn.close_reason().is_some()) - .unwrap_or_default() + .unwrap_or(true) } /// Waits for this [`Connection`] to become open. @@ -223,187 +321,145 @@ impl Connection { _ => {} } + self.reconnect(); + drop(watch_rx.changed().await) } - /// Sends a new [`Outbound`] RPC over this [`Connection`]. - pub fn send(&self) -> Result> { - (|| { - let opt = self.inner.watch_rx.borrow(); - let Some(conn) = opt.as_ref() else { - return Err(ErrorInner::NotConnected); - }; - - // `open_bi` only blocks if there are too many outbound streams. - let (mut tx, rx) = match conn.open_bi().now_or_never() { - Some(Ok(stream)) => stream, - Some(Err(err)) => return Err(err.into()), - None => return Err(ErrorInner::TooManyConcurrentRpcs), - }; - - // This can only block if send buffer is full. - tx.write_u8(RPC::ID) - .now_or_never() - .ok_or_else(|| ErrorInner::SendBufferFull)?; - - let (recv, send) = BiDirectionalStream::new(tx, rx) - .upgrade::(); - - Ok(Outbound { - send: SinkExt::<&RPC::Request>::sink_map_err(send, |err: transport::Error| { - Error::new(err) - }), - recv: recv.map_err(Error::new), - }) - })() - .map_err(Error::new) - .tap_err(|err| { - if err.is_connection_error() { + /// Sends an RPC over this [`Connection`]. + pub fn send_rpc<'a, RPC, H>( + &'a self, + handler: H, + ) -> Result> + 'a> + where + RPC: RpcV2, + H: HandleRpc + 'a, + { + let mut rpc = self.new_rpc::().tap_err(|err| { + if err.requires_reconnect() { self.reconnect(); } + })?; + + Ok(async move { + handler.handle_rpc(rpc).await.tap_err(|err| { + if err.0.requires_reconnect() { + self.reconnect(); + } + }) + }) + + // Ok({ async move { todo!() } }) + } + + fn new_rpc(&self) -> Result, ErrorInner> { + let quic = self.inner.watch_rx.borrow(); + let Some(conn) = quic.as_ref() else { + return Err(ErrorInner::NotConnected.into()); + }; + + // `open_bi` only blocks if there are too many outbound streams. + let (mut tx, rx) = match conn.open_bi().now_or_never() { + Some(Ok(stream)) => stream, + Some(Err(err)) => return Err(err.into()), + None => return Err(ErrorInner::TooManyConcurrentRpcs), + }; + + // This can only block if send buffer is full. + tx.write_u8(RPC::ID) + .now_or_never() + .ok_or_else(|| ErrorInner::SendBufferFull)??; + + let (recv, send) = BiDirectionalStream::new(tx, rx).upgrade::(); + + Ok(Outbound { + send: SinkExt::<&RPC::Request>::sink_map_err(send, |err: transport2::Error| { + Error::new(err) + }), + recv: recv.map_err(Error::new), }) } fn reconnect(&self) { // If we can't acquire the lock then reconnection is already in progress. - let Ok(watch_tx) = self.inner.watch_tx.clone().try_lock_owned() else { + let Ok(guard) = self.inner.watch_tx.clone().try_lock_owned() else { return; }; let this = self.inner.clone(); tokio::spawn(async move { - let mut interval = tokio::time::interval(this.client.config.reconnect_interval); + let mut interval = + tokio::time::interval((*this.client.config).as_ref().reconnect_interval); interval.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip); loop { interval.tick().await; - if let Ok(conn) = this.clone().new_quic_connection().await { - watch_tx.send(Some(conn)); - return; + let res = this + .client + .connect(this.remote_addr, &this.remote_peer_id, guard.1.clone()) + .await; + + match res { + Ok(conn) => { + let quic = conn.inner.watch_rx.borrow(); + + // should always be `Some`, as we just established the connection + let _ = guard.0.send(Some(quic.as_ref().unwrap().clone())); + return; + } + Err(err) => { + metrics::counter!( + "wcn_rpc_client_connection_errors", + StringLabel<"remote_addr", SocketAddrV4> => &this.remote_addr, + StringLabel<"remote_peer_id", PeerId> => &this.remote_peer_id, + EnumLabel<"kind", ErrorKind> => err.0.discriminant() + ) + .increment(1); + } } } }); } } -impl ConnectionInner { - async fn new_quic_connection(self: Arc) -> Result { - let timeout = self.client.config.connection_timeout; - - async move { - // `libp2p_tls` uses this "l" placeholder as server_name. - let conn = self - .client - .endpoint - .connect(self.remote_addr.into(), "l")? - .await?; - - let peer_id = quic::connection_peer_id(&conn) - .map_err(|err| ErrorInner::ExtractPeerId(err.to_string()))?; - - if peer_id != self.remote_peer_id { - tracing::warn!( - expected = ?self.remote_peer_id, - got = ?peer_id, - addr = ?self.remote_addr, - "Wrong PeerId" - ); - - return Err(ErrorInner::WrongPeerId(peer_id)); - } - - // write connection header - let mut tx = conn.open_uni().await?; - tx.write_u32(super::PROTOCOL_VERSION).await?; - tx.write_all(&API::NAME.0).await?; - - Ok(conn) - } - .with_timeout(timeout) - .await - .map_err(|_| ErrorInner::Timeout)? - .map_err(Error::new) - } -} - -impl RpcImpl -where - K: Send + Sync + 'static, - API: Api, - Req: Message, - Resp: Message, - C: Codec, -{ - /// Sends this RPC over the provided [`Connection`]. - pub fn send( - conn: &Connection, - args: Args, - ) -> Result + '_> - where - API::RpcHandler: RpcHandler, - Args: 'static, - { - let mut rpc = conn.send::()?; - let handler = &conn.inner.client.rpc_handler; - Ok(async move { handler.handle_rpc(&mut rpc, args).await }) - } -} +/// Default implementation of [`RpcHandler`]. +/// +/// Automatically implements [`RpcHandler`] for all (unary)[rpc::UnaryV2] RPCs. +/// +/// For your (streaming)[rpc::StreamingV2] RPCs you'll need to provide a manual +/// implementation of [`RpcHandler`] for this type. +#[derive(Clone, Copy, Debug, Default)] +pub struct DefaultRpcHandler(pub Args); -impl Outbound> +impl<'a, RPC> HandleRpc for DefaultRpcHandler<&'a RPC::Request> where - API: Api, - Req: Message, - Resp: Message, - C: Codec, + RPC: sealed::UnaryRpc, { - /// Handles this [`Outbound`] [`rpc::UnaryV2`]. - pub async fn handle(&mut self, req: Req) -> Result { - self.sink().send(req).await?; - self.stream() - .next() - .await - .ok_or_else(|| Error::new(transport::Error::StreamFinished))? - } -} - -/// Default implementation of [`RpcHandler`]. -#[derive_where(Clone, Debug, Default; S)] -pub struct DefaultRpcHandler { - state: S, - _marker: PhantomData, -} + type Output = RPC::Response; -impl DefaultRpcHandler { - /// Creates a new [`DefaultRpcHandler`]. - pub fn new(state: S) -> Self { - Self { - state, - _marker: PhantomData, - } + fn handle_rpc( + self, + mut rpc: Outbound, + ) -> impl Future> + Send { + async move { rpc.handle_unary(self.0).await } } } -impl RpcHandler, Req> - for DefaultRpcHandler +impl RpcImpl where - API: Api, - Req: Message, - Resp: Message, - C: Codec, - Err: Send + Sync + 'static, - S: Clone + Send + Sync + 'static, - Error: Into, + K: 'static, + Req: MessageV2, + Resp: MessageV2, + C: Codec + Codec, { - type Result = Result; - - async fn handle_rpc( - &self, - rpc: &mut Outbound>, - req: Req, - ) -> Self::Result { - rpc.handle(req).await.map_err(Into::into) + /// Sends this RPC over the provided [`Connection`]. + pub fn send<'a, API: Api, H: HandleRpc + 'a>( + conn: &'a Connection, + rpc_handler: H, + ) -> Result> + 'a> { + conn.send_rpc(rpc_handler) } } @@ -419,29 +475,6 @@ impl Error { fn new(err: impl Into) -> Self { Self(err.into()) } - - /// Indicates whether this [`Error`] is caused by the - /// [`OutboundConnection`] being closed / broken. - /// - /// Such errors may be fixed by a reconnect. Consider - /// (waiting)[OutboundConnection::wait_open] for the [`OutboundConnection`] - /// to become open again. - pub fn is_connection_error(&self) -> bool { - match &self.0 { - ErrorInner::NotConnected - | ErrorInner::Quic(_) - | ErrorInner::ExtractPeerId(_) - | ErrorInner::WrongPeerId(_) - | ErrorInner::Connect(_) - | ErrorInner::Connection(_) - | ErrorInner::Io(_) - | ErrorInner::Write(_) - | ErrorInner::Timeout - | ErrorInner::Transport(_) => true, - - ErrorInner::TooManyConcurrentRpcs | ErrorInner::SendBufferFull => false, - } - } } impl From for Error { @@ -450,7 +483,9 @@ impl From for Error { } } -#[derive(Debug, thiserror::Error)] +#[derive(Debug, thiserror::Error, EnumDiscriminants)] +#[strum_discriminants(name(ErrorKind))] +#[strum_discriminants(derive(Ordinalize, IntoStaticStr))] enum ErrorInner { #[error("Not connected")] NotConnected, @@ -458,8 +493,8 @@ enum ErrorInner { #[error("QUIC: {0}")] Quic(#[from] quic::Error), - #[error("Failed to extract PeerId")] - ExtractPeerId(String), + #[error(transparent)] + ExtractPeerId(#[from] quic::ExtractPeerIdError), #[error("Wrong PeerId: {0}")] WrongPeerId(PeerId), @@ -486,5 +521,60 @@ enum ErrorInner { Timeout, #[error("Transport: {0}")] - Transport(#[from] transport::Error), + Transport(#[from] transport2::Error), + + #[error("Unknown ConnectionStatusCode({0})")] + UnknownConnectionStatusCode(i32), + + #[error("Unsupported protocol")] + UnsupportedProtocol, + + #[error("Unknown API")] + UnknownApi, + + #[error("Unauthorized")] + Unauthorized, +} + +impl ErrorInner { + fn requires_reconnect(&self) -> bool { + match self { + ErrorInner::NotConnected + | ErrorInner::Quic(_) + | ErrorInner::ExtractPeerId(_) + | ErrorInner::WrongPeerId(_) + | ErrorInner::Connect(_) + | ErrorInner::Connection(_) + | ErrorInner::Io(_) + | ErrorInner::Write(_) + | ErrorInner::Timeout + | ErrorInner::Transport(_) + | ErrorInner::UnknownConnectionStatusCode(_) + | ErrorInner::UnsupportedProtocol + | ErrorInner::UnknownApi + | ErrorInner::Unauthorized => true, + + ErrorInner::TooManyConcurrentRpcs | ErrorInner::SendBufferFull => false, + } + } +} + +fn check_connection_status(code: i32) -> Result<(), ErrorInner> { + let code = ConnectionStatusCode::try_from(code) + .map_err(|err| ErrorInner::UnknownConnectionStatusCode(err.input))?; + + Err(match code { + ConnectionStatusCode::Ok => return Ok(()), + ConnectionStatusCode::UnsupportedProtocol => ErrorInner::UnsupportedProtocol, + ConnectionStatusCode::UnknownApi => ErrorInner::UnknownApi, + ConnectionStatusCode::Unauthorized => ErrorInner::Unauthorized, + }) } + +impl metrics::Enum for ErrorKind { + fn as_str(&self) -> &'static str { + self.into() + } +} + +// TODO: Vec Load Balancer diff --git a/crates/rpc/src/lib.rs b/crates/rpc/src/lib.rs index 3a18ccf9..471e6e52 100644 --- a/crates/rpc/src/lib.rs +++ b/crates/rpc/src/lib.rs @@ -1,12 +1,16 @@ #![allow(async_fn_in_trait)] #![allow(clippy::manual_async_fn)] -pub use libp2p::{identity, Multiaddr, PeerId}; use { - derive_more::Display, + derive_more::{derive::TryFrom, Display}, serde::{Deserialize, Serialize}, std::{borrow::Cow, fmt::Debug, marker::PhantomData, net::SocketAddr, str::FromStr}, transport::Codec, + transport2::Codec as CodecV2, +}; +pub use { + libp2p::{identity, Multiaddr, PeerId}, + transport2::PostcardCodec, }; #[cfg(feature = "client")] @@ -20,6 +24,7 @@ pub use client::Client; pub mod server; #[cfg(feature = "server")] pub mod server2; +use serde::de::DeserializeOwned; #[cfg(feature = "server")] pub use server::{IntoServer, Server}; @@ -27,6 +32,7 @@ pub mod middleware; pub mod quic; pub mod transport; +mod transport2; #[cfg(test)] mod test; @@ -57,14 +63,12 @@ const PROTOCOL_VERSION: u32 = 0; /// ``` pub trait Api: Clone + Send + Sync + 'static { /// [`ApiName`] of this [`Api`]. - /// - /// [`ApiName`] used const NAME: ApiName; /// `enum` representation of all RPC IDs of this [`Api`]. /// /// Should be convertible from/into `u8`. - type RpcId; + type RpcId: Copy + Into + TryFrom; } /// [`Api`] name. @@ -75,21 +79,29 @@ pub type ApiName = ServerName; /// Expected to be implemented on unit types and should not contain any data. /// /// See [`StreamingV2`] RPC and [`UnaryV2`] RPC. -pub trait RpcV2 { +pub trait RpcV2: Sized + 'static { /// ID of this [`Rpc`]. const ID: u8; - /// [`Api`] this [`Rpc`] belongs to. - type Api: Api; - /// Request type of this [`Rpc`]. type Request: Message; + type RequestRef<'a>: Serialize + Unpin + Sync + Send + 'a; + /// Response type of this [`Rpc`]. type Response: Message; /// Serialization codec of this [`Rpc`]. - type Codec: Codec; + type Codec: CodecV2 + CodecV2; +} + +pub(crate) mod sealed { + pub trait UnaryRpc: super::RpcV2 {} + + impl UnaryRpc for super::UnaryV2 where + Self: super::RpcV2 + { + } } /// Generic [`RpcV2`] implementation. @@ -97,20 +109,20 @@ pub trait RpcV2 { /// Not intended to be used directly by the users of this crate. /// /// Use [`StreamingV2`] or [`UnaryV2`] instead. -pub struct RpcImpl { - _marker: PhantomData<(K, API, Req, Resp, C)>, +pub struct RpcImpl { + _marker: PhantomData<(K, Req, Resp, C)>, } -impl RpcV2 for RpcImpl +impl RpcV2 for RpcImpl where - API: Api, - Req: Message, - Resp: Message, - C: Codec, + K: 'static, + Req: MessageV2, + Resp: MessageV2, + C: CodecV2 + CodecV2, { const ID: u8 = ID; - type Api = API; type Request = Req; + type RequestRef<'a> = &'a Req; type Response = Resp; type Codec = C; } @@ -121,15 +133,35 @@ where /// responses. /// /// Use type aliases to conviniently define RPCs of this kind. -pub type StreamingV2 = - RpcImpl; +pub type StreamingV2<'a, const ID: u8, Req, Resp, C> = RpcImpl; /// Unary (request-response) [`RpcV2`]. /// /// Client sends a single request and server responds with a single response. /// /// Use type aliases to conviniently define RPCs of this kind. -pub type UnaryV2 = RpcImpl; +pub type UnaryV2 = RpcImpl; + +pub trait MessageRef: Serialize + DeserializeOwned + Unpin + Sync + Send {} + +pub trait MessageV2: Serialize + DeserializeOwned + Unpin + Sync + Send + 'static { + type Borrowed<'a>: Serialize + Unpin + Sync + Send + 'a; +} + +// type BorrowedRequest<'a, RPC> = <::Request as +// MessageV2>::Borrowed<'a>; + +pub trait StaticMessage: + Serialize + for<'de> Deserialize<'de> + Unpin + Sync + Send + 'static +{ +} + +impl MessageV2 for Msg +where + Msg: StaticMessage, +{ + type Borrowed<'a> = Self; +} /// Error codes produced by this module. pub mod error_code { @@ -410,3 +442,33 @@ impl Debug for PeerAddr { Debug::fmt(&self.to_string(), f) } } + +#[derive(Clone, Copy, Debug, TryFrom)] +#[try_from(repr)] +#[repr(i32)] +enum ConnectionStatusCode { + Ok = 0, + + UnsupportedProtocol = -1, + UnknownApi = -2, + Unauthorized = -3, +} + +impl MessageV2 for Result +where + T: MessageV2, + E: MessageV2, +{ + type Borrowed<'a> = Result, E::Borrowed<'a>>; +} + +impl MessageV2 for Option +where + T: MessageV2, +{ + type Borrowed<'a> = Option>; +} + +impl MessageV2 for () { + type Borrowed<'a> = (); +} diff --git a/crates/rpc/src/quic/client.rs b/crates/rpc/src/quic/client.rs index 3615a3f4..f7350815 100644 --- a/crates/rpc/src/quic/client.rs +++ b/crates/rpc/src/quic/client.rs @@ -1,7 +1,6 @@ use { super::{ConnectionHeader, ExtractPeerIdError, InvalidMultiaddrError, PROTOCOL_VERSION}, crate::{ - self as rpc, client::{self, AnyPeer, Config, Result}, transport::{self, BiDirectionalStream, Handshake, NoHandshake, PendingConnection}, Id as RpcId, @@ -201,7 +200,10 @@ fn new_connection( ))); } - write_connection_header(&conn, ConnectionHeader { server_name }).await?; + write_connection_header(&conn, ConnectionHeader { + server_name: Some(server_name), + }) + .await?; handshake .handle(peer_id, PendingConnection(conn.clone())) @@ -385,12 +387,6 @@ impl ConnectionError { } } -impl From for rpc::Error { - fn from(err: ConnectionError) -> Self { - err.as_metrics_label().into() - } -} - #[derive(Debug, From, thiserror::Error)] pub enum EstablishStreamError { #[error("Invalid Multiaddr")] @@ -412,20 +408,6 @@ pub enum EstablishStreamError { Lock, } -impl From for rpc::Error { - fn from(err: EstablishStreamError) -> Self { - match err { - EstablishStreamError::InvalidMultiaddr(_) => "quic_client_invalid_multiaddr", - EstablishStreamError::NoAvailablePeers => "quic_client_no_available_peers", - EstablishStreamError::Connection(err) => return err.into(), - EstablishStreamError::Timeout => "quic_client_establish_stream_timeout", - EstablishStreamError::Rng => todo!(), - EstablishStreamError::Lock => todo!(), - } - .into() - } -} - impl From> for EstablishStreamError { fn from(_: PoisonError) -> Self { Self::Lock diff --git a/crates/rpc/src/quic/mod.rs b/crates/rpc/src/quic/mod.rs index f037fa5e..40806aa4 100644 --- a/crates/rpc/src/quic/mod.rs +++ b/crates/rpc/src/quic/mod.rs @@ -2,7 +2,6 @@ use nix::sys::socket::{setsockopt, sockopt}; use { crate::{ - self as rpc, transport::{self, Priority}, ServerName, }, @@ -30,9 +29,8 @@ mod metrics; const PROTOCOL_VERSION: u32 = 1; -#[derive(Default)] pub(crate) struct ConnectionHeader { - pub server_name: ServerName, + pub server_name: Option, } #[derive(Clone, Debug, thiserror::Error, Eq, PartialEq)] @@ -225,24 +223,3 @@ enum IpTosDscp { /// Lower-Effort, RFC8622 Le = 0b0000_0100, } - -impl From for rpc::Error { - fn from(err: quinn::ConnectionError) -> Self { - use quinn::ConnectionError as Error; - - match err { - Error::VersionMismatch => "quinn_quic_version_mismatch".into(), - Error::TransportError(err) => rpc::Error::new("quinn_transport").with_description(err), - Error::ConnectionClosed(err) => { - rpc::Error::new("quinn_connection_closed").with_description(err) - } - Error::ApplicationClosed(err) => { - rpc::Error::new("quinn_application_closed").with_description(err) - } - Error::Reset => "quinn_conection_reset".into(), - Error::TimedOut => "quinn_connection_timeout".into(), - Error::LocallyClosed => "quinn_connection_locally_closed".into(), - Error::CidsExhausted => "quinn_connectino_cids_exhausted".into(), - } - } -} diff --git a/crates/rpc/src/quic/server.rs b/crates/rpc/src/quic/server.rs index e3bcdb12..4b8ef873 100644 --- a/crates/rpc/src/quic/server.rs +++ b/crates/rpc/src/quic/server.rs @@ -267,7 +267,7 @@ where } } -pub(crate) async fn read_connection_header( +async fn read_connection_header( conn: &quinn::Connection, ) -> Result { let mut rx = conn.accept_uni().await?; @@ -275,10 +275,11 @@ pub(crate) async fn read_connection_header( let protocol_version = rx.read_u32().await?; let server_name = match protocol_version { + 0 => None, super::PROTOCOL_VERSION => { let mut buf = [0; 16]; rx.read_exact(&mut buf).await?; - ServerName(buf) + Some(ServerName(buf)) } ver => return Err(ConnectionError::UnsupportedProtocolVersion(ver)), }; diff --git a/crates/rpc/src/server2.rs b/crates/rpc/src/server2.rs index 874d5e7b..200f3d7e 100644 --- a/crates/rpc/src/server2.rs +++ b/crates/rpc/src/server2.rs @@ -3,55 +3,92 @@ use { self as rpc, quic::{ self, - server::{ - filter::{self, Filter, RejectionReason}, - read_connection_header, - }, + server::filter::{self, Filter, RejectionReason}, }, - transport::{self, BiDirectionalStream, RecvStream, SendStream}, + transport, + transport2::{self, BiDirectionalStream, RecvStream, SendStream}, + Api, ApiName, + ConnectionStatusCode, RpcV2, + ServerName, + }, + derive_where::derive_where, + futures::{ + sink::SinkMapErr, + stream::MapErr, + FutureExt, + Sink, + SinkExt, + Stream, + TryFutureExt as _, + TryStreamExt as _, }, - futures::{future::MapErr, sink::SinkMapErr, Sink, Stream, TryFutureExt as _}, - libp2p::{identity::Keypair, PeerId}, + libp2p::{identity, PeerId}, quinn::crypto::rustls::{self, QuicServerConfig}, - sealed::ConnectionRouter, std::{future::Future, io, marker::PhantomData, sync::Arc, time::Duration}, - tokio::sync::{OwnedSemaphorePermit, Semaphore}, + tap::Pipe as _, + tokio::{ + io::{AsyncReadExt, AsyncWriteExt}, + sync::{OwnedSemaphorePermit, Semaphore}, + }, wc::{ future::FutureExt as _, - metrics::{self, future_metrics, Enum as _, EnumLabel, StringLabel}, + metrics::{self, future_metrics, Enum as _, EnumLabel, FutureExt as _, StringLabel}, }, }; -/// Server-specific part of an RPC [`Api`](super::Api). -pub trait Api: super::Api { - /// [`InboundConnectionHandler`] of this [`Api`]. - type InboundConnectionHandler: InboundConnectionHandler; -} +// TODO: Authorization, metrics, timeouts -/// Handler of newly established [`InboundConnection`]s. -/// -/// Every time a new [`InboundConnection`] gets established it's being passed -/// into an [`InboundConnectionHandler`]. -pub trait InboundConnectionHandler: Clone + Send + Sync + 'static { - type Api; +/// Handler of newly established inbound [`Connection`]s. +pub trait HandleConnection: Clone + Send + Sync + 'static { + /// RPC [`Api`] the connections of which are being handled. + type Api: Api; - fn handle( + /// Handles the provided inbound [`Connection`]. + fn handle_connection( &self, - conn: &mut InboundConnection, - ) -> impl Future + Send; + conn: Connection<'_, Self::Api>, + ) -> impl Future> + Send; } -/// Handler of a specific type of [`Inbound`] RPCs. -pub trait InboundRpcHandler -where - RPC: RpcV2, -{ - /// Handles the provided [`Outbound`] RPC. +/// Handler of [`Inbound`] RPCs. +pub trait HandleRpc { + /// Handles the provided [`Inbound`] RPC. fn handle_rpc(&self, rpc: &mut Inbound) -> impl Future> + Send; } +pub trait Rpc: RpcV2 { + /// Handle this RPC using the provided handler. + /// + /// Caller is expected to ensure that the [`InboundRpc::id()`] is correct. + fn handle>( + rpc: InboundRpc, + handler: &impl HandleRpc, + ) -> impl Future> { + if cfg!(debug_assertions) { + let id: u8 = rpc.id.into(); + assert_eq!(id, Self::ID); + } + + let (recv, send) = rpc.stream.upgrade(); + + let mut rpc = Inbound { + send: SinkExt::<&Self::Response>::sink_map_err(send, |err: transport2::Error| { + Error::new(err) + }), + recv: recv.map_err(Error::new), + _permit: rpc.permit, + }; + + async move { handler.handle_rpc(&mut rpc).await } + .with_metrics(future_metrics!("wcn_rpc_server_rpc")) + } +} + +impl Rpc for RPC where RPC: RpcV2 {} + +/// RPC server config. pub struct Config { /// Name of the server. For metrics purposes only. pub name: &'static str, @@ -59,8 +96,11 @@ pub struct Config { /// [`Multiaddr`] to bind the server to. pub port: u16, - /// [`Keypair`] of the server. - pub keypair: Keypair, + /// [`identity::Keypair`] of the server. + pub keypair: identity::Keypair, + + /// Timeout of establishing an inbound connection. + pub connection_timeout: Duration, /// Maximum global number of concurrent connections. pub max_connections: u32, @@ -78,80 +118,140 @@ pub struct Config { pub priority: transport::Priority, } -/// Serves a single RPC API on the specified port. -pub fn serve( - cfg: Config, - connection_handler: impl InboundConnectionHandler, -) -> Result> { - multiplex(cfg, (connection_handler,)) +/// Creates a new RPC [`Api`] server. +pub fn new(connection_handler: impl HandleConnection) -> impl Server { + ApiServer { connection_handler } } -/// Serves multiple RPC APIs on the specified port. -/// -/// `connection_handlers` is expected to be a tuple of -/// [`InboundConnectionHandler`]s. -pub fn multiplex(cfg: Config, connection_handlers: H) -> Result> +/// RPC server. +pub trait Server: Sized + Send + Sync + 'static where - H: sealed::ConnectionRouter, + Self: sealed::ConnectionRouter, { - let transport_config = quic::new_quinn_transport_config(cfg.max_concurrent_rpcs); - let server_tls_config = libp2p_tls::make_server_config(&cfg.keypair).map_err(Error::new)?; - let server_tls_config = QuicServerConfig::try_from(server_tls_config).map_err(Error::new)?; - let mut server_config = quinn::ServerConfig::with_crypto(Arc::new(server_tls_config)); - server_config.transport = transport_config.clone(); - server_config.migration(false); - - let endpoint = quic::new_quinn_endpoint( - ([0, 0, 0, 0], cfg.port).into(), - &cfg.keypair, - transport_config, - Some(server_config), - cfg.priority, - ) - .map_err(Error::new)?; - - let connection_filter = Filter::new(&filter::Config { - max_connections: cfg.max_connections, - max_connections_per_ip: cfg.max_connections_per_ip, - max_connection_rate_per_ip: cfg.max_connection_rate_per_ip, - }) - .map_err(Error::new)?; - - let rpc_semaphore = Arc::new(Semaphore::new(cfg.max_concurrent_rpcs as usize)); - - Ok(accept_connections( - cfg, - endpoint, - connection_filter, - rpc_semaphore, - connection_handlers, - )) + /// Multiplexes `self` with another [`Server`]. + fn multiplex(self, api_server: impl Server) -> impl Server { + Multiplexer { + head: api_server, + tail: self, + } + } + + /// Runs this RPC [`Server`] + fn serve(self, cfg: Config) -> Result> { + let transport_config = quic::new_quinn_transport_config(cfg.max_concurrent_rpcs); + let server_tls_config = libp2p_tls::make_server_config(&cfg.keypair).map_err(Error::new)?; + let server_tls_config = + QuicServerConfig::try_from(server_tls_config).map_err(Error::new)?; + let mut server_config = quinn::ServerConfig::with_crypto(Arc::new(server_tls_config)); + server_config.transport = transport_config.clone(); + server_config.migration(false); + + let endpoint = quic::new_quinn_endpoint( + ([0, 0, 0, 0], cfg.port).into(), + &cfg.keypair, + transport_config, + Some(server_config), + cfg.priority, + ) + .map_err(Error::new)?; + + let connection_filter = Filter::new(&filter::Config { + max_connections: cfg.max_connections, + max_connections_per_ip: cfg.max_connections_per_ip, + max_connection_rate_per_ip: cfg.max_connection_rate_per_ip, + }) + .map_err(Error::new)?; + + let rpc_semaphore = Arc::new(Semaphore::new(cfg.max_concurrent_rpcs as usize)); + + Ok(accept_connections( + cfg, + endpoint, + connection_filter, + rpc_semaphore, + self, + )) + } } -struct Server { - config: Config, - endpoint: quinn::Endpoint, +mod sealed { + use super::*; - connection_filter: Filter, - rpc_semaphore: Arc, + pub trait ConnectionRouter: Clone + Send + Sync + 'static { + /// Routes [`Connection`] to the [`Api`] connection handler. + fn route_connection( + &self, + api_name: &ApiName, + conn: Connection<'_>, + ) -> impl Future>> + Send; + } +} + +#[derive_where(Clone)] +struct ApiServer { + connection_handler: H, } -async fn accept_connections( +#[derive(Clone)] +struct Multiplexer { + head: A, + tail: B, +} + +impl sealed::ConnectionRouter for ApiServer { + async fn route_connection( + &self, + api_name: &ApiName, + conn: Connection<'_>, + ) -> Option> { + if api_name != &H::Api::NAME { + return None; + } + + Some( + self.connection_handler + .handle_connection(conn.specify_api()) + .await, + ) + } +} + +impl sealed::ConnectionRouter for Multiplexer +where + A: sealed::ConnectionRouter, + B: sealed::ConnectionRouter, +{ + async fn route_connection( + &self, + api_name: &ApiName, + conn: Connection<'_>, + ) -> Option> { + match self.head.route_connection(api_name, conn).await { + opt @ Some(_) => opt, + None => self.tail.route_connection(api_name, conn).await, + } + } +} + +impl Server for R {} + +async fn accept_connections( config: Config, endpoint: quinn::Endpoint, connection_filter: Filter, rpc_semaphore: Arc, - handlers: H, + router: R, ) { while let Some(incoming) = endpoint.accept().await { match connection_filter.try_acquire_permit(&incoming) { Ok(permit) => match incoming.accept() { Ok(connecting) => accept_connection( + config.connection_timeout, config.name, connecting, permit, rpc_semaphore.clone(), - handlers.clone(), + router.clone(), ), Err(err) => tracing::warn!(?err, "failed to accept incoming connection"), @@ -184,302 +284,193 @@ async fn accept_connections( } } -fn accept_connection( +fn accept_connection( + timeout: Duration, server_name: &'static str, connecting: quinn::Connecting, permit: filter::Permit, rpc_semaphore: Arc, router: R, ) { + use ConnectionStatusCode as Status; + async move { - let conn = connecting - .with_timeout(Duration::from_millis(1000)) - .await - .map_err(|_| ErrorInner::ConnectionTimeout)? - .map_err(Error::new)?; + let (api_name, conn, mut tx) = async move { + let conn = connecting.await?; + let remote_peer_id = quic::connection_peer_id(&conn)?; - conn.accept_uni().await.map_err(Error::new)?; + let (mut tx, mut rx) = conn.accept_bi().await?; - let protocol_version = rx.read_u32().await?; + let protocol_version = rx.read_u32().await?; - let server_name = match protocol_version { - super::PROTOCOL_VERSION => { - let mut buf = [0; 16]; - rx.read_exact(&mut buf).await?; - ServerName(buf) - } - ver => return Err(ConnectionError::UnsupportedProtocolVersion(ver)), - }; + let api_name = match protocol_version { + super::PROTOCOL_VERSION => { + let mut buf = [0; 16]; + rx.read_exact(&mut buf).await?; + ServerName(buf) + } + ver => { + tx.write_i32(Status::UnsupportedProtocol as i32).await?; + return Err(ErrorInner::UnsupportedProtocolVersion(ver)); + } + }; - let header = read_connection_header(&conn) - .with_timeout(Duration::from_millis(500)) - .await - .map_err(|_| ErrorInner::ReadConnectionHeaderTimeout)??; + let conn = ConnectionInner { + server_name, + _permit: permit, + remote_peer_id, + rpc_semaphore, + quic: conn, + }; - let conn = InboundConnection { - server_name, - permit, - rpc_semaphore, - inner: conn, + Ok((api_name, conn, tx)) + } + .with_timeout(timeout) + .map_err(|_| ErrorInner::ConnectionTimeout) + .await? + .map_err(Error::new)?; + + let conn = Connection { + inner: &conn, _marker: PhantomData, }; - router.route_connection(header.server_name, conn).await + match router.route_connection(&api_name, conn).await { + Some(res) => res, + None => { + tx.write_i32(ConnectionStatusCode::UnknownApi as i32) + .await + .map_err(Error::new)?; + + Err(ErrorInner::UnknownApi(api_name).into()) + } + } } .map_err(|err| tracing::debug!(?err, "Inbound connection handler failed")) - .with_metrics(future_metrics!("wcn_rpc_quic_server_inbound_connection")) + .with_metrics(future_metrics!("wcn_rpc_server_inbound_connection")) .pipe(tokio::spawn); } -pub struct InboundConnection { - server_name: &'static str, - - permit: filter::Permit, - rpc_semaphore: Arc, - - inner: quinn::Connection, - +/// Inbound connection. +#[derive(Clone, Copy)] +pub struct Connection<'a, API = ()> { + inner: &'a ConnectionInner, _marker: PhantomData, } -/// Inbound RPC of a specific type. -pub struct Inbound { - recv: MapErr, fn(transport::Error) -> Error>, - send: SinkMapErr, fn(transport::Error) -> Error>, -} - -impl Inbound { - /// Returns [`Stream`] of inbound requests. - pub fn stream(&mut self) -> &mut impl Stream> { - &mut self.recv - } - - /// Returns [`Sink`] of outbound responses. - pub fn sink(&mut self) -> &mut impl Sink { - &mut self.send - } -} - -impl InboundConnection { - fn set_api(self) -> InboundConnection { - InboundConnection { - server_name: self.server_name, - permit: self.permit, - rpc_semaphore: self.rpc_semaphore, +impl<'a> Connection<'a> { + fn specify_api(self) -> Connection<'a, API> { + Connection { inner: self.inner, - _marker: (), + _marker: PhantomData, } } } -impl InboundConnection { - pub fn peer_id(&self) -> PeerId { - todo!() - } - - pub async fn handle>( - &self, - rpc_handler: impl Fn(InboundRpc) -> F, - ) -> InboundConnectionHandlerResult { - loop { - match self.handle_rpc(rpc_handler).await { - Ok(fut) => tokio::spawn(fut), - Err(RpcHandlerError::TooManyRpc) => continue, - Err(err) => return Err(err), - }; - } - } +struct ConnectionInner { + server_name: &'static str, - pub async fn handle_rpc>( - &self, - rpc_handler: impl Fn(InboundRpc) -> F, - ) -> InboundConnectionHandlerResult> { - let (tx, mut rx) = self.inner.accept_bi().await?; - - let Some(permit) = self.acquire_stream_permit() else { - metrics::counter!( - "wcn_rpc_quic_server_streams_dropped", - StringLabel<"server_name"> => self.server_name - ) - .increment(1); - return Err(RpcHandlerError::TooManyRpc); - }; + remote_peer_id: PeerId, - async move { - let _permit = permit; + _permit: filter::Permit, + rpc_semaphore: Arc, - let rpc = InboundRpc { - id: None, - stream: BiDirectionalStream::new(tx, rx), - }; + quic: quinn::Connection, +} - rpc_handler.handle(&mut rpc).await +impl<'a, API: Api> From<&'a mut ConnectionInner> for Connection<'a, API> { + fn from(inner: &'a mut ConnectionInner) -> Self { + Self { + inner, + _marker: PhantomData, } - .with_metrics(future_metrics!("wcn_rpc_quic_server_inbound_stream")) - } - - fn acquire_stream_permit(&self) -> Option { - metrics::gauge!("wcn_rpc_quic_server_available_stream_permits", StringLabel<"server_name"> => self.server_name) - .set(self.stream_semaphore.available_permits() as f64); - - self.rpc_semaphore - .clone() - .try_acquire_owned() - .ok() - .tap_none(|| { - metrics::counter!("wcn_rpc_quic_server_throttled_streams", StringLabel<"server_name"> => self.server_name) - .increment(1); - }) } } -async fn read_rpc_id(stream: &mut BiDirectionalStream) -> Result { - stream - .rx - .read_u8() - .with_timeout(Duration::from_millis(500)) - .await - .map_err(|err| err.to_string())? - .map_err(|err| format!("{err:?}")) +/// Inbound RPC with yet undefined type. +pub struct InboundRpc { + id: API::RpcId, + stream: BiDirectionalStream, + permit: OwnedSemaphorePermit, } -mod sealed { - use super::*; - - pub trait ConnectionRouter: Clone { - fn route_connection( - &self, - api_name: ApiName, - connection: InboundConnection, - ) -> impl Future>; +impl InboundRpc { + /// Returns ID of this [`InboundRpc`]. + pub fn id(&self) -> API::RpcId { + self.id } } -impl ConnectionRouter for (A,) -where - A: InboundConnectionHandler, -{ - async fn route_connection( - &self, - api_name: ApiName, - conn: InboundConnection, - ) -> Result<(), InboundConnectionHandlerError> { - async move { - match &api_name { - A::Api::NAME => self.0.handle_connection(&mut conn.set_api()), - _ => Err(InboundConnectionHandlerError::UnknownApi(api_name)), - } - } - } +/// Inbound RPC of a specific type. +pub struct Inbound { + recv: MapErr, fn(transport2::Error) -> Error>, + send: SinkMapErr, fn(transport2::Error) -> Error>, + _permit: OwnedSemaphorePermit, } -impl ConnectionRouter for (A, B) -where - A: InboundConnectionHandler, - B: InboundConnectionHandler, -{ - async fn route_connection( - &self, - api_name: ApiName, - conn: InboundConnection, - ) -> Result<(), InboundConnectionHandlerError> { - async move { - match &api_name { - A::Api::NAME => self.0.handle_connection(&mut conn.set_api()), - B::Api::NAME => self.1.handle_connection(&mut conn.set_api()), - _ => Err(InboundConnectionHandlerError::UnknownApi(api_name)), - } - } +impl Inbound { + /// Returns [`Stream`] of inbound responses. + pub fn stream(&mut self) -> &mut impl Stream> { + &mut self.recv } -} -impl ConnectionRouter for (A, B, C) -where - A: InboundConnectionHandler, - B: InboundConnectionHandler, - C: InboundConnectionHandler, -{ - async fn route_connection( - &self, - api_name: ApiName, - conn: InboundConnection, - ) -> Result<(), InboundConnectionHandlerError> { - async move { - match &api_name { - A::Api::NAME => self.0.handle_connection(&mut conn.set_api()), - B::Api::NAME => self.1.handle_connection(&mut conn.set_api()), - C::Api::NAME => self.1.handle_connection(&mut conn.set_api()), - _ => Err(InboundConnectionHandlerError::UnknownApi(api_name)), - } - } + /// Returns [`Sink`] of outbound requests. + pub fn sink(&mut self) -> &mut impl Sink<&RPC::Response, Error = Error> { + &mut self.send } } -// #[derive(Debug, thiserror::Error)] -// pub enum Error { -// #[error("Transport: {0}")] -// Transport(String), - -// #[error("Crypto: {0}")] -// Crypto(String), - -// #[error("Config: {0}")] -// Config(String), -// } - -#[derive(Debug, thiserror::Error)] -pub enum InboundConnectionHandlerError { - #[error("Transport: {0}")] - Transport(String), - - #[error("Timeout establishing inbound connection")] - ConnectionTimeout, - - #[error("Timeout reading inbound connection header")] - ReadConnectionHeaderTimeout, - - #[error("Unknown API: {0}")] - UnknownApi(rpc::ApiName), -} - -pub type InboundConnectionHandlerResult = Result; - -#[derive(Debug, thiserror::Error)] -pub enum RpcHandlerError { - #[error("Too many concurrent RPCs")] - TooManyRpc, +impl Connection<'_, API> { + /// Returns [`PeerId`] of the remote peer. + pub fn remote_peer_id(&self) -> &PeerId { + &self.inner.remote_peer_id + } - #[error("Read RPC ID: {0}")] - ReadRpcId(#[from] ReadRpcIdError), + /// Accepts the next [`InboundRpc`]. + pub async fn accept_rpc(&self) -> Result> { + loop { + let (tx, mut rx) = self.inner.quic.accept_bi().await.map_err(Error::new)?; + + let Some(permit) = self.acquire_stream_permit() else { + metrics::counter!( + "wcn_rpc_server_rpcs_dropped", + StringLabel<"server_name"> => self.inner.server_name + ) + .increment(1); + continue; + }; - #[error(transparent)] - UnknownRpc(#[from] UnknownRpcError), + // when we receive a stream there's always at least some data in it + let id = rx + .read_u8() + .now_or_never() + .ok_or_else(|| ErrorInner::ReadRpcId)? + .map_err(Error::new)?; - #[error("Transport: {0}")] - Transport(String), -} + let id = id.try_into().map_err(|_| ErrorInner::UnknownRpcId(id))?; -pub type RpcHandlerResult = Result; + return Ok(InboundRpc { + id, + stream: BiDirectionalStream::new(tx, rx), + permit, + }); + } + } -#[derive(Debug, thiserror::Error)] -pub enum ReadRpcIdError { - #[error("IO: {0:?}")] - IO(io::Error), + fn acquire_stream_permit(&self) -> Option { + metrics::gauge!("wcn_rpc_server_available_rpc_permits", StringLabel<"server_name"> => self.inner.server_name) + .set(self.inner.rpc_semaphore.available_permits() as f64); - #[error("Timeout")] - Timeout, + self.inner.rpc_semaphore.clone().try_acquire_owned().ok() + } } -#[derive(Debug, thiserror::Error)] -#[error("Unknown RPC (ID: {0})")] -pub struct UnknownRpcError(pub u8); - -/// RPC [`Client`] error. +/// RPC [`Server`] error. #[derive(Debug, thiserror::Error)] #[error(transparent)] pub struct Error(ErrorInner); -/// RPC [`Client`] result. +/// RPC [`Server`] result. pub type Result = std::result::Result; impl Error { @@ -505,18 +496,33 @@ enum ErrorInner { #[error("QUIC: {0}")] Quic(#[from] quic::Error), + #[error(transparent)] + ExtractPeerId(#[from] quic::ExtractPeerIdError), + #[error("Connection: {0:?}")] Connection(#[from] quinn::ConnectionError), #[error("Timeout establishing inbound connection")] ConnectionTimeout, - #[error("Timeout reading inbound connection header")] - ReadConnectionHeaderTimeout, + #[error("IO: {0:?}")] + Io(#[from] io::Error), + + #[error("Failed to read ConnectionHeader: {0:?}")] + ReadHeader(#[from] quinn::ReadExactError), + + #[error("Unsupported protocol version: {0}")] + UnsupportedProtocolVersion(u32), #[error("Unknown API: {0}")] UnknownApi(rpc::ApiName), #[error("Transport: {0}")] - Transport(#[from] transport::Error), + Transport(#[from] transport2::Error), + + #[error("Failed to read RPC ID without blocking")] + ReadRpcId, + + #[error("Unknown RPC ID: {0}")] + UnknownRpcId(u8), } diff --git a/crates/rpc/src/transport.rs b/crates/rpc/src/transport.rs index cc9ba8d9..2cf665e8 100644 --- a/crates/rpc/src/transport.rs +++ b/crates/rpc/src/transport.rs @@ -56,8 +56,8 @@ impl Codec for JsonCodec { /// Untyped bi-directional stream. pub struct BiDirectionalStream { - pub(crate) rx: RawRecvStream, - pub(crate) tx: RawSendStream, + rx: RawRecvStream, + tx: RawSendStream, } type RawSendStream = FramedWrite; diff --git a/crates/rpc/src/transport2.rs b/crates/rpc/src/transport2.rs new file mode 100644 index 00000000..d5acb8ae --- /dev/null +++ b/crates/rpc/src/transport2.rs @@ -0,0 +1,195 @@ +use { + crate::{Message, MessageV2}, + bytes::{BufMut as _, Bytes, BytesMut}, + futures::{stream::MapErr, Sink, TryStreamExt}, + pin_project::pin_project, + serde::{Deserialize, Serialize}, + std::{ + io, + pin::Pin, + task::{self, ready}, + }, + tokio_serde::{Deserializer, Framed, Serializer}, + tokio_stream::Stream, + tokio_util::codec::{FramedRead, FramedWrite, LengthDelimitedCodec}, +}; + +/// Serialization codec. +pub trait Codec: + Serializer> + + for<'a> Serializer> + + Deserializer> + + Unpin + + Default + + Send + + Sync + + 'static +{ +} + +impl Codec for C where + C: Serializer> + + for<'a> Serializer> + + Deserializer> + + Unpin + + Default + + Send + + Sync + + 'static +{ +} + +#[derive(Clone, Copy, Debug, Default)] +pub struct PostcardCodec; + +impl Deserializer for PostcardCodec +where + for<'a> T: Deserialize<'a>, +{ + type Error = io::Error; + + fn deserialize(self: Pin<&mut Self>, src: &BytesMut) -> Result { + postcard::from_bytes(&src).map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err)) + } +} + +impl Serializer for PostcardCodec +where + T: Serialize, +{ + type Error = io::Error; + + fn serialize(self: Pin<&mut Self>, data: &T) -> Result { + postcard::experimental::serialized_size(data) + .and_then(|size| postcard::to_io(data, BytesMut::with_capacity(size).writer())) + .map(|writer| writer.into_inner().freeze()) + .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err)) + } +} + +/// Untyped bi-directional stream. +pub struct BiDirectionalStream { + pub(crate) rx: RawRecvStream, + pub(crate) tx: RawSendStream, +} + +type RawSendStream = FramedWrite; +type RawRecvStream = FramedRead; + +impl BiDirectionalStream { + pub fn new(tx: quinn::SendStream, rx: quinn::RecvStream) -> Self { + Self { + tx: FramedWrite::new(tx, LengthDelimitedCodec::new()), + rx: FramedRead::new(rx, LengthDelimitedCodec::new()), + } + } + + pub(crate) fn upgrade>(self) -> (RecvStream, SendStream) { + ( + RecvStream(Framed::new(self.rx.map_err(Into::into), C::default())), + SendStream { + inner: self.tx, + codec: C::default(), + }, + ) + } +} + +/// [`Stream`] of outbound [`Message`]s. +#[pin_project(project = SendStreamProj)] +pub struct SendStream { + #[pin] + inner: RawSendStream, + #[pin] + codec: C, +} + +impl Sink<&T> for SendStream +where + C: Serializer>, +{ + type Error = Error; + + fn poll_ready( + self: Pin<&mut Self>, + cx: &mut task::Context<'_>, + ) -> task::Poll> { + self.project().inner.poll_ready(cx).map_err(Into::into) + } + + fn start_send(mut self: Pin<&mut Self>, item: &T) -> Result<(), Self::Error> { + let bytes = tokio_serde::Serializer::serialize(self.as_mut().project().codec, item) + .map_err(Into::into)?; + + self.as_mut().project().inner.start_send(bytes)?; + + Ok(()) + } + + fn poll_flush( + self: Pin<&mut Self>, + cx: &mut task::Context<'_>, + ) -> task::Poll> { + self.project().inner.poll_flush(cx).map_err(Into::into) + } + + fn poll_close( + mut self: Pin<&mut Self>, + cx: &mut task::Context<'_>, + ) -> task::Poll> { + ready!(self.as_mut().project().inner.poll_flush(cx))?; + self.project().inner.poll_close(cx).map_err(Into::into) + } +} + +/// [`Stream`] of inbound [`Message`]s. +#[pin_project] +pub struct RecvStream>( + #[allow(clippy::type_complexity)] + #[pin] + Framed Error>, T, T, C>, +); + +impl> Stream for RecvStream { + type Item = Result; + + fn poll_next( + self: Pin<&mut Self>, + cx: &mut task::Context<'_>, + ) -> task::Poll> { + self.project().0.poll_next(cx) + } + + fn size_hint(&self) -> (usize, Option) { + self.0.size_hint() + } +} + +#[derive(Clone, Debug, thiserror::Error, Eq, PartialEq)] +pub enum Error { + #[error("IO: {0:?}")] + IO(io::ErrorKind), + + #[error("Stream unexpectedly finished")] + StreamFinished, + + #[error("Codec: {_0}")] + Codec(String), + + #[error("{_0}")] + Other(String), +} + +impl From for Error { + fn from(err: io::Error) -> Self { + Self::IO(err.kind()) + } +} + +impl From for Error { + fn from(err: quinn::ConnectionError) -> Self { + Self::Other(format!("Connection: {err:?}")) + } +} + +pub type Result = std::result::Result; diff --git a/crates/storage_api2/src/lib.rs b/crates/storage_api2/src/lib.rs index a385407c..67bea47c 100644 --- a/crates/storage_api2/src/lib.rs +++ b/crates/storage_api2/src/lib.rs @@ -5,9 +5,8 @@ pub use { wcn_rpc::{identity, Multiaddr, PeerAddr, PeerId}, }; use { - derive_more::AsRef, futures::{FutureExt as _, TryFutureExt as _}, - std::{future::Future, marker::PhantomData, str::FromStr, time::Duration}, + std::{borrow::Cow, future::Future, str::FromStr, time::Duration}, time::OffsetDateTime as DateTime, }; @@ -15,9 +14,9 @@ pub mod operation; pub use operation::Operation; #[cfg(any(feature = "rpc_client", feature = "rpc_server"))] -pub mod rpc; +mod rpc; -/// Namespace within WCN network. +/// Namespace within a WCN cluster. /// /// Namespaces are isolated and every [`StorageApi`] [`Operation`] gets executed /// on a specific [`Namespace`]. @@ -32,6 +31,18 @@ pub struct Namespace { id: u8, } +/// Version of the keyspace of a WCN cluster. +/// +/// Keyspace changes after data rebalancing within a WCN Cluster. +/// For data consistency reasons WCN Coordinators and WCN Replicas need to +/// operate using same [`KeyspaceVersion`]. So for Coordinator->Replica +/// [`StorageApi`] calls [`Operation`]s need to include the expected +/// [`KeyspaceVersion`]. +/// +/// For Client->Coordinator and Replica->Database calls the [`KeyspaceVersion`] +/// validation is not required. +pub type KeyspaceVersion = u64; + /// WCN Storage API. /// /// Lingua franka of the WCN network: @@ -43,354 +54,125 @@ pub struct Namespace { /// servers). /// - Replicas use it to finally execute the operations on their local WCN /// Database instances. -pub trait StorageApi { - type Error: From; - +pub trait StorageApi: Clone + Send + Sync + 'static { /// Executes the provided [`operation::Get`]. - fn get( - &self, - get: operation::Get, - ) -> impl Future, Self::Error>> + Send { + fn get<'a>( + &'a self, + get: operation::Get<'a>, + ) -> impl Future>> + Send + 'a { self.execute(get).map(operation::Output::downcast_result) } /// Executes the provided [`operation::Set`]. - fn set(&self, set: operation::Set) -> impl Future> + Send { + fn set<'a>(&'a self, set: operation::Set<'a>) -> impl Future> + Send { self.execute(set).map(operation::Output::downcast_result) } /// Executes the provided [`operation::Del`]. - fn del(&self, del: operation::Del) -> impl Future> + Send { + fn del<'a>(&'a self, del: operation::Del<'a>) -> impl Future> + Send { self.execute(del).map(operation::Output::downcast_result) } /// Executes the provided [`operation::GetExp`]. - fn get_exp( - &self, - get_exp: operation::GetExp, - ) -> impl Future, Self::Error>> + Send { + fn get_exp<'a>( + &'a self, + get_exp: operation::GetExp<'a>, + ) -> impl Future>> + Send { self.execute(get_exp) .map(operation::Output::downcast_result) } /// Executes the provided [`operation::SetExp`]. - fn set_exp( - &self, - set_exp: operation::SetExp, - ) -> impl Future> + Send { + fn set_exp<'a>( + &'a self, + set_exp: operation::SetExp<'a>, + ) -> impl Future> + Send { self.execute(set_exp) .map(operation::Output::downcast_result) } /// Executes the provided [`operation::HGet`]. - fn hget( - &self, - hget: operation::HGet, - ) -> impl Future, Self::Error>> + Send { + fn hget<'a>( + &'a self, + hget: operation::HGet<'a>, + ) -> impl Future>> + Send { self.execute(hget).map(operation::Output::downcast_result) } /// Executes the provided [`operation::HSet`]. - fn hset(&self, hset: operation::HSet) -> impl Future> + Send { + fn hset<'a>(&'a self, hset: operation::HSet<'a>) -> impl Future> + Send { self.execute(hset).map(operation::Output::downcast_result) } /// Executes the provided [`operation::HDel`]. - fn hdel(&self, hdel: operation::HDel) -> impl Future> + Send { + fn hdel<'a>(&'a self, hdel: operation::HDel<'a>) -> impl Future> + Send { self.execute(hdel).map(operation::Output::downcast_result) } /// Executes the provided [`operation::HGetExp`]. - fn hget_exp( - &self, - hget_exp: operation::HGetExp, - ) -> impl Future, Self::Error>> + Send { + fn hget_exp<'a>( + &'a self, + hget_exp: operation::HGetExp<'a>, + ) -> impl Future>> + Send { self.execute(hget_exp) .map(operation::Output::downcast_result) } /// Executes the provided [`operation::HSetExp`]. - fn hset_exp( - &self, - hset_exp: operation::HSetExp, - ) -> impl Future> + Send { + fn hset_exp<'a>( + &'a self, + hset_exp: operation::HSetExp<'a>, + ) -> impl Future> + Send { self.execute(hset_exp) .map(operation::Output::downcast_result) } /// Executes the provided [`operation::HCard`]. - fn hcard( - &self, - hcard: operation::HCard, - ) -> impl Future> + Send { + fn hcard<'a>( + &'a self, + hcard: operation::HCard<'a>, + ) -> impl Future> + Send { self.execute(hcard).map(operation::Output::downcast_result) } /// Executes the provided [`operation::HScan`]. - fn hscan( - &self, - hscan: operation::HScan, - ) -> impl Future> + Send { + fn hscan<'a>( + &'a self, + hscan: operation::HScan<'a>, + ) -> impl Future> + Send { self.execute(hscan).map(operation::Output::downcast_result) } /// Executes the provided [`StorageApi`] [`Operation`]. - fn execute( - &self, - operation: impl Into + Send, - ) -> impl Future> + Send; - - /// Makes this [`StorageApi`] [`Namespaced`]. - fn namespaced(self, namespace: impl Into) -> Namespaced - where - Self: Sized, - { - Namespaced { - namespace: namespace.into(), - storage_api: self, - _marker: PhantomData, - } - } - - /// Makes this [`StorageApi`] [`Namespaced`] using references instead of - /// owned values. - fn namespaced_ref>(&self, namespace: N) -> Namespaced - where - Self: Sized, - { - Namespaced { - namespace, - storage_api: self, - _marker: PhantomData, - } - } -} - -/// A convienience wrapper around a [`StorageApi`] for client usage. -/// -/// Each function on this wrapper has the same arguments as the respective -/// [`Operation`] constructor with [`Namespace`] being automatically specified. -#[derive(Clone, Debug)] -pub struct Namespaced> { - namespace: N, - storage_api: T, - _marker: PhantomData, -} - -/// Owned [`StorageApi`]. -/// -/// Required to make [`Namespaced`] generic over ownership. -pub struct Owned(S); - -impl Namespaced -where - N: AsRef, - T: AsRef, - S: StorageApi, -{ - /// Returns reference to the underlying [`Namespace`]. - pub fn namespace(&self) -> &Namespace { - self.namespace.as_ref() - } - - /// Returns reference to the underlying [`StorageApi`]. - pub fn storage_api(&self) -> &S { - self.storage_api.as_ref() - } - - /// Gets a [`Record`] by the provided [`Key`]. - pub async fn get(&self, key: Key>) -> Result, S::Error> { - self.storage_api() - .get(operation::Get::new(*self.namespace(), key)) - .await - } - - /// Sets a new [`Entry`]. - async fn set( - &self, - key: Key>, - value: Value>, - expiration: impl Into, - ) -> Result<(), S::Error> { - let namespace = *self.namespace(); - self.storage_api() - .set(operation::Set::new(namespace, key, value, expiration)) - .await - } - - /// Deletes an [`Entry`] by the provided [`Key`]. - async fn del(&self, key: Key>) -> Result<(), S::Error> { - self.storage_api() - .del(operation::Del::new(*self.namespace(), key)) - .await - } - - /// Gets an [`EntryExpiration`] by the provided [`Key`]. - async fn get_exp( - &self, - key: Key>, - ) -> Result, S::Error> { - self.storage_api() - .get_exp(operation::GetExp::new(*self.namespace(), key)) - .await - } - - /// Sets [`EntryExpiration`] on the [`Entry`] with the provided [`Key`]. - async fn set_exp( - &self, - key: Key>, - expiration: impl Into, - ) -> Result<(), S::Error> { - self.storage_api() - .set_exp(operation::SetExp::new(*self.namespace(), key, expiration)) - .await - } - - /// Gets a map [`Record`] by the provided [`Key`] and [`Field`]. - async fn hget( - &self, - key: Key>, - field: Field>, - ) -> Result, S::Error> { - self.storage_api() - .hget(operation::HGet::new(*self.namespace(), key, field)) - .await - } - - /// Sets a new [`MapEntry`]. - async fn hset( - &self, - key: Key>, - field: Field>, - value: Value>, - expiration: impl Into, - ) -> Result<(), S::Error> { - let namespace = *self.namespace(); - self.storage_api() - .hset(operation::HSet::new( - namespace, key, value, field, expiration, - )) - .await - } - - /// Deletes a [`MapEntry`] by the provided [`Key`] and [`Field`]. - async fn hdel( - &self, - key: Key>, - field: Field>, - ) -> Result<(), S::Error> { - self.storage_api() - .hdel(operation::HDel::new(*self.namespace(), key, field)) - .await - } - - /// Gets a [`EntryExpiration`] by the provided [`Key`] and [`Field`]. - async fn hget_exp( - &self, - key: Key>, - field: Field>, - ) -> Result, S::Error> { - self.storage_api() - .hget_exp(operation::HGetExp::new(*self.namespace(), key, field)) - .await - } - - /// Sets [`Expiration`] on the [`MapEntry`] with the provided [`Key`] and - /// [`Field`]. - async fn hset_exp( - &self, - key: Key>, - field: Field>, - expiration: impl Into, - ) -> Result<(), S::Error> { - let namespace = *self.namespace(); - self.storage_api() - .hset_exp(operation::HSetExp::new(namespace, key, field, expiration)) - .await - } - - /// Returns cardinality of the map with the provided [`Key`]. - async fn hcard(&self, key: Key>) -> Result { - self.storage_api() - .hcard(operation::HCard::new(*self.namespace(), key)) - .await - } - - /// Returns a [`MapPage`] by iterating over the [`Field`]s of the map with - /// the provided [`Key`]. - async fn hscan( - &self, - key: Key>, - count: impl Into, - cursor: Option>>, - ) -> Result { - self.storage_api() - .hscan(operation::HScan::new(*self.namespace(), key, count, cursor)) - .await - } - - /// Returns [`Value`]s of the map with the provided [`Key`]. - async fn hvals(&self, key: Key>) -> Result, S::Error> { - // `1000` is generous, relay has ~100 limit for these small maps - self.hscan(key, 1000u32, None::) - .map_ok(|page| page.records.into_iter().map(|rec| rec.value).collect()) - .await - } + fn execute<'a>( + &'a self, + operation: impl Into> + Send, + ) -> impl Future> + Send; } /// Raw bytes. -pub type Bytes = Vec; +pub type Bytes<'a> = Cow<'a, [u8]>; /// Key in a KV storage. #[derive(Clone, Debug)] -pub struct Key(pub T); - -impl Key { - /// Converts `Self` into `Key`. - pub fn convert(self) -> Key - where - T: Into, - { - Self(self.into()) - } -} +pub struct Key<'a>(pub Bytes<'a>); /// Value in a KV storage. -#[derive(Clone, Debug)] -pub struct Value(pub T); - -impl Value { - /// Converts `Self` into `Value`. - pub fn convert(self) -> Value - where - T: Into, - { - Self(self.into()) - } -} +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct Value<'a>(pub Bytes<'a>); /// Subkey of a [`MapEntry`]. -#[derive(Clone, Debug)] -pub struct Field(pub T); - -impl Field { - /// Converts `Self` into `Field`. - pub fn convert(self) -> Value - where - T: Into, - { - Self(self.into()) - } -} +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct Field<'a>(pub Bytes<'a>); /// Basic KV storage entry. #[derive(Clone, Debug)] -pub struct Entry { +pub struct Entry<'a> { /// [`Key`] of this [`Entry`]. - pub key: Key, + pub key: Key<'a>, /// [`Value`] of this [`Entry`]. - pub value: Value, + pub value: Value<'a>, /// Expiration time of this [`Entry`]. pub expiration: EntryExpiration, @@ -399,34 +181,18 @@ pub struct Entry { pub version: EntryVersion, } -impl Entry { - /// Creates a new [`Entry`]. - pub fn new( - key: Key>, - value: Value>, - expiration: impl Into, - ) -> Self { - Self { - key: key.convert(), - value: value.convert(), - expiration: expiration.into(), - version: EntryVersion::new(), - } - } -} - /// Map entry in which each [`Value`] is associated with both [`Key`] and subkey /// ([`Field`]). #[derive(Clone, Debug)] -pub struct MapEntry { +pub struct MapEntry<'a> { /// [`Key`] of this [`Entry`]. - pub key: Key, + pub key: Key<'a>, /// [`Field`] of this [`Entry`]. - pub field: Field, + pub field: Field<'a>, /// [`Value`] of this [`Entry`]. - pub value: Value, + pub value: Value<'a>, /// Expiration time of this [`Entry`]. pub expiration: EntryExpiration, @@ -435,29 +201,11 @@ pub struct MapEntry { pub version: EntryVersion, } -impl MapEntry { - /// Creates a new [`MapEntry`]. - pub fn new( - key: Key>, - field: Field>, - value: Value>, - expiration: impl Into, - ) -> Self { - Self { - key: key.convert(), - field: field.convert(), - value: value.convert(), - expiration: expiration.into(), - version: EntryVersion::new(), - } - } -} - /// [`Entry`]/[`MapEntry`] without the associated [`Key`]/[`Field`]. #[derive(Clone, Debug, Eq, PartialEq)] pub struct Record { /// Value of this [`Record`]. - pub value: Value, + pub value: Value<'static>, /// Expiration time of the associated [`Entry`]/[`MapEntry`]. pub expiration: EntryExpiration, @@ -467,13 +215,13 @@ pub struct Record { } /// [`MapEntry`] without the associated [`Key`]. -#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Debug, PartialEq, Eq)] pub struct MapRecord { /// Field of this [`MapRecord`]. - pub field: Field, + pub field: Field<'static>, /// Value of this [`MapRecord`]. - pub value: Value, + pub value: Value<'static>, /// Expiration time of the associated [`MapEntry`]. pub expiration: EntryExpiration, @@ -572,30 +320,97 @@ impl MapPage { } } -impl AsRef for Owned { - fn as_ref(&self) -> &S { - &self.0 - } -} - -impl AsRef for Namespace { - fn as_ref(&self) -> &Namespace { - self - } -} - impl FromStr for Namespace { type Err = InvalidNamespaceError; fn from_str(s: &str) -> Result { + use InvalidNamespaceError as Error; + let mut parts = s.split('/'); - let addr = parts.next()?; - // const_hex::decode_to_array(input) - todo!() + let (operator_id, id) = (|| Some((parts.next()?, parts.next()?)))() + .ok_or(Error("Not enough components".into()))?; + + if parts.next().is_some() { + return Err(Error("Too many components".into())); + } + + Ok(Self { + node_operator_id: const_hex::decode_to_array(operator_id) + .map_err(|err| Error(format!("Invalid node operator id: {err}").into()))?, + id: id + .parse() + .map_err(|err| Error(format!("Invalid id: {err}").into()))?, + }) } } #[derive(Debug, thiserror::Error)] #[error("Invalid namespace: {_0}")] -pub struct InvalidNamespaceError(String); +pub struct InvalidNamespaceError(Cow<'static, str>); + +/// Result of [`StorageApi`]. +pub type Result = std::result::Result; + +/// Error of [`StorageApi`]. +#[derive(Debug, thiserror::Error)] +#[error("{kind:?}({details:?})")] +pub struct Error { + kind: ErrorKind, + details: Option, +} + +impl Error { + /// Returns [`ErrorKind`] of this [`Error`]. + pub fn kind(&self) -> ErrorKind { + self.kind + } +} + +/// [`Error`] kind. +#[derive(Clone, Copy, Debug)] +pub enum ErrorKind { + /// Client is not authorized to perfrom an [`Operation`]. + Unauthorized, + + /// [`KeyspaceVersion`] mismatch. + KeyspaceVersionMismatch, + + /// [`Operation`] timeout. + Timeout, + + /// Internal error. + Internal, + + /// Transport error. + Transport, + + // NOTE: This is effectively a bug, it's here just for completeness. + /// [`operation::WrongOutputError`]. + WrongOperationOutput, + + /// Unable to determine [`ErrorKind`] of an [`Error`]. + Unknown, +} + +impl Error { + /// Creates a new [`Error`]. + fn new(kind: ErrorKind, details: Option) -> Self { + Self { kind, details } + } +} + +impl From for Error { + fn from(kind: ErrorKind) -> Self { + Self { + kind, + details: None, + } + } +} + +#[cfg(test)] +#[test] +fn test_namespace_from_str() { + todo!() +} diff --git a/crates/storage_api2/src/operation.rs b/crates/storage_api2/src/operation.rs index e69aac90..7458be38 100644 --- a/crates/storage_api2/src/operation.rs +++ b/crates/storage_api2/src/operation.rs @@ -2,18 +2,17 @@ use { crate::{ - Bytes, Entry, EntryExpiration, EntryVersion, Field, Key, + KeyspaceVersion, MapEntry, MapPage, MapRecord, Namespace, Record, - Value, }, derive_more::derive::{From, TryInto}, std::any::type_name, @@ -25,20 +24,20 @@ use { #[derive(Clone, Debug, From, EnumDiscriminants)] #[strum_discriminants(name(Name))] #[strum_discriminants(derive(Ordinalize))] -pub enum Operation { - Get(Get), - Set(Set), - Del(Del), - GetExp(GetExp), - SetExp(SetExp), - - HGet(HGet), - HSet(HSet), - HDel(HDel), - HGetExp(HGetExp), - HSetExp(HSetExp), - HCard(HCard), - HScan(HScan), +pub enum Operation<'a> { + Get(Get<'a>), + Set(Set<'a>), + Del(Del<'a>), + GetExp(GetExp<'a>), + SetExp(SetExp<'a>), + + HGet(HGet<'a>), + HSet(HSet<'a>), + HDel(HDel<'a>), + HGetExp(HGetExp<'a>), + HSetExp(HSetExp<'a>), + HCard(HCard<'a>), + HScan(HScan<'a>), } impl metrics::Enum for Name { @@ -60,14 +59,14 @@ impl metrics::Enum for Name { } } -impl Operation { +impl<'a> Operation<'a> { /// Returns [`Name`] of this [`Operation`]. pub fn name(&self) -> Name { self.discriminant() } - /// Returns [`Key`] of this [`Operation`]. - pub fn key(&self) -> &Key { + /// Returns key of this [`Operation`]. + pub fn key(&self) -> &Key<'a> { match self { Self::Get(get) => &get.key, Self::Set(set) => &set.entry.key, @@ -87,269 +86,112 @@ impl Operation { /// Gets a [`Record`] by the provided [`Key`]. #[derive(Clone, Debug)] -pub struct Get { +pub struct Get<'a> { pub namespace: Namespace, - pub key: Key, -} - -impl Get { - /// Creates a new [`Get`] operation. - pub fn new(namespace: impl Into, key: Key>) -> Self { - Self { - namespace: namespace.into(), - key: key.into(), - } - } + pub key: Key<'a>, + pub keyspace_version: Option, } /// Sets a new [`Entry`]. #[derive(Clone, Debug)] -pub struct Set { +pub struct Set<'a> { pub namespace: Namespace, - pub entry: Entry, -} - -impl Set { - /// Creates a new [`Set`] operation. - pub fn new( - namespace: impl Into, - key: Key>, - value: Value>, - expiration: impl Into, - ) -> Self { - Self { - namespace: namespace.into(), - entry: Entry::new(key, value, expiration), - } - } + pub entry: Entry<'a>, + pub keyspace_version: Option, } /// Deletes an [`Entry`] by the provided [`Key`]. #[derive(Clone, Debug)] -pub struct Del { +pub struct Del<'a> { pub namespace: Namespace, - pub key: Key, + pub key: Key<'a>, pub version: EntryVersion, -} - -impl Del { - /// Creates a new [`Del`] operation. - pub fn new(namespace: impl Into, key: Key>) -> Self { - Self { - namespace: namespace.into(), - key: key.into(), - version: EntryVersion::new(), - } - } + pub keyspace_version: Option, } /// Gets an [`EntryExpiration`] by the provided [`Key`]. #[derive(Clone, Debug)] -pub struct GetExp { +pub struct GetExp<'a> { pub namespace: Namespace, - pub key: Key, -} - -impl GetExp { - /// Creates a new [`GetExp`] operation. - pub fn new(namespace: impl Into, key: Key>) -> Self { - Self { - namespace: namespace.into(), - key: key.into(), - } - } + pub key: Key<'a>, + pub keyspace_version: Option, } /// Sets [`EntryExpiration`] on the [`Entry`] with the provided [`Key`]. #[derive(Clone, Debug)] -pub struct SetExp { +pub struct SetExp<'a> { pub namespace: Namespace, - pub key: Key, + pub key: Key<'a>, pub expiration: EntryExpiration, pub version: EntryVersion, -} - -impl SetExp { - /// Creates a new [`SetExp`] operation. - pub fn new( - namespace: impl Into, - key: Key>, - expiration: impl Into, - ) -> Self { - Self { - namespace: namespace.into(), - key: key.into(), - expiration: expiration.into(), - version: EntryVersion::new(), - } - } + pub keyspace_version: Option, } /// Gets a map [`Record`] by the provided [`Key`] and [`Field`]. #[derive(Clone, Debug)] -pub struct HGet { +pub struct HGet<'a> { pub namespace: Namespace, - pub key: Key, - pub field: Field, -} - -impl HGet { - /// Creates a new [`HGet`] operation. - pub fn new( - namespace: impl Into, - key: Key>, - field: Field>, - ) -> Self { - Self { - namespace: namespace.into(), - key: key.into(), - field: field.convert(), - } - } + pub key: Key<'a>, + pub field: Field<'a>, + pub keyspace_version: Option, } /// Sets a new [`MapEntry`]. #[derive(Clone, Debug)] -pub struct HSet { +pub struct HSet<'a> { pub namespace: Namespace, - pub entry: MapEntry, -} - -impl HSet { - /// Creates a new [`HSet`] operation. - pub fn new( - namespace: impl Into, - key: Key>, - value: Value>, - field: Field>, - expiration: impl Into, - ) -> Self { - Self { - namespace: namespace.into(), - entry: MapEntry::new(key, field, value, expiration), - } - } + pub entry: MapEntry<'a>, + pub keyspace_version: Option, } /// Deletes a [`MapEntry`] by the provided [`Key`] and [`Field`]. #[derive(Clone, Debug)] -pub struct HDel { +pub struct HDel<'a> { pub namespace: Namespace, - pub key: Key, - pub field: Field, + pub key: Key<'a>, + pub field: Field<'a>, pub version: EntryVersion, -} - -impl HDel { - /// Creates a new [`HDel`] operation. - pub fn new( - namespace: impl Into, - key: Key>, - field: Field>, - ) -> Self { - Self { - namespace: namespace.into(), - key: key.into(), - field: field.convert(), - version: EntryVersion::new(), - } - } + pub keyspace_version: Option, } /// Gets a [`EntryExpiration`] by the provided [`Key`] and [`Field`]. #[derive(Clone, Debug)] -pub struct HGetExp { +pub struct HGetExp<'a> { pub namespace: Namespace, - pub key: Key, - pub field: Field, -} - -impl HGetExp { - /// Creates a new [`HGetExp`] operation. - pub fn new( - namespace: impl Into, - key: Key>, - field: Field>, - ) -> Self { - Self { - namespace: namespace.into(), - key: key.into(), - field: field.convert(), - } - } + pub key: Key<'a>, + pub field: Field<'a>, + pub keyspace_version: Option, } /// Sets [`Expiration`] on the [`MapEntry`] with the provided [`Key`] and /// [`Field`]. #[derive(Clone, Debug)] -pub struct HSetExp { +pub struct HSetExp<'a> { pub namespace: Namespace, - pub key: Key, - pub field: Field, + pub key: Key<'a>, + pub field: Field<'a>, pub expiration: EntryExpiration, pub version: EntryVersion, -} - -impl HSetExp { - /// Creates a new [`HSetExp`] operation. - pub fn new( - namespace: impl Into, - key: Key>, - field: Field>, - expiration: impl Into, - ) -> Self { - Self { - namespace: namespace.into(), - key: key.into(), - field: field.convert(), - expiration: expiration.into(), - version: EntryVersion::new(), - } - } + pub keyspace_version: Option, } /// Returns cardinality of the map with the provided [`Key`]. #[derive(Clone, Debug)] -pub struct HCard { +pub struct HCard<'a> { pub namespace: Namespace, - pub key: Key, -} - -impl HCard { - /// Creates a new [`HCard`] operation. - pub fn new(namespace: impl Into, key: Key>) -> Self { - Self { - namespace: namespace.into(), - key: key.into(), - } - } + pub key: Key<'a>, + pub keyspace_version: Option, } /// Returns a [`MapPage`] by iterating over the [`Field`]s of the map with /// the provided [`Key`]. #[derive(Clone, Debug)] -pub struct HScan { +pub struct HScan<'a> { pub namespace: Namespace, - pub key: Key, + pub key: Key<'a>, pub count: u32, - pub cursor: Option, -} - -impl HScan { - /// Creates a new [`HCard`] operation. - pub fn new( - namespace: impl Into, - key: Key>, - count: impl Into, - cursor: Option>>, - ) -> Self { - Self { - namespace: namespace.into(), - key: key.into(), - count: count.into(), - cursor: cursor.map(Field::convert), - } - } + pub cursor: Option>, + pub keyspace_version: Option, } /// [`Operation`] output. @@ -377,11 +219,11 @@ impl Output { pub fn downcast_result(operation_result: Result) -> Result where Self: TryInto>, - WrongOutput: Into, + WrongOutputError: Into, { operation_result? .try_into() - .map_err(|err| WrongOutput { + .map_err(|err| WrongOutputError { expected: type_name::(), got: err.input.discriminant(), }) @@ -391,7 +233,16 @@ impl Output { #[derive(Clone, Debug, thiserror::Error)] #[error("Wrong operation output (expected: {expected}, got: {got})")] -pub struct WrongOutput { +pub struct WrongOutputError { expected: &'static str, got: OutputName, } + +impl From for crate::Error { + fn from(err: WrongOutputError) -> Self { + Self::new( + crate::ErrorKind::WrongOperationOutput, + Some(format!("{err}")), + ) + } +} diff --git a/crates/storage_api2/src/rpc/client.rs b/crates/storage_api2/src/rpc/client.rs index c1912cdf..cef0ed41 100644 --- a/crates/storage_api2/src/rpc/client.rs +++ b/crates/storage_api2/src/rpc/client.rs @@ -1,388 +1,297 @@ use { super::*, - crate::{operation, MapPage, MapRecord, Operation, Record, StorageApi}, + crate::{operation, MapPage, Operation, Record, Result}, futures::SinkExt, - std::{collections::HashSet, result::Result as StdResult, time::Duration}, - wcn_rpc::{ - client::middleware::{MeteredExt, Timeouts, WithTimeouts, WithTimeoutsExt as _}, - identity::Keypair, - middleware::Metered, - transport::{self, NoHandshake}, - PeerAddr, - }, + std::future::Future, + wcn_rpc::client2::{Connection, DefaultConnectionHandler, DefaultRpcHandler}, }; -/// Storage API RPC client. -#[derive(Clone)] -pub struct Client { - inner: Inner, +impl wcn_rpc::client2::Api for StorageApi +where + Self: Api, +{ + type ConnectionParameters = (); + type ConnectionHandler = DefaultConnectionHandler; + // type RpcHandler = DefaultRpcHandler; } -type Inner = Metered>; - -/// [`Client`] config. -#[derive(Clone, Debug)] -pub struct Config { - /// [`Keypair`] of the [`Client`]. - pub keypair: Keypair, - - /// Name of the RPC server the [`Client`] is supposed to connect to. - pub server_name: rpc::ServerName, - - /// Timeout of establishing a network connection. - pub connection_timeout: Duration, - - /// Timeout of a [`Client`] RPC call. - pub rpc_timeout: Duration, - - /// Additional label to be used for all metrics of the [`Server`]. - pub metrics_tag: &'static str, -} - -impl Config { - pub fn new(server_name: rpc::ServerName) -> Self { - Self { - keypair: Keypair::generate_ed25519(), - server_name, - connection_timeout: Duration::from_secs(5), - rpc_timeout: Duration::from_secs(10), - metrics_tag: "default", - } - } - - /// Overwrites [`Config::keypair`]. - pub fn with_keypair(mut self, keypair: Keypair) -> Self { - self.keypair = keypair; - self - } - - /// Overwrites [`Config::keypair`]. - pub fn with_keypair(mut self, keypair: Keypair) -> Self { - self.keypair = keypair; - self - } - - /// Overwrites [`Config::connection_timeout`]. - pub fn with_connection_timeout(mut self, timeout: Duration) -> Self { - self.connection_timeout = timeout; - self - } - - /// Overwrites [`Config::operation_timeout`]. - pub fn with_operation_timeout(mut self, timeout: Duration) -> Self { - self.rpc_timeout = timeout; - self - } - - pub fn with_max_attempts(mut self, max_attempts: usize) -> Self { - self.max_attempts = max_attempts; - self - } - - /// Overwrites [`Config::metrics_tag`]. - pub fn with_metrics_tag(mut self, tag: &'static str) -> Self { - self.metrics_tag = tag; - self - } +async fn f(f: F) -> F::Output { + f.await } -impl Client { - /// Creates a new [`Client`]. - pub fn new(config: Config) -> StdResult { - let rpc_client_config = wcn_rpc::client::Config { - keypair: config.keypair, - known_peers: HashSet::new(), - handshake: NoHandshake, - connection_timeout: config.connection_timeout, - server_name: config.server_name, - priority: transport::Priority::High, +impl crate::StorageApi for Connection> +where + StorageApi: wcn_rpc::client2::Api< + ConnectionParameters = (), + ConnectionHandler = DefaultConnectionHandler, + // RpcHandler = DefaultRpcHandler, + >, +{ + fn get<'a>( + &'a self, + get: operation::Get<'a>, + ) -> impl Future>> + Send { + let req = GetRequest { + namespace: get.namespace.into(), + // key: get.key.0.into_owned().into(), + keyspace_version: get.keyspace_version, }; - let timeouts = Timeouts::new().with_default(config.rpc_timeout); - - let rpc_client = wcn_rpc::quic::Client::new(rpc_client_config) - .map_err(|err| CreationError(err.to_string()))? - .with_timeouts(timeouts) - .metered_with_tag(config.metrics_tag); - - Ok(Self { inner: rpc_client }) - } + async move { + let opt = Get::send(self, DefaultRpcHandler(&req))?.await??; - pub fn remote_storage<'a>(&'a self, server_addr: &'a PeerAddr) -> RemoteStorage<'a> { - RemoteStorage { - client: self, - server_addr, - expected_keyspace_version: None, - } - } -} - -/// Handle to a remote Storage API (Server). -#[derive(Clone, Copy)] -pub struct RemoteStorage<'a> { - client: &'a Client, - server_addr: &'a PeerAddr, - expected_keyspace_version: Option, -} - -impl RemoteStorage<'_> { - fn rpc_client(&self) -> &Inner { - &self.client.inner - } - - fn context(&self, namespace: &Namespace) -> Context { - Context { - namespace_node_operator_id: namespace.node_operator_id, - namespace_id: namespace.id, - keyspace_version: self.expected_keyspace_version, - } - } - - /// Specifies the expected version of the keyspace of the [`RemoteStorage`]. - pub fn expecting_keyspace_version(mut self, version: u64) -> Self { - self.expected_keyspace_version = Some(version); - self - } -} - -impl<'a> StorageApi for RemoteStorage<'a> { - type Error = Error; - - async fn get(&self, get: operation::Get) -> Result> { - Get::send(self.rpc_client(), self.server_addr, &GetRequest { - context: self.context(&get.namespace), - key: get.key.into(), - }) - .await - .map(|opt| { - opt.map(|resp| Record { - value: resp.value.into(), + Ok::<_, crate::Error>(opt.map(|resp| Record { + value: Value(resp.value), expiration: resp.expiration.into(), version: resp.version.into(), - }) - }) - .map_err(Into::into) + })) + } } - async fn set(&self, set: operation::Set) -> Result<()> { - Set::send(self.rpc_client(), self.server_addr, &SetRequest { - context: self.context(&set.namespace), - key: set.entry.key.into(), - value: set.entry.value.into(), - expiration: set.entry.expiration.into(), - version: set.entry.version.into(), - }) - .await - .map_err(Into::into) + async fn set(&self, set: operation::Set<'_>) -> Result<()> { + todo!() } - async fn set_exp(&self, set_exp: operation::SetExp) -> Result<()> { - SetExp::send(self.rpc_client(), self.server_addr, &SetExpRequest { - context: self.context(&set_exp.namespace), - key: set_exp.key.into(), - expiration: set_exp.expiration.into(), - version: set_exp.version.into(), - }) - .await - .map_err(Into::into) + async fn del(&self, del: operation::Del<'_>) -> Result<()> { + todo!() } - async fn del(&self, del: operation::Del) -> Result<()> { - Del::send(self.rpc_client(), self.server_addr, &DelRequest { - context: self.context(&del.namespace), - key: del.key.into(), - version: del.version.into(), - }) - .await - .map_err(Into::into) + async fn get_exp(&self, get_exp: operation::GetExp<'_>) -> Result> { + todo!() } - async fn get_exp(&self, get_exp: operation::GetExp) -> Result> { - GetExp::send(self.rpc_client(), self.server_addr, &GetExpRequest { - context: self.context(&get_exp.namespace), - key: get_exp.key.into(), - }) - .await - .map(|opt| opt.map(|resp| EntryExpiration::from(resp.expiration))) - .map_err(Into::into) + async fn set_exp(&self, set_exp: operation::SetExp<'_>) -> Result<()> { + todo!() } - async fn hget(&self, hget: operation::HGet) -> Result> { - HGet::send(self.rpc_client(), self.server_addr, &HGetRequest { - context: self.context(&hget.namespace), - key: hget.key.into(), - field: hget.field.into(), - }) - .await - .map(|opt| { - opt.map(|resp| Record { - value: resp.value.into(), - expiration: resp.expiration.into(), - version: resp.version.into(), - }) - }) - .map_err(Into::into) + async fn hget(&self, hget: operation::HGet<'_>) -> Result> { + todo!() } - async fn hset(&self, hset: operation::HSet) -> Result<()> { - HSet::send(self.rpc_client(), self.server_addr, &HSetRequest { - context: self.context(&hset.namespace), - key: hset.entry.key.into(), - field: hset.entry.field.into(), - value: hset.entry.value.into(), - expiration: hset.entry.expiration.into(), - version: hset.entry.version.into(), - }) - .await - .map_err(Into::into) + async fn hset(&self, hset: operation::HSet<'_>) -> Result<()> { + todo!() } - async fn hdel(&self, hdel: operation::HDel) -> Result<()> { - HDel::send(self.rpc_client(), self.server_addr, &HDelRequest { - context: self.context(&hdel.namespace), - key: hdel.key.into(), - field: hdel.field.into(), - version: hdel.version.into(), - }) - .await - .map_err(Into::into) + async fn hdel(&self, hdel: operation::HDel<'_>) -> Result<()> { + todo!() } - async fn hget_exp(&self, hget_exp: operation::HGetExp) -> Result> { - HGetExp::send(self.rpc_client(), self.server_addr, &HGetExpRequest { - context: self.context(&hget_exp.namespace), - key: hget_exp.key.into(), - field: hget_exp.field.into(), - }) - .await - .map(|opt| opt.map(|resp| EntryExpiration::from(resp.expiration))) - .map_err(Into::into) + async fn hget_exp(&self, hget_exp: operation::HGetExp<'_>) -> Result> { + todo!() } - async fn hset_exp(&self, hset_exp: operation::HSetExp) -> Result<()> { - HSetExp::send(self.rpc_client(), self.server_addr, &HSetExpRequest { - context: self.context(&hset_exp.namespace), - key: hset_exp.key.into(), - field: hset_exp.field.into(), - expiration: hset_exp.expiration.into(), - version: hset_exp.version.into(), - }) - .await - .map_err(Into::into) + async fn hset_exp(&self, hset_exp: operation::HSetExp<'_>) -> Result<()> { + todo!() } - async fn hcard(&self, hcard: operation::HCard) -> Result { - HCard::send(self.rpc_client(), self.server_addr, &HCardRequest { - context: self.context(&hcard.namespace), - key: hcard.key.into(), - }) - .await - .map(|resp| resp.cardinality) - .map_err(Into::into) + async fn hcard(&self, hcard: operation::HCard<'_>) -> Result { + todo!() } - async fn hscan(&self, hscan: operation::HScan) -> Result { - let count = hscan.count; - - let resp = HScan::send(self.rpc_client(), self.server_addr, &HScanRequest { - context: self.context(&hscan.namespace), - key: hscan.key.into(), - count: hscan.count, - cursor: hscan.cursor.map(Into::into), - }) - .await - .map_err(Error::from)?; - - Ok(MapPage { - has_next: resp.records.len() >= count as usize, - records: resp - .records - .into_iter() - .map(|record| MapRecord { - field: record.field.into(), - value: record.value.into(), - expiration: EntryExpiration::from(record.expiration), - version: EntryVersion::from(record.version), - }) - .collect(), - }) + async fn hscan(&self, hscan: operation::HScan<'_>) -> Result { + todo!() } async fn execute( &self, - operation: impl Into + Send, + operation: impl Into> + Send, ) -> Result { - match operation.into() { - Operation::Get(get) => self.get(get).await.map(Into::into), - Operation::Set(set) => self.set(set).await.map(Into::into), - Operation::Del(del) => self.del(del).await.map(Into::into), - Operation::GetExp(get_exp) => self.get_exp(get_exp).await.map(Into::into), - Operation::SetExp(set_exp) => self.set_exp(set_exp).await.map(Into::into), - Operation::HGet(hget) => self.hget(hget).await.map(Into::into), - Operation::HSet(hset) => self.hset(hset).await.map(Into::into), - Operation::HDel(hdel) => self.hdel(hdel).await.map(Into::into), - Operation::HGetExp(hget_exp) => self.hget_exp(hget_exp).await.map(Into::into), - Operation::HSetExp(hset_exp) => self.hset_exp(hset_exp).await.map(Into::into), - Operation::HCard(hcard) => self.hcard(hcard).await.map(Into::into), - Operation::HScan(hscan) => self.hscan(hscan).await.map(Into::into), - } - } -} - -/// Error of [`Client::new`]. -#[derive(Clone, Debug, thiserror::Error)] -#[error("{_0}")] -pub struct CreationError(String); - -/// Error of a [`Client`] operation. -#[derive(Clone, Debug, PartialEq, Eq, Hash, thiserror::Error)] -pub enum Error { - /// Transport errort. - #[error("Transport: {_0}")] - Transport(String), - - /// Operation timed out. - #[error("Timeout")] - Timeout, - - /// Server is throttling. - #[error("Throttled")] - Throttled, - - /// Client is not authorized to perform the operation. - #[error("Unauthorized")] - Unauthorized, - - /// Keyspace versions of client and server don't match. - #[error("Keyspace version mismatch")] - KeyspaceVersionMismatch, - - /// Other client/server error. - #[error("{_0}")] - Other(String), -} - -impl From for Error { - fn from(err: wcn_rpc::client::Error) -> Self { - let rpc_err = match err { - wcn_rpc::client::Error::Transport(err) => return Self::Transport(err.to_string()), - wcn_rpc::client::Error::Rpc { error, .. } => error, - }; - - match rpc_err.code.as_ref() { - wcn_rpc::error_code::TIMEOUT => Self::Timeout, - error_code::KEYSPACE_VERSION_MISMATCH => Self::KeyspaceVersionMismatch, - error_code::UNAUTHORIZED => Self::Unauthorized, - _ => Self::Other(format!("{rpc_err:?}")), - } + todo!() } } -/// [`Client`] operation [`Result`]. -pub type Result = std::result::Result; - -impl From for Error { - fn from(err: operation::WrongOutput) -> Self { - Self::Other(err.to_string()) +// impl<'a> Storage for RemoteStorage<'a> { +// type Error = Error; + +// async fn get(&self, get: operation::Get) -> Result> { +// Get::send(self.rpc_client(), self.server_addr, &GetRequest { +// context: self.context(&get.namespace), +// key: get.key.into(), +// }) +// .await +// .map(|opt| { +// opt.map(|resp| Record { +// value: resp.value.into(), +// expiration: resp.expiration.into(), +// version: resp.version.into(), +// }) +// }) +// .map_err(Into::into) +// } + +// async fn set(&self, set: operation::Set) -> Result<()> { +// Set::send(self.rpc_client(), self.server_addr, &SetRequest { +// context: self.context(&set.namespace), +// key: set.entry.key.into(), +// value: set.entry.value.into(), +// expiration: set.entry.expiration.into(), +// version: set.entry.version.into(), +// }) +// .await +// .map_err(Into::into) +// } + +// async fn set_exp(&self, set_exp: operation::SetExp) -> Result<()> { +// SetExp::send(self.rpc_client(), self.server_addr, &SetExpRequest { +// context: self.context(&set_exp.namespace), +// key: set_exp.key.into(), +// expiration: set_exp.expiration.into(), +// version: set_exp.version.into(), +// }) +// .await +// .map_err(Into::into) +// } + +// async fn del(&self, del: operation::Del) -> Result<()> { +// Del::send(self.rpc_client(), self.server_addr, &DelRequest { +// context: self.context(&del.namespace), +// key: del.key.into(), +// version: del.version.into(), +// }) +// .await +// .map_err(Into::into) +// } + +// async fn get_exp(&self, get_exp: operation::GetExp) -> +// Result> { GetExp::send(self.rpc_client(), +// self.server_addr, &GetExpRequest { context: +// self.context(&get_exp.namespace), key: get_exp.key.into(), +// }) +// .await +// .map(|opt| opt.map(|resp| EntryExpiration::from(resp.expiration))) +// .map_err(Into::into) +// } + +// async fn hget(&self, hget: operation::HGet) -> Result> { +// HGet::send(self.rpc_client(), self.server_addr, &HGetRequest { +// context: self.context(&hget.namespace), +// key: hget.key.into(), +// field: hget.field.into(), +// }) +// .await +// .map(|opt| { +// opt.map(|resp| Record { +// value: resp.value.into(), +// expiration: resp.expiration.into(), +// version: resp.version.into(), +// }) +// }) +// .map_err(Into::into) +// } + +// async fn hset(&self, hset: operation::HSet) -> Result<()> { +// HSet::send(self.rpc_client(), self.server_addr, &HSetRequest { +// context: self.context(&hset.namespace), +// key: hset.entry.key.into(), +// field: hset.entry.field.into(), +// value: hset.entry.value.into(), +// expiration: hset.entry.expiration.into(), +// version: hset.entry.version.into(), +// }) +// .await +// .map_err(Into::into) +// } + +// async fn hdel(&self, hdel: operation::HDel) -> Result<()> { +// HDel::send(self.rpc_client(), self.server_addr, &HDelRequest { +// context: self.context(&hdel.namespace), +// key: hdel.key.into(), +// field: hdel.field.into(), +// version: hdel.version.into(), +// }) +// .await +// .map_err(Into::into) +// } + +// async fn hget_exp(&self, hget_exp: operation::HGetExp) -> +// Result> { HGetExp::send(self.rpc_client(), +// self.server_addr, &HGetExpRequest { context: +// self.context(&hget_exp.namespace), key: hget_exp.key.into(), +// field: hget_exp.field.into(), +// }) +// .await +// .map(|opt| opt.map(|resp| EntryExpiration::from(resp.expiration))) +// .map_err(Into::into) +// } + +// async fn hset_exp(&self, hset_exp: operation::HSetExp) -> Result<()> { +// HSetExp::send(self.rpc_client(), self.server_addr, &HSetExpRequest { +// context: self.context(&hset_exp.namespace), +// key: hset_exp.key.into(), +// field: hset_exp.field.into(), +// expiration: hset_exp.expiration.into(), +// version: hset_exp.version.into(), +// }) +// .await +// .map_err(Into::into) +// } + +// async fn hcard(&self, hcard: operation::HCard) -> Result { +// HCard::send(self.rpc_client(), self.server_addr, &HCardRequest { +// context: self.context(&hcard.namespace), +// key: hcard.key.into(), +// }) +// .await +// .map(|resp| resp.cardinality) +// .map_err(Into::into) +// } + +// async fn hscan(&self, hscan: operation::HScan) -> Result { +// let count = hscan.count; + +// let resp = HScan::send(self.rpc_client(), self.server_addr, +// &HScanRequest { context: self.context(&hscan.namespace), +// key: hscan.key.into(), +// count: hscan.count, +// cursor: hscan.cursor.map(Into::into), +// }) +// .await +// .map_err(Error::from)?; + +// Ok(MapPage { +// has_next: resp.records.len() >= count as usize, +// records: resp +// .records +// .into_iter() +// .map(|record| MapRecord { +// field: record.field.into(), +// value: record.value.into(), +// expiration: EntryExpiration::from(record.expiration), +// version: EntryVersion::from(record.version), +// }) +// .collect(), +// }) +// } + +// async fn execute( +// &self, +// operation: impl Into + Send, +// ) -> Result { +// match operation.into() { +// Operation::Get(get) => self.get(get).await.map(Into::into), +// Operation::Set(set) => self.set(set).await.map(Into::into), +// Operation::Del(del) => self.del(del).await.map(Into::into), +// Operation::GetExp(get_exp) => +// self.get_exp(get_exp).await.map(Into::into), +// Operation::SetExp(set_exp) => self.set_exp(set_exp).await.map(Into::into), +// Operation::HGet(hget) => self.hget(hget).await.map(Into::into), +// Operation::HSet(hset) => self.hset(hset).await.map(Into::into), +// Operation::HDel(hdel) => self.hdel(hdel).await.map(Into::into), +// Operation::HGetExp(hget_exp) => +// self.hget_exp(hget_exp).await.map(Into::into), +// Operation::HSetExp(hset_exp) => +// self.hset_exp(hset_exp).await.map(Into::into), +// Operation::HCard(hcard) => self.hcard(hcard).await.map(Into::into), +// Operation::HScan(hscan) => +// self.hscan(hscan).await.map(Into::into), } +// } +// } + +impl From for crate::Error { + fn from(err: wcn_rpc::client2::Error) -> Self { + Self::new( + crate::ErrorKind::Transport, + Some(format!("wcn_rpc::client::Error: {err}")), + ) } } diff --git a/crates/storage_api2/src/rpc/mod.rs b/crates/storage_api2/src/rpc/mod.rs index 83d8ec2c..ae5891a2 100644 --- a/crates/storage_api2/src/rpc/mod.rs +++ b/crates/storage_api2/src/rpc/mod.rs @@ -1,100 +1,163 @@ use { - crate::{EntryExpiration, EntryVersion, Namespace}, + crate::{Bytes, EntryExpiration, EntryVersion, Field, Key, Value}, + derive_more::derive::TryFrom, serde::{Deserialize, Serialize}, - wcn_rpc::{self as rpc}, + std::marker::PhantomData, + wcn_rpc::{self as rpc, Api, ApiName, MessageV2, PostcardCodec, StaticMessage}, }; #[cfg(feature = "rpc_client")] -pub mod client; -#[cfg(feature = "rpc_client")] -pub use client::Client; -#[cfg(feature = "rpc_server")] -pub mod server; +mod client; #[cfg(feature = "rpc_server")] -pub use server::Server; +mod server; + +#[derive(Clone, Copy, Debug, TryFrom)] +#[try_from(repr)] +#[repr(u8)] +pub enum Id { + Get = 0, + Set = 1, + Del = 2, + SetExp = 3, + GetExp = 4, + + HGet = 5, + HSet = 6, + HDel = 7, + HSetExp = 8, + HGetExp = 9, + HCard = 10, + HScan = 11, +} + +impl From for u8 { + fn from(id: Id) -> Self { + id as u8 + } +} -/// Storage API RPC server hosted by a WCN Replication Coordinator. -pub const COORDINATOR_RPC_SERVER_NAME: rpc::ServerName = - rpc::ServerName::new("StorageApiCoordinator"); +#[derive(Clone, Copy, Debug)] +pub struct StorageApi(PhantomData); -/// Storage API RPC server hosted by a WCN Replica. -pub const REPLICA_RPC_SERVER_NAME: rpc::ServerName = rpc::ServerName::new("StorageApiReplica"); +pub mod api_kind { + #[derive(Clone, Copy, Debug)] + pub struct Coordinator; -/// Storage API RPC server hosted by a WCN Database. -pub const DATABASE_RPC_SERVER_NAME: rpc::ServerName = rpc::ServerName::new("StorageApiDatabase"); + #[derive(Clone, Copy, Debug)] + pub struct Replica; -/// RPC error codes produced by this module. -mod error_code { - /// Client is not authorized to perform the operation. - pub const UNAUTHORIZED: &str = "unauthorized"; + #[derive(Clone, Copy, Debug)] + pub struct Database; +} - /// Keyspace versions of the client and the server don't match. - pub const KEYSPACE_VERSION_MISMATCH: &str = "keyspace_version_mismatch"; +pub type StorageApiCoordinator = StorageApi; - /// Provided key was invalid. - pub const INVALID_KEY: &str = "invalid_key"; +impl Api for StorageApiCoordinator { + const NAME: ApiName = ApiName::new("StorageApiCoordinator"); + type RpcId = Id; } -#[derive(Clone, Debug, Serialize, Deserialize)] -struct Context { - namespace_node_operator_id: [u8; 20], - namespace_id: u8, - keyspace_version: Option, +pub type StorageApiReplica = StorageApi; + +impl Api for StorageApiReplica { + const NAME: ApiName = ApiName::new("StorageApiReplica"); + type RpcId = Id; } -impl +pub type StorageApiDatabase = StorageApi; -#[derive(Debug, Serialize, Deserialize)] -struct Key(Vec); +impl Api for StorageApiDatabase { + const NAME: ApiName = ApiName::new("StorageApiDatabase"); + type RpcId = Id; +} -#[derive(Debug, Serialize, Deserialize)] -struct Value(Vec); +#[derive(Clone, Debug, Serialize, Deserialize)] +struct Namespace { + node_operator_id: [u8; 20], + id: u8, +} -#[derive(Debug, Serialize, Deserialize)] -struct Field(Vec); +type UnaryRpc = rpc::UnaryV2; -type Get = rpc::Unary<{ rpc::id(b"Get") }, GetRequest, Option>; +type Get = UnaryRpc<{ Id::Get as u8 }, GetRequest, Result>>; #[derive(Clone, Debug, Serialize, Deserialize)] struct GetRequest { - context: Context, - key: Key, + namespace: Namespace, + // key: Bytes<'static>, + keyspace_version: Option, +} + +impl Rpc for Get { + const ID: u8 = { Id::Get as u8 }; + type Request<'a> = GetRequest<'a>; + type Response<'a> = GetResponse<'a>; + type Codec = PostcardCodec; } +impl StaticMessage for GetRequest {} + +// impl MessageV2 for GetRequest<'static> { +// type Borrowed<'a> = GetRequest<'a>; +// } + #[derive(Clone, Debug, Serialize, Deserialize)] struct GetResponse { - context: Context, - value: Value, + namespace: Namespace, + value: Bytes<'static>, expiration: UnixTimestampSecs, version: UnixTimestampMicros, + + keyspace_version: Option, } -type Set = rpc::Unary<{ rpc::id(b"Set") }, SetRequest, ()>; +impl StaticMessage for GetResponse {} + +type Set = UnaryRpc<{ Id::Set as u8 }, SetRequest<'static>, Result<()>>; #[derive(Clone, Debug, Serialize, Deserialize)] -struct SetRequest { - context: Context, - key: Key, - value: Value, +struct SetRequest<'a> { + namespace: Namespace, + key: Bytes<'a>, + value: Bytes<'a>, expiration: UnixTimestampSecs, version: UnixTimestampMicros, + + keyspace_version: Option, } -type Del = rpc::Unary<{ rpc::id(b"Del") }, DelRequest, ()>; +impl MessageV2 for SetRequest<'static> { + type Borrowed<'a> = SetRequest<'a>; +} + +type Del = UnaryRpc<{ Id::Del as u8 }, DelRequest<'static>, Result<()>>; #[derive(Clone, Debug, Serialize, Deserialize)] -struct DelRequest { - context: Context, - key: Key, +struct DelRequest<'a> { + namespace: Namespace, + key: Bytes<'a>, version: UnixTimestampMicros, + + keyspace_version: Option, +} + +impl MessageV2 for DelRequest<'static> { + type Borrowed<'a> = DelRequest<'a>; } -type GetExp = rpc::Unary<{ rpc::id(b"GetExp") }, GetExpRequest, Option>; +type GetExp = + UnaryRpc<{ Id::GetExp as u8 }, GetExpRequest<'static>, Result>>; #[derive(Clone, Debug, Serialize, Deserialize)] -struct GetExpRequest { - context: Context, - key: Key, +struct GetExpRequest<'a> { + namespace: Namespace, + key: Bytes<'a>, + + keyspace_version: Option, +} + +impl MessageV2 for GetExpRequest<'static> { + type Borrowed<'a> = GetExpRequest<'a>; } #[derive(Clone, Debug, Serialize, Deserialize)] @@ -102,61 +165,96 @@ struct GetExpResponse { expiration: UnixTimestampSecs, } -type SetExp = rpc::Unary<{ rpc::id(b"SetExp") }, SetExpRequest, ()>; +impl StaticMessage for GetExpResponse {} + +type SetExp = UnaryRpc<{ Id::SetExp as u8 }, SetExpRequest<'static>, Result<()>>; #[derive(Clone, Debug, Serialize, Deserialize)] -struct SetExpRequest { - context: Context, - key: Key, +struct SetExpRequest<'a> { + namespace: Namespace, + key: Bytes<'a>, expiration: UnixTimestampSecs, version: UnixTimestampMicros, + + keyspace_version: Option, } -type HGet = rpc::Unary<{ rpc::id(b"HGet") }, HGetRequest, Option>; +impl MessageV2 for SetExpRequest<'static> { + type Borrowed<'a> = DelRequest<'a>; +} + +type HGet = UnaryRpc<{ Id::HGet as u8 }, HGetRequest<'static>, Result>>; #[derive(Clone, Debug, Serialize, Deserialize)] -struct HGetRequest { - context: Context, - key: Key, - field: Field, +struct HGetRequest<'a> { + namespace: Namespace, + key: Bytes<'a>, + field: Bytes<'a>, + + keyspace_version: Option, +} + +impl MessageV2 for HGetRequest<'static> { + type Borrowed<'a> = HGetRequest<'a>; } #[derive(Clone, Debug, Serialize, Deserialize)] struct HGetResponse { - value: Value, + value: Bytes<'static>, expiration: UnixTimestampSecs, version: UnixTimestampMicros, } -type HSet = rpc::Unary<{ rpc::id(b"HSet") }, HSetRequest, ()>; +impl StaticMessage for HGetResponse {} + +type HSet = UnaryRpc<{ Id::HSet as u8 }, HSetRequest<'static>, Result<()>>; #[derive(Clone, Debug, Serialize, Deserialize)] -struct HSetRequest { - context: Context, - key: Key, - field: Field, - value: Value, +struct HSetRequest<'a> { + namespace: Namespace, + key: Bytes<'a>, + field: Bytes<'a>, + value: Bytes<'a>, expiration: UnixTimestampSecs, version: UnixTimestampMicros, + + keyspace_version: Option, +} + +impl MessageV2 for HSetRequest<'static> { + type Borrowed<'a> = HSetRequest<'a>; } -type HDel = rpc::Unary<{ rpc::id(b"HDel") }, HDelRequest, ()>; +type HDel = UnaryRpc<{ Id::HDel as u8 }, HDelRequest<'static>, Result<()>>; #[derive(Clone, Debug, Serialize, Deserialize)] -struct HDelRequest { - context: Context, - key: Key, - field: Field, +struct HDelRequest<'a> { + namespace: Namespace, + key: Bytes<'a>, + field: Bytes<'a>, version: UnixTimestampMicros, + + keyspace_version: Option, } -type HGetExp = rpc::Unary<{ rpc::id(b"HGetExp") }, HGetExpRequest, Option>; +impl MessageV2 for HDelRequest<'static> { + type Borrowed<'a> = HDelRequest<'a>; +} + +type HGetExp = + UnaryRpc<{ Id::HGetExp as u8 }, HGetExpRequest<'static>, Result>>; #[derive(Clone, Debug, Serialize, Deserialize)] -struct HGetExpRequest { - context: Context, - key: Key, - field: Field, +struct HGetExpRequest<'a> { + namespace: Namespace, + key: Bytes<'a>, + field: Bytes<'a>, + + keyspace_version: Option, +} + +impl MessageV2 for HGetExpRequest<'static> { + type Borrowed<'a> = HGetExpRequest<'a>; } #[derive(Clone, Debug, Serialize, Deserialize)] @@ -164,23 +262,37 @@ struct HGetExpResponse { expiration: UnixTimestampSecs, } -type HSetExp = rpc::Unary<{ rpc::id(b"HSetExp") }, HSetExpRequest, ()>; +impl StaticMessage for HGetExpResponse {} + +type HSetExp = UnaryRpc<{ Id::HSetExp as u8 }, HSetExpRequest<'static>, Result<()>>; #[derive(Clone, Debug, Serialize, Deserialize)] -struct HSetExpRequest { - context: Context, - key: Key, - field: Field, +struct HSetExpRequest<'a> { + namespace: Namespace, + key: Bytes<'a>, + field: Bytes<'a>, expiration: UnixTimestampSecs, version: UnixTimestampMicros, + + keyspace_version: Option, +} + +impl MessageV2 for HSetExpRequest<'static> { + type Borrowed<'a> = HSetExpRequest<'a>; } -type HCard = rpc::Unary<{ rpc::id(b"HCard") }, HCardRequest, HCardResponse>; +type HCard = UnaryRpc<{ Id::HCard as u8 }, HCardRequest<'static>, Result>; #[derive(Clone, Debug, Serialize, Deserialize)] -struct HCardRequest { - context: Context, - key: Key, +struct HCardRequest<'a> { + namespace: Namespace, + key: Bytes<'a>, + + keyspace_version: Option, +} + +impl MessageV2 for HCardRequest<'static> { + type Borrowed<'a> = HCardRequest<'a>; } #[derive(Clone, Debug, Serialize, Deserialize)] @@ -188,14 +300,22 @@ struct HCardResponse { cardinality: u64, } -type HScan = rpc::Unary<{ rpc::id(b"HScan") }, HScanRequest, HScanResponse>; +impl StaticMessage for HCardResponse {} + +type HScan = UnaryRpc<{ Id::HScan as u8 }, HScanRequest<'static>, Result>; #[derive(Clone, Debug, Serialize, Deserialize)] -struct HScanRequest { - context: Context, - key: Key, +struct HScanRequest<'a> { + namespace: Namespace, + key: Bytes<'a>, count: u32, - cursor: Option, + cursor: Option>, + + keyspace_version: Option, +} + +impl MessageV2 for HScanRequest<'static> { + type Borrowed<'a> = HScanRequest<'a>; } #[derive(Clone, Debug, Serialize, Deserialize)] @@ -204,10 +324,12 @@ struct HScanResponse { has_more: bool, } +impl StaticMessage for HScanResponse {} + #[derive(Clone, Debug, Serialize, Deserialize)] struct HScanResponseRecord { - field: Field, - value: Value, + field: Bytes<'static>, + value: Bytes<'static>, expiration: UnixTimestampSecs, version: UnixTimestampMicros, } @@ -246,47 +368,96 @@ impl From for EntryVersion { } } -impl From for Namespace { - fn from(ctx: Context) -> Self { +impl From for Namespace { + fn from(ns: crate::Namespace) -> Self { Self { - node_operator_id: ctx.namespace_node_operator_id, - id: ctx.namespace_id, + node_operator_id: ns.node_operator_id, + id: ns.id, } } } -impl From for crate::Key { - fn from(key: Key) -> Self { - Self(key.0) +impl From for crate::Namespace { + fn from(ns: Namespace) -> Self { + Self { + node_operator_id: ns.node_operator_id, + id: ns.id, + } } } -impl From for Key { - fn from(key: crate::Key) -> Self { - Self(key.0) - } +#[derive(Clone, Debug, Serialize, Deserialize)] +struct Error { + code: u8, + details: Option, } -impl From for crate::Value { - fn from(value: Value) -> Self { - Self(value.0) +impl Error { + fn new(code: ErrorCode, details: Option) -> Self { + Self { + code: code as u8, + details, + } } } -impl From for Value { - fn from(value: crate::Value) -> Self { - Self(value.0) +impl From for Error { + fn from(code: ErrorCode) -> Self { + Self::new(code, None) } } -impl From for crate::Field { - fn from(field: Field) -> Self { - Self(field.0) +#[derive(TryFrom)] +#[try_from(repr)] +#[repr(u8)] +enum ErrorCode { + Internal = 0, + Unauthorized = 1, + KeyspaceVersionMismatch = 2, + Timeout = 3, +} + +type Result = std::result::Result; + +impl From for crate::Error { + fn from(err: Error) -> Self { + use crate::ErrorKind; + + let Ok(code) = ErrorCode::try_from(err.code) else { + return Self::new( + crate::ErrorKind::Unknown, + Some(format!("Unexpected error code: {}", err.code)), + ); + }; + + let kind = match code { + ErrorCode::Unauthorized => ErrorKind::Unauthorized, + ErrorCode::KeyspaceVersionMismatch => ErrorKind::KeyspaceVersionMismatch, + ErrorCode::Timeout => ErrorKind::Timeout, + ErrorCode::Internal => ErrorKind::Internal, + }; + + Self::new(kind, err.details) } } -impl From for Field { - fn from(field: crate::Field) -> Self { - Self(field.0) +impl From for Error { + fn from(err: crate::Error) -> Self { + use crate::ErrorKind; + + let code = match err.kind { + ErrorKind::Unauthorized => ErrorCode::Unauthorized, + ErrorKind::KeyspaceVersionMismatch => ErrorCode::KeyspaceVersionMismatch, + ErrorKind::Timeout => ErrorCode::Timeout, + + ErrorKind::Internal + | ErrorKind::Transport + | ErrorKind::WrongOperationOutput + | ErrorKind::Unknown => ErrorCode::Internal, + }; + + Error::new(code, err.details) } } + +impl StaticMessage for Error {} diff --git a/crates/storage_api2/src/rpc/server.rs b/crates/storage_api2/src/rpc/server.rs index 13bc9ae8..8a34d391 100644 --- a/crates/storage_api2/src/rpc/server.rs +++ b/crates/storage_api2/src/rpc/server.rs @@ -1,6 +1,6 @@ use { super::*, - crate::{operation, StorageApi}, + crate::operation, futures::SinkExt as _, std::{collections::HashSet, future::Future, sync::Arc, time::Duration}, wcn_rpc::{ @@ -10,7 +10,8 @@ use { ClientConnectionInfo, ConnectionInfo, }, - transport::{self, BiDirectionalStream, NoHandshake, PendingConnection, PostcardCodec}, + server2::{Connection, HandleConnection, HandleRpc, Inbound, Result}, + transport::{self, BiDirectionalStream, NoHandshake, PostcardCodec}, }, }; @@ -26,285 +27,262 @@ pub struct Config { pub operation_timeout: Duration, } -/// Storage API server. -pub trait Server: StorageApi + Clone + Send + Sync + 'static { - /// Checks whether the provided keyspace version matches the one of the [`Server`]. - fn validate_keyspace_version(&self, version: u64) -> bool; - - /// Converts this Storage API [`Server`] into an [`rpc::Server`]. - fn into_rpc_server(self, cfg: Config) -> impl rpc::Server { - let timeouts = Timeouts::new().with_default(cfg.operation_timeout); - - let rpc_server_config = wcn_rpc::server::Config { - name: cfg.name, - handshake: NoHandshake, - }; - - RpcServer { - api_server: self, - config: rpc_server_config, - } - .with_timeouts(timeouts) - .metered() - } -} - -struct RpcHandler<'a, S> { - api_server: &'a S, - conn_info: &'a ConnectionInfo<(), ()>, -} - -impl RpcHandler<'_, S> { - - async fn get(&self, req: GetRequest) -> wcn_rpc::Result> { - let record = self - .api_server - .get(operation::Get { - namespace: - key: self.prepare_key(req.key)?, - }) - .await - .map_err(Error::into_rpc_error)?; - - Ok(record.map(|rec| GetResponse { - value: rec.value, - expiration: rec.expiration.timestamp(), - version: rec.version.timestamp(), - })) - } - - async fn set(&self, req: SetRequest) -> wcn_rpc::Result<()> { - let entry = Entry { - key: self.prepare_key(req.key)?, - value: req.value, - expiration: EntryExpiration::from(req.expiration), - version: EntryVersion::from(req.version), - }; - - self.api_server - .execute_set(operation::Set { entry }) - .await - .map_err(Error::into_rpc_error) - } - - async fn del(&self, req: DelRequest) -> wcn_rpc::Result<()> { - self.api_server - .del(operation::Del { - key: self.prepare_key(req.key)?, - version: EntryVersion::from(req.version), - }) - .await - .map_err(Error::into_rpc_error) - } - - async fn get_exp(&self, req: GetExpRequest) -> wcn_rpc::Result> { - let expiration = self - .api_server - .execute_get_exp(operation::GetExp { - key: self.prepare_key(req.key)?, - }) - .await - .map_err(Error::into_rpc_error)?; - - Ok(expiration.map(|exp| GetExpResponse { - expiration: exp.timestamp(), - })) - } - - async fn set_exp(&self, req: SetExpRequest) -> wcn_rpc::Result<()> { - self.api_server - .execute_set_exp(operation::SetExp { - key: self.prepare_key(req.key)?, - expiration: EntryExpiration::from(req.expiration), - version: EntryVersion::from(req.version), - }) - .await - .map_err(Error::into_rpc_error) - } - - async fn hget(&self, req: HGetRequest) -> wcn_rpc::Result> { - let record = self - .api_server - .execute_hget(operation::HGet { - key: self.prepare_key(req.key)?, - field: req.field, - }) - .await - .map_err(Error::into_rpc_error)?; - - Ok(record.map(|rec| HGetResponse { - value: rec.value, - expiration: rec.expiration.timestamp(), - version: rec.version.timestamp(), - })) - } - - async fn hset(&self, req: HSetRequest) -> wcn_rpc::Result<()> { - let entry = MapEntry { - key: self.prepare_key(req.key)?, - field: req.field, - value: req.value, - expiration: EntryExpiration::from(req.expiration), - version: EntryVersion::from(req.version), - }; - - self.api_server - .execute_hset(operation::HSet { entry }) - .await - .map_err(Error::into_rpc_error) - } - - async fn hdel(&self, req: HDelRequest) -> wcn_rpc::Result<()> { - self.api_server - .execute_hdel(operation::HDel { - key: self.prepare_key(req.key)?, - field: req.field, - version: EntryVersion::from(req.version), - }) - .await - .map_err(Error::into_rpc_error) - } - - async fn hget_exp(&self, req: HGetExpRequest) -> wcn_rpc::Result> { - let expiration = self - .api_server - .execute_hget_exp(operation::HGetExp { - key: self.prepare_key(req.key)?, - field: req.field, - }) - .await - .map_err(Error::into_rpc_error)?; - - Ok(expiration.map(|exp| HGetExpResponse { - expiration: exp.timestamp(), - })) - } - - async fn hset_exp(&self, req: HSetExpRequest) -> wcn_rpc::Result<()> { - self.api_server - .execute_hset_exp(operation::HSetExp { - key: self.prepare_key(req.key)?, - field: req.field, - expiration: EntryExpiration::from(req.expiration), - version: EntryVersion::from(req.version), - }) - .await - .map_err(Error::into_rpc_error) - } - - async fn hcard(&self, req: HCardRequest) -> wcn_rpc::Result { - self.api_server - .execute_hcard(operation::HCard { - key: self.prepare_key(req.key)?, - }) - .await - .map(|cardinality| HCardResponse { cardinality }) - .map_err(Error::into_rpc_error) - } - - async fn hscan(&self, req: HScanRequest) -> wcn_rpc::Result { - let page = self - .api_server - .execute_hscan(operation::HScan { - key: self.prepare_key(req.key)?, - count: req.count, - cursor: req.cursor, - }) - .await - .map_err(Error::into_rpc_error)?; - - Ok(HScanResponse { - records: page - .records - .into_iter() - .map(|rec| HScanResponseRecord { - field: rec.field, - value: rec.value, - expiration: rec.expiration.timestamp(), - version: rec.version.timestamp(), - }) - .collect(), - has_more: page.has_next, - }) - } +#[derive(Clone)] +struct ConnectionHandler { + storage_api: S, + api_kind: Kind, } -#[derive(Clone, Debug)] -struct RpcServer { - api_server: S, - config: rpc::server::Config, -} - -impl rpc::Server for RpcServer +impl HandleConnection for ConnectionHandler where - S: Server, + S: crate::StorageApi + Clone + Send + Sync + 'static, + Kind: Clone + Send + Sync + 'static, + StorageApi: Api, { - type Handshake = NoHandshake; - type ConnectionData = (); - type Codec = PostcardCodec; - - fn config(&self) -> &wcn_rpc::server::Config { - &self.config - } + type Api = super::StorageApi; - fn handle_rpc<'a>( - &'a self, - id: rpc::Id, - stream: BiDirectionalStream, - conn_info: &'a ClientConnectionInfo, - ) -> impl Future + Send + 'a { - async move { - let handler = RpcHandler { - api_server: &self.api_server, - conn_info, - }; - - let _ = match id { - Get::ID => Get::handle(stream, |req| handler.get(req)).await, - Set::ID => Set::handle(stream, |req| handler.set(req)).await, - Del::ID => Del::handle(stream, |req| handler.del(req)).await, - GetExp::ID => GetExp::handle(stream, |req| handler.get_exp(req)).await, - SetExp::ID => SetExp::handle(stream, |req| handler.set_exp(req)).await, - - HGet::ID => HGet::handle(stream, |req| handler.hget(req)).await, - HSet::ID => HSet::handle(stream, |req| handler.hset(req)).await, - HDel::ID => HDel::handle(stream, |req| handler.hdel(req)).await, - HGetExp::ID => HGetExp::handle(stream, |req| handler.hget_exp(req)).await, - HSetExp::ID => HSetExp::handle(stream, |req| handler.hset_exp(req)).await, - HCard::ID => HCard::handle(stream, |req| handler.hcard(req)).await, - HScan::ID => HScan::handle(stream, |req| handler.hscan(req)).await, - - id => return tracing::warn!("Unexpected RPC: {}", rpc::Name::new(id)), - } - .map_err( - |err| tracing::debug!(name = %rpc::Name::new(id), ?err, "Failed to handle RPC"), - ); - } + async fn handle_connection(&self, conn: Connection<'_, Self::Api>) -> Result<()> { + todo!() } } -/// Error of a [`Server`] operation. -#[derive(Clone, Debug)] -pub struct Error(String); - -impl Error { - pub fn new(err: E) -> Self { - Self(format!("{err}")) - } - - fn into_rpc_error(self) -> wcn_rpc::Error { - wcn_rpc::Error { - code: "internal".into(), - description: Some(self.0.into()), - } - } +struct RpcHandler { + storage_api: S, } -/// [`Server`] operation [`Result`]. -pub type Result = std::result::Result; - -impl From for Error { - fn from(err: operation::WrongOutput) -> Self { - Self(err.to_string()) +impl HandleRpc for RpcHandler { + async fn handle_rpc(&self, rpc: &mut Inbound) -> Result<()> { + todo!() } } + +// impl RpcHandler<'_, S> { +// async fn get(&self, req: GetRequest) -> +// wcn_rpc::Result> { let record = self +// .storage_api +// .get(operation::Get { +// namespace: (), +// key: self.prepare_key(req.key)?, +// }) +// .await +// .map_err(Error::into_rpc_error)?; + +// Ok(record.map(|rec| GetResponse { +// value: rec.value, +// expiration: rec.expiration.timestamp(), +// version: rec.version.timestamp(), +// })) +// } + +// async fn set(&self, req: SetRequest) -> wcn_rpc::Result<()> { +// let entry = Entry { +// key: self.prepare_key(req.key)?, +// value: req.value, +// expiration: EntryExpiration::from(req.expiration), +// version: EntryVersion::from(req.version), +// }; + +// self.storage_api +// .execute_set(operation::Set { entry }) +// .await +// .map_err(Error::into_rpc_error) +// } + +// async fn del(&self, req: DelRequest) -> wcn_rpc::Result<()> { +// self.storage_api +// .del(operation::Del { +// key: self.prepare_key(req.key)?, +// version: EntryVersion::from(req.version), +// }) +// .await +// .map_err(Error::into_rpc_error) +// } + +// async fn get_exp(&self, req: GetExpRequest) -> +// wcn_rpc::Result> { let expiration = self +// .storage_api +// .execute_get_exp(operation::GetExp { +// key: self.prepare_key(req.key)?, +// }) +// .await +// .map_err(Error::into_rpc_error)?; + +// Ok(expiration.map(|exp| GetExpResponse { +// expiration: exp.timestamp(), +// })) +// } + +// async fn set_exp(&self, req: SetExpRequest) -> wcn_rpc::Result<()> { +// self.storage_api +// .execute_set_exp(operation::SetExp { +// key: self.prepare_key(req.key)?, +// expiration: EntryExpiration::from(req.expiration), +// version: EntryVersion::from(req.version), +// }) +// .await +// .map_err(Error::into_rpc_error) +// } + +// async fn hget(&self, req: HGetRequest) -> +// wcn_rpc::Result> { let record = self +// .storage_api +// .execute_hget(operation::HGet { +// key: self.prepare_key(req.key)?, +// field: req.field, +// }) +// .await +// .map_err(Error::into_rpc_error)?; + +// Ok(record.map(|rec| HGetResponse { +// value: rec.value, +// expiration: rec.expiration.timestamp(), +// version: rec.version.timestamp(), +// })) +// } + +// async fn hset(&self, req: HSetRequest) -> wcn_rpc::Result<()> { +// let entry = MapEntry { +// key: self.prepare_key(req.key)?, +// field: req.field, +// value: req.value, +// expiration: EntryExpiration::from(req.expiration), +// version: EntryVersion::from(req.version), +// }; + +// self.storage_api +// .execute_hset(operation::HSet { entry }) +// .await +// .map_err(Error::into_rpc_error) +// } + +// async fn hdel(&self, req: HDelRequest) -> wcn_rpc::Result<()> { +// self.storage_api +// .execute_hdel(operation::HDel { +// key: self.prepare_key(req.key)?, +// field: req.field, +// version: EntryVersion::from(req.version), +// }) +// .await +// .map_err(Error::into_rpc_error) +// } + +// async fn hget_exp(&self, req: HGetExpRequest) -> +// wcn_rpc::Result> { let expiration = self +// .storage_api +// .execute_hget_exp(operation::HGetExp { +// key: self.prepare_key(req.key)?, +// field: req.field, +// }) +// .await +// .map_err(Error::into_rpc_error)?; + +// Ok(expiration.map(|exp| HGetExpResponse { +// expiration: exp.timestamp(), +// })) +// } + +// async fn hset_exp(&self, req: HSetExpRequest) -> wcn_rpc::Result<()> { +// self.storage_api +// .execute_hset_exp(operation::HSetExp { +// key: self.prepare_key(req.key)?, +// field: req.field, +// expiration: EntryExpiration::from(req.expiration), +// version: EntryVersion::from(req.version), +// }) +// .await +// .map_err(Error::into_rpc_error) +// } + +// async fn hcard(&self, req: HCardRequest) -> +// wcn_rpc::Result { self.storage_api +// .execute_hcard(operation::HCard { +// key: self.prepare_key(req.key)?, +// }) +// .await +// .map(|cardinality| HCardResponse { cardinality }) +// .map_err(Error::into_rpc_error) +// } + +// async fn hscan(&self, req: HScanRequest) -> +// wcn_rpc::Result { let page = self +// .storage_api +// .execute_hscan(operation::HScan { +// key: self.prepare_key(req.key)?, +// count: req.count, +// cursor: req.cursor, +// }) +// .await +// .map_err(Error::into_rpc_error)?; + +// Ok(HScanResponse { +// records: page +// .records +// .into_iter() +// .map(|rec| HScanResponseRecord { +// field: rec.field, +// value: rec.value, +// expiration: rec.expiration.timestamp(), +// version: rec.version.timestamp(), +// }) +// .collect(), +// has_more: page.has_next, +// }) +// } +// } + +// #[derive(Clone, Debug)] +// struct RpcServer { +// api_server: S, +// config: rpc::server::Config, +// } + +// impl rpc::Server for RpcServer +// where +// S: Server, +// { +// type Handshake = NoHandshake; +// type ConnectionData = (); +// type Codec = PostcardCodec; + +// fn config(&self) -> &wcn_rpc::server::Config { +// &self.config +// } + +// fn handle_rpc<'a>( +// &'a self, +// id: rpc::Id, +// stream: BiDirectionalStream, +// conn_info: &'a ClientConnectionInfo, +// ) -> impl Future + Send + 'a { +// async move { +// let handler = RpcHandler { +// storage_api: &self.api_server, +// conn_info, +// }; + +// let _ = match id { +// Get::ID => Get::handle(stream, |req| handler.get(req)).await, +// Set::ID => Set::handle(stream, |req| handler.set(req)).await, +// Del::ID => Del::handle(stream, |req| handler.del(req)).await, +// GetExp::ID => GetExp::handle(stream, |req| +// handler.get_exp(req)).await, SetExp::ID => +// SetExp::handle(stream, |req| handler.set_exp(req)).await, + +// HGet::ID => HGet::handle(stream, |req| +// handler.hget(req)).await, HSet::ID => HSet::handle(stream, +// |req| handler.hset(req)).await, HDel::ID => +// HDel::handle(stream, |req| handler.hdel(req)).await, +// HGetExp::ID => HGetExp::handle(stream, |req| handler.hget_exp(req)).await, +// HSetExp::ID => HSetExp::handle(stream, |req| +// handler.hset_exp(req)).await, HCard::ID => +// HCard::handle(stream, |req| handler.hcard(req)).await, +// HScan::ID => HScan::handle(stream, |req| handler.hscan(req)).await, + +// id => return tracing::warn!("Unexpected RPC: {}", +// rpc::Name::new(id)), } +// .map_err( +// |err| tracing::debug!(name = %rpc::Name::new(id), ?err, "Failed to handle RPC"), +// ); +// } +// } +// } From 68eaaaae2cdc4aa09076943e3bd3f1884de669fa Mon Sep 17 00:00:00 2001 From: Darksome Date: Thu, 26 Jun 2025 13:24:32 +0000 Subject: [PATCH 58/79] WIP --- crates/rpc/src/client2.rs | 162 ++++++----- crates/rpc/src/lib.rs | 126 +++++---- crates/rpc/src/server2.rs | 3 +- crates/rpc/src/transport2.rs | 61 +++-- crates/storage_api2/src/rpc/client.rs | 27 +- crates/storage_api2/src/rpc/mod.rs | 379 +++++++++++++------------- flake.nix | 1 + 7 files changed, 409 insertions(+), 350 deletions(-) diff --git a/crates/rpc/src/client2.rs b/crates/rpc/src/client2.rs index d658f72a..92f14f12 100644 --- a/crates/rpc/src/client2.rs +++ b/crates/rpc/src/client2.rs @@ -1,13 +1,13 @@ use { crate::{ quic::{self}, - sealed, transport, transport2::{self, BiDirectionalStream, Codec, RecvStream, SendStream}, + BorrowedRequest, ConnectionStatusCode, - MessageV2, - RpcImpl, + MessageOwned, RpcV2, + UnaryV2, }, derive_where::derive_where, futures::{ @@ -22,8 +22,10 @@ use { }, libp2p::{identity, PeerId}, std::{ + borrow::Borrow, future::Future, io, + marker::PhantomData, net::{SocketAddr, SocketAddrV4}, sync::Arc, time::Duration, @@ -41,6 +43,7 @@ use { }; // TODO: metrics, timeouts + /// Client-specific part of an RPC [Api][`super::Api`]. pub trait Api: super::Api + Sized { /// Outbound [`Connection`] parameters. @@ -50,7 +53,7 @@ pub trait Api: super::Api + Sized { type ConnectionHandler: HandleConnection; //// Implementor of [`HandleRpc`] for the RPCs of this RPC [`Api`]. - // type RpcHandler: Send + Sync + 'static; + type RpcHandler: Send + Sync + 'static; } /// Handler of newly established outbound [`Connection`]s. @@ -58,7 +61,7 @@ pub trait HandleConnection: Clone + Send + Sync + 'static { /// Creates a new instance of [`Api::RpcHandler`]. /// /// Each outbound [`Connection`] gets a separate RPC handler. - // fn new_rpc_handler(&self, args: Args) -> API::RpcHandler; + fn new_rpc_handler(&self) -> API::RpcHandler; /// Handles the provided outbound [`Connection`]. fn handle_connection( @@ -69,10 +72,15 @@ pub trait HandleConnection: Clone + Send + Sync + 'static { } /// Handler of [`Outbound`] RPCs. -pub trait HandleRpc: Send + Sync { +pub trait HandleRpc<'a, RPC: RpcV2>: Send + Sync { type Output; - fn handle_rpc(self, rpc: Outbound) -> impl Future> + Send; + fn handle_rpc( + &self, + rpc: Outbound<'_, RPC>, + ) -> impl Future> + Send + where + RPC: 'a; } /// RPC [`Client`] config. @@ -214,6 +222,7 @@ impl Client { remote_peer_id: *peer_id, watch_rx: rx, watch_tx: Arc::new(tokio::sync::Mutex::new((tx, params))), + rpc_handler: self.connection_handler.new_rpc_handler(), }), } } @@ -227,11 +236,11 @@ pub struct DefaultConnectionHandler; impl HandleConnection for DefaultConnectionHandler where - API: Api, + API: Api, { - // fn new_rpc_handler(&self) -> ::RpcHandler { - // DefaultRpcHandler - // } + fn new_rpc_handler(&self) -> ::RpcHandler { + DefaultRpcHandler + } async fn handle_connection(&self, _conn: &Connection, _params: &()) -> Result<()> { Ok(()) @@ -239,32 +248,27 @@ where } /// Outbound RPC of a specific type. -pub struct Outbound { +pub struct Outbound<'a, RPC: RpcV2> { + rpc: &'a RPC, + stream: OutboundStream, +} + +struct OutboundStream { send: SinkMapErr, fn(transport2::Error) -> Error>, recv: MapErr, fn(transport2::Error) -> Error>, } -impl Outbound { - /// Returns [`Sink`] of outbound requests. - pub fn sink(&mut self) -> &mut (impl for<'a> Sink<&'a RPC::Request, Error = Error> + 'static) { - &mut self.send - } - - /// Returns [`Stream`] of inbound responses. - pub fn stream(&mut self) -> &mut impl Stream> { - &mut self.recv - } - - /// Handles this [`Outbound`] unary RPC. - pub async fn handle_unary(&mut self, req: &RPC::Request) -> Result - where - RPC: sealed::UnaryRpc, - { - self.sink().send(req).await?; - self.stream() - .next() - .await - .ok_or_else(|| Error::new(transport2::Error::StreamFinished))? +impl<'a, RPC: RpcV2> Outbound<'a, RPC> { + /// Returns the underlying RPC, [`Sink`] of requests and [`Stream`] of + /// responses. + pub fn unpack( + &mut self, + ) -> ( + &RPC, + &mut (impl for<'r> Sink<&'r BorrowedRequest<'r, RPC>, Error = Error> + 'static), + &mut impl Stream>, + ) { + (&self.rpc, &mut self.stream.send, &mut self.stream.recv) } } @@ -287,6 +291,8 @@ struct ConnectionInner { watch_rx: watch::Receiver>, watch_tx: Arc>, + + rpc_handler: API::RpcHandler, } impl Connection { @@ -326,33 +332,35 @@ impl Connection { drop(watch_rx.changed().await) } - /// Sends an RPC over this [`Connection`]. - pub fn send_rpc<'a, RPC, H>( + /// Sends the provided RPC over this [`Connection`]. + pub fn send<'a: 'b, 'b, RPC, Output>( &'a self, - handler: H, - ) -> Result> + 'a> + rpc: &'b RPC, + ) -> Result> + 'b> where - RPC: RpcV2, - H: HandleRpc + 'a, + RPC: RpcV2 + 'b, + API::RpcHandler: HandleRpc<'b, RPC, Output = Output>, { - let mut rpc = self.new_rpc::().tap_err(|err| { + let stream = self.new_outbound_stream::().tap_err(|err| { if err.requires_reconnect() { self.reconnect(); } })?; Ok(async move { - handler.handle_rpc(rpc).await.tap_err(|err| { - if err.0.requires_reconnect() { - self.reconnect(); - } - }) + self.inner + .rpc_handler + .handle_rpc(Outbound { rpc, stream }) + .await + .tap_err(|err| { + if err.0.requires_reconnect() { + self.reconnect(); + } + }) }) - - // Ok({ async move { todo!() } }) } - fn new_rpc(&self) -> Result, ErrorInner> { + fn new_outbound_stream(&self) -> Result, ErrorInner> { let quic = self.inner.watch_rx.borrow(); let Some(conn) = quic.as_ref() else { return Err(ErrorInner::NotConnected.into()); @@ -372,7 +380,7 @@ impl Connection { let (recv, send) = BiDirectionalStream::new(tx, rx).upgrade::(); - Ok(Outbound { + Ok(OutboundStream { send: SinkExt::<&RPC::Request>::sink_map_err(send, |err: transport2::Error| { Error::new(err) }), @@ -431,35 +439,55 @@ impl Connection { /// For your (streaming)[rpc::StreamingV2] RPCs you'll need to provide a manual /// implementation of [`RpcHandler`] for this type. #[derive(Clone, Copy, Debug, Default)] -pub struct DefaultRpcHandler(pub Args); +pub struct DefaultRpcHandler; -impl<'a, RPC> HandleRpc for DefaultRpcHandler<&'a RPC::Request> +impl<'a, const ID: u8, Req, Resp, C> HandleRpc<'a, UnaryV2<'a, ID, Req, Resp, C>> + for DefaultRpcHandler where - RPC: sealed::UnaryRpc, + Req: MessageOwned, + Resp: MessageOwned, + C: Codec + Codec, { - type Output = RPC::Response; + type Output = Resp; - fn handle_rpc( - self, - mut rpc: Outbound, - ) -> impl Future> + Send { - async move { rpc.handle_unary(self.0).await } + async fn handle_rpc( + &self, + mut outbound: Outbound<'_, UnaryV2<'a, ID, Req, Resp, C>>, + ) -> Result { + let (rpc, tx, rx) = outbound.unpack(); + + tx.send(rpc.request).await?; + rx.next() + .await + .ok_or_else(|| Error::new(transport2::Error::StreamFinished))? } } -impl RpcImpl +impl<'a, const ID: u8, Req, Resp, C> UnaryV2<'a, ID, Req, Resp, C> where - K: 'static, - Req: MessageV2, - Resp: MessageV2, + Req: MessageOwned, + Resp: MessageOwned, C: Codec + Codec, { - /// Sends this RPC over the provided [`Connection`]. - pub fn send<'a, API: Api, H: HandleRpc + 'a>( + pub fn new(request: &'a Req::Borrowed<'a>) -> Self { + Self { + request, + _marker: PhantomData, + } + } + + /// Sends this unary RPC over the provided connection. + pub fn send( conn: &'a Connection, - rpc_handler: H, - ) -> Result> + 'a> { - conn.send_rpc(rpc_handler) + request: &'a Req::Borrowed<'a>, + ) -> Result> + 'a> + where + API::RpcHandler: HandleRpc<'a, Self, Output = Output>, + { + conn.send(Self { + request, + _marker: PhantomData, + }) } } diff --git a/crates/rpc/src/lib.rs b/crates/rpc/src/lib.rs index 471e6e52..b495348e 100644 --- a/crates/rpc/src/lib.rs +++ b/crates/rpc/src/lib.rs @@ -3,8 +3,15 @@ use { derive_more::{derive::TryFrom, Display}, - serde::{Deserialize, Serialize}, - std::{borrow::Cow, fmt::Debug, marker::PhantomData, net::SocketAddr, str::FromStr}, + serde::{de::DeserializeOwned, Deserialize, Serialize}, + std::{ + borrow::Cow, + fmt::Debug, + future::Future, + marker::PhantomData, + net::SocketAddr, + str::FromStr, + }, transport::Codec, transport2::Codec as CodecV2, }; @@ -24,7 +31,6 @@ pub use client::Client; pub mod server; #[cfg(feature = "server")] pub mod server2; -use serde::de::DeserializeOwned; #[cfg(feature = "server")] pub use server::{IntoServer, Server}; @@ -74,94 +80,84 @@ pub trait Api: Clone + Send + Sync + 'static { /// [`Api`] name. pub type ApiName = ServerName; -/// Specification of a remote procedure call. -/// -/// Expected to be implemented on unit types and should not contain any data. -/// -/// See [`StreamingV2`] RPC and [`UnaryV2`] RPC. -pub trait RpcV2: Sized + 'static { +/// Remote procedure call. +pub trait RpcV2: Sized + Send + Sync { /// ID of this [`Rpc`]. const ID: u8; /// Request type of this [`Rpc`]. - type Request: Message; - - type RequestRef<'a>: Serialize + Unpin + Sync + Send + 'a; + type Request: MessageOwned; /// Response type of this [`Rpc`]. - type Response: Message; + type Response: MessageOwned; /// Serialization codec of this [`Rpc`]. type Codec: CodecV2 + CodecV2; -} - -pub(crate) mod sealed { - pub trait UnaryRpc: super::RpcV2 {} - impl UnaryRpc for super::UnaryV2 where - Self: super::RpcV2 + #[cfg(feature = "client")] + /// Sends this RPC over the provided connection. + fn send<'a, API: client2::Api, Output>( + &'a self, + conn: &'a client2::Connection, + ) -> client2::Result> + 'a> + where + API::RpcHandler: client2::HandleRpc<'a, Self, Output = Output>, { + conn.send(self) } } -/// Generic [`RpcV2`] implementation. -/// -/// Not intended to be used directly by the users of this crate. -/// -/// Use [`StreamingV2`] or [`UnaryV2`] instead. -pub struct RpcImpl { - _marker: PhantomData<(K, Req, Resp, C)>, +type BorrowedRequest<'a, RPC> = <::Request as MessageOwned>::Borrowed<'a>; +type BorrowedResponse<'a, RPC> = <::Response as MessageOwned>::Borrowed<'a>; + +pub struct UnaryV2< + 'a, + const ID: u8, + Req: MessageOwned, + Resp: MessageOwned, + C: CodecV2 + CodecV2, +> { + pub request: &'a Req::Borrowed<'a>, + pub _marker: PhantomData<(Req, Resp, C)>, } -impl RpcV2 for RpcImpl +impl<'a, const ID: u8, Req, Resp, C> RpcV2 for UnaryV2<'a, ID, Req, Resp, C> where - K: 'static, - Req: MessageV2, - Resp: MessageV2, + Req: MessageOwned, + Resp: MessageOwned, C: CodecV2 + CodecV2, { const ID: u8 = ID; type Request = Req; - type RequestRef<'a> = &'a Req; type Response = Resp; type Codec = C; } -/// Bi-directional streaming [`RpcV2`]. -/// -/// Client sends a stream of requests and server responds with a stream of -/// responses. -/// -/// Use type aliases to conviniently define RPCs of this kind. -pub type StreamingV2<'a, const ID: u8, Req, Resp, C> = RpcImpl; +// impl<'s, RPC> RpcV2 for RPC +// where +// RPC: UnaryRpcV2<'s>, +// { +// const ID: u8 = RPC::ID; -/// Unary (request-response) [`RpcV2`]. -/// -/// Client sends a single request and server responds with a single response. -/// -/// Use type aliases to conviniently define RPCs of this kind. -pub type UnaryV2 = RpcImpl; +// type Request<'a> = Self; -pub trait MessageRef: Serialize + DeserializeOwned + Unpin + Sync + Send {} +// type Response<'a> = Self::Request<'a>; -pub trait MessageV2: Serialize + DeserializeOwned + Unpin + Sync + Send + 'static { - type Borrowed<'a>: Serialize + Unpin + Sync + Send + 'a; -} +// type Codec = Self::Codec; -// type BorrowedRequest<'a, RPC> = <::Request as -// MessageV2>::Borrowed<'a>; +// type Output = as ToOwned>::Owned; +// } -pub trait StaticMessage: - Serialize + for<'de> Deserialize<'de> + Unpin + Sync + Send + 'static -{ +pub trait MessageOwned: DeserializeOwned + Serialize + Unpin + Sync + Send + 'static { + type Borrowed<'a>: MessageBorrowed; } -impl MessageV2 for Msg -where - Msg: StaticMessage, -{ - type Borrowed<'a> = Self; -} +pub trait MessageBorrowed: Serialize + Unpin + Sync + Send {} + +impl MessageBorrowed for T where T: Serialize + Unpin + Sync + Send {} + +// type OwnedResponse = <::Response<'static> as +// ToOwned>::Owned; /// Error codes produced by this module. pub mod error_code { @@ -454,21 +450,21 @@ enum ConnectionStatusCode { Unauthorized = -3, } -impl MessageV2 for Result +impl MessageOwned for Result where - T: MessageV2, - E: MessageV2, + T: MessageOwned, + E: MessageOwned, { type Borrowed<'a> = Result, E::Borrowed<'a>>; } -impl MessageV2 for Option +impl MessageOwned for Option where - T: MessageV2, + T: MessageOwned, { type Borrowed<'a> = Option>; } -impl MessageV2 for () { +impl MessageOwned for () { type Borrowed<'a> = (); } diff --git a/crates/rpc/src/server2.rs b/crates/rpc/src/server2.rs index 200f3d7e..226f50b6 100644 --- a/crates/rpc/src/server2.rs +++ b/crates/rpc/src/server2.rs @@ -9,6 +9,7 @@ use { transport2::{self, BiDirectionalStream, RecvStream, SendStream}, Api, ApiName, + BorrowedResponse, ConnectionStatusCode, RpcV2, ServerName, @@ -415,7 +416,7 @@ impl Inbound { } /// Returns [`Sink`] of outbound requests. - pub fn sink(&mut self) -> &mut impl Sink<&RPC::Response, Error = Error> { + pub fn sink(&mut self) -> &mut impl for<'a> Sink<&'a BorrowedResponse<'a, RPC>, Error = Error> { &mut self.send } } diff --git a/crates/rpc/src/transport2.rs b/crates/rpc/src/transport2.rs index d5acb8ae..369cc82a 100644 --- a/crates/rpc/src/transport2.rs +++ b/crates/rpc/src/transport2.rs @@ -1,48 +1,57 @@ use { - crate::{Message, MessageV2}, + crate::{Message, MessageOwned}, bytes::{BufMut as _, Bytes, BytesMut}, futures::{stream::MapErr, Sink, TryStreamExt}, pin_project::pin_project, serde::{Deserialize, Serialize}, std::{ + borrow::Cow, io, pin::Pin, task::{self, ready}, }, - tokio_serde::{Deserializer, Framed, Serializer}, + tokio_serde::Framed, tokio_stream::Stream, tokio_util::codec::{FramedRead, FramedWrite, LengthDelimitedCodec}, }; /// Serialization codec. -pub trait Codec: - Serializer> - + for<'a> Serializer> - + Deserializer> - + Unpin - + Default - + Send - + Sync - + 'static +pub trait Codec: + for<'a> Serializer> + Serializer + Deserializer { } -impl Codec for C where - C: Serializer> - + for<'a> Serializer> - + Deserializer> - + Unpin - + Default - + Send - + Sync - + 'static +impl Codec for C +where + M: MessageOwned, + C: for<'a> Serializer> + Serializer + Deserializer, +{ +} + +pub trait Serializer: + tokio_serde::Serializer> + Unpin + Default + Send + Sync + 'static +{ +} + +impl Serializer for S where + S: tokio_serde::Serializer> + Unpin + Default + Send + Sync + 'static +{ +} + +pub trait Deserializer: + tokio_serde::Deserializer> + Unpin + Default + Send + Sync + 'static +{ +} + +impl Deserializer for D where + D: tokio_serde::Deserializer> + Unpin + Default + Send + Sync + 'static { } #[derive(Clone, Copy, Debug, Default)] pub struct PostcardCodec; -impl Deserializer for PostcardCodec +impl tokio_serde::Deserializer for PostcardCodec where for<'a> T: Deserialize<'a>, { @@ -53,7 +62,7 @@ where } } -impl Serializer for PostcardCodec +impl tokio_serde::Serializer for PostcardCodec where T: Serialize, { @@ -84,7 +93,9 @@ impl BiDirectionalStream { } } - pub(crate) fn upgrade>(self) -> (RecvStream, SendStream) { + pub(crate) fn upgrade>( + self, + ) -> (RecvStream, SendStream) { ( RecvStream(Framed::new(self.rx.map_err(Into::into), C::default())), SendStream { @@ -144,13 +155,13 @@ where /// [`Stream`] of inbound [`Message`]s. #[pin_project] -pub struct RecvStream>( +pub struct RecvStream>( #[allow(clippy::type_complexity)] #[pin] Framed Error>, T, T, C>, ); -impl> Stream for RecvStream { +impl> Stream for RecvStream { type Item = Result; fn poll_next( diff --git a/crates/storage_api2/src/rpc/client.rs b/crates/storage_api2/src/rpc/client.rs index cef0ed41..1541ad9a 100644 --- a/crates/storage_api2/src/rpc/client.rs +++ b/crates/storage_api2/src/rpc/client.rs @@ -3,7 +3,7 @@ use { crate::{operation, MapPage, Operation, Record, Result}, futures::SinkExt, std::future::Future, - wcn_rpc::client2::{Connection, DefaultConnectionHandler, DefaultRpcHandler}, + wcn_rpc::client2::{Connection, DefaultConnectionHandler, DefaultRpcHandler, HandleRpc}, }; impl wcn_rpc::client2::Api for StorageApi @@ -12,7 +12,7 @@ where { type ConnectionParameters = (); type ConnectionHandler = DefaultConnectionHandler; - // type RpcHandler = DefaultRpcHandler; + type RpcHandler = DefaultRpcHandler; } async fn f(f: F) -> F::Output { @@ -24,21 +24,28 @@ where StorageApi: wcn_rpc::client2::Api< ConnectionParameters = (), ConnectionHandler = DefaultConnectionHandler, - // RpcHandler = DefaultRpcHandler, + RpcHandler = DefaultRpcHandler, >, { fn get<'a>( &'a self, get: operation::Get<'a>, ) -> impl Future>> + Send { - let req = GetRequest { - namespace: get.namespace.into(), - // key: get.key.0.into_owned().into(), - keyspace_version: get.keyspace_version, - }; - async move { - let opt = Get::send(self, DefaultRpcHandler(&req))?.await??; + let req = GetRequest { + namespace: get.namespace.into(), + key: get.key.0, + keyspace_version: get.keyspace_version, + }; + + let rpc = Get { + request: &req, + _marker: PhantomData, + }; + + let opt = self.send(&rpc)?.await??; + + // let opt = rpc.send(self)?.await??; Ok::<_, crate::Error>(opt.map(|resp| Record { value: Value(resp.value), diff --git a/crates/storage_api2/src/rpc/mod.rs b/crates/storage_api2/src/rpc/mod.rs index ae5891a2..b1ecf661 100644 --- a/crates/storage_api2/src/rpc/mod.rs +++ b/crates/storage_api2/src/rpc/mod.rs @@ -2,8 +2,8 @@ use { crate::{Bytes, EntryExpiration, EntryVersion, Field, Key, Value}, derive_more::derive::TryFrom, serde::{Deserialize, Serialize}, - std::marker::PhantomData, - wcn_rpc::{self as rpc, Api, ApiName, MessageV2, PostcardCodec, StaticMessage}, + std::{borrow::Borrow, marker::PhantomData}, + wcn_rpc::{self as rpc, Api, ApiName, MessageOwned, PostcardCodec, RpcV2}, }; #[cfg(feature = "rpc_client")] @@ -71,31 +71,33 @@ impl Api for StorageApiDatabase { type RpcId = Id; } -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Copy, Debug, Serialize, Deserialize)] struct Namespace { node_operator_id: [u8; 20], id: u8, } -type UnaryRpc = rpc::UnaryV2; +type UnaryRpc<'a, const ID: u8, Req, Resp> = rpc::UnaryV2<'a, ID, Req, Resp, PostcardCodec>; -type Get = UnaryRpc<{ Id::Get as u8 }, GetRequest, Result>>; +type Get<'a> = UnaryRpc<'a, { Id::Get as u8 }, GetRequest<'static>, Result>>; -#[derive(Clone, Debug, Serialize, Deserialize)] -struct GetRequest { +#[derive(Debug, Serialize, Deserialize)] +struct GetRequest<'a> { namespace: Namespace, - // key: Bytes<'static>, + key: Bytes<'a>, keyspace_version: Option, } -impl Rpc for Get { - const ID: u8 = { Id::Get as u8 }; - type Request<'a> = GetRequest<'a>; - type Response<'a> = GetResponse<'a>; - type Codec = PostcardCodec; +impl MessageOwned for GetRequest<'static> { + type Borrowed<'a> = GetRequest<'a>; } -impl StaticMessage for GetRequest {} +// #[derive(Clone, Debug, Serialize, Deserialize)] +// struct GetRequest { +// namespace: Namespace, +// // key: Bytes<'static>, +// keyspace_version: Option, +// } // impl MessageV2 for GetRequest<'static> { // type Borrowed<'a> = GetRequest<'a>; @@ -111,228 +113,239 @@ struct GetResponse { keyspace_version: Option, } -impl StaticMessage for GetResponse {} +impl MessageOwned for GetResponse { + type Borrowed<'a> = Self; +} -type Set = UnaryRpc<{ Id::Set as u8 }, SetRequest<'static>, Result<()>>; +// impl StaticMessage for GetResponse {} -#[derive(Clone, Debug, Serialize, Deserialize)] -struct SetRequest<'a> { - namespace: Namespace, - key: Bytes<'a>, - value: Bytes<'a>, - expiration: UnixTimestampSecs, - version: UnixTimestampMicros, +// type Set = UnaryRpc<{ Id::Set as u8 }, SetRequest<'static>, Result<()>>; - keyspace_version: Option, -} +// #[derive(Clone, Debug, Serialize, Deserialize)] +// struct SetRequest<'a> { +// namespace: Namespace, +// key: Bytes<'a>, +// value: Bytes<'a>, +// expiration: UnixTimestampSecs, +// version: UnixTimestampMicros, -impl MessageV2 for SetRequest<'static> { - type Borrowed<'a> = SetRequest<'a>; -} +// keyspace_version: Option, +// } -type Del = UnaryRpc<{ Id::Del as u8 }, DelRequest<'static>, Result<()>>; +// impl MessageV2 for SetRequest<'static> { +// type Borrowed<'a> = SetRequest<'a>; +// } -#[derive(Clone, Debug, Serialize, Deserialize)] -struct DelRequest<'a> { - namespace: Namespace, - key: Bytes<'a>, - version: UnixTimestampMicros, +// type Del = UnaryRpc<{ Id::Del as u8 }, DelRequest<'static>, Result<()>>; - keyspace_version: Option, -} +// #[derive(Clone, Debug, Serialize, Deserialize)] +// struct DelRequest<'a> { +// namespace: Namespace, +// key: Bytes<'a>, +// version: UnixTimestampMicros, -impl MessageV2 for DelRequest<'static> { - type Borrowed<'a> = DelRequest<'a>; -} +// keyspace_version: Option, +// } -type GetExp = - UnaryRpc<{ Id::GetExp as u8 }, GetExpRequest<'static>, Result>>; +// impl MessageV2 for DelRequest<'static> { +// type Borrowed<'a> = DelRequest<'a>; +// } -#[derive(Clone, Debug, Serialize, Deserialize)] -struct GetExpRequest<'a> { - namespace: Namespace, - key: Bytes<'a>, +// type GetExp = +// UnaryRpc<{ Id::GetExp as u8 }, GetExpRequest<'static>, +// Result>>; - keyspace_version: Option, -} +// #[derive(Clone, Debug, Serialize, Deserialize)] +// struct GetExpRequest<'a> { +// namespace: Namespace, +// key: Bytes<'a>, -impl MessageV2 for GetExpRequest<'static> { - type Borrowed<'a> = GetExpRequest<'a>; -} +// keyspace_version: Option, +// } -#[derive(Clone, Debug, Serialize, Deserialize)] -struct GetExpResponse { - expiration: UnixTimestampSecs, -} +// impl MessageV2 for GetExpRequest<'static> { +// type Borrowed<'a> = GetExpRequest<'a>; +// } -impl StaticMessage for GetExpResponse {} +// #[derive(Clone, Debug, Serialize, Deserialize)] +// struct GetExpResponse { +// expiration: UnixTimestampSecs, +// } -type SetExp = UnaryRpc<{ Id::SetExp as u8 }, SetExpRequest<'static>, Result<()>>; +// impl StaticMessage for GetExpResponse {} -#[derive(Clone, Debug, Serialize, Deserialize)] -struct SetExpRequest<'a> { - namespace: Namespace, - key: Bytes<'a>, - expiration: UnixTimestampSecs, - version: UnixTimestampMicros, +// type SetExp = UnaryRpc<{ Id::SetExp as u8 }, SetExpRequest<'static>, +// Result<()>>; - keyspace_version: Option, -} +// #[derive(Clone, Debug, Serialize, Deserialize)] +// struct SetExpRequest<'a> { +// namespace: Namespace, +// key: Bytes<'a>, +// expiration: UnixTimestampSecs, +// version: UnixTimestampMicros, -impl MessageV2 for SetExpRequest<'static> { - type Borrowed<'a> = DelRequest<'a>; -} +// keyspace_version: Option, +// } -type HGet = UnaryRpc<{ Id::HGet as u8 }, HGetRequest<'static>, Result>>; +// impl MessageV2 for SetExpRequest<'static> { +// type Borrowed<'a> = DelRequest<'a>; +// } -#[derive(Clone, Debug, Serialize, Deserialize)] -struct HGetRequest<'a> { - namespace: Namespace, - key: Bytes<'a>, - field: Bytes<'a>, +// type HGet = UnaryRpc<{ Id::HGet as u8 }, HGetRequest<'static>, +// Result>>; - keyspace_version: Option, -} +// #[derive(Clone, Debug, Serialize, Deserialize)] +// struct HGetRequest<'a> { +// namespace: Namespace, +// key: Bytes<'a>, +// field: Bytes<'a>, -impl MessageV2 for HGetRequest<'static> { - type Borrowed<'a> = HGetRequest<'a>; -} +// keyspace_version: Option, +// } -#[derive(Clone, Debug, Serialize, Deserialize)] -struct HGetResponse { - value: Bytes<'static>, - expiration: UnixTimestampSecs, - version: UnixTimestampMicros, -} +// impl MessageV2 for HGetRequest<'static> { +// type Borrowed<'a> = HGetRequest<'a>; +// } -impl StaticMessage for HGetResponse {} +// #[derive(Clone, Debug, Serialize, Deserialize)] +// struct HGetResponse { +// value: Bytes<'static>, +// expiration: UnixTimestampSecs, +// version: UnixTimestampMicros, +// } -type HSet = UnaryRpc<{ Id::HSet as u8 }, HSetRequest<'static>, Result<()>>; +// impl StaticMessage for HGetResponse {} -#[derive(Clone, Debug, Serialize, Deserialize)] -struct HSetRequest<'a> { - namespace: Namespace, - key: Bytes<'a>, - field: Bytes<'a>, - value: Bytes<'a>, - expiration: UnixTimestampSecs, - version: UnixTimestampMicros, +// type HSet = UnaryRpc<{ Id::HSet as u8 }, HSetRequest<'static>, Result<()>>; - keyspace_version: Option, -} +// #[derive(Clone, Debug, Serialize, Deserialize)] +// struct HSetRequest<'a> { +// namespace: Namespace, +// key: Bytes<'a>, +// field: Bytes<'a>, +// value: Bytes<'a>, +// expiration: UnixTimestampSecs, +// version: UnixTimestampMicros, -impl MessageV2 for HSetRequest<'static> { - type Borrowed<'a> = HSetRequest<'a>; -} +// keyspace_version: Option, +// } -type HDel = UnaryRpc<{ Id::HDel as u8 }, HDelRequest<'static>, Result<()>>; +// impl MessageV2 for HSetRequest<'static> { +// type Borrowed<'a> = HSetRequest<'a>; +// } -#[derive(Clone, Debug, Serialize, Deserialize)] -struct HDelRequest<'a> { - namespace: Namespace, - key: Bytes<'a>, - field: Bytes<'a>, - version: UnixTimestampMicros, +// type HDel = UnaryRpc<{ Id::HDel as u8 }, HDelRequest<'static>, Result<()>>; - keyspace_version: Option, -} +// #[derive(Clone, Debug, Serialize, Deserialize)] +// struct HDelRequest<'a> { +// namespace: Namespace, +// key: Bytes<'a>, +// field: Bytes<'a>, +// version: UnixTimestampMicros, -impl MessageV2 for HDelRequest<'static> { - type Borrowed<'a> = HDelRequest<'a>; -} +// keyspace_version: Option, +// } -type HGetExp = - UnaryRpc<{ Id::HGetExp as u8 }, HGetExpRequest<'static>, Result>>; +// impl MessageV2 for HDelRequest<'static> { +// type Borrowed<'a> = HDelRequest<'a>; +// } -#[derive(Clone, Debug, Serialize, Deserialize)] -struct HGetExpRequest<'a> { - namespace: Namespace, - key: Bytes<'a>, - field: Bytes<'a>, +// type HGetExp = +// UnaryRpc<{ Id::HGetExp as u8 }, HGetExpRequest<'static>, +// Result>>; - keyspace_version: Option, -} +// #[derive(Clone, Debug, Serialize, Deserialize)] +// struct HGetExpRequest<'a> { +// namespace: Namespace, +// key: Bytes<'a>, +// field: Bytes<'a>, -impl MessageV2 for HGetExpRequest<'static> { - type Borrowed<'a> = HGetExpRequest<'a>; -} +// keyspace_version: Option, +// } -#[derive(Clone, Debug, Serialize, Deserialize)] -struct HGetExpResponse { - expiration: UnixTimestampSecs, -} +// impl MessageV2 for HGetExpRequest<'static> { +// type Borrowed<'a> = HGetExpRequest<'a>; +// } -impl StaticMessage for HGetExpResponse {} +// #[derive(Clone, Debug, Serialize, Deserialize)] +// struct HGetExpResponse { +// expiration: UnixTimestampSecs, +// } -type HSetExp = UnaryRpc<{ Id::HSetExp as u8 }, HSetExpRequest<'static>, Result<()>>; +// impl StaticMessage for HGetExpResponse {} -#[derive(Clone, Debug, Serialize, Deserialize)] -struct HSetExpRequest<'a> { - namespace: Namespace, - key: Bytes<'a>, - field: Bytes<'a>, - expiration: UnixTimestampSecs, - version: UnixTimestampMicros, +// type HSetExp = UnaryRpc<{ Id::HSetExp as u8 }, HSetExpRequest<'static>, +// Result<()>>; - keyspace_version: Option, -} +// #[derive(Clone, Debug, Serialize, Deserialize)] +// struct HSetExpRequest<'a> { +// namespace: Namespace, +// key: Bytes<'a>, +// field: Bytes<'a>, +// expiration: UnixTimestampSecs, +// version: UnixTimestampMicros, -impl MessageV2 for HSetExpRequest<'static> { - type Borrowed<'a> = HSetExpRequest<'a>; -} +// keyspace_version: Option, +// } -type HCard = UnaryRpc<{ Id::HCard as u8 }, HCardRequest<'static>, Result>; +// impl MessageV2 for HSetExpRequest<'static> { +// type Borrowed<'a> = HSetExpRequest<'a>; +// } -#[derive(Clone, Debug, Serialize, Deserialize)] -struct HCardRequest<'a> { - namespace: Namespace, - key: Bytes<'a>, +// type HCard = UnaryRpc<{ Id::HCard as u8 }, HCardRequest<'static>, +// Result>; - keyspace_version: Option, -} +// #[derive(Clone, Debug, Serialize, Deserialize)] +// struct HCardRequest<'a> { +// namespace: Namespace, +// key: Bytes<'a>, -impl MessageV2 for HCardRequest<'static> { - type Borrowed<'a> = HCardRequest<'a>; -} +// keyspace_version: Option, +// } -#[derive(Clone, Debug, Serialize, Deserialize)] -struct HCardResponse { - cardinality: u64, -} +// impl MessageV2 for HCardRequest<'static> { +// type Borrowed<'a> = HCardRequest<'a>; +// } -impl StaticMessage for HCardResponse {} +// #[derive(Clone, Debug, Serialize, Deserialize)] +// struct HCardResponse { +// cardinality: u64, +// } -type HScan = UnaryRpc<{ Id::HScan as u8 }, HScanRequest<'static>, Result>; +// impl StaticMessage for HCardResponse {} -#[derive(Clone, Debug, Serialize, Deserialize)] -struct HScanRequest<'a> { - namespace: Namespace, - key: Bytes<'a>, - count: u32, - cursor: Option>, +// type HScan = UnaryRpc<{ Id::HScan as u8 }, HScanRequest<'static>, +// Result>; - keyspace_version: Option, -} +// #[derive(Clone, Debug, Serialize, Deserialize)] +// struct HScanRequest<'a> { +// namespace: Namespace, +// key: Bytes<'a>, +// count: u32, +// cursor: Option>, -impl MessageV2 for HScanRequest<'static> { - type Borrowed<'a> = HScanRequest<'a>; -} +// keyspace_version: Option, +// } -#[derive(Clone, Debug, Serialize, Deserialize)] -struct HScanResponse { - records: Vec, - has_more: bool, -} +// impl MessageV2 for HScanRequest<'static> { +// type Borrowed<'a> = HScanRequest<'a>; +// } + +// #[derive(Clone, Debug, Serialize, Deserialize)] +// struct HScanResponse { +// records: Vec, +// has_more: bool, +// } -impl StaticMessage for HScanResponse {} +// impl StaticMessage for HScanResponse {} -#[derive(Clone, Debug, Serialize, Deserialize)] -struct HScanResponseRecord { - field: Bytes<'static>, - value: Bytes<'static>, - expiration: UnixTimestampSecs, - version: UnixTimestampMicros, -} +// #[derive(Clone, Debug, Serialize, Deserialize)] +// struct HScanResponseRecord { +// field: Bytes<'static>, +// value: Bytes<'static>, +// expiration: UnixTimestampSecs, +// version: UnixTimestampMicros, +// } #[derive(Clone, Copy, Debug, Serialize, Deserialize)] struct UnixTimestampSecs(u64); @@ -460,4 +473,6 @@ impl From for Error { } } -impl StaticMessage for Error {} +impl MessageOwned for Error { + type Borrowed<'a> = Self; +} diff --git a/flake.nix b/flake.nix index f530c2d3..be43f747 100644 --- a/flake.nix +++ b/flake.nix @@ -30,6 +30,7 @@ pkg-config openssl clang + gcc13 # jemalloc fails to build on gcc14 (in debug builds) ]; rustc = { stable = fenixPackages.stable.rustc; From 973e78adeffeaa086e4ed9ee04f8103de30af7ce Mon Sep 17 00:00:00 2001 From: Darksome Date: Fri, 27 Jun 2025 15:09:40 +0000 Subject: [PATCH 59/79] =?UTF-8?q?type=20checks=20=F0=9F=8E=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.lock | 1 + Cargo.toml | 1 + crates/rpc/src/client2.rs | 164 +++++------ crates/rpc/src/lib.rs | 136 ++++----- crates/rpc/src/server2.rs | 179 +++++++++--- crates/rpc/src/transport2.rs | 15 +- crates/storage_api2/Cargo.toml | 1 + crates/storage_api2/src/lib.rs | 267 +++++++++--------- crates/storage_api2/src/operation.rs | 180 ++++++------ crates/storage_api2/src/rpc/client.rs | 308 ++++----------------- crates/storage_api2/src/rpc/mod.rs | 383 +++++--------------------- crates/storage_api2/src/rpc/server.rs | 371 ++++++++----------------- 12 files changed, 726 insertions(+), 1280 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d4cd6d59..ef307a23 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8088,6 +8088,7 @@ dependencies = [ "futures", "serde", "strum", + "tap", "thiserror 1.0.64", "time", "tracing", diff --git a/Cargo.toml b/Cargo.toml index 573a68ad..2687c4f7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,6 +28,7 @@ derive_more = { version = "1.0.0", features = [ ] } derivative = "2" derive-where = "1.5" +tap = "1.0" core = { package = "wcn_core", path = "crates/core" } auth = { package = "wcn_auth", path = "crates/auth" } domain = { package = "wcn_domain", path = "crates/domain" } diff --git a/crates/rpc/src/client2.rs b/crates/rpc/src/client2.rs index 92f14f12..f49a9dd0 100644 --- a/crates/rpc/src/client2.rs +++ b/crates/rpc/src/client2.rs @@ -2,12 +2,11 @@ use { crate::{ quic::{self}, transport, - transport2::{self, BiDirectionalStream, Codec, RecvStream, SendStream}, + transport2::{self, BiDirectionalStream, RecvStream, SendStream}, BorrowedRequest, ConnectionStatusCode, - MessageOwned, RpcV2, - UnaryV2, + UnaryRpc, }, derive_where::derive_where, futures::{ @@ -22,10 +21,8 @@ use { }, libp2p::{identity, PeerId}, std::{ - borrow::Borrow, future::Future, io, - marker::PhantomData, net::{SocketAddr, SocketAddrV4}, sync::Arc, time::Duration, @@ -72,17 +69,20 @@ pub trait HandleConnection: Clone + Send + Sync + 'static { } /// Handler of [`Outbound`] RPCs. -pub trait HandleRpc<'a, RPC: RpcV2>: Send + Sync { +pub trait HandleRpc: Send + Sync + 'static { + type Input<'a>: Send + Sync + 'a; type Output; - fn handle_rpc( - &self, - rpc: Outbound<'_, RPC>, - ) -> impl Future> + Send - where - RPC: 'a; + fn handle_rpc<'a>( + &'a self, + rpc: Outbound, + input: &'a Self::Input<'a>, + ) -> impl Future> + Send + 'a; } +type RpcHandlerInput<'a, H, RPC> = >::Input<'a>; +type RpcHandlerOutput = >::Output; + /// RPC [`Client`] config. #[derive(Clone, Debug)] pub struct Config { @@ -232,14 +232,14 @@ impl Client { /// /// No-op, doesn't do anything with the [`Connection`]. #[derive(Clone, Copy, Debug, Default)] -pub struct DefaultConnectionHandler; +pub struct ConnectionHandler; -impl HandleConnection for DefaultConnectionHandler +impl HandleConnection for ConnectionHandler where - API: Api, + API: Api, { fn new_rpc_handler(&self) -> ::RpcHandler { - DefaultRpcHandler + RpcHandler } async fn handle_connection(&self, _conn: &Connection, _params: &()) -> Result<()> { @@ -248,27 +248,35 @@ where } /// Outbound RPC of a specific type. -pub struct Outbound<'a, RPC: RpcV2> { - rpc: &'a RPC, - stream: OutboundStream, -} - -struct OutboundStream { +pub struct Outbound { + #[allow(clippy::type_complexity)] send: SinkMapErr, fn(transport2::Error) -> Error>, + + #[allow(clippy::type_complexity)] recv: MapErr, fn(transport2::Error) -> Error>, } -impl<'a, RPC: RpcV2> Outbound<'a, RPC> { - /// Returns the underlying RPC, [`Sink`] of requests and [`Stream`] of - /// responses. - pub fn unpack( +impl Outbound { + /// Returns [`Sink`] of outbound requests. + pub fn sink(&mut self) -> &mut impl for<'a> Sink<&'a BorrowedRequest<'a, RPC>, Error = Error> { + &mut self.send + } + + /// Returns [`Stream`] of inbound responses. + pub fn stream(&mut self) -> &mut impl Stream> { + &mut self.recv + } +} + +impl Outbound { + /// Returns mutable references to the underlying request/response streams. + pub fn streams_mut( &mut self, ) -> ( - &RPC, - &mut (impl for<'r> Sink<&'r BorrowedRequest<'r, RPC>, Error = Error> + 'static), + &mut (impl for<'a, 'b> Sink<&'a BorrowedRequest<'b, RPC>, Error = Error> + 'static), &mut impl Stream>, ) { - (&self.rpc, &mut self.stream.send, &mut self.stream.recv) + (&mut self.send, &mut self.recv) } } @@ -295,6 +303,10 @@ struct ConnectionInner { rpc_handler: API::RpcHandler, } +pub fn assert_send_future(s: impl Future + Send) -> impl Future + Send { + s +} + impl Connection { /// Returns [`SocketAddrV4`] of the remote peer. pub fn remote_peer_addr(&self) -> &SocketAddrV4 { @@ -333,37 +345,44 @@ impl Connection { } /// Sends the provided RPC over this [`Connection`]. - pub fn send<'a: 'b, 'b, RPC, Output>( + pub fn send<'a, RPC: RpcV2>( &'a self, - rpc: &'b RPC, - ) -> Result> + 'b> + input: &'a RpcHandlerInput<'a, API::RpcHandler, RPC>, + ) -> Result>> + Send + 'a> where - RPC: RpcV2 + 'b, - API::RpcHandler: HandleRpc<'b, RPC, Output = Output>, + API::RpcHandler: HandleRpc, { - let stream = self.new_outbound_stream::().tap_err(|err| { + let rpc = self.new_outbound_rpc::().tap_err(|err| { if err.requires_reconnect() { self.reconnect(); } })?; - Ok(async move { + let fut = async move { self.inner .rpc_handler - .handle_rpc(Outbound { rpc, stream }) + .handle_rpc(rpc, input) .await .tap_err(|err| { if err.0.requires_reconnect() { self.reconnect(); } }) - }) + }; + + // Ok(fut) + + Ok(assert_send_future(fut)) } - fn new_outbound_stream(&self) -> Result, ErrorInner> { + // pub fn rpc_handler(&self) -> &API::RpcHandler { + // &self.inner.rpc_handler + // } + + fn new_outbound_rpc(&self) -> Result, ErrorInner> { let quic = self.inner.watch_rx.borrow(); let Some(conn) = quic.as_ref() else { - return Err(ErrorInner::NotConnected.into()); + return Err(ErrorInner::NotConnected); }; // `open_bi` only blocks if there are too many outbound streams. @@ -380,7 +399,7 @@ impl Connection { let (recv, send) = BiDirectionalStream::new(tx, rx).upgrade::(); - Ok(OutboundStream { + Ok(Outbound { send: SinkExt::<&RPC::Request>::sink_map_err(send, |err: transport2::Error| { Error::new(err) }), @@ -432,65 +451,32 @@ impl Connection { } } -/// Default implementation of [`RpcHandler`]. +/// Default implementation of [`HandleRpc`]. /// -/// Automatically implements [`RpcHandler`] for all (unary)[rpc::UnaryV2] RPCs. +/// Automatically implements [`HandleRpc`] for all [`UnaryRpc`]s. /// -/// For your (streaming)[rpc::StreamingV2] RPCs you'll need to provide a manual -/// implementation of [`RpcHandler`] for this type. +/// You'll need to provide a manual implementation of [`HandleRpc`] for your +/// custom RPCs. #[derive(Clone, Copy, Debug, Default)] -pub struct DefaultRpcHandler; +pub struct RpcHandler; -impl<'a, const ID: u8, Req, Resp, C> HandleRpc<'a, UnaryV2<'a, ID, Req, Resp, C>> - for DefaultRpcHandler -where - Req: MessageOwned, - Resp: MessageOwned, - C: Codec + Codec, -{ - type Output = Resp; - - async fn handle_rpc( - &self, - mut outbound: Outbound<'_, UnaryV2<'a, ID, Req, Resp, C>>, - ) -> Result { - let (rpc, tx, rx) = outbound.unpack(); +impl HandleRpc for RpcHandler { + type Input<'a> = BorrowedRequest<'a, RPC>; + type Output = RPC::Response; - tx.send(rpc.request).await?; + async fn handle_rpc<'a>( + &'a self, + mut rpc: Outbound, + req: &'a BorrowedRequest<'a, RPC>, + ) -> Result { + let (tx, rx) = rpc.streams_mut(); + tx.send(req).await?; rx.next() .await .ok_or_else(|| Error::new(transport2::Error::StreamFinished))? } } -impl<'a, const ID: u8, Req, Resp, C> UnaryV2<'a, ID, Req, Resp, C> -where - Req: MessageOwned, - Resp: MessageOwned, - C: Codec + Codec, -{ - pub fn new(request: &'a Req::Borrowed<'a>) -> Self { - Self { - request, - _marker: PhantomData, - } - } - - /// Sends this unary RPC over the provided connection. - pub fn send( - conn: &'a Connection, - request: &'a Req::Borrowed<'a>, - ) -> Result> + 'a> - where - API::RpcHandler: HandleRpc<'a, Self, Output = Output>, - { - conn.send(Self { - request, - _marker: PhantomData, - }) - } -} - /// RPC [`Client`] error. #[derive(Debug, thiserror::Error)] #[error(transparent)] diff --git a/crates/rpc/src/lib.rs b/crates/rpc/src/lib.rs index b495348e..baa94b57 100644 --- a/crates/rpc/src/lib.rs +++ b/crates/rpc/src/lib.rs @@ -4,14 +4,7 @@ use { derive_more::{derive::TryFrom, Display}, serde::{de::DeserializeOwned, Deserialize, Serialize}, - std::{ - borrow::Cow, - fmt::Debug, - future::Future, - marker::PhantomData, - net::SocketAddr, - str::FromStr, - }, + std::{borrow::Cow, fmt::Debug, marker::PhantomData, net::SocketAddr, str::FromStr}, transport::Codec, transport2::Codec as CodecV2, }; @@ -46,85 +39,56 @@ mod test; const PROTOCOL_VERSION: u32 = 0; /// RPC API specification. -/// -/// Expected to be implemented on unit types and should not contain data. -/// -/// # Example -/// -/// ``` -/// use wcn_rpc::ApiName; -/// -/// struct MyApi; -/// -/// enum RpcId { -/// CreateUser = 0, -/// UpdateUser = 1, -/// DeleteUser = 2, -/// } -/// -/// impl wcn_rpc::Api for MyApi { -/// const NAME: ApiName = ApiName::new("myApi"); -/// type RpcId = RpcId; -/// } -/// ``` pub trait Api: Clone + Send + Sync + 'static { /// [`ApiName`] of this [`Api`]. const NAME: ApiName; /// `enum` representation of all RPC IDs of this [`Api`]. - /// - /// Should be convertible from/into `u8`. - type RpcId: Copy + Into + TryFrom; + type RpcId: Copy + Into + TryFrom + Send + Sync + 'static; } /// [`Api`] name. pub type ApiName = ServerName; /// Remote procedure call. -pub trait RpcV2: Sized + Send + Sync { +pub trait RpcV2: Sized + Send + Sync + 'static { /// ID of this [`Rpc`]. const ID: u8; /// Request type of this [`Rpc`]. - type Request: MessageOwned; + type Request: MessageV2; /// Response type of this [`Rpc`]. - type Response: MessageOwned; + type Response: MessageV2; /// Serialization codec of this [`Rpc`]. type Codec: CodecV2 + CodecV2; - - #[cfg(feature = "client")] - /// Sends this RPC over the provided connection. - fn send<'a, API: client2::Api, Output>( - &'a self, - conn: &'a client2::Connection, - ) -> client2::Result> + 'a> - where - API::RpcHandler: client2::HandleRpc<'a, Self, Output = Output>, - { - conn.send(self) - } } -type BorrowedRequest<'a, RPC> = <::Request as MessageOwned>::Borrowed<'a>; -type BorrowedResponse<'a, RPC> = <::Response as MessageOwned>::Borrowed<'a>; +/// [`RpcV2::Request`]. +pub type Request = ::Request; -pub struct UnaryV2< - 'a, - const ID: u8, - Req: MessageOwned, - Resp: MessageOwned, - C: CodecV2 + CodecV2, -> { - pub request: &'a Req::Borrowed<'a>, - pub _marker: PhantomData<(Req, Resp, C)>, +/// [`RpcV2::Response`]. +pub type Response = ::Response; + +/// [`MessageV2::Borrowed`] of [`RpcV2::Request`]. +pub type BorrowedRequest<'a, RPC> = <::Request as MessageV2>::Borrowed<'a>; + +/// [`MessageV2::Borrowed`] of [`RpcV2::Response`]. +pub type BorrowedResponse<'a, RPC> = <::Response as MessageV2>::Borrowed<'a>; + +/// Request-response RPC. +pub trait UnaryRpc: RpcV2 {} + +/// Default implementation of [`UnaryRpc`]. +pub struct UnaryV2 + CodecV2> { + _marker: PhantomData<(Req, Resp, C)>, } -impl<'a, const ID: u8, Req, Resp, C> RpcV2 for UnaryV2<'a, ID, Req, Resp, C> +impl RpcV2 for UnaryV2 where - Req: MessageOwned, - Resp: MessageOwned, + Req: MessageV2, + Resp: MessageV2, C: CodecV2 + CodecV2, { const ID: u8 = ID; @@ -133,31 +97,23 @@ where type Codec = C; } -// impl<'s, RPC> RpcV2 for RPC -// where -// RPC: UnaryRpcV2<'s>, -// { -// const ID: u8 = RPC::ID; - -// type Request<'a> = Self; - -// type Response<'a> = Self::Request<'a>; - -// type Codec = Self::Codec; - -// type Output = as ToOwned>::Owned; -// } - -pub trait MessageOwned: DeserializeOwned + Serialize + Unpin + Sync + Send + 'static { - type Borrowed<'a>: MessageBorrowed; +impl UnaryRpc for UnaryV2 +where + Req: MessageV2, + Resp: MessageV2, + C: CodecV2 + CodecV2, +{ } -pub trait MessageBorrowed: Serialize + Unpin + Sync + Send {} +/// RPC message. +pub trait MessageV2: DeserializeOwned + Serialize + Unpin + Sync + Send + 'static { + type Borrowed<'a>: BorrowedMessage; +} -impl MessageBorrowed for T where T: Serialize + Unpin + Sync + Send {} +/// Borrowed [Message][`MessageV2`]. +pub trait BorrowedMessage: Serialize + Unpin + Sync + Send {} -// type OwnedResponse = <::Response<'static> as -// ToOwned>::Owned; +impl BorrowedMessage for T where T: Serialize + Unpin + Sync + Send {} /// Error codes produced by this module. pub mod error_code { @@ -450,21 +406,25 @@ enum ConnectionStatusCode { Unauthorized = -3, } -impl MessageOwned for Result +impl MessageV2 for Result where - T: MessageOwned, - E: MessageOwned, + T: MessageV2, + E: MessageV2, { type Borrowed<'a> = Result, E::Borrowed<'a>>; } -impl MessageOwned for Option +impl MessageV2 for Option where - T: MessageOwned, + T: MessageV2, { type Borrowed<'a> = Option>; } -impl MessageOwned for () { +impl MessageV2 for () { type Borrowed<'a> = (); } + +impl MessageV2 for u64 { + type Borrowed<'a> = Self; +} diff --git a/crates/rpc/src/server2.rs b/crates/rpc/src/server2.rs index 226f50b6..2011eaae 100644 --- a/crates/rpc/src/server2.rs +++ b/crates/rpc/src/server2.rs @@ -13,6 +13,7 @@ use { ConnectionStatusCode, RpcV2, ServerName, + UnaryRpc, }, derive_where::derive_where, futures::{ @@ -22,6 +23,7 @@ use { Sink, SinkExt, Stream, + StreamExt, TryFutureExt as _, TryStreamExt as _, }, @@ -34,7 +36,7 @@ use { sync::{OwnedSemaphorePermit, Semaphore}, }, wc::{ - future::FutureExt as _, + future::{FutureExt as _, StaticFutureExt}, metrics::{self, future_metrics, Enum as _, EnumLabel, FutureExt as _, StringLabel}, }, }; @@ -54,41 +56,73 @@ pub trait HandleConnection: Clone + Send + Sync + 'static { } /// Handler of [`Inbound`] RPCs. -pub trait HandleRpc { +pub trait HandleRpc: Send + Sync { /// Handles the provided [`Inbound`] RPC. - fn handle_rpc(&self, rpc: &mut Inbound) -> impl Future> + Send; + fn handle_rpc<'a>( + &'a self, + rpc: &'a mut Inbound, + ) -> impl Future> + Send + 'a; } -pub trait Rpc: RpcV2 { - /// Handle this RPC using the provided handler. - /// - /// Caller is expected to ensure that the [`InboundRpc::id()`] is correct. - fn handle>( - rpc: InboundRpc, - handler: &impl HandleRpc, - ) -> impl Future> { - if cfg!(debug_assertions) { - let id: u8 = rpc.id.into(); - assert_eq!(id, Self::ID); - } +// /// [`HandleRpc`] specialization for [`UnaryRpc`]s. +// pub trait HandleUnaryRpc: Send + Sync { +// /// Handles the provided RPC request. +// fn handle_unary_rpc( +// &self, +// request: RPC::Request, +// responder: Responder<'_, RPC>, +// ) -> impl Future> + Send; +// } + +/// [`HandleRpc`] specialization for [`UnaryRpc`]s. +pub trait HandleRequest: Send + Sync { + fn handle_request( + &self, + request: RPC::Request, + ) -> impl Future + Send + '_; +} - let (recv, send) = rpc.stream.upgrade(); +// /// [`UnaryRpc`] responder. +// pub trait Responder: Send { +// /// Sends an RPC response. +// fn respond(self, response: &BorrowedResponse) -> impl Future> + Send; } - let mut rpc = Inbound { - send: SinkExt::<&Self::Response>::sink_map_err(send, |err: transport2::Error| { - Error::new(err) - }), - recv: recv.map_err(Error::new), - _permit: rpc.permit, - }; +// struct ResponderImpl { +// sink: SinkMapErr, fn(transport2::Error) -> Error>, +// } - async move { handler.handle_rpc(&mut rpc).await } - .with_metrics(future_metrics!("wcn_rpc_server_rpc")) +// impl<'a, RPC: UnaryRpc> Responder for ResponderImpl<'a, RPC> { +// fn respond(self, response: &BorrowedResponse) -> impl Future> + Send { self.sink.send(response) +// } +// } + +impl HandleRpc for H +where + RPC: UnaryRpc, + H: HandleRequest, +{ + fn handle_rpc<'a>( + &'a self, + rpc: &'a mut Inbound, + ) -> impl Future> + Send + 'a { + async { + let req = rpc + .recv + .next() + .await + .ok_or_else(|| Error::new(transport2::Error::StreamFinished))??; + + let resp = self.handle_request(req).await; + + rpc.send.send(&resp).await?; + + Ok(()) + } } } -impl Rpc for RPC where RPC: RpcV2 {} - /// RPC server config. pub struct Config { /// Name of the server. For metrics purposes only. @@ -395,6 +429,37 @@ pub struct InboundRpc { permit: OwnedSemaphorePermit, } +impl InboundRpc { + /// Handles this RPC using the provided handler. + pub fn handle( + self, + handler: &impl HandleRpc, + ) -> impl Future> + Send + '_ { + async move { handler.handle_rpc(&mut self.upgrade()).await } + .with_metrics(future_metrics!("wcn_rpc_server_rpc")) + } + + /// Upgrades this untyped [`InboundRpc`] into a typed one. + /// + /// Caller is expected to ensure that the [`InboundRpc::id()`] is correct. + fn upgrade(self) -> Inbound { + if cfg!(debug_assertions) { + let id: u8 = self.id.into(); + assert_eq!(id, RPC::ID); + } + + let (recv, send) = self.stream.upgrade(); + + Inbound { + send: SinkExt::<&RPC::Response>::sink_map_err(send, |err: transport2::Error| { + Error::new(err) + }), + recv: recv.map_err(Error::new), + _permit: self.permit, + } + } +} + impl InboundRpc { /// Returns ID of this [`InboundRpc`]. pub fn id(&self) -> API::RpcId { @@ -404,20 +469,40 @@ impl InboundRpc { /// Inbound RPC of a specific type. pub struct Inbound { + #[allow(clippy::type_complexity)] recv: MapErr, fn(transport2::Error) -> Error>, + + #[allow(clippy::type_complexity)] send: SinkMapErr, fn(transport2::Error) -> Error>, + _permit: OwnedSemaphorePermit, } impl Inbound { - /// Returns [`Stream`] of inbound responses. - pub fn stream(&mut self) -> &mut impl Stream> { - &mut self.recv + /// Returns mutable references to the underlying request/response streams. + pub fn streams_mut( + &mut self, + ) -> ( + &mut impl Stream>, + &mut (impl for<'a, 'b> Sink<&'a BorrowedResponse<'b, RPC>, Error = Error> + 'static), + ) { + (&mut self.recv, &mut self.send) } +} + +pub struct Responder<'a, RPC: UnaryRpc> { + rpc: &'a mut Inbound, +} - /// Returns [`Sink`] of outbound requests. - pub fn sink(&mut self) -> &mut impl for<'a> Sink<&'a BorrowedResponse<'a, RPC>, Error = Error> { - &mut self.send +impl<'a, RPC: UnaryRpc> Responder<'a, RPC> { + pub fn respond<'r>( + self, + response: &'r BorrowedResponse<'r, RPC>, + ) -> impl Future> + Send + 'r + where + 'a: 'r, + { + self.rpc.send.send(response) } } @@ -427,6 +512,34 @@ impl Connection<'_, API> { &self.inner.remote_peer_id } + /// Handles this [`Connection`] by handling all [`InboundRpc`] using the + /// provided `handler_fn`. + pub async fn handle( + &self, + rpc_handler: &H, + handler_fn: fn(InboundRpc, H) -> Fut, + ) -> Result<()> + where + H: Clone + Send + Sync + 'static, + Fut: Future> + Send + 'static, + { + loop { + let rpc = self.accept_rpc().await?; + let handler = rpc_handler.clone(); + + async move { handler_fn(rpc, handler).await }.spawn(); + } + } + + /// Handles the next [`InboundRpc`] using the provided `handler_fn`. + pub async fn handle_rpc(&self, f: impl FnOnce(InboundRpc) -> F) -> Result<()> + where + F: Future> + Send, + { + let rpc = self.accept_rpc().await?; + f(rpc).await + } + /// Accepts the next [`InboundRpc`]. pub async fn accept_rpc(&self) -> Result> { loop { diff --git a/crates/rpc/src/transport2.rs b/crates/rpc/src/transport2.rs index 369cc82a..533e1109 100644 --- a/crates/rpc/src/transport2.rs +++ b/crates/rpc/src/transport2.rs @@ -1,11 +1,10 @@ use { - crate::{Message, MessageOwned}, + crate::MessageV2, bytes::{BufMut as _, Bytes, BytesMut}, futures::{stream::MapErr, Sink, TryStreamExt}, pin_project::pin_project, serde::{Deserialize, Serialize}, std::{ - borrow::Cow, io, pin::Pin, task::{self, ready}, @@ -16,14 +15,14 @@ use { }; /// Serialization codec. -pub trait Codec: +pub trait Codec: for<'a> Serializer> + Serializer + Deserializer { } impl Codec for C where - M: MessageOwned, + M: MessageV2, C: for<'a> Serializer> + Serializer + Deserializer, { } @@ -58,7 +57,7 @@ where type Error = io::Error; fn deserialize(self: Pin<&mut Self>, src: &BytesMut) -> Result { - postcard::from_bytes(&src).map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err)) + postcard::from_bytes(src).map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err)) } } @@ -93,7 +92,7 @@ impl BiDirectionalStream { } } - pub(crate) fn upgrade>( + pub(crate) fn upgrade>( self, ) -> (RecvStream, SendStream) { ( @@ -155,13 +154,13 @@ where /// [`Stream`] of inbound [`Message`]s. #[pin_project] -pub struct RecvStream>( +pub struct RecvStream>( #[allow(clippy::type_complexity)] #[pin] Framed Error>, T, T, C>, ); -impl> Stream for RecvStream { +impl> Stream for RecvStream { type Item = Result; fn poll_next( diff --git a/crates/storage_api2/Cargo.toml b/crates/storage_api2/Cargo.toml index fe419c01..b3bd1ed8 100644 --- a/crates/storage_api2/Cargo.toml +++ b/crates/storage_api2/Cargo.toml @@ -17,6 +17,7 @@ wc = { workspace = true, features = ["future", "metrics"] } auth = { workspace = true } derive_more = { workspace = true, features = ["from", "try_into"] } strum = { workspace = true , features = ["derive"] } +tap = { workspace = true } wcn_rpc = { workspace = true } serde = "1" diff --git a/crates/storage_api2/src/lib.rs b/crates/storage_api2/src/lib.rs index 67bea47c..c8136908 100644 --- a/crates/storage_api2/src/lib.rs +++ b/crates/storage_api2/src/lib.rs @@ -5,7 +5,8 @@ pub use { wcn_rpc::{identity, Multiaddr, PeerAddr, PeerId}, }; use { - futures::{FutureExt as _, TryFutureExt as _}, + futures::FutureExt as _, + serde::{Deserialize, Serialize}, std::{borrow::Cow, future::Future, str::FromStr, time::Duration}, time::OffsetDateTime as DateTime, }; @@ -14,13 +15,13 @@ pub mod operation; pub use operation::Operation; #[cfg(any(feature = "rpc_client", feature = "rpc_server"))] -mod rpc; +pub mod rpc; /// Namespace within a WCN cluster. /// /// Namespaces are isolated and every [`StorageApi`] [`Operation`] gets executed /// on a specific [`Namespace`]. -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Copy, Debug, Serialize, Deserialize)] pub struct Namespace { /// ID of the node operator to which this namespace belongs. /// @@ -35,7 +36,7 @@ pub struct Namespace { /// /// Keyspace changes after data rebalancing within a WCN Cluster. /// For data consistency reasons WCN Coordinators and WCN Replicas need to -/// operate using same [`KeyspaceVersion`]. So for Coordinator->Replica +/// operate using the same [`KeyspaceVersion`]. So for Coordinator->Replica /// [`StorageApi`] calls [`Operation`]s need to include the expected /// [`KeyspaceVersion`]. /// @@ -58,26 +59,32 @@ pub trait StorageApi: Clone + Send + Sync + 'static { /// Executes the provided [`operation::Get`]. fn get<'a>( &'a self, - get: operation::Get<'a>, - ) -> impl Future>> + Send + 'a { + get: &'a operation::Get<'a>, + ) -> impl Future>>> + Send + 'a { self.execute(get).map(operation::Output::downcast_result) } /// Executes the provided [`operation::Set`]. - fn set<'a>(&'a self, set: operation::Set<'a>) -> impl Future> + Send { + fn set<'a>( + &'a self, + set: &'a operation::Set<'a>, + ) -> impl Future> + Send + 'a { self.execute(set).map(operation::Output::downcast_result) } /// Executes the provided [`operation::Del`]. - fn del<'a>(&'a self, del: operation::Del<'a>) -> impl Future> + Send { + fn del<'a>( + &'a self, + del: &'a operation::Del<'a>, + ) -> impl Future> + Send + 'a { self.execute(del).map(operation::Output::downcast_result) } /// Executes the provided [`operation::GetExp`]. fn get_exp<'a>( &'a self, - get_exp: operation::GetExp<'a>, - ) -> impl Future>> + Send { + get_exp: &'a operation::GetExp<'a>, + ) -> impl Future>> + Send + 'a { self.execute(get_exp) .map(operation::Output::downcast_result) } @@ -85,8 +92,8 @@ pub trait StorageApi: Clone + Send + Sync + 'static { /// Executes the provided [`operation::SetExp`]. fn set_exp<'a>( &'a self, - set_exp: operation::SetExp<'a>, - ) -> impl Future> + Send { + set_exp: &'a operation::SetExp<'a>, + ) -> impl Future> + Send + 'a { self.execute(set_exp) .map(operation::Output::downcast_result) } @@ -94,26 +101,32 @@ pub trait StorageApi: Clone + Send + Sync + 'static { /// Executes the provided [`operation::HGet`]. fn hget<'a>( &'a self, - hget: operation::HGet<'a>, - ) -> impl Future>> + Send { + hget: &'a operation::HGet<'a>, + ) -> impl Future>>> + Send + 'a { self.execute(hget).map(operation::Output::downcast_result) } /// Executes the provided [`operation::HSet`]. - fn hset<'a>(&'a self, hset: operation::HSet<'a>) -> impl Future> + Send { + fn hset<'a>( + &'a self, + hset: &'a operation::HSet<'a>, + ) -> impl Future> + Send + 'a { self.execute(hset).map(operation::Output::downcast_result) } /// Executes the provided [`operation::HDel`]. - fn hdel<'a>(&'a self, hdel: operation::HDel<'a>) -> impl Future> + Send { + fn hdel<'a>( + &'a self, + hdel: &'a operation::HDel<'a>, + ) -> impl Future> + Send + 'a { self.execute(hdel).map(operation::Output::downcast_result) } /// Executes the provided [`operation::HGetExp`]. fn hget_exp<'a>( &'a self, - hget_exp: operation::HGetExp<'a>, - ) -> impl Future>> + Send { + hget_exp: &'a operation::HGetExp<'a>, + ) -> impl Future>> + Send + 'a { self.execute(hget_exp) .map(operation::Output::downcast_result) } @@ -121,8 +134,8 @@ pub trait StorageApi: Clone + Send + Sync + 'static { /// Executes the provided [`operation::HSetExp`]. fn hset_exp<'a>( &'a self, - hset_exp: operation::HSetExp<'a>, - ) -> impl Future> + Send { + hset_exp: &'a operation::HSetExp<'a>, + ) -> impl Future> + Send + 'a { self.execute(hset_exp) .map(operation::Output::downcast_result) } @@ -130,113 +143,93 @@ pub trait StorageApi: Clone + Send + Sync + 'static { /// Executes the provided [`operation::HCard`]. fn hcard<'a>( &'a self, - hcard: operation::HCard<'a>, - ) -> impl Future> + Send { + hcard: &'a operation::HCard<'a>, + ) -> impl Future> + Send + 'a { self.execute(hcard).map(operation::Output::downcast_result) } /// Executes the provided [`operation::HScan`]. fn hscan<'a>( &'a self, - hscan: operation::HScan<'a>, - ) -> impl Future> + Send { + hscan: &'a operation::HScan<'a>, + ) -> impl Future>> + Send + 'a { self.execute(hscan).map(operation::Output::downcast_result) } /// Executes the provided [`StorageApi`] [`Operation`]. fn execute<'a>( &'a self, - operation: impl Into> + Send, - ) -> impl Future> + Send; + operation: impl Into> + Send + 'a, + ) -> impl Future>> + Send + 'a; } /// Raw bytes. pub type Bytes<'a> = Cow<'a, [u8]>; -/// Key in a KV storage. -#[derive(Clone, Debug)] -pub struct Key<'a>(pub Bytes<'a>); - -/// Value in a KV storage. -#[derive(Clone, Debug, Eq, PartialEq)] -pub struct Value<'a>(pub Bytes<'a>); - -/// Subkey of a [`MapEntry`]. -#[derive(Clone, Debug, Eq, PartialEq)] -pub struct Field<'a>(pub Bytes<'a>); - -/// Basic KV storage entry. -#[derive(Clone, Debug)] -pub struct Entry<'a> { - /// [`Key`] of this [`Entry`]. - pub key: Key<'a>, - - /// [`Value`] of this [`Entry`]. - pub value: Value<'a>, +/// Raw [`Bytes`] value with metadata related to this value. +/// +/// [`Record`]s are being deleted from WCN Database after specified +/// [`Record::expiration`] time. +/// +/// A [`Record`] can not be overwritten by another [`Record`] with a lesser +/// [version][`Record::version`]. +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +pub struct Record<'a> { + /// Value of this [`Record`]. + pub value: Bytes<'a>, - /// Expiration time of this [`Entry`]. - pub expiration: EntryExpiration, + /// Expiration time of [`Record`]. + pub expiration: RecordExpiration, - /// Version of this [`Entry`]. - pub version: EntryVersion, + /// Version of this [`Record`]. + pub version: RecordVersion, } -/// Map entry in which each [`Value`] is associated with both [`Key`] and subkey -/// ([`Field`]). -#[derive(Clone, Debug)] -pub struct MapEntry<'a> { - /// [`Key`] of this [`Entry`]. - pub key: Key<'a>, - - /// [`Field`] of this [`Entry`]. - pub field: Field<'a>, - - /// [`Value`] of this [`Entry`]. - pub value: Value<'a>, - - /// Expiration time of this [`Entry`]. - pub expiration: EntryExpiration, - - /// Version of this [`Entry`]. - pub version: EntryVersion, +impl<'a> Record<'a> { + /// Converts `Self` into 'static. + pub fn into_static(self) -> Record<'static> { + Record { + value: Cow::Owned(self.value.into_owned()), + expiration: self.expiration, + version: self.version, + } + } } -/// [`Entry`]/[`MapEntry`] without the associated [`Key`]/[`Field`]. -#[derive(Clone, Debug, Eq, PartialEq)] -pub struct Record { - /// Value of this [`Record`]. - pub value: Value<'static>, - - /// Expiration time of the associated [`Entry`]/[`MapEntry`]. - pub expiration: EntryExpiration, +/// Entry within a Map. +/// +/// Maps are a separate data type of WCN Datbase, similar to Redis Hashes. +/// They differ from regular KV pairs by having a subkey (AKA +/// [field][MapEntry::field]). +/// +/// Each Map key contains an ordered set of entries (ascending order by +/// [`MapEntry::field`]). +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct MapEntry<'a> { + /// Subkey of this [`MapEntry`]. + pub field: Bytes<'a>, - /// Version of the associated [`Entry`]/[`MapEntry`]. - pub version: EntryVersion, + /// [`Record`] of this [`MapEntry`]. + pub record: Record<'a>, } -/// [`MapEntry`] without the associated [`Key`]. -#[derive(Clone, Debug, PartialEq, Eq)] -pub struct MapRecord { - /// Field of this [`MapRecord`]. - pub field: Field<'static>, - - /// Value of this [`MapRecord`]. - pub value: Value<'static>, - - /// Expiration time of the associated [`MapEntry`]. - pub expiration: EntryExpiration, - - /// Version of the associated [`MapEntry`]. - pub version: EntryVersion, +impl<'a> MapEntry<'a> { + /// Converts `Self` into 'static. + pub fn into_static(self) -> MapEntry<'static> { + MapEntry { + field: Cow::Owned(self.field.into_owned()), + record: self.record.into_static(), + } + } } -/// [`Entry`]/[`MapEntry`] expiration time. -#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] -pub struct EntryExpiration { +/// Expiration time of a [`Record`]. +#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)] +pub struct RecordExpiration { unix_timestamp_secs: u64, } -impl From for EntryExpiration { +impl From for RecordExpiration { fn from(dur: Duration) -> Self { Self { unix_timestamp_secs: (DateTime::now_utc() + dur).unix_timestamp() as u64, @@ -244,7 +237,7 @@ impl From for EntryExpiration { } } -impl From for EntryExpiration { +impl From for RecordExpiration { fn from(dt: DateTime) -> Self { Self { unix_timestamp_secs: dt.unix_timestamp() as u64, @@ -252,19 +245,9 @@ impl From for EntryExpiration { } } -impl EntryExpiration { - pub fn from_unix_timestamp_secs(timestamp: u64) -> Self { - Self { - unix_timestamp_secs: timestamp, - } - } - - pub fn unix_timestamp_secs(&self) -> u64 { - self.unix_timestamp_secs - } - - pub fn to_duration(&self) -> Duration { - let expiry = DateTime::from_unix_timestamp(self.unix_timestamp_secs as i64) +impl From for Duration { + fn from(exp: RecordExpiration) -> Self { + let expiry = DateTime::from_unix_timestamp(exp.unix_timestamp_secs as i64) .unwrap_or(DateTime::UNIX_EPOCH); (expiry - DateTime::now_utc()) @@ -273,15 +256,18 @@ impl EntryExpiration { } } -/// [`Entry`]/[`MapEntry`] version. -#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] -pub struct EntryVersion { - unix_timestamp_micros: u64, +/// Version of a [`Record`]. +/// +/// [`RecordVersion`] is a local client-side generated timestamp. +#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)] +pub struct RecordVersion { + /// UNIX timestamp (microseconds) representation of this [`RecordVersion`]. + pub unix_timestamp_micros: u64, } -impl EntryVersion { - #[allow(clippy::new_without_default)] - pub fn new() -> EntryVersion { +impl RecordVersion { + /// Generates a new [`RecordVersion`] using the current timestamp. + pub fn now() -> RecordVersion { Self { unix_timestamp_micros: std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) @@ -289,35 +275,37 @@ impl EntryVersion { .as_micros() as u64, } } - - pub fn from_unix_timestamp_micros(timestamp: u64) -> Self { - Self { - unix_timestamp_micros: timestamp, - } - } - - pub fn unix_timestamp_micros(&self) -> u64 { - self.unix_timestamp_micros - } } -/// Page of [`MapRecord`]s. -#[derive(Clone, Debug, PartialEq, Eq)] -pub struct MapPage { - /// [`MapRecords`] of this [`Page`]. - pub records: Vec, +/// Page of [map entries][MapEntry]. +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct MapPage<'a> { + /// [`MapRecord`]s of this [`Page`]. + pub entries: Vec>, /// Indicator of whether there's a next [`Page`] or not. pub has_next: bool, } -impl MapPage { +impl<'a> MapPage<'a> { /// Returns cursor pointing to the next [`Page`] if there is one. - pub fn next_page_cursor(&self) -> Option<&Field> { + pub fn next_page_cursor(&self) -> Option<&Bytes<'a>> { self.has_next - .then(|| self.records.last().map(|entry| &entry.field)) + .then(|| self.entries.last().map(|entry| &entry.field)) .flatten() } + + /// Converts `Self` into 'static. + pub fn into_static(self) -> MapPage<'static> { + MapPage { + entries: self + .entries + .into_iter() + .map(MapEntry::into_static) + .collect(), + has_next: self.has_next, + } + } } impl FromStr for Namespace { @@ -345,14 +333,15 @@ impl FromStr for Namespace { } } +/// Error of parsing [`Namespace`] from a string. #[derive(Debug, thiserror::Error)] #[error("Invalid namespace: {_0}")] pub struct InvalidNamespaceError(Cow<'static, str>); -/// Result of [`StorageApi`]. +/// [`StorageApi`] result. pub type Result = std::result::Result; -/// Error of [`StorageApi`]. +/// [`StorageApi`] error. #[derive(Debug, thiserror::Error)] #[error("{kind:?}({details:?})")] pub struct Error { @@ -385,10 +374,6 @@ pub enum ErrorKind { /// Transport error. Transport, - // NOTE: This is effectively a bug, it's here just for completeness. - /// [`operation::WrongOutputError`]. - WrongOperationOutput, - /// Unable to determine [`ErrorKind`] of an [`Error`]. Unknown, } diff --git a/crates/storage_api2/src/operation.rs b/crates/storage_api2/src/operation.rs index 7458be38..17600e64 100644 --- a/crates/storage_api2/src/operation.rs +++ b/crates/storage_api2/src/operation.rs @@ -2,21 +2,22 @@ use { crate::{ - Entry, - EntryExpiration, - EntryVersion, - Field, - Key, + Bytes, + Error, + ErrorKind, KeyspaceVersion, MapEntry, MapPage, - MapRecord, Namespace, Record, + RecordExpiration, + RecordVersion, + Result, }, derive_more::derive::{From, TryInto}, - std::any::type_name, + serde::{Deserialize, Serialize}, strum::{EnumDiscriminants, IntoDiscriminant}, + tap::TapFallible as _, wc::metrics::{self, enum_ordinalize::Ordinalize}, }; @@ -25,19 +26,19 @@ use { #[strum_discriminants(name(Name))] #[strum_discriminants(derive(Ordinalize))] pub enum Operation<'a> { - Get(Get<'a>), - Set(Set<'a>), - Del(Del<'a>), - GetExp(GetExp<'a>), - SetExp(SetExp<'a>), + Get(&'a Get<'a>), + Set(&'a Set<'a>), + Del(&'a Del<'a>), + GetExp(&'a GetExp<'a>), + SetExp(&'a SetExp<'a>), - HGet(HGet<'a>), - HSet(HSet<'a>), - HDel(HDel<'a>), - HGetExp(HGetExp<'a>), - HSetExp(HSetExp<'a>), - HCard(HCard<'a>), - HScan(HScan<'a>), + HGet(&'a HGet<'a>), + HSet(&'a HSet<'a>), + HDel(&'a HDel<'a>), + HGetExp(&'a HGetExp<'a>), + HSetExp(&'a HSetExp<'a>), + HCard(&'a HCard<'a>), + HScan(&'a HScan<'a>), } impl metrics::Enum for Name { @@ -66,15 +67,15 @@ impl<'a> Operation<'a> { } /// Returns key of this [`Operation`]. - pub fn key(&self) -> &Key<'a> { + pub fn key(&self) -> &Bytes<'a> { match self { Self::Get(get) => &get.key, - Self::Set(set) => &set.entry.key, + Self::Set(set) => &set.key, Self::Del(del) => &del.key, Self::GetExp(get_exp) => &get_exp.key, Self::SetExp(set_exp) => &set_exp.key, Self::HGet(hget) => &hget.key, - Self::HSet(hset) => &hset.entry.key, + Self::HSet(hset) => &hset.key, Self::HDel(hdel) => &hdel.key, Self::HGetExp(hget_exp) => &hget_exp.key, Self::HSetExp(hset_exp) => &hset_exp.key, @@ -84,113 +85,115 @@ impl<'a> Operation<'a> { } } -/// Gets a [`Record`] by the provided [`Key`]. -#[derive(Clone, Debug)] +/// Gets a [`Record`] by the provided key. +#[derive(Clone, Debug, Serialize, Deserialize)] pub struct Get<'a> { pub namespace: Namespace, - pub key: Key<'a>, + pub key: Bytes<'a>, pub keyspace_version: Option, } -/// Sets a new [`Entry`]. -#[derive(Clone, Debug)] +/// Sets a new [`Record`] under the provided key. +#[derive(Clone, Debug, Serialize, Deserialize)] pub struct Set<'a> { pub namespace: Namespace, - pub entry: Entry<'a>, + pub key: Bytes<'a>, + pub record: Record<'a>, pub keyspace_version: Option, } -/// Deletes an [`Entry`] by the provided [`Key`]. -#[derive(Clone, Debug)] +/// Deletes a [`Record`] by the provided key. +#[derive(Clone, Debug, Serialize, Deserialize)] pub struct Del<'a> { pub namespace: Namespace, - pub key: Key<'a>, - pub version: EntryVersion, + pub key: Bytes<'a>, + pub version: RecordVersion, pub keyspace_version: Option, } -/// Gets an [`EntryExpiration`] by the provided [`Key`]. -#[derive(Clone, Debug)] +/// Gets a [`RecordExpiration`] by the provided key. +#[derive(Clone, Debug, Serialize, Deserialize)] pub struct GetExp<'a> { pub namespace: Namespace, - pub key: Key<'a>, + pub key: Bytes<'a>, pub keyspace_version: Option, } -/// Sets [`EntryExpiration`] on the [`Entry`] with the provided [`Key`]. -#[derive(Clone, Debug)] +/// Sets [`RecordExpiration`] on the [`Record`] with the provided key. +#[derive(Clone, Debug, Serialize, Deserialize)] pub struct SetExp<'a> { pub namespace: Namespace, - pub key: Key<'a>, - pub expiration: EntryExpiration, - pub version: EntryVersion, + pub key: Bytes<'a>, + pub expiration: RecordExpiration, + pub version: RecordVersion, pub keyspace_version: Option, } -/// Gets a map [`Record`] by the provided [`Key`] and [`Field`]. -#[derive(Clone, Debug)] +/// Gets a Map [`Record`] by the provided key and field. +#[derive(Clone, Debug, Serialize, Deserialize)] pub struct HGet<'a> { pub namespace: Namespace, - pub key: Key<'a>, - pub field: Field<'a>, + pub key: Bytes<'a>, + pub field: Bytes<'a>, pub keyspace_version: Option, } /// Sets a new [`MapEntry`]. -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Serialize, Deserialize)] pub struct HSet<'a> { pub namespace: Namespace, + pub key: Bytes<'a>, pub entry: MapEntry<'a>, pub keyspace_version: Option, } -/// Deletes a [`MapEntry`] by the provided [`Key`] and [`Field`]. -#[derive(Clone, Debug)] +/// Deletes a [`MapEntry`] by the provided key and field. +#[derive(Clone, Debug, Serialize, Deserialize)] pub struct HDel<'a> { pub namespace: Namespace, - pub key: Key<'a>, - pub field: Field<'a>, - pub version: EntryVersion, + pub key: Bytes<'a>, + pub field: Bytes<'a>, + pub version: RecordVersion, pub keyspace_version: Option, } -/// Gets a [`EntryExpiration`] by the provided [`Key`] and [`Field`]. -#[derive(Clone, Debug)] +/// Gets a [`RecordExpiration`] by the provided key and field. +#[derive(Clone, Debug, Serialize, Deserialize)] pub struct HGetExp<'a> { pub namespace: Namespace, - pub key: Key<'a>, - pub field: Field<'a>, + pub key: Bytes<'a>, + pub field: Bytes<'a>, pub keyspace_version: Option, } -/// Sets [`Expiration`] on the [`MapEntry`] with the provided [`Key`] and -/// [`Field`]. -#[derive(Clone, Debug)] +/// Sets [`RecordExpiration`] on the [`MapEntry`] with the provided key and +/// field. +#[derive(Clone, Debug, Serialize, Deserialize)] pub struct HSetExp<'a> { pub namespace: Namespace, - pub key: Key<'a>, - pub field: Field<'a>, - pub expiration: EntryExpiration, - pub version: EntryVersion, + pub key: Bytes<'a>, + pub field: Bytes<'a>, + pub expiration: RecordExpiration, + pub version: RecordVersion, pub keyspace_version: Option, } -/// Returns cardinality of the map with the provided [`Key`]. -#[derive(Clone, Debug)] +/// Returns cardinality of the Map with the provided key. +#[derive(Clone, Debug, Serialize, Deserialize)] pub struct HCard<'a> { pub namespace: Namespace, - pub key: Key<'a>, + pub key: Bytes<'a>, pub keyspace_version: Option, } -/// Returns a [`MapPage`] by iterating over the [`Field`]s of the map with -/// the provided [`Key`]. -#[derive(Clone, Debug)] +/// Returns a [`MapPage`] by iterating over the fields of the Map with +/// the provided key. +#[derive(Clone, Debug, Serialize, Deserialize)] pub struct HScan<'a> { pub namespace: Namespace, - pub key: Key<'a>, + pub key: Bytes<'a>, pub count: u32, - pub cursor: Option>, + pub cursor: Option>, pub keyspace_version: Option, } @@ -198,51 +201,30 @@ pub struct HScan<'a> { #[derive(Clone, Debug, From, PartialEq, Eq, EnumDiscriminants, TryInto)] #[strum_discriminants(name(OutputName))] #[strum_discriminants(derive(strum::Display))] -pub enum Output { - Record(Option), - Expiration(Option), - MapRecord(Option), - MapPage(MapPage), +pub enum Output<'a> { + Record(Option>), + Expiration(Option), + MapPage(MapPage<'a>), Cardinality(u64), None, } -impl From<()> for Output { +impl<'a> From<()> for Output<'a> { fn from(_: ()) -> Self { Self::None } } -impl Output { +impl<'a> Output<'a> { /// Tries to downcast an [`Output`] within a [`Result`] into a concrete /// output type. - pub fn downcast_result(operation_result: Result) -> Result + pub fn downcast_result(operation_result: Result) -> Result where Self: TryInto>, - WrongOutputError: Into, { operation_result? .try_into() - .map_err(|err| WrongOutputError { - expected: type_name::(), - got: err.input.discriminant(), - }) - .map_err(Into::into) - } -} - -#[derive(Clone, Debug, thiserror::Error)] -#[error("Wrong operation output (expected: {expected}, got: {got})")] -pub struct WrongOutputError { - expected: &'static str, - got: OutputName, -} - -impl From for crate::Error { - fn from(err: WrongOutputError) -> Self { - Self::new( - crate::ErrorKind::WrongOperationOutput, - Some(format!("{err}")), - ) + .tap_err(|err| tracing::error!(?err, "Failed to downcast output")) + .map_err(|err| Error::new(ErrorKind::Internal, Some(err.to_string()))) } } diff --git a/crates/storage_api2/src/rpc/client.rs b/crates/storage_api2/src/rpc/client.rs index 1541ad9a..3ab83ef1 100644 --- a/crates/storage_api2/src/rpc/client.rs +++ b/crates/storage_api2/src/rpc/client.rs @@ -1,299 +1,95 @@ use { super::*, - crate::{operation, MapPage, Operation, Record, Result}, - futures::SinkExt, - std::future::Future, - wcn_rpc::client2::{Connection, DefaultConnectionHandler, DefaultRpcHandler, HandleRpc}, + crate::{operation, MapPage, Operation, Record, Result, StorageApi}, + wcn_rpc::client2::{Connection, ConnectionHandler, RpcHandler}, }; -impl wcn_rpc::client2::Api for StorageApi +impl wcn_rpc::client2::Api for Api where - Self: Api, + Self: wcn_rpc::Api, { type ConnectionParameters = (); - type ConnectionHandler = DefaultConnectionHandler; - type RpcHandler = DefaultRpcHandler; + type ConnectionHandler = ConnectionHandler; + type RpcHandler = RpcHandler; } -async fn f(f: F) -> F::Output { - f.await -} - -impl crate::StorageApi for Connection> +impl StorageApi for Connection> where - StorageApi: wcn_rpc::client2::Api< + Api: wcn_rpc::client2::Api< ConnectionParameters = (), - ConnectionHandler = DefaultConnectionHandler, - RpcHandler = DefaultRpcHandler, + ConnectionHandler = ConnectionHandler, + RpcHandler = RpcHandler, >, { - fn get<'a>( - &'a self, - get: operation::Get<'a>, - ) -> impl Future>> + Send { - async move { - let req = GetRequest { - namespace: get.namespace.into(), - key: get.key.0, - keyspace_version: get.keyspace_version, - }; - - let rpc = Get { - request: &req, - _marker: PhantomData, - }; - - let opt = self.send(&rpc)?.await??; - - // let opt = rpc.send(self)?.await??; - - Ok::<_, crate::Error>(opt.map(|resp| Record { - value: Value(resp.value), - expiration: resp.expiration.into(), - version: resp.version.into(), - })) - } + async fn get(&self, op: &operation::Get<'_>) -> Result>> { + self.send::(&op)?.await?.map_err(Into::into) } - async fn set(&self, set: operation::Set<'_>) -> Result<()> { - todo!() + async fn set(&self, op: &operation::Set<'_>) -> Result<()> { + self.send::(&op)?.await?.map_err(Into::into) } - async fn del(&self, del: operation::Del<'_>) -> Result<()> { - todo!() + async fn del(&self, op: &operation::Del<'_>) -> Result<()> { + self.send::(&op)?.await?.map_err(Into::into) } - async fn get_exp(&self, get_exp: operation::GetExp<'_>) -> Result> { - todo!() + async fn get_exp(&self, op: &operation::GetExp<'_>) -> Result> { + self.send::(&op)?.await?.map_err(Into::into) } - async fn set_exp(&self, set_exp: operation::SetExp<'_>) -> Result<()> { - todo!() + async fn set_exp(&self, op: &operation::SetExp<'_>) -> Result<()> { + self.send::(&op)?.await?.map_err(Into::into) } - async fn hget(&self, hget: operation::HGet<'_>) -> Result> { - todo!() + async fn hget(&self, op: &operation::HGet<'_>) -> Result>> { + self.send::(&op)?.await?.map_err(Into::into) } - async fn hset(&self, hset: operation::HSet<'_>) -> Result<()> { - todo!() + async fn hset(&self, op: &operation::HSet<'_>) -> Result<()> { + self.send::(&op)?.await?.map_err(Into::into) } - async fn hdel(&self, hdel: operation::HDel<'_>) -> Result<()> { - todo!() + async fn hdel(&self, op: &operation::HDel<'_>) -> Result<()> { + self.send::(&op)?.await?.map_err(Into::into) } - async fn hget_exp(&self, hget_exp: operation::HGetExp<'_>) -> Result> { - todo!() + async fn hget_exp(&self, op: &operation::HGetExp<'_>) -> Result> { + self.send::(&op)?.await?.map_err(Into::into) } - async fn hset_exp(&self, hset_exp: operation::HSetExp<'_>) -> Result<()> { - todo!() + async fn hset_exp(&self, op: &operation::HSetExp<'_>) -> Result<()> { + self.send::(&op)?.await?.map_err(Into::into) } - async fn hcard(&self, hcard: operation::HCard<'_>) -> Result { - todo!() + async fn hcard(&self, op: &operation::HCard<'_>) -> Result { + self.send::(&op)?.await?.map_err(Into::into) } - async fn hscan(&self, hscan: operation::HScan<'_>) -> Result { - todo!() + async fn hscan(&self, op: &operation::HScan<'_>) -> Result> { + self.send::(&op)?.await?.map_err(Into::into) } - async fn execute( - &self, - operation: impl Into> + Send, - ) -> Result { - todo!() + async fn execute<'a>( + &'a self, + operation: impl Into> + Send + 'a, + ) -> Result> { + match operation.into() { + Operation::Get(get) => self.get(get).await.map(Into::into), + Operation::Set(set) => self.set(set).await.map(Into::into), + Operation::Del(del) => self.del(del).await.map(Into::into), + Operation::GetExp(get_exp) => self.get_exp(get_exp).await.map(Into::into), + Operation::SetExp(set_exp) => self.set_exp(set_exp).await.map(Into::into), + Operation::HGet(hget) => self.hget(hget).await.map(Into::into), + Operation::HSet(hset) => self.hset(hset).await.map(Into::into), + Operation::HDel(hdel) => self.hdel(hdel).await.map(Into::into), + Operation::HGetExp(hget_exp) => self.hget_exp(hget_exp).await.map(Into::into), + Operation::HSetExp(hset_exp) => self.hset_exp(hset_exp).await.map(Into::into), + Operation::HCard(hcard) => self.hcard(hcard).await.map(Into::into), + Operation::HScan(hscan) => self.hscan(hscan).await.map(Into::into), + } } } -// impl<'a> Storage for RemoteStorage<'a> { -// type Error = Error; - -// async fn get(&self, get: operation::Get) -> Result> { -// Get::send(self.rpc_client(), self.server_addr, &GetRequest { -// context: self.context(&get.namespace), -// key: get.key.into(), -// }) -// .await -// .map(|opt| { -// opt.map(|resp| Record { -// value: resp.value.into(), -// expiration: resp.expiration.into(), -// version: resp.version.into(), -// }) -// }) -// .map_err(Into::into) -// } - -// async fn set(&self, set: operation::Set) -> Result<()> { -// Set::send(self.rpc_client(), self.server_addr, &SetRequest { -// context: self.context(&set.namespace), -// key: set.entry.key.into(), -// value: set.entry.value.into(), -// expiration: set.entry.expiration.into(), -// version: set.entry.version.into(), -// }) -// .await -// .map_err(Into::into) -// } - -// async fn set_exp(&self, set_exp: operation::SetExp) -> Result<()> { -// SetExp::send(self.rpc_client(), self.server_addr, &SetExpRequest { -// context: self.context(&set_exp.namespace), -// key: set_exp.key.into(), -// expiration: set_exp.expiration.into(), -// version: set_exp.version.into(), -// }) -// .await -// .map_err(Into::into) -// } - -// async fn del(&self, del: operation::Del) -> Result<()> { -// Del::send(self.rpc_client(), self.server_addr, &DelRequest { -// context: self.context(&del.namespace), -// key: del.key.into(), -// version: del.version.into(), -// }) -// .await -// .map_err(Into::into) -// } - -// async fn get_exp(&self, get_exp: operation::GetExp) -> -// Result> { GetExp::send(self.rpc_client(), -// self.server_addr, &GetExpRequest { context: -// self.context(&get_exp.namespace), key: get_exp.key.into(), -// }) -// .await -// .map(|opt| opt.map(|resp| EntryExpiration::from(resp.expiration))) -// .map_err(Into::into) -// } - -// async fn hget(&self, hget: operation::HGet) -> Result> { -// HGet::send(self.rpc_client(), self.server_addr, &HGetRequest { -// context: self.context(&hget.namespace), -// key: hget.key.into(), -// field: hget.field.into(), -// }) -// .await -// .map(|opt| { -// opt.map(|resp| Record { -// value: resp.value.into(), -// expiration: resp.expiration.into(), -// version: resp.version.into(), -// }) -// }) -// .map_err(Into::into) -// } - -// async fn hset(&self, hset: operation::HSet) -> Result<()> { -// HSet::send(self.rpc_client(), self.server_addr, &HSetRequest { -// context: self.context(&hset.namespace), -// key: hset.entry.key.into(), -// field: hset.entry.field.into(), -// value: hset.entry.value.into(), -// expiration: hset.entry.expiration.into(), -// version: hset.entry.version.into(), -// }) -// .await -// .map_err(Into::into) -// } - -// async fn hdel(&self, hdel: operation::HDel) -> Result<()> { -// HDel::send(self.rpc_client(), self.server_addr, &HDelRequest { -// context: self.context(&hdel.namespace), -// key: hdel.key.into(), -// field: hdel.field.into(), -// version: hdel.version.into(), -// }) -// .await -// .map_err(Into::into) -// } - -// async fn hget_exp(&self, hget_exp: operation::HGetExp) -> -// Result> { HGetExp::send(self.rpc_client(), -// self.server_addr, &HGetExpRequest { context: -// self.context(&hget_exp.namespace), key: hget_exp.key.into(), -// field: hget_exp.field.into(), -// }) -// .await -// .map(|opt| opt.map(|resp| EntryExpiration::from(resp.expiration))) -// .map_err(Into::into) -// } - -// async fn hset_exp(&self, hset_exp: operation::HSetExp) -> Result<()> { -// HSetExp::send(self.rpc_client(), self.server_addr, &HSetExpRequest { -// context: self.context(&hset_exp.namespace), -// key: hset_exp.key.into(), -// field: hset_exp.field.into(), -// expiration: hset_exp.expiration.into(), -// version: hset_exp.version.into(), -// }) -// .await -// .map_err(Into::into) -// } - -// async fn hcard(&self, hcard: operation::HCard) -> Result { -// HCard::send(self.rpc_client(), self.server_addr, &HCardRequest { -// context: self.context(&hcard.namespace), -// key: hcard.key.into(), -// }) -// .await -// .map(|resp| resp.cardinality) -// .map_err(Into::into) -// } - -// async fn hscan(&self, hscan: operation::HScan) -> Result { -// let count = hscan.count; - -// let resp = HScan::send(self.rpc_client(), self.server_addr, -// &HScanRequest { context: self.context(&hscan.namespace), -// key: hscan.key.into(), -// count: hscan.count, -// cursor: hscan.cursor.map(Into::into), -// }) -// .await -// .map_err(Error::from)?; - -// Ok(MapPage { -// has_next: resp.records.len() >= count as usize, -// records: resp -// .records -// .into_iter() -// .map(|record| MapRecord { -// field: record.field.into(), -// value: record.value.into(), -// expiration: EntryExpiration::from(record.expiration), -// version: EntryVersion::from(record.version), -// }) -// .collect(), -// }) -// } - -// async fn execute( -// &self, -// operation: impl Into + Send, -// ) -> Result { -// match operation.into() { -// Operation::Get(get) => self.get(get).await.map(Into::into), -// Operation::Set(set) => self.set(set).await.map(Into::into), -// Operation::Del(del) => self.del(del).await.map(Into::into), -// Operation::GetExp(get_exp) => -// self.get_exp(get_exp).await.map(Into::into), -// Operation::SetExp(set_exp) => self.set_exp(set_exp).await.map(Into::into), -// Operation::HGet(hget) => self.hget(hget).await.map(Into::into), -// Operation::HSet(hset) => self.hset(hset).await.map(Into::into), -// Operation::HDel(hdel) => self.hdel(hdel).await.map(Into::into), -// Operation::HGetExp(hget_exp) => -// self.hget_exp(hget_exp).await.map(Into::into), -// Operation::HSetExp(hset_exp) => -// self.hset_exp(hset_exp).await.map(Into::into), -// Operation::HCard(hcard) => self.hcard(hcard).await.map(Into::into), -// Operation::HScan(hscan) => -// self.hscan(hscan).await.map(Into::into), } -// } -// } - impl From for crate::Error { fn from(err: wcn_rpc::client2::Error) -> Self { Self::new( diff --git a/crates/storage_api2/src/rpc/mod.rs b/crates/storage_api2/src/rpc/mod.rs index b1ecf661..35002b49 100644 --- a/crates/storage_api2/src/rpc/mod.rs +++ b/crates/storage_api2/src/rpc/mod.rs @@ -1,15 +1,15 @@ use { - crate::{Bytes, EntryExpiration, EntryVersion, Field, Key, Value}, + crate::{operation, MapPage, Record, RecordExpiration}, derive_more::derive::TryFrom, serde::{Deserialize, Serialize}, - std::{borrow::Borrow, marker::PhantomData}, - wcn_rpc::{self as rpc, Api, ApiName, MessageOwned, PostcardCodec, RpcV2}, + std::marker::PhantomData, + wcn_rpc::{ApiName, MessageV2 as Message, PostcardCodec}, }; #[cfg(feature = "rpc_client")] -mod client; +pub mod client; #[cfg(feature = "rpc_server")] -mod server; +pub mod server; #[derive(Clone, Copy, Debug, TryFrom)] #[try_from(repr)] @@ -36,8 +36,9 @@ impl From for u8 { } } +/// `wcn_rpc` implementation of [`StorageApi`](super::StorageApi). #[derive(Clone, Copy, Debug)] -pub struct StorageApi(PhantomData); +pub struct Api(PhantomData); pub mod api_kind { #[derive(Clone, Copy, Debug)] @@ -50,353 +51,106 @@ pub mod api_kind { pub struct Database; } -pub type StorageApiCoordinator = StorageApi; +pub type CoordinatorApi = Api; -impl Api for StorageApiCoordinator { +impl wcn_rpc::Api for CoordinatorApi { const NAME: ApiName = ApiName::new("StorageApiCoordinator"); type RpcId = Id; } -pub type StorageApiReplica = StorageApi; +pub type ReplicaApi = Api; -impl Api for StorageApiReplica { +impl wcn_rpc::Api for ReplicaApi { const NAME: ApiName = ApiName::new("StorageApiReplica"); type RpcId = Id; } -pub type StorageApiDatabase = StorageApi; +pub type DatabaseApi = Api; -impl Api for StorageApiDatabase { +impl wcn_rpc::Api for DatabaseApi { const NAME: ApiName = ApiName::new("StorageApiDatabase"); type RpcId = Id; } -#[derive(Clone, Copy, Debug, Serialize, Deserialize)] -struct Namespace { - node_operator_id: [u8; 20], - id: u8, -} - -type UnaryRpc<'a, const ID: u8, Req, Resp> = rpc::UnaryV2<'a, ID, Req, Resp, PostcardCodec>; +type UnaryRpc = wcn_rpc::UnaryV2; -type Get<'a> = UnaryRpc<'a, { Id::Get as u8 }, GetRequest<'static>, Result>>; +type Get = UnaryRpc<{ Id::Get as u8 }, operation::Get<'static>, Result>>>; +type Set = UnaryRpc<{ Id::Set as u8 }, operation::Set<'static>, Result<()>>; +type Del = UnaryRpc<{ Id::Del as u8 }, operation::Del<'static>, Result<()>>; -#[derive(Debug, Serialize, Deserialize)] -struct GetRequest<'a> { - namespace: Namespace, - key: Bytes<'a>, - keyspace_version: Option, -} +type GetExp = + UnaryRpc<{ Id::GetExp as u8 }, operation::GetExp<'static>, Result>>; +type SetExp = UnaryRpc<{ Id::SetExp as u8 }, operation::SetExp<'static>, Result<()>>; -impl MessageOwned for GetRequest<'static> { - type Borrowed<'a> = GetRequest<'a>; -} +type HGet = UnaryRpc<{ Id::HGet as u8 }, operation::HGet<'static>, Result>>>; +type HSet = UnaryRpc<{ Id::HSet as u8 }, operation::HSet<'static>, Result<()>>; +type HDel = UnaryRpc<{ Id::HDel as u8 }, operation::HDel<'static>, Result<()>>; -// #[derive(Clone, Debug, Serialize, Deserialize)] -// struct GetRequest { -// namespace: Namespace, -// // key: Bytes<'static>, -// keyspace_version: Option, -// } +type HGetExp = + UnaryRpc<{ Id::HGetExp as u8 }, operation::HGetExp<'static>, Result>>; +type HSetExp = UnaryRpc<{ Id::HSetExp as u8 }, operation::HSetExp<'static>, Result<()>>; -// impl MessageV2 for GetRequest<'static> { -// type Borrowed<'a> = GetRequest<'a>; -// } +type HCard = UnaryRpc<{ Id::HCard as u8 }, operation::HCard<'static>, Result>; +type HScan = UnaryRpc<{ Id::HScan as u8 }, operation::HScan<'static>, Result>>; -#[derive(Clone, Debug, Serialize, Deserialize)] -struct GetResponse { - namespace: Namespace, - value: Bytes<'static>, - expiration: UnixTimestampSecs, - version: UnixTimestampMicros, - - keyspace_version: Option, +impl Message for operation::Get<'static> { + type Borrowed<'a> = operation::Get<'a>; } -impl MessageOwned for GetResponse { - type Borrowed<'a> = Self; +impl Message for operation::Set<'static> { + type Borrowed<'a> = operation::Set<'a>; } -// impl StaticMessage for GetResponse {} - -// type Set = UnaryRpc<{ Id::Set as u8 }, SetRequest<'static>, Result<()>>; - -// #[derive(Clone, Debug, Serialize, Deserialize)] -// struct SetRequest<'a> { -// namespace: Namespace, -// key: Bytes<'a>, -// value: Bytes<'a>, -// expiration: UnixTimestampSecs, -// version: UnixTimestampMicros, - -// keyspace_version: Option, -// } - -// impl MessageV2 for SetRequest<'static> { -// type Borrowed<'a> = SetRequest<'a>; -// } - -// type Del = UnaryRpc<{ Id::Del as u8 }, DelRequest<'static>, Result<()>>; - -// #[derive(Clone, Debug, Serialize, Deserialize)] -// struct DelRequest<'a> { -// namespace: Namespace, -// key: Bytes<'a>, -// version: UnixTimestampMicros, - -// keyspace_version: Option, -// } - -// impl MessageV2 for DelRequest<'static> { -// type Borrowed<'a> = DelRequest<'a>; -// } - -// type GetExp = -// UnaryRpc<{ Id::GetExp as u8 }, GetExpRequest<'static>, -// Result>>; - -// #[derive(Clone, Debug, Serialize, Deserialize)] -// struct GetExpRequest<'a> { -// namespace: Namespace, -// key: Bytes<'a>, - -// keyspace_version: Option, -// } - -// impl MessageV2 for GetExpRequest<'static> { -// type Borrowed<'a> = GetExpRequest<'a>; -// } - -// #[derive(Clone, Debug, Serialize, Deserialize)] -// struct GetExpResponse { -// expiration: UnixTimestampSecs, -// } - -// impl StaticMessage for GetExpResponse {} - -// type SetExp = UnaryRpc<{ Id::SetExp as u8 }, SetExpRequest<'static>, -// Result<()>>; - -// #[derive(Clone, Debug, Serialize, Deserialize)] -// struct SetExpRequest<'a> { -// namespace: Namespace, -// key: Bytes<'a>, -// expiration: UnixTimestampSecs, -// version: UnixTimestampMicros, - -// keyspace_version: Option, -// } - -// impl MessageV2 for SetExpRequest<'static> { -// type Borrowed<'a> = DelRequest<'a>; -// } - -// type HGet = UnaryRpc<{ Id::HGet as u8 }, HGetRequest<'static>, -// Result>>; - -// #[derive(Clone, Debug, Serialize, Deserialize)] -// struct HGetRequest<'a> { -// namespace: Namespace, -// key: Bytes<'a>, -// field: Bytes<'a>, - -// keyspace_version: Option, -// } - -// impl MessageV2 for HGetRequest<'static> { -// type Borrowed<'a> = HGetRequest<'a>; -// } +impl Message for operation::Del<'static> { + type Borrowed<'a> = operation::Del<'a>; +} -// #[derive(Clone, Debug, Serialize, Deserialize)] -// struct HGetResponse { -// value: Bytes<'static>, -// expiration: UnixTimestampSecs, -// version: UnixTimestampMicros, -// } +impl Message for operation::GetExp<'static> { + type Borrowed<'a> = operation::GetExp<'a>; +} -// impl StaticMessage for HGetResponse {} +impl Message for operation::SetExp<'static> { + type Borrowed<'a> = operation::SetExp<'a>; +} -// type HSet = UnaryRpc<{ Id::HSet as u8 }, HSetRequest<'static>, Result<()>>; +impl Message for operation::HSet<'static> { + type Borrowed<'a> = operation::HSet<'a>; +} -// #[derive(Clone, Debug, Serialize, Deserialize)] -// struct HSetRequest<'a> { -// namespace: Namespace, -// key: Bytes<'a>, -// field: Bytes<'a>, -// value: Bytes<'a>, -// expiration: UnixTimestampSecs, -// version: UnixTimestampMicros, +impl Message for operation::HGet<'static> { + type Borrowed<'a> = operation::HGet<'a>; +} -// keyspace_version: Option, -// } - -// impl MessageV2 for HSetRequest<'static> { -// type Borrowed<'a> = HSetRequest<'a>; -// } - -// type HDel = UnaryRpc<{ Id::HDel as u8 }, HDelRequest<'static>, Result<()>>; - -// #[derive(Clone, Debug, Serialize, Deserialize)] -// struct HDelRequest<'a> { -// namespace: Namespace, -// key: Bytes<'a>, -// field: Bytes<'a>, -// version: UnixTimestampMicros, - -// keyspace_version: Option, -// } - -// impl MessageV2 for HDelRequest<'static> { -// type Borrowed<'a> = HDelRequest<'a>; -// } - -// type HGetExp = -// UnaryRpc<{ Id::HGetExp as u8 }, HGetExpRequest<'static>, -// Result>>; - -// #[derive(Clone, Debug, Serialize, Deserialize)] -// struct HGetExpRequest<'a> { -// namespace: Namespace, -// key: Bytes<'a>, -// field: Bytes<'a>, - -// keyspace_version: Option, -// } - -// impl MessageV2 for HGetExpRequest<'static> { -// type Borrowed<'a> = HGetExpRequest<'a>; -// } - -// #[derive(Clone, Debug, Serialize, Deserialize)] -// struct HGetExpResponse { -// expiration: UnixTimestampSecs, -// } - -// impl StaticMessage for HGetExpResponse {} - -// type HSetExp = UnaryRpc<{ Id::HSetExp as u8 }, HSetExpRequest<'static>, -// Result<()>>; - -// #[derive(Clone, Debug, Serialize, Deserialize)] -// struct HSetExpRequest<'a> { -// namespace: Namespace, -// key: Bytes<'a>, -// field: Bytes<'a>, -// expiration: UnixTimestampSecs, -// version: UnixTimestampMicros, - -// keyspace_version: Option, -// } - -// impl MessageV2 for HSetExpRequest<'static> { -// type Borrowed<'a> = HSetExpRequest<'a>; -// } - -// type HCard = UnaryRpc<{ Id::HCard as u8 }, HCardRequest<'static>, -// Result>; - -// #[derive(Clone, Debug, Serialize, Deserialize)] -// struct HCardRequest<'a> { -// namespace: Namespace, -// key: Bytes<'a>, - -// keyspace_version: Option, -// } - -// impl MessageV2 for HCardRequest<'static> { -// type Borrowed<'a> = HCardRequest<'a>; -// } - -// #[derive(Clone, Debug, Serialize, Deserialize)] -// struct HCardResponse { -// cardinality: u64, -// } - -// impl StaticMessage for HCardResponse {} - -// type HScan = UnaryRpc<{ Id::HScan as u8 }, HScanRequest<'static>, -// Result>; - -// #[derive(Clone, Debug, Serialize, Deserialize)] -// struct HScanRequest<'a> { -// namespace: Namespace, -// key: Bytes<'a>, -// count: u32, -// cursor: Option>, - -// keyspace_version: Option, -// } +impl Message for operation::HDel<'static> { + type Borrowed<'a> = operation::HDel<'a>; +} -// impl MessageV2 for HScanRequest<'static> { -// type Borrowed<'a> = HScanRequest<'a>; -// } - -// #[derive(Clone, Debug, Serialize, Deserialize)] -// struct HScanResponse { -// records: Vec, -// has_more: bool, -// } - -// impl StaticMessage for HScanResponse {} - -// #[derive(Clone, Debug, Serialize, Deserialize)] -// struct HScanResponseRecord { -// field: Bytes<'static>, -// value: Bytes<'static>, -// expiration: UnixTimestampSecs, -// version: UnixTimestampMicros, -// } - -#[derive(Clone, Copy, Debug, Serialize, Deserialize)] -struct UnixTimestampSecs(u64); - -impl From for UnixTimestampSecs { - fn from(exp: EntryExpiration) -> Self { - Self(exp.unix_timestamp_secs) - } +impl Message for operation::HGetExp<'static> { + type Borrowed<'a> = operation::HGetExp<'a>; } -impl From for EntryExpiration { - fn from(timestamp: UnixTimestampSecs) -> Self { - Self { - unix_timestamp_secs: timestamp.0, - } - } +impl Message for operation::HSetExp<'static> { + type Borrowed<'a> = operation::HSetExp<'a>; } -#[derive(Clone, Copy, Debug, Serialize, Deserialize)] -struct UnixTimestampMicros(u64); +impl Message for operation::HCard<'static> { + type Borrowed<'a> = operation::HCard<'a>; +} -impl From for UnixTimestampMicros { - fn from(version: EntryVersion) -> Self { - Self(version.unix_timestamp_micros) - } +impl Message for operation::HScan<'static> { + type Borrowed<'a> = operation::HScan<'a>; } -impl From for EntryVersion { - fn from(timestamp: UnixTimestampMicros) -> Self { - Self { - unix_timestamp_micros: timestamp.0, - } - } +impl Message for Record<'static> { + type Borrowed<'a> = Record<'a>; } -impl From for Namespace { - fn from(ns: crate::Namespace) -> Self { - Self { - node_operator_id: ns.node_operator_id, - id: ns.id, - } - } +impl Message for RecordExpiration { + type Borrowed<'a> = Self; } -impl From for crate::Namespace { - fn from(ns: Namespace) -> Self { - Self { - node_operator_id: ns.node_operator_id, - id: ns.id, - } - } +impl Message for MapPage<'static> { + type Borrowed<'a> = MapPage<'a>; } #[derive(Clone, Debug, Serialize, Deserialize)] @@ -427,7 +181,6 @@ enum ErrorCode { Internal = 0, Unauthorized = 1, KeyspaceVersionMismatch = 2, - Timeout = 3, } type Result = std::result::Result; @@ -446,7 +199,6 @@ impl From for crate::Error { let kind = match code { ErrorCode::Unauthorized => ErrorKind::Unauthorized, ErrorCode::KeyspaceVersionMismatch => ErrorKind::KeyspaceVersionMismatch, - ErrorCode::Timeout => ErrorKind::Timeout, ErrorCode::Internal => ErrorKind::Internal, }; @@ -461,11 +213,10 @@ impl From for Error { let code = match err.kind { ErrorKind::Unauthorized => ErrorCode::Unauthorized, ErrorKind::KeyspaceVersionMismatch => ErrorCode::KeyspaceVersionMismatch, - ErrorKind::Timeout => ErrorCode::Timeout, ErrorKind::Internal + | ErrorKind::Timeout | ErrorKind::Transport - | ErrorKind::WrongOperationOutput | ErrorKind::Unknown => ErrorCode::Internal, }; @@ -473,6 +224,6 @@ impl From for Error { } } -impl MessageOwned for Error { +impl Message for Error { type Borrowed<'a> = Self; } diff --git a/crates/storage_api2/src/rpc/server.rs b/crates/storage_api2/src/rpc/server.rs index 8a34d391..f8d136fb 100644 --- a/crates/storage_api2/src/rpc/server.rs +++ b/crates/storage_api2/src/rpc/server.rs @@ -1,288 +1,159 @@ use { super::*, - crate::operation, - futures::SinkExt as _, - std::{collections::HashSet, future::Future, sync::Arc, time::Duration}, + crate::{rpc::Id as RpcId, StorageApi}, wcn_rpc::{ - middleware::Timeouts, - server::{ - middleware::{MeteredExt, WithTimeoutsExt}, - ClientConnectionInfo, - ConnectionInfo, - }, - server2::{Connection, HandleConnection, HandleRpc, Inbound, Result}, - transport::{self, BiDirectionalStream, NoHandshake, PostcardCodec}, + server2::{Connection, HandleConnection, HandleRequest, Result}, + Request, + Response, }, }; -/// Storage namespace. -pub type Namespace = Vec; +/// Creates a new [`CoordinatorApi`] RPC server. +pub fn coordinator(storage_api: impl StorageApi) -> impl wcn_rpc::server2::Server { + new::(storage_api) +} + +/// Creates a new [`ReplicaApi`] RPC server. +pub fn replica(storage_api: impl StorageApi) -> impl wcn_rpc::server2::Server { + new::(storage_api) +} -/// Storage API [`Server`] config. -pub struct Config { - /// Name of the [`Server`]. - pub name: rpc::ServerName, +/// Creates a new [`DatabaseApi`] RPC server. +pub fn database(storage_api: impl StorageApi) -> impl wcn_rpc::server2::Server { + new::(storage_api) +} - /// Timeout of a [`Server`] operation. - pub operation_timeout: Duration, +fn new(storage_api: impl StorageApi) -> impl wcn_rpc::server2::Server +where + Kind: Clone + Send + Sync + 'static, + Api: wcn_rpc::Api, +{ + wcn_rpc::server2::new(ConnectionHandler { + rpc_handler: RpcHandler { storage_api }, + _marker: PhantomData, + }) } #[derive(Clone)] -struct ConnectionHandler { - storage_api: S, - api_kind: Kind, +struct ConnectionHandler { + rpc_handler: RpcHandler, + _marker: PhantomData, } impl HandleConnection for ConnectionHandler where - S: crate::StorageApi + Clone + Send + Sync + 'static, + S: StorageApi, Kind: Clone + Send + Sync + 'static, - StorageApi: Api, + Api: wcn_rpc::Api, { - type Api = super::StorageApi; + type Api = super::Api; async fn handle_connection(&self, conn: Connection<'_, Self::Api>) -> Result<()> { - todo!() + conn.handle(&self.rpc_handler, |rpc, handler| async move { + match rpc.id() { + RpcId::Get => rpc.handle::(&handler).await, + RpcId::Set => rpc.handle::(&handler).await, + RpcId::Del => rpc.handle::(&handler).await, + RpcId::SetExp => todo!(), + RpcId::GetExp => todo!(), + RpcId::HGet => todo!(), + RpcId::HSet => todo!(), + RpcId::HDel => todo!(), + RpcId::HSetExp => todo!(), + RpcId::HGetExp => todo!(), + RpcId::HCard => todo!(), + RpcId::HScan => todo!(), + } + }) + .await } } -struct RpcHandler { +#[derive(Clone)] +struct RpcHandler { storage_api: S, } -impl HandleRpc for RpcHandler { - async fn handle_rpc(&self, rpc: &mut Inbound) -> Result<()> { - todo!() +impl HandleRequest for RpcHandler { + async fn handle_request(&self, req: Request) -> Response { + self.storage_api + .get(&req) + .await + .map(|opt| opt.map(Record::into_static)) + .map_err(Into::into) } } -// impl RpcHandler<'_, S> { -// async fn get(&self, req: GetRequest) -> -// wcn_rpc::Result> { let record = self -// .storage_api -// .get(operation::Get { -// namespace: (), -// key: self.prepare_key(req.key)?, -// }) -// .await -// .map_err(Error::into_rpc_error)?; - -// Ok(record.map(|rec| GetResponse { -// value: rec.value, -// expiration: rec.expiration.timestamp(), -// version: rec.version.timestamp(), -// })) -// } - -// async fn set(&self, req: SetRequest) -> wcn_rpc::Result<()> { -// let entry = Entry { -// key: self.prepare_key(req.key)?, -// value: req.value, -// expiration: EntryExpiration::from(req.expiration), -// version: EntryVersion::from(req.version), -// }; - -// self.storage_api -// .execute_set(operation::Set { entry }) -// .await -// .map_err(Error::into_rpc_error) -// } - -// async fn del(&self, req: DelRequest) -> wcn_rpc::Result<()> { -// self.storage_api -// .del(operation::Del { -// key: self.prepare_key(req.key)?, -// version: EntryVersion::from(req.version), -// }) -// .await -// .map_err(Error::into_rpc_error) -// } - -// async fn get_exp(&self, req: GetExpRequest) -> -// wcn_rpc::Result> { let expiration = self -// .storage_api -// .execute_get_exp(operation::GetExp { -// key: self.prepare_key(req.key)?, -// }) -// .await -// .map_err(Error::into_rpc_error)?; - -// Ok(expiration.map(|exp| GetExpResponse { -// expiration: exp.timestamp(), -// })) -// } - -// async fn set_exp(&self, req: SetExpRequest) -> wcn_rpc::Result<()> { -// self.storage_api -// .execute_set_exp(operation::SetExp { -// key: self.prepare_key(req.key)?, -// expiration: EntryExpiration::from(req.expiration), -// version: EntryVersion::from(req.version), -// }) -// .await -// .map_err(Error::into_rpc_error) -// } - -// async fn hget(&self, req: HGetRequest) -> -// wcn_rpc::Result> { let record = self -// .storage_api -// .execute_hget(operation::HGet { -// key: self.prepare_key(req.key)?, -// field: req.field, -// }) -// .await -// .map_err(Error::into_rpc_error)?; - -// Ok(record.map(|rec| HGetResponse { -// value: rec.value, -// expiration: rec.expiration.timestamp(), -// version: rec.version.timestamp(), -// })) -// } - -// async fn hset(&self, req: HSetRequest) -> wcn_rpc::Result<()> { -// let entry = MapEntry { -// key: self.prepare_key(req.key)?, -// field: req.field, -// value: req.value, -// expiration: EntryExpiration::from(req.expiration), -// version: EntryVersion::from(req.version), -// }; - -// self.storage_api -// .execute_hset(operation::HSet { entry }) -// .await -// .map_err(Error::into_rpc_error) -// } - -// async fn hdel(&self, req: HDelRequest) -> wcn_rpc::Result<()> { -// self.storage_api -// .execute_hdel(operation::HDel { -// key: self.prepare_key(req.key)?, -// field: req.field, -// version: EntryVersion::from(req.version), -// }) -// .await -// .map_err(Error::into_rpc_error) -// } - -// async fn hget_exp(&self, req: HGetExpRequest) -> -// wcn_rpc::Result> { let expiration = self -// .storage_api -// .execute_hget_exp(operation::HGetExp { -// key: self.prepare_key(req.key)?, -// field: req.field, -// }) -// .await -// .map_err(Error::into_rpc_error)?; - -// Ok(expiration.map(|exp| HGetExpResponse { -// expiration: exp.timestamp(), -// })) -// } - -// async fn hset_exp(&self, req: HSetExpRequest) -> wcn_rpc::Result<()> { -// self.storage_api -// .execute_hset_exp(operation::HSetExp { -// key: self.prepare_key(req.key)?, -// field: req.field, -// expiration: EntryExpiration::from(req.expiration), -// version: EntryVersion::from(req.version), -// }) -// .await -// .map_err(Error::into_rpc_error) -// } +impl HandleRequest for RpcHandler { + async fn handle_request(&self, req: Request) -> Response { + self.storage_api.set(&req).await.map_err(Into::into) + } +} -// async fn hcard(&self, req: HCardRequest) -> -// wcn_rpc::Result { self.storage_api -// .execute_hcard(operation::HCard { -// key: self.prepare_key(req.key)?, -// }) -// .await -// .map(|cardinality| HCardResponse { cardinality }) -// .map_err(Error::into_rpc_error) -// } +impl HandleRequest for RpcHandler { + async fn handle_request(&self, req: Request) -> Response { + self.storage_api.del(&req).await.map_err(Into::into) + } +} -// async fn hscan(&self, req: HScanRequest) -> -// wcn_rpc::Result { let page = self -// .storage_api -// .execute_hscan(operation::HScan { -// key: self.prepare_key(req.key)?, -// count: req.count, -// cursor: req.cursor, -// }) -// .await -// .map_err(Error::into_rpc_error)?; +impl HandleRequest for RpcHandler { + async fn handle_request(&self, req: Request) -> Response { + self.storage_api.get_exp(&req).await.map_err(Into::into) + } +} -// Ok(HScanResponse { -// records: page -// .records -// .into_iter() -// .map(|rec| HScanResponseRecord { -// field: rec.field, -// value: rec.value, -// expiration: rec.expiration.timestamp(), -// version: rec.version.timestamp(), -// }) -// .collect(), -// has_more: page.has_next, -// }) -// } -// } +impl HandleRequest for RpcHandler { + async fn handle_request(&self, req: Request) -> Response { + self.storage_api.set_exp(&req).await.map_err(Into::into) + } +} -// #[derive(Clone, Debug)] -// struct RpcServer { -// api_server: S, -// config: rpc::server::Config, -// } +impl HandleRequest for RpcHandler { + async fn handle_request(&self, req: Request) -> Response { + self.storage_api + .hget(&req) + .await + .map(|opt| opt.map(Record::into_static)) + .map_err(Into::into) + } +} -// impl rpc::Server for RpcServer -// where -// S: Server, -// { -// type Handshake = NoHandshake; -// type ConnectionData = (); -// type Codec = PostcardCodec; +impl HandleRequest for RpcHandler { + async fn handle_request(&self, req: Request) -> Response { + self.storage_api.hset(&req).await.map_err(Into::into) + } +} -// fn config(&self) -> &wcn_rpc::server::Config { -// &self.config -// } +impl HandleRequest for RpcHandler { + async fn handle_request(&self, req: Request) -> Response { + self.storage_api.hdel(&req).await.map_err(Into::into) + } +} -// fn handle_rpc<'a>( -// &'a self, -// id: rpc::Id, -// stream: BiDirectionalStream, -// conn_info: &'a ClientConnectionInfo, -// ) -> impl Future + Send + 'a { -// async move { -// let handler = RpcHandler { -// storage_api: &self.api_server, -// conn_info, -// }; +impl HandleRequest for RpcHandler { + async fn handle_request(&self, req: Request) -> Response { + self.storage_api.hget_exp(&req).await.map_err(Into::into) + } +} -// let _ = match id { -// Get::ID => Get::handle(stream, |req| handler.get(req)).await, -// Set::ID => Set::handle(stream, |req| handler.set(req)).await, -// Del::ID => Del::handle(stream, |req| handler.del(req)).await, -// GetExp::ID => GetExp::handle(stream, |req| -// handler.get_exp(req)).await, SetExp::ID => -// SetExp::handle(stream, |req| handler.set_exp(req)).await, +impl HandleRequest for RpcHandler { + async fn handle_request(&self, req: Request) -> Response { + self.storage_api.hset_exp(&req).await.map_err(Into::into) + } +} -// HGet::ID => HGet::handle(stream, |req| -// handler.hget(req)).await, HSet::ID => HSet::handle(stream, -// |req| handler.hset(req)).await, HDel::ID => -// HDel::handle(stream, |req| handler.hdel(req)).await, -// HGetExp::ID => HGetExp::handle(stream, |req| handler.hget_exp(req)).await, -// HSetExp::ID => HSetExp::handle(stream, |req| -// handler.hset_exp(req)).await, HCard::ID => -// HCard::handle(stream, |req| handler.hcard(req)).await, -// HScan::ID => HScan::handle(stream, |req| handler.hscan(req)).await, +impl HandleRequest for RpcHandler { + async fn handle_request(&self, req: Request) -> Response { + self.storage_api.hcard(&req).await.map_err(Into::into) + } +} -// id => return tracing::warn!("Unexpected RPC: {}", -// rpc::Name::new(id)), } -// .map_err( -// |err| tracing::debug!(name = %rpc::Name::new(id), ?err, "Failed to handle RPC"), -// ); -// } -// } -// } +impl HandleRequest for RpcHandler { + async fn handle_request(&self, req: Request) -> Response { + self.storage_api + .hscan(&req) + .await + .map(MapPage::into_static) + .map_err(Into::into) + } +} From f826ce9159579e4d15139825677f8e8d89b54892 Mon Sep 17 00:00:00 2001 From: Github Bot Date: Fri, 27 Jun 2025 15:26:04 +0000 Subject: [PATCH 60/79] Bump VERSION to 250627.0 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index b166d569..9f8c16d6 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -250620.0 +250627.0 From 0efc451c0f1fa61ad475c1b7a86d2c0c4a7bf58e Mon Sep 17 00:00:00 2001 From: Darksome Date: Fri, 27 Jun 2025 15:27:29 +0000 Subject: [PATCH 61/79] remove unused files --- contracts/out/Cluster.sol/Bitmask.json | 1 - contracts/test/Suite.sol | 797 ------------------------- 2 files changed, 798 deletions(-) delete mode 100644 contracts/out/Cluster.sol/Bitmask.json delete mode 100644 contracts/test/Suite.sol diff --git a/contracts/out/Cluster.sol/Bitmask.json b/contracts/out/Cluster.sol/Bitmask.json deleted file mode 100644 index 49c292ba..00000000 --- a/contracts/out/Cluster.sol/Bitmask.json +++ /dev/null @@ -1 +0,0 @@ -{"abi":[],"bytecode":{"object":"0x608060405234601d57600e6021565b603e602c823930815050603e90f35b6027565b60405190565b5f80fdfe60806040525f80fdfea26469706673582212204aa32359976a200130b15990eea5f63a381b6d2388088cc5e76b3b7d8e36e1a264736f6c634300081c0033","sourceMap":"9259:1079:24:-:0;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;","linkReferences":{}},"deployedBytecode":{"object":"0x60806040525f80fdfea26469706673582212204aa32359976a200130b15990eea5f63a381b6d2388088cc5e76b3b7d8e36e1a264736f6c634300081c0033","sourceMap":"9259:1079:24:-:0;;;;;","linkReferences":{}},"methodIdentifiers":{},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.28+commit.7893614a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/Cluster.sol\":\"Bitmask\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[\":@openzeppelin-contracts-5.3.0/=dependencies/@openzeppelin-contracts-5.3.0/\",\":forge-std-1.9.7/=dependencies/forge-std-1.9.7/src/\",\":forge-std/=dependencies/forge-std/src/\",\":openzeppelin-contracts/=dependencies/@openzeppelin-contracts-5.3.0/\"],\"viaIR\":true},\"sources\":{\"dependencies/openzeppelin-contracts/utils/Panic.sol\":{\"keccak256\":\"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a\",\"dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG\"]},\"dependencies/openzeppelin-contracts/utils/math/Math.sol\":{\"keccak256\":\"0x1225214420c83ebcca88f2ae2b50f053aaa7df7bd684c3e878d334627f2edfc6\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6c5fab4970634f9ab9a620983dc1c8a30153981a0b1a521666e269d0a11399d3\",\"dweb:/ipfs/QmVRnBC575MESGkEHndjujtR7qub2FzU9RWy9eKLp4hPZB\"]},\"dependencies/openzeppelin-contracts/utils/math/SafeCast.sol\":{\"keccak256\":\"0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b1d578337048cad08c1c03041cca5978eff5428aa130c781b271ad9e5566e1f8\",\"dweb:/ipfs/QmPFKL2r9CBsMwmUqqdcFPfHZB2qcs9g1HDrPxzWSxomvy\"]},\"src/Cluster.sol\":{\"keccak256\":\"0xac5b938cdbe809da30fdf59bd2492c6aa341ff7ea88f152be3543202b7485a44\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://d5a43c1a46e45e9b06a441c5f0bd6cd2cba55c7a2aa2ffe605c2b51bd1823b89\",\"dweb:/ipfs/QmcSR9umgpQyM4YtDCrBC7nhSQD1UuTdUqEUCwCohB58Fy\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.28+commit.7893614a"},"language":"Solidity","output":{"abi":[],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"remappings":["@openzeppelin-contracts-5.3.0/=dependencies/@openzeppelin-contracts-5.3.0/","forge-std-1.9.7/=dependencies/forge-std-1.9.7/src/","forge-std/=dependencies/forge-std/src/","openzeppelin-contracts/=dependencies/@openzeppelin-contracts-5.3.0/"],"optimizer":{"enabled":false,"runs":200},"metadata":{"bytecodeHash":"ipfs"},"compilationTarget":{"src/Cluster.sol":"Bitmask"},"evmVersion":"cancun","libraries":{},"viaIR":true},"sources":{"dependencies/openzeppelin-contracts/utils/Panic.sol":{"keccak256":"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a","urls":["bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a","dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG"],"license":"MIT"},"dependencies/openzeppelin-contracts/utils/math/Math.sol":{"keccak256":"0x1225214420c83ebcca88f2ae2b50f053aaa7df7bd684c3e878d334627f2edfc6","urls":["bzz-raw://6c5fab4970634f9ab9a620983dc1c8a30153981a0b1a521666e269d0a11399d3","dweb:/ipfs/QmVRnBC575MESGkEHndjujtR7qub2FzU9RWy9eKLp4hPZB"],"license":"MIT"},"dependencies/openzeppelin-contracts/utils/math/SafeCast.sol":{"keccak256":"0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54","urls":["bzz-raw://b1d578337048cad08c1c03041cca5978eff5428aa130c781b271ad9e5566e1f8","dweb:/ipfs/QmPFKL2r9CBsMwmUqqdcFPfHZB2qcs9g1HDrPxzWSxomvy"],"license":"MIT"},"src/Cluster.sol":{"keccak256":"0xac5b938cdbe809da30fdf59bd2492c6aa341ff7ea88f152be3543202b7485a44","urls":["bzz-raw://d5a43c1a46e45e9b06a441c5f0bd6cd2cba55c7a2aa2ffe605c2b51bd1823b89","dweb:/ipfs/QmcSR9umgpQyM4YtDCrBC7nhSQD1UuTdUqEUCwCohB58Fy"],"license":"MIT"}},"version":1},"id":24} \ No newline at end of file diff --git a/contracts/test/Suite.sol b/contracts/test/Suite.sol deleted file mode 100644 index be498c80..00000000 --- a/contracts/test/Suite.sol +++ /dev/null @@ -1,797 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -import "../dependencies/forge-std/src/Test.sol"; -import {Vm} from "../dependencies/forge-std/src/Vm.sol"; -import "../dependencies/forge-std/src/console.sol"; - -import "../src/Cluster.sol"; - -import "../dependencies/openzeppelin-contracts/utils/Strings.sol"; - -uint256 constant OWNER = 12345; -uint256 constant NEW_OWNER = 56789; -uint256 constant ANYONE = 9000; -uint256 constant OPERATOR = 1; - -bytes constant DEFAULT_OPERATOR_DATA = "Some operator specific data"; -uint16 constant MAX_OPERATOR_DATA_BYTES = 4096; - -contract ClusterTest is Test { - using Bitmask for uint256; - using Strings for uint256; - - Cluster cluster; - ClusterView clusterView; - - constructor() { - newCluster(); - } - - function test_bitmask() public pure { - uint256 bitmask; - - for (uint256 i = 0; i < 256; i++) { - bitmask = Bitmask.fill(uint8(i)); - assertEq(bitmask.count1(), i); - - if (i == 0) { - assertEq(bitmask.highest1(), 0); - } else { - assertEq(bitmask.highest1(), i - 1); - assertEq(bitmask.is1(uint8(i - 1)), true); - if (i != 256) { - assertEq(bitmask.is1(uint8(i)), false); - } - } - } - - bitmask = Bitmask.fill(5); - assertEq(bitmask, 0x1F); - - bitmask = bitmask.set1(5); - bitmask = bitmask.set1(6); - bitmask = bitmask.set1(7); - assertEq(bitmask, 0xFF); - assertEq(bitmask.count1(), 8); - assertEq(bitmask.highest1(), 7); - - bitmask = bitmask.set0(5); - assertEq(bitmask, 0xDF); - assertEq(bitmask.count1(), 7); - assertEq(bitmask.highest1(), 7); - - assertEq(parseBitmask("1010"), 10); - - assert(parseBitmask("1010").isSubsetOf(parseBitmask("1110"))); - assert(!parseBitmask("1010").isSubsetOf(parseBitmask("1101"))); - } - - // contructor - - function test_canNotCreateClusterWithTooManyOperators() public { - vm.expectRevert(); - newCluster(257); - } - - function test_canCreateClusterWithMaxNumberOfOperators() public { - newCluster(256); - } - - function test_clusterContainsInitialNodeOperators() public view { - assertNodeOperatorSlotsLength(5); - for (uint256 i = 0; i < 5; i++) { - assertNodeOperatorSlot(i, newNodeOperator(i + 1)); - } - } - - function test_clusterContainsInitialKeyspace() public view { - assertKeyspace(0, newKeyspace("11111")); - assertKeyspace(1, newKeyspace("0")); - } - - function test_clusterInitialVersionIs0() public view { - assertVersion(0); - } - - function test_clusterInitialKeyspaceVersionIs0() public view { - assertKeyspaceVersion(0); - } - - // addNodeOperator - - function test_anyoneCanNotAddNodeOperator() public { - expectRevert("not the owner"); - addNodeOperator(ANYONE, 5, newNodeOperator(6)); - } - - function test_operatorCanNotAddAnotherNodeOperator() public { - expectRevert("not the owner"); - addNodeOperator(ANYONE, 5, newNodeOperator(6)); - } - - function test_ownerCanAddNodeOperator() public { - addNodeOperator(OWNER, 5, newNodeOperator(6)); - } - - function test_addNodeOperatorBumpsVersion() public { - addNodeOperator(OWNER, 5, newNodeOperator(6)); - assertVersion(1); - } - - function test_addNodeOperatorDoesNotBumpKeyspaceVersion() public { - addNodeOperator(OWNER, 5, newNodeOperator(6)); - assertKeyspaceVersion(0); - } - - function test_addNodeOperatorEmitsEventNodeOperatorAdded() public { - NodeOperator memory operator = newNodeOperator(6); - vm.expectEmit(); - emit NodeOperatorAdded(5, operator, 1); - addNodeOperator(OWNER, 5, operator); - } - - // updateNodeOperator - - function test_anyoneCanNotUpdateNodeOperator() public { - expectRevert("unauthorized"); - updateNodeOperator(ANYONE, newNodeOperator(1, "new data")); - } - - function test_ownerCanUpdateNodeOperator() public { - updateNodeOperator(OWNER, newNodeOperator(1, "new data")); - } - - function test_operatorCanNotUpdateAnotherNodeOperator() public { - expectRevert("unauthorized"); - updateNodeOperator(1, newNodeOperator(2, "new data")); - } - - function test_operatorCanUpdateItself() public { - updateNodeOperator(1, newNodeOperator(1, "new data")); - } - - function test_updateNodeOperatorDoesUpdateTheData() public { - NodeOperator memory operator = newNodeOperator(1, "new data"); - updateNodeOperator(1, operator); - assertNodeOperatorSlot(0, operator); - } - - function test_updateNodeOperatorBumpsVersion() public { - updateNodeOperator(1, newNodeOperator(1, "new data")); - assertVersion(1); - } - - function test_updateNodeOperatorDoesNotBumpKeyspaceVersion() public { - updateNodeOperator(1, newNodeOperator(1, "new data")); - assertKeyspaceVersion(0); - } - - function test_updateNodeOperatorEmitsEventNodeOperatorUpdated() public { - NodeOperator memory operator = newNodeOperator(1, "new data"); - vm.expectEmit(); - emit NodeOperatorUpdated(operator, 1); - updateNodeOperator(1, operator); - } - - // removeNodeOperator - - function test_anyoneCanNotRemoveNodeOperator() public { - expectRevert("not the owner"); - removeNodeOperator(ANYONE, 1); - } - - function test_operatorCanNotRemoveAnotherNodeOperator() public { - expectRevert("not the owner"); - removeNodeOperator(1, 2); - } - - function test_operatorCanNotRemoveItself() public { - expectRevert("not the owner"); - removeNodeOperator(1, 1); - } - - function test_ownerCanRemoveNodeOperator() public { - addNodeOperator(OWNER, 5, newNodeOperator(6)); - removeNodeOperator(OWNER, 6); - } - - function test_canNotRemoveNodeOperatorInKeyspace() public { - expectRevert("in keyspace"); - removeNodeOperator(OWNER, 1); - } - - function test_removeNodeOperatorClearsTheSlot() public { - addNodeOperator(OWNER, 5, newNodeOperator(6)); - assertNodeOperatorSlotsLength(6); - removeNodeOperator(OWNER, 6); - assertNodeOperatorSlotsLength(5); - } - - function test_removeNodeOperatorBumpsVersion() public { - addNodeOperator(OWNER, 5, newNodeOperator(6)); - assertVersion(1); - removeNodeOperator(OWNER, 6); - assertVersion(2); - } - - function test_removeNodeOperatorDoesNotBumpKeyspaceVersion() public { - addNodeOperator(OWNER, 5, newNodeOperator(6)); - removeNodeOperator(OWNER, 6); - assertKeyspaceVersion(0); - } - - function test_removeNodeOperatorEmitsEventNodeOperatorRemoved() public { - addNodeOperator(OWNER, 5, newNodeOperator(6)); - vm.expectEmit(); - emit NodeOperatorRemoved(vm.addr(6), 2); - removeNodeOperator(OWNER, 6); - } - - // startMigration - - function test_anyoneCanNotStartMigration() public { - expectRevert("not the owner"); - startMigration(ANYONE, newKeyspace("01111")); - } - - function test_operatorCanNotStartMigration() public { - expectRevert("not the owner"); - startMigration(OPERATOR, newKeyspace("01111")); - } - - function test_ownerCanStartMigration() public { - startMigration(OWNER, newKeyspace("01111")); - } - - function test_canNotStartMigrationWhenMaintenanceInProgress() public { - startMaintenance(1); - expectRevert("maintenance in progress"); - startMigration(OWNER, newKeyspace("01111")); - } - - function test_canNotStartMigrationWhenMigrationInProgress() public { - startMigration(OWNER, newKeyspace("01111")); - expectRevert("migration in progress"); - startMigration(OWNER, newKeyspace("11111")); - } - - function test_startMigrationBumpsVersion() public { - startMigration(OWNER, newKeyspace("01111")); - assertVersion(1); - } - - function test_startMigrationBumpsKeyspaceVersion() public { - startMigration(OWNER, newKeyspace("01111")); - assertKeyspaceVersion(1); - } - - function test_startMigrationEmitsMigrationStartedEvent() public { - Keyspace memory keyspace = newKeyspace("01111"); - vm.expectEmit(); - emit MigrationStarted(1, keyspace, 1, 1); - startMigration(OWNER, keyspace); - } - - function test_startMigrationInitializesMigration() public { - addNodeOperator(OWNER, 5, newNodeOperator(6)); - addNodeOperator(OWNER, 6, newNodeOperator(7)); - startMigration(OWNER, newKeyspace("1111101")); - assertMigration(1, "1111101"); - } - - function test_startMigrationPopulatesMigrationKeyspace() public { - addNodeOperator(OWNER, 5, newNodeOperator(6)); - addNodeOperator(OWNER, 6, newNodeOperator(7)); - Keyspace memory keyspace = newKeyspace("1111101"); - startMigration(OWNER, keyspace); - assertKeyspace(1, keyspace); - } - - // completeMigration - - function test_anyoneCanNotCompleteMigration() public { - startMigration(OWNER, newKeyspace("01111")); - expectRevert("unknown operator"); - completeMigration(ANYONE, 1); - } - - function test_ownerCanNotCompleteMigration() public { - startMigration(OWNER, newKeyspace("01111")); - expectRevert("unknown operator"); - completeMigration(OWNER, 1); - } - - function test_operatorCanNotCompleteNonExistentMigration() public { - expectRevert("no migration"); - completeMigration(OPERATOR, 1); - } - - function test_operatorCanCompleteMigration() public { - startMigration(OWNER, newKeyspace("01111")); - completeMigration(OPERATOR, 1); - } - - function test_canNotCompleteMigrationTwice() public { - startMigration(OWNER, newKeyspace("01111")); - completeMigration(OPERATOR, 1); - expectRevert("not pulling"); - completeMigration(OPERATOR, 1); - } - - function test_completeMigrationBumpsVersion() public { - startMigration(OWNER, newKeyspace("01111")); - completeMigration(OPERATOR, 1); - assertVersion(2); - } - - function test_completeMigrationRemovesOperatorFromPullingOperators() public { - startMigration(OWNER, newKeyspace("11110")); - assertMigration(1, "11110"); - completeMigration(5, 1); - assertMigration(1, "01110"); - completeMigration(3, 1); - assertMigration(1, "01010"); - completeMigration(2, 1); - assertMigration(1, "01000"); - completeMigration(4, 1); - assertMigration(1, "00000"); - } - - function test_completeMigrationDoesNotBumpKeyspaceVersionIfNotCompleted() public { - assertKeyspaceVersion(0); - startMigration(OWNER, newKeyspace("01111")); - assertKeyspaceVersion(1); - completeMigration(1, 1); - assertKeyspaceVersion(1); - } - - function test_completeMigrationDoesNotBumpKeyspaceVersionIfCompleted() public { - assertKeyspaceVersion(0); - startMigration(OWNER, newKeyspace("01111")); - assertKeyspaceVersion(1); - for (uint256 i = 0; i < 4; i++) { - completeMigration(i + 1, 1); - } - assertKeyspaceVersion(1); - } - - function test_completeMigrationEmitsMigrationDataPullCompletedEventIfNotCompleted() public { - startMigration(OWNER, newKeyspace("01111")); - vm.expectEmit(); - emit MigrationDataPullCompleted(1, vm.addr(1), 2); - completeMigration(1, 1); - } - - function test_completeMigrationEmitsMigrationCompletedEventIfCompleted() public { - startMigration(OWNER, newKeyspace("01111")); - completeMigration(1, 1); - completeMigration(2, 1); - completeMigration(3, 1); - - vm.expectEmit(); - emit MigrationCompleted(1, vm.addr(4), 5); - completeMigration(4, 1); - } - - // abortMigration - - function test_anyoneCanNotAbortMigration() public { - startMigration(OWNER, newKeyspace("01111")); - expectRevert("not the owner"); - abortMigration(ANYONE, 1); - } - - function test_operatorCanNotAbortMigration() public { - startMigration(OWNER, newKeyspace("01111")); - expectRevert("not the owner"); - abortMigration(OPERATOR, 1); - } - - function test_ownerCanAbortMigration() public { - startMigration(OWNER, newKeyspace("01111")); - abortMigration(OWNER, 1); - } - - function test_canNotAbortNonExistentMigration() public { - expectRevert("no migration"); - abortMigration(OWNER, 1); - } - - function test_abortMigrationBumpsVersion() public { - startMigration(OWNER, newKeyspace("01111")); - abortMigration(OWNER, 1); - assertVersion(2); - } - - function test_abortMigrationRevertsKeyspaceVersion() public { - assertKeyspaceVersion(0); - startMigration(OWNER, newKeyspace("01111")); - assertKeyspaceVersion(1); - abortMigration(OWNER, 1); - assertKeyspaceVersion(0); - } - - function test_abortMigrationClearsPullingOperators() public { - startMigration(OWNER, newKeyspace("01111")); - abortMigration(OWNER, 1); - assertMigration(1, "00000"); - } - - function test_abortMigrationEmitsMigrationAbortedEvent() public { - startMigration(OWNER, newKeyspace("01111")); - vm.expectEmit(); - emit MigrationAborted(1, 2); - abortMigration(OWNER, 1); - } - - // startMaintenance - - function test_anyoneCanNotStartMaintenance() public { - expectRevert("unauthorized"); - startMaintenance(ANYONE); - } - - function test_ownerCanStartMaintenance() public { - startMaintenance(OWNER); - } - - function test_operatorCanStartMaintenance() public { - startMaintenance(OPERATOR); - } - - function test_canNotStartMaintenanceWhenMaintenanceInProgress() public { - startMaintenance(1); - expectRevert("maintenance in progress"); - startMaintenance(2); - } - - function test_canNotStartMaintenanceWhenMigrationInProgress() public { - startMigration(OWNER, newKeyspace("01111")); - expectRevert("migration in progress"); - startMaintenance(1); - } - - function test_startMaintenanceBumpsVersion() public { - startMaintenance(1); - assertVersion(1); - } - - function test_startMaintenanceDoesNotBumpKeyspaceVersion() public { - startMaintenance(1); - assertKeyspaceVersion(0); - } - - function test_startMaintenanceUpdatesMaintenance() public { - startMaintenance(1); - assertMaintenance(1); - } - - function test_startMaintenanceEmitsMaintenanceStartedEvent() public { - vm.expectEmit(); - emit MaintenanceStarted(vm.addr(1), 1); - startMaintenance(1); - } - - // finishMaintenance - - function test_anyoneCanNotFinishMaintenance() public { - startMaintenance(1); - expectRevert("unauthorized"); - finishMaintenance(ANYONE); - } - - function test_anotherOperatorCanNotFinishMaintenance() public { - startMaintenance(2); - expectRevert("unauthorized"); - finishMaintenance(1); - } - - function test_ownerCanFinishMaintenance() public { - startMaintenance(1); - finishMaintenance(OWNER); - } - - function test_operatorCanFinishMaintenance() public { - startMaintenance(OPERATOR); - finishMaintenance(OPERATOR); - } - - function test_canNotFinishNonExistentMaintenance() public { - expectRevert("no maintenance"); - finishMaintenance(1); - } - - function test_finishMaintenanceBumpsVersion() public { - startMaintenance(1); - finishMaintenance(1); - assertVersion(2); - } - - function test_finishMaintenanceDoesNotBumpKeyspaceVersion() public { - startMaintenance(1); - finishMaintenance(1); - assertKeyspaceVersion(0); - } - - function test_finishMaintenanceFreesMaintenanceSlot() public { - startMaintenance(1); - finishMaintenance(1); - assertNoMaintenance(); - } - - function test_finishMaintenanceEmitsMaintenanceFinishedEvent() public { - startMaintenance(1); - vm.expectEmit(); - emit MaintenanceFinished(2); - finishMaintenance(1); - } - - // updateSettings - - function test_anyoneCanNotUpdateSettings() public { - expectRevert("not the owner"); - updateSettings(ANYONE, Settings({ maxOperatorDataBytes: 100 })); - } - - function test_operatorCanNotUpdateSettings() public { - expectRevert("not the owner"); - updateSettings(OPERATOR, Settings({ maxOperatorDataBytes: 100 })); - } - - function test_ownerCanUpdateSettings() public { - updateSettings(OWNER, Settings({ maxOperatorDataBytes: 100 })); - } - - function test_updateSettingsUpdatesMaxOperatorDataBytes() public { - updateSettings(OWNER, Settings({ maxOperatorDataBytes: 5 })); - expectRevert("operator data too large"); - addNodeOperator(OWNER, 5, newNodeOperator(10, "123456")); - } - - function test_updateSettingsBumpsVersion() public { - updateSettings(OWNER, Settings({ maxOperatorDataBytes: 100 })); - assertVersion(1); - } - - function test_updateSettingsDoesNotBumpKeyspaceVersion() public { - updateSettings(OWNER, Settings({ maxOperatorDataBytes: 100 })); - assertKeyspaceVersion(0); - } - - // transferOwnership - - function test_anyoneCanNotTransferOwnership() public { - expectRevert("not the owner"); - transferOwnership(ANYONE, ANYONE); - } - - function test_operatorCanNotTransferOwnership() public { - expectRevert("not the owner"); - transferOwnership(OPERATOR, OPERATOR); - } - - function test_ownerCanTransferOwnership() public { - transferOwnership(OWNER, NEW_OWNER); - } - - function test_transferOwnershipChangesOwner() public { - transferOwnership(OWNER, NEW_OWNER); - startMigration(NEW_OWNER, newKeyspace("01111")); - } - - // full lifecycle - - function test_fullClusterLifecycle() public { - updateNodeOperator(1, newNodeOperator(1, "operator1")); - startMaintenance(2); - updateNodeOperator(3, newNodeOperator(3, "operator3")); - finishMaintenance(2); - - addNodeOperator(OWNER, 5, newNodeOperator(6, "operator6")); - addNodeOperator(OWNER, 6, newNodeOperator(7, "operator7")); - addNodeOperator(OWNER, 7, newNodeOperator(8, "operator8")); - startMigration(OWNER, newKeyspace("11111111")); - updateNodeOperator(1, newNodeOperator(1, "operator1")); - for (uint256 i = 0; i < 8; i++) { - completeMigration(i + 1, 1); - } - updateNodeOperator(3, newNodeOperator(3, "operator1")); - startMaintenance(7); - updateNodeOperator(7, newNodeOperator(7, "operator1")); - finishMaintenance(OWNER); - - startMigration(OWNER, newKeyspace("10111111")); - for (uint256 i = 0; i < 8; i++) { - if (i != 6) { - completeMigration(i + 1, 2); - } - } - - addNodeOperator(OWNER, 8, newNodeOperator(9, "operator9")); - startMigration(OWNER, newKeyspace("110111111")); - for (uint256 i = 0; i < 8; i++) { - if (i != 6) { - completeMigration(i + 1, 3); - } - } - abortMigration(OWNER, 3); - - transferOwnership(OWNER, NEW_OWNER); - updateSettings(NEW_OWNER, Settings({ maxOperatorDataBytes: 1024 })); - - assertKeyspaceVersion(2); - } - - // internal - - function newCluster() internal { - newCluster(5); - } - - function newCluster(uint256 operatorsCount) internal { - newCluster(Settings({ maxOperatorDataBytes: MAX_OPERATOR_DATA_BYTES }), operatorsCount); - } - - function newCluster(Settings memory settings, uint256 operatorsCount) internal { - setCaller(OWNER); - - NodeOperator[] memory operators = new NodeOperator[](operatorsCount); - for (uint256 i = 0; i < operatorsCount; i++) { - operators[i] = newNodeOperator(i + 1); - } - - cluster = new Cluster(settings, operators); - // ECRecover address. Constructor failed - if (address(cluster) == address(1)) { - return; - } - - updateClusterView(); - } - - function updateClusterView() internal { - clusterView = cluster.getView(); - } - - function setCaller(uint256 caller) internal { - vm.prank(vm.addr(caller)); - } - - function expectRevert(bytes memory revertBytes) internal { - vm.expectRevert(revertBytes); - } - - function assertNodeOperatorSlotsLength(uint256 expected) internal view { - assertEq(clusterView.nodeOperatorSlots.length, expected); - } - - function assertNodeOperatorSlot(uint256 idx, NodeOperator memory slot) internal view { - assertEq(clusterView.nodeOperatorSlots[idx].addr, slot.addr); - assertEq(clusterView.nodeOperatorSlots[idx].data, slot.data); - } - - function assertVersion(uint128 expectedVersion) internal view { - assertEq(clusterView.version, expectedVersion); - } - - function assertKeyspaceVersion(uint64 expectedVersion) internal view { - assertEq(clusterView.keyspaceVersion, expectedVersion); - } - - function assertKeyspace(uint256 idx, Keyspace memory expected) internal view { - assertEq(clusterView.keyspaces[idx].operatorsBitmask, expected.operatorsBitmask); - assertEq(clusterView.keyspaces[idx].replicationStrategy, expected.replicationStrategy); - } - - function assertMigration(uint64 id, string memory pullingOperatorsBitmaskStr) internal view { - uint256 pullingOperatorsBitmask = parseBitmask(pullingOperatorsBitmaskStr); - - assertEq(clusterView.migration.id, id); - assertEq(clusterView.migration.pullingOperatorsBitmask, pullingOperatorsBitmask); - } - - function assertMaintenance(uint256 operator) internal view { - assertEq(clusterView.maintenance.slot, vm.addr(operator)); - } - - function assertNoMaintenance() internal view { - assertEq(clusterView.maintenance.slot, address(0)); - } - - function startMigration(uint256 caller, Keyspace memory keyspace) internal { - setCaller(caller); - cluster.startMigration(keyspace); - updateClusterView(); - } - - function completeMigration(uint256 caller, uint64 id) internal { - setCaller(caller); - cluster.completeMigration(id); - updateClusterView(); - } - - function abortMigration(uint256 caller, uint64 id) internal { - setCaller(caller); - cluster.abortMigration(id); - updateClusterView(); - } - - function startMaintenance(uint256 caller) internal { - setCaller(caller); - cluster.startMaintenance(); - updateClusterView(); - } - - function finishMaintenance(uint256 caller) internal { - setCaller(caller); - cluster.finishMaintenance(); - updateClusterView(); - } - - function addNodeOperator(uint256 caller, uint8 idx, NodeOperator memory operator) internal { - setCaller(caller); - cluster.addNodeOperator(idx, operator); - updateClusterView(); - } - - function updateNodeOperator(uint256 caller, NodeOperator memory operator) internal { - setCaller(caller); - cluster.updateNodeOperator(operator); - updateClusterView(); - } - - function removeNodeOperator(uint256 caller, uint256 privateKey) internal { - setCaller(caller); - cluster.removeNodeOperator(vm.addr(privateKey)); - updateClusterView(); - } - - function updateSettings(uint256 caller, Settings memory settings) internal { - setCaller(caller); - cluster.updateSettings(settings); - updateClusterView(); - } - - function transferOwnership(uint256 caller, uint256 newOwner) internal { - setCaller(caller); - cluster.transferOwnership(vm.addr(newOwner)); - updateClusterView(); - } - - // function emptyNodeOperatorSlot() internal pure returns (NodeOperator memory) { - // NodeOperator memory operator; - // return operator; - // } - - function newNodeOperator(uint256 privateKey) internal pure returns (NodeOperator memory) { - return newNodeOperator(privateKey, abi.encodePacked("operator ", privateKey.toString())); - } - - function newNodeOperator(uint256 privateKey, bytes memory data) internal pure returns (NodeOperator memory) { - return NodeOperator({ addr: vm.addr(privateKey), data: data }); - } -} - -function newKeyspace(string memory operatorsBitmaskStr) pure returns (Keyspace memory) { - return newKeyspace(operatorsBitmaskStr, 0); -} - -function newKeyspace(string memory operatorsBitmaskStr, uint8 replicationStrategy) pure returns (Keyspace memory) { - return Keyspace({ - operatorsBitmask: parseBitmask(operatorsBitmaskStr), - replicationStrategy: replicationStrategy - }); -} - -function parseBitmask(string memory binary) pure returns (uint256 result) { - bytes memory b = bytes(binary); - for (uint256 i = 0; i < b.length; i++) { - result <<= 1; - bytes1 c = b[i]; - require(c == "0" || c == "1", "Invalid binary char"); - if (c == "1") { - result |= 1; - } - } -} From e68503f61b61a771dd686cdc8914f3bea5168775 Mon Sep 17 00:00:00 2001 From: Darksome Date: Fri, 27 Jun 2025 15:33:58 +0000 Subject: [PATCH 62/79] remove Config AsRef --- Cargo.lock | 1 - crates/rpc/Cargo.toml | 1 - crates/rpc/src/client2.rs | 11 ++--------- 3 files changed, 2 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dd199636..6758fe08 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8080,7 +8080,6 @@ dependencies = [ name = "wcn_rpc" version = "0.1.0" dependencies = [ - "arc-swap", "backoff", "bytes", "derivative", diff --git a/crates/rpc/Cargo.toml b/crates/rpc/Cargo.toml index 8f0e03e7..26d7643d 100644 --- a/crates/rpc/Cargo.toml +++ b/crates/rpc/Cargo.toml @@ -48,7 +48,6 @@ socket2 = "0.5.5" nix = { version = "0.28", default-features = false, features = ["socket", "net"] } governor = { version = "0.8", default-features = false, features = ["std"] } mini-moka = { version = "0.10", default-features = false, features = ["sync"] } -arc-swap = "1.7" [dev-dependencies] tracing-subscriber = "0.3" diff --git a/crates/rpc/src/client2.rs b/crates/rpc/src/client2.rs index f49a9dd0..e1409650 100644 --- a/crates/rpc/src/client2.rs +++ b/crates/rpc/src/client2.rs @@ -102,12 +102,6 @@ pub struct Config { pub priority: transport::Priority, } -impl AsRef for Config { - fn as_ref(&self) -> &Config { - self - } -} - /// RPC client responsible for establishing outbound [`Connection`]s to remote /// peers. #[derive_where(Clone)] @@ -187,7 +181,7 @@ impl Client { Ok(conn) } - .with_timeout((*self.config).as_ref().connection_timeout) + .with_timeout(self.config.connection_timeout) .await .map_err(|_| ErrorInner::Timeout)? .map_err(Error::new) @@ -416,8 +410,7 @@ impl Connection { let this = self.inner.clone(); tokio::spawn(async move { - let mut interval = - tokio::time::interval((*this.client.config).as_ref().reconnect_interval); + let mut interval = tokio::time::interval(this.client.config.reconnect_interval); interval.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip); loop { From 8585d99974977a2bbc38daa6617ac8d104c33466 Mon Sep 17 00:00:00 2001 From: Darksome Date: Fri, 27 Jun 2025 15:59:36 +0000 Subject: [PATCH 63/79] fix clippy --- crates/storage_api2/src/lib.rs | 4 ++-- crates/storage_api2/src/operation.rs | 4 ++-- crates/storage_api2/src/rpc/client.rs | 24 ++++++++++++------------ 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/crates/storage_api2/src/lib.rs b/crates/storage_api2/src/lib.rs index c8136908..6bf7fbc2 100644 --- a/crates/storage_api2/src/lib.rs +++ b/crates/storage_api2/src/lib.rs @@ -185,7 +185,7 @@ pub struct Record<'a> { pub version: RecordVersion, } -impl<'a> Record<'a> { +impl Record<'_> { /// Converts `Self` into 'static. pub fn into_static(self) -> Record<'static> { Record { @@ -213,7 +213,7 @@ pub struct MapEntry<'a> { pub record: Record<'a>, } -impl<'a> MapEntry<'a> { +impl MapEntry<'_> { /// Converts `Self` into 'static. pub fn into_static(self) -> MapEntry<'static> { MapEntry { diff --git a/crates/storage_api2/src/operation.rs b/crates/storage_api2/src/operation.rs index 17600e64..7d4201d9 100644 --- a/crates/storage_api2/src/operation.rs +++ b/crates/storage_api2/src/operation.rs @@ -209,13 +209,13 @@ pub enum Output<'a> { None, } -impl<'a> From<()> for Output<'a> { +impl From<()> for Output<'_> { fn from(_: ()) -> Self { Self::None } } -impl<'a> Output<'a> { +impl Output<'_> { /// Tries to downcast an [`Output`] within a [`Result`] into a concrete /// output type. pub fn downcast_result(operation_result: Result) -> Result diff --git a/crates/storage_api2/src/rpc/client.rs b/crates/storage_api2/src/rpc/client.rs index 3ab83ef1..e71fe617 100644 --- a/crates/storage_api2/src/rpc/client.rs +++ b/crates/storage_api2/src/rpc/client.rs @@ -22,51 +22,51 @@ where >, { async fn get(&self, op: &operation::Get<'_>) -> Result>> { - self.send::(&op)?.await?.map_err(Into::into) + self.send::(op)?.await?.map_err(Into::into) } async fn set(&self, op: &operation::Set<'_>) -> Result<()> { - self.send::(&op)?.await?.map_err(Into::into) + self.send::(op)?.await?.map_err(Into::into) } async fn del(&self, op: &operation::Del<'_>) -> Result<()> { - self.send::(&op)?.await?.map_err(Into::into) + self.send::(op)?.await?.map_err(Into::into) } async fn get_exp(&self, op: &operation::GetExp<'_>) -> Result> { - self.send::(&op)?.await?.map_err(Into::into) + self.send::(op)?.await?.map_err(Into::into) } async fn set_exp(&self, op: &operation::SetExp<'_>) -> Result<()> { - self.send::(&op)?.await?.map_err(Into::into) + self.send::(op)?.await?.map_err(Into::into) } async fn hget(&self, op: &operation::HGet<'_>) -> Result>> { - self.send::(&op)?.await?.map_err(Into::into) + self.send::(op)?.await?.map_err(Into::into) } async fn hset(&self, op: &operation::HSet<'_>) -> Result<()> { - self.send::(&op)?.await?.map_err(Into::into) + self.send::(op)?.await?.map_err(Into::into) } async fn hdel(&self, op: &operation::HDel<'_>) -> Result<()> { - self.send::(&op)?.await?.map_err(Into::into) + self.send::(op)?.await?.map_err(Into::into) } async fn hget_exp(&self, op: &operation::HGetExp<'_>) -> Result> { - self.send::(&op)?.await?.map_err(Into::into) + self.send::(op)?.await?.map_err(Into::into) } async fn hset_exp(&self, op: &operation::HSetExp<'_>) -> Result<()> { - self.send::(&op)?.await?.map_err(Into::into) + self.send::(op)?.await?.map_err(Into::into) } async fn hcard(&self, op: &operation::HCard<'_>) -> Result { - self.send::(&op)?.await?.map_err(Into::into) + self.send::(op)?.await?.map_err(Into::into) } async fn hscan(&self, op: &operation::HScan<'_>) -> Result> { - self.send::(&op)?.await?.map_err(Into::into) + self.send::(op)?.await?.map_err(Into::into) } async fn execute<'a>( From 471b33417814308eb55d11c43432d0aa6df10467 Mon Sep 17 00:00:00 2001 From: Darksome Date: Fri, 27 Jun 2025 16:06:26 +0000 Subject: [PATCH 64/79] Namespace::from_str test --- crates/storage_api2/src/lib.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/crates/storage_api2/src/lib.rs b/crates/storage_api2/src/lib.rs index 6bf7fbc2..530d41d3 100644 --- a/crates/storage_api2/src/lib.rs +++ b/crates/storage_api2/src/lib.rs @@ -397,5 +397,13 @@ impl From for Error { #[cfg(test)] #[test] fn test_namespace_from_str() { - todo!() + fn ns(s: &str) -> Result { + s.parse() + } + + assert!(ns("0x14Cb1e6fb683A83455cA283e10f4959740A49ed7/0").is_ok()); + assert!(ns("14Cb1e6fb683A83455cA283e10f4959740A49ed7/0").is_ok()); + assert!(ns("14Cb1e6fb683A83455cA283e10f4959740A49ed7/255").is_ok()); + assert!(ns("14Cb1e6fb683A83455cA283e10f4959740A49ed7/256").is_err()); + assert!(ns("4Cb1e6fb683A83455cA283e10f4959740A49ed7/1").is_err()); } From 8ceb1e218249b9f842e6bebae8f853c31c59a9b4 Mon Sep 17 00:00:00 2001 From: Darksome Date: Fri, 27 Jun 2025 16:22:11 +0000 Subject: [PATCH 65/79] cleanup --- crates/rpc/src/client2.rs | 30 +++-------------------- crates/rpc/src/lib.rs | 9 ------- crates/rpc/src/quic/client.rs | 26 ++++++++------------ crates/rpc/src/server2.rs | 45 ++-------------------------------- crates/rpc/src/transport2.rs | 4 +-- crates/storage_api2/src/lib.rs | 2 +- 6 files changed, 18 insertions(+), 98 deletions(-) diff --git a/crates/rpc/src/client2.rs b/crates/rpc/src/client2.rs index e1409650..e8dbecb2 100644 --- a/crates/rpc/src/client2.rs +++ b/crates/rpc/src/client2.rs @@ -250,18 +250,6 @@ pub struct Outbound { recv: MapErr, fn(transport2::Error) -> Error>, } -impl Outbound { - /// Returns [`Sink`] of outbound requests. - pub fn sink(&mut self) -> &mut impl for<'a> Sink<&'a BorrowedRequest<'a, RPC>, Error = Error> { - &mut self.send - } - - /// Returns [`Stream`] of inbound responses. - pub fn stream(&mut self) -> &mut impl Stream> { - &mut self.recv - } -} - impl Outbound { /// Returns mutable references to the underlying request/response streams. pub fn streams_mut( @@ -277,7 +265,7 @@ impl Outbound { /// Outbound connection. /// /// Existence of an instance of this type doesn't guarantee that the actual -/// network [`Connection`] is already established (or will ever be established). +/// network connection is already established (or will ever be established). #[derive_where(Clone)] pub struct Connection { inner: Arc>, @@ -297,10 +285,6 @@ struct ConnectionInner { rpc_handler: API::RpcHandler, } -pub fn assert_send_future(s: impl Future + Send) -> impl Future + Send { - s -} - impl Connection { /// Returns [`SocketAddrV4`] of the remote peer. pub fn remote_peer_addr(&self) -> &SocketAddrV4 { @@ -352,7 +336,7 @@ impl Connection { } })?; - let fut = async move { + Ok(async move { self.inner .rpc_handler .handle_rpc(rpc, input) @@ -362,17 +346,9 @@ impl Connection { self.reconnect(); } }) - }; - - // Ok(fut) - - Ok(assert_send_future(fut)) + }) } - // pub fn rpc_handler(&self) -> &API::RpcHandler { - // &self.inner.rpc_handler - // } - fn new_outbound_rpc(&self) -> Result, ErrorInner> { let quic = self.inner.watch_rx.borrow(); let Some(conn) = quic.as_ref() else { diff --git a/crates/rpc/src/lib.rs b/crates/rpc/src/lib.rs index a771ce05..d09f5a32 100644 --- a/crates/rpc/src/lib.rs +++ b/crates/rpc/src/lib.rs @@ -315,15 +315,6 @@ impl Error { /// RPC result. pub type Result = std::result::Result; -/// RPC error. -pub struct Error2 { - /// Error code. - pub code: u8, - - /// Error description. - pub description: Option, -} - // Workaround for this compliler bug: https://github.com/rust-lang/rust/issues/100013 // https://github.com/rust-lang/rust/issues/100013#issuecomment-2210995259 // TODO: remove when fixed diff --git a/crates/rpc/src/quic/client.rs b/crates/rpc/src/quic/client.rs index f7350815..0a7d19bd 100644 --- a/crates/rpc/src/quic/client.rs +++ b/crates/rpc/src/quic/client.rs @@ -141,7 +141,7 @@ impl Client { } #[derive(Clone, Debug)] -pub(crate) struct ConnectionHandler { +pub(super) struct ConnectionHandler { inner: Arc>, handshake: H, } @@ -234,7 +234,7 @@ fn new_connection( } impl ConnectionHandler { - pub(crate) fn new( + pub(super) fn new( peer_id: PeerId, addr: SocketAddr, server_name: ServerName, @@ -264,28 +264,22 @@ impl ConnectionHandler { } } - pub(crate) async fn open_bi( + async fn establish_stream( &self, - ) -> Result<(quinn::SendStream, quinn::RecvStream), EstablishStreamError> { + rpc_id: RpcId, + ) -> Result { let fut = self.inner.write()?.connection.clone(); let conn = fut.await; - match conn.open_bi().await { - Ok(bi) => Ok(bi), + let (mut tx, rx) = match conn.open_bi().await { + Ok(bi) => bi, Err(_) => self .reconnect(conn.stable_id())? .await .open_bi() .await - .map_err(|err| EstablishStreamError::Connection(err.into())), - } - } - - pub(crate) async fn establish_stream( - &self, - rpc_id: RpcId, - ) -> Result { - let (mut tx, rx) = self.open_bi().await?; + .map_err(|err| EstablishStreamError::Connection(err.into()))?, + }; tx.write_u128(rpc_id) .await @@ -493,7 +487,7 @@ impl Client { } } -pub(crate) async fn write_connection_header( +async fn write_connection_header( conn: &quinn::Connection, header: ConnectionHeader, ) -> Result<(), ConnectionError> { diff --git a/crates/rpc/src/server2.rs b/crates/rpc/src/server2.rs index 2011eaae..522e36a5 100644 --- a/crates/rpc/src/server2.rs +++ b/crates/rpc/src/server2.rs @@ -64,40 +64,15 @@ pub trait HandleRpc: Send + Sync { ) -> impl Future> + Send + 'a; } -// /// [`HandleRpc`] specialization for [`UnaryRpc`]s. -// pub trait HandleUnaryRpc: Send + Sync { -// /// Handles the provided RPC request. -// fn handle_unary_rpc( -// &self, -// request: RPC::Request, -// responder: Responder<'_, RPC>, -// ) -> impl Future> + Send; -// } - /// [`HandleRpc`] specialization for [`UnaryRpc`]s. pub trait HandleRequest: Send + Sync { + /// Handles the provided RPC request. fn handle_request( &self, request: RPC::Request, ) -> impl Future + Send + '_; } -// /// [`UnaryRpc`] responder. -// pub trait Responder: Send { -// /// Sends an RPC response. -// fn respond(self, response: &BorrowedResponse) -> impl Future> + Send; } - -// struct ResponderImpl { -// sink: SinkMapErr, fn(transport2::Error) -> Error>, -// } - -// impl<'a, RPC: UnaryRpc> Responder for ResponderImpl<'a, RPC> { -// fn respond(self, response: &BorrowedResponse) -> impl Future> + Send { self.sink.send(response) -// } -// } - impl HandleRpc for H where RPC: UnaryRpc, @@ -490,22 +465,6 @@ impl Inbound { } } -pub struct Responder<'a, RPC: UnaryRpc> { - rpc: &'a mut Inbound, -} - -impl<'a, RPC: UnaryRpc> Responder<'a, RPC> { - pub fn respond<'r>( - self, - response: &'r BorrowedResponse<'r, RPC>, - ) -> impl Future> + Send + 'r - where - 'a: 'r, - { - self.rpc.send.send(response) - } -} - impl Connection<'_, API> { /// Returns [`PeerId`] of the remote peer. pub fn remote_peer_id(&self) -> &PeerId { @@ -541,7 +500,7 @@ impl Connection<'_, API> { } /// Accepts the next [`InboundRpc`]. - pub async fn accept_rpc(&self) -> Result> { + async fn accept_rpc(&self) -> Result> { loop { let (tx, mut rx) = self.inner.quic.accept_bi().await.map_err(Error::new)?; diff --git a/crates/rpc/src/transport2.rs b/crates/rpc/src/transport2.rs index 533e1109..2fa4723e 100644 --- a/crates/rpc/src/transport2.rs +++ b/crates/rpc/src/transport2.rs @@ -105,7 +105,7 @@ impl BiDirectionalStream { } } -/// [`Stream`] of outbound [`Message`]s. +/// [`Stream`] of outbound [Message][`MessageV2`]s. #[pin_project(project = SendStreamProj)] pub struct SendStream { #[pin] @@ -152,7 +152,7 @@ where } } -/// [`Stream`] of inbound [`Message`]s. +/// [`Stream`] of inbound [Message][`MessageV2`]s. #[pin_project] pub struct RecvStream>( #[allow(clippy::type_complexity)] diff --git a/crates/storage_api2/src/lib.rs b/crates/storage_api2/src/lib.rs index 530d41d3..8cfc0a8f 100644 --- a/crates/storage_api2/src/lib.rs +++ b/crates/storage_api2/src/lib.rs @@ -198,7 +198,7 @@ impl Record<'_> { /// Entry within a Map. /// -/// Maps are a separate data type of WCN Datbase, similar to Redis Hashes. +/// Maps are a separate data type of WCN Database, similar to Redis Hashes. /// They differ from regular KV pairs by having a subkey (AKA /// [field][MapEntry::field]). /// From 2a7f149f94bd452ebfc1736eda0c09fe639a2078 Mon Sep 17 00:00:00 2001 From: Darksome Date: Mon, 30 Jun 2025 10:11:48 +0000 Subject: [PATCH 66/79] fix: missing match arms --- crates/storage_api2/src/rpc/server.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/crates/storage_api2/src/rpc/server.rs b/crates/storage_api2/src/rpc/server.rs index f8d136fb..645c3571 100644 --- a/crates/storage_api2/src/rpc/server.rs +++ b/crates/storage_api2/src/rpc/server.rs @@ -54,15 +54,15 @@ where RpcId::Get => rpc.handle::(&handler).await, RpcId::Set => rpc.handle::(&handler).await, RpcId::Del => rpc.handle::(&handler).await, - RpcId::SetExp => todo!(), - RpcId::GetExp => todo!(), - RpcId::HGet => todo!(), - RpcId::HSet => todo!(), - RpcId::HDel => todo!(), - RpcId::HSetExp => todo!(), - RpcId::HGetExp => todo!(), - RpcId::HCard => todo!(), - RpcId::HScan => todo!(), + RpcId::SetExp => rpc.handle::(&handler).await, + RpcId::GetExp => rpc.handle::(&handler).await, + RpcId::HGet => rpc.handle::(&handler).await, + RpcId::HSet => rpc.handle::(&handler).await, + RpcId::HDel => rpc.handle::(&handler).await, + RpcId::HSetExp => rpc.handle::(&handler).await, + RpcId::HGetExp => rpc.handle::(&handler).await, + RpcId::HCard => rpc.handle::(&handler).await, + RpcId::HScan => rpc.handle::(&handler).await, } }) .await From 0efe983ad5349d914e6409fd81eae666e688e900 Mon Sep 17 00:00:00 2001 From: Github Bot Date: Mon, 30 Jun 2025 10:12:15 +0000 Subject: [PATCH 67/79] Bump VERSION to 250630.0 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 9f8c16d6..b46821fd 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -250627.0 +250630.0 From a22d4cfe56b64018b3cc3977b9e230e229232773 Mon Sep 17 00:00:00 2001 From: Darksome Date: Mon, 30 Jun 2025 20:07:45 +0000 Subject: [PATCH 68/79] integration tests --- Cargo.lock | 3 + crates/rpc/src/client2.rs | 7 + crates/rpc/src/server2.rs | 63 ++-- crates/storage_api2/Cargo.toml | 5 + crates/storage_api2/src/lib.rs | 6 +- crates/storage_api2/src/operation.rs | 26 +- crates/storage_api2/src/rpc/client.rs | 38 +- crates/storage_api2/src/rpc/mod.rs | 8 +- crates/storage_api2/tests/integration.rs | 451 +++++++++++++++++++++++ 9 files changed, 555 insertions(+), 52 deletions(-) create mode 100644 crates/storage_api2/tests/integration.rs diff --git a/Cargo.lock b/Cargo.lock index 6758fe08..e62ba96f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8136,12 +8136,15 @@ dependencies = [ "const-hex", "derive_more 1.0.0", "futures", + "rand 0.8.5", "serde", "strum", "tap", "thiserror 1.0.64", "time", + "tokio", "tracing", + "tracing-subscriber", "wc", "wcn_auth", "wcn_rpc", diff --git a/crates/rpc/src/client2.rs b/crates/rpc/src/client2.rs index e8dbecb2..208b8991 100644 --- a/crates/rpc/src/client2.rs +++ b/crates/rpc/src/client2.rs @@ -179,6 +179,13 @@ impl Client { drop(guard); + tracing::info!( + api = %API::NAME, + addr = %conn.remote_peer_addr(), + peer_id = %conn.remote_peer_id(), + "Connection established" + ); + Ok(conn) } .with_timeout(self.config.connection_timeout) diff --git a/crates/rpc/src/server2.rs b/crates/rpc/src/server2.rs index 522e36a5..c1732c4f 100644 --- a/crates/rpc/src/server2.rs +++ b/crates/rpc/src/server2.rs @@ -147,7 +147,7 @@ where } /// Runs this RPC [`Server`] - fn serve(self, cfg: Config) -> Result> { + fn serve(self, cfg: Config) -> Result + Send> { let transport_config = quic::new_quinn_transport_config(cfg.max_concurrent_rpcs); let server_tls_config = libp2p_tls::make_server_config(&cfg.keypair).map_err(Error::new)?; let server_tls_config = @@ -174,6 +174,8 @@ where let rpc_semaphore = Arc::new(Semaphore::new(cfg.max_concurrent_rpcs as usize)); + tracing::info!(port = cfg.port, server_name = cfg.name, "Serving"); + Ok(accept_connections( cfg, endpoint, @@ -188,12 +190,14 @@ mod sealed { use super::*; pub trait ConnectionRouter: Clone + Send + Sync + 'static { + fn contains_api(&self, api_name: &ApiName) -> bool; + /// Routes [`Connection`] to the [`Api`] connection handler. fn route_connection( &self, api_name: &ApiName, conn: Connection<'_>, - ) -> impl Future>> + Send; + ) -> impl Future> + Send; } } @@ -209,20 +213,18 @@ struct Multiplexer { } impl sealed::ConnectionRouter for ApiServer { - async fn route_connection( - &self, - api_name: &ApiName, - conn: Connection<'_>, - ) -> Option> { - if api_name != &H::Api::NAME { - return None; + fn contains_api(&self, api_name: &ApiName) -> bool { + api_name == &H::Api::NAME + } + + async fn route_connection(&self, api_name: &ApiName, conn: Connection<'_>) -> Result<()> { + if !self.contains_api(api_name) { + return Err(ErrorInner::UnknownApi(*api_name).into()); } - Some( - self.connection_handler - .handle_connection(conn.specify_api()) - .await, - ) + self.connection_handler + .handle_connection(conn.specify_api()) + .await } } @@ -231,14 +233,15 @@ where A: sealed::ConnectionRouter, B: sealed::ConnectionRouter, { - async fn route_connection( - &self, - api_name: &ApiName, - conn: Connection<'_>, - ) -> Option> { - match self.head.route_connection(api_name, conn).await { - opt @ Some(_) => opt, - None => self.tail.route_connection(api_name, conn).await, + fn contains_api(&self, api_name: &ApiName) -> bool { + self.head.contains_api(api_name) || self.tail.contains_api(api_name) + } + + async fn route_connection(&self, api_name: &ApiName, conn: Connection<'_>) -> Result<()> { + if self.head.contains_api(api_name) { + self.head.route_connection(api_name, conn).await + } else { + self.tail.route_connection(api_name, conn).await } } } @@ -345,16 +348,14 @@ fn accept_connection( _marker: PhantomData, }; - match router.route_connection(&api_name, conn).await { - Some(res) => res, - None => { - tx.write_i32(ConnectionStatusCode::UnknownApi as i32) - .await - .map_err(Error::new)?; + let status = if router.contains_api(&api_name) { + ConnectionStatusCode::Ok + } else { + ConnectionStatusCode::UnknownApi + }; + tx.write_i32(status as i32).await.map_err(Error::new)?; - Err(ErrorInner::UnknownApi(api_name).into()) - } - } + router.route_connection(&api_name, conn).await } .map_err(|err| tracing::debug!(?err, "Inbound connection handler failed")) .with_metrics(future_metrics!("wcn_rpc_server_inbound_connection")) diff --git a/crates/storage_api2/Cargo.toml b/crates/storage_api2/Cargo.toml index b3bd1ed8..116a43bf 100644 --- a/crates/storage_api2/Cargo.toml +++ b/crates/storage_api2/Cargo.toml @@ -26,3 +26,8 @@ tracing = "0.1" futures = "0.3" time = "0.3" const-hex = "1.14" + +[dev-dependencies] +tokio = { version = "1", default-features = false } +tracing-subscriber = { version = "0.3", features = ["env-filter"] } +rand = "0.8" diff --git a/crates/storage_api2/src/lib.rs b/crates/storage_api2/src/lib.rs index 8cfc0a8f..0d23500e 100644 --- a/crates/storage_api2/src/lib.rs +++ b/crates/storage_api2/src/lib.rs @@ -21,7 +21,7 @@ pub mod rpc; /// /// Namespaces are isolated and every [`StorageApi`] [`Operation`] gets executed /// on a specific [`Namespace`]. -#[derive(Clone, Copy, Debug, Serialize, Deserialize)] +#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq)] pub struct Namespace { /// ID of the node operator to which this namespace belongs. /// @@ -342,7 +342,7 @@ pub struct InvalidNamespaceError(Cow<'static, str>); pub type Result = std::result::Result; /// [`StorageApi`] error. -#[derive(Debug, thiserror::Error)] +#[derive(Clone, Debug, thiserror::Error, PartialEq, Eq)] #[error("{kind:?}({details:?})")] pub struct Error { kind: ErrorKind, @@ -357,7 +357,7 @@ impl Error { } /// [`Error`] kind. -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum ErrorKind { /// Client is not authorized to perfrom an [`Operation`]. Unauthorized, diff --git a/crates/storage_api2/src/operation.rs b/crates/storage_api2/src/operation.rs index 7d4201d9..8a5b2ada 100644 --- a/crates/storage_api2/src/operation.rs +++ b/crates/storage_api2/src/operation.rs @@ -22,7 +22,7 @@ use { }; /// Sum type of all Storage API operations. -#[derive(Clone, Debug, From, EnumDiscriminants)] +#[derive(Clone, Debug, From, EnumDiscriminants, PartialEq, Eq)] #[strum_discriminants(name(Name))] #[strum_discriminants(derive(Ordinalize))] pub enum Operation<'a> { @@ -86,7 +86,7 @@ impl<'a> Operation<'a> { } /// Gets a [`Record`] by the provided key. -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] pub struct Get<'a> { pub namespace: Namespace, pub key: Bytes<'a>, @@ -94,7 +94,7 @@ pub struct Get<'a> { } /// Sets a new [`Record`] under the provided key. -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] pub struct Set<'a> { pub namespace: Namespace, pub key: Bytes<'a>, @@ -103,7 +103,7 @@ pub struct Set<'a> { } /// Deletes a [`Record`] by the provided key. -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] pub struct Del<'a> { pub namespace: Namespace, pub key: Bytes<'a>, @@ -112,7 +112,7 @@ pub struct Del<'a> { } /// Gets a [`RecordExpiration`] by the provided key. -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] pub struct GetExp<'a> { pub namespace: Namespace, pub key: Bytes<'a>, @@ -120,7 +120,7 @@ pub struct GetExp<'a> { } /// Sets [`RecordExpiration`] on the [`Record`] with the provided key. -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] pub struct SetExp<'a> { pub namespace: Namespace, pub key: Bytes<'a>, @@ -130,7 +130,7 @@ pub struct SetExp<'a> { } /// Gets a Map [`Record`] by the provided key and field. -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] pub struct HGet<'a> { pub namespace: Namespace, pub key: Bytes<'a>, @@ -139,7 +139,7 @@ pub struct HGet<'a> { } /// Sets a new [`MapEntry`]. -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] pub struct HSet<'a> { pub namespace: Namespace, pub key: Bytes<'a>, @@ -148,7 +148,7 @@ pub struct HSet<'a> { } /// Deletes a [`MapEntry`] by the provided key and field. -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] pub struct HDel<'a> { pub namespace: Namespace, pub key: Bytes<'a>, @@ -158,7 +158,7 @@ pub struct HDel<'a> { } /// Gets a [`RecordExpiration`] by the provided key and field. -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] pub struct HGetExp<'a> { pub namespace: Namespace, pub key: Bytes<'a>, @@ -168,7 +168,7 @@ pub struct HGetExp<'a> { /// Sets [`RecordExpiration`] on the [`MapEntry`] with the provided key and /// field. -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] pub struct HSetExp<'a> { pub namespace: Namespace, pub key: Bytes<'a>, @@ -179,7 +179,7 @@ pub struct HSetExp<'a> { } /// Returns cardinality of the Map with the provided key. -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] pub struct HCard<'a> { pub namespace: Namespace, pub key: Bytes<'a>, @@ -188,7 +188,7 @@ pub struct HCard<'a> { /// Returns a [`MapPage`] by iterating over the fields of the Map with /// the provided key. -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] pub struct HScan<'a> { pub namespace: Namespace, pub key: Bytes<'a>, diff --git a/crates/storage_api2/src/rpc/client.rs b/crates/storage_api2/src/rpc/client.rs index e71fe617..42e406f2 100644 --- a/crates/storage_api2/src/rpc/client.rs +++ b/crates/storage_api2/src/rpc/client.rs @@ -1,9 +1,45 @@ +#![allow(private_interfaces)] + +pub use wcn_rpc::client2::Config; use { super::*, crate::{operation, MapPage, Operation, Record, Result, StorageApi}, - wcn_rpc::client2::{Connection, ConnectionHandler, RpcHandler}, + wcn_rpc::client2::{Client, Connection, ConnectionHandler, RpcHandler}, }; +/// RPC [`Client`] of [`CoordinatorApi`]. +pub type Coordinator = Client; + +/// Outbound [`Connection`] to [`CoordinatorApi`]. +pub type CoordinatorConnection = Connection; + +/// RPC [`Client`] of [`ReplicaApi`]. +pub type Replica = Client; + +/// Outbound [`Connection`] to [`ReplicaApi`]. +pub type ReplicaConnection = Connection; + +/// RPC [`Client`] of [`DatabaseApi`]. +pub type Database = Client; + +/// Outbound [`Connection`] to [`DatabaseApi`]. +pub type DatabaseConnection = Connection; + +/// Creates a new [`Coordinator`] RPC client. +pub fn coordinator(config: Config) -> wcn_rpc::client2::Result { + Client::new(config, ConnectionHandler) +} + +/// Creates a new [`ReplicaApi`] RPC client. +pub fn replica(config: Config) -> wcn_rpc::client2::Result { + Client::new(config, ConnectionHandler) +} + +/// Creates a new [`DatabaseApi`] RPC client. +pub fn database(config: Config) -> wcn_rpc::client2::Result { + Client::new(config, ConnectionHandler) +} + impl wcn_rpc::client2::Api for Api where Self: wcn_rpc::Api, diff --git a/crates/storage_api2/src/rpc/mod.rs b/crates/storage_api2/src/rpc/mod.rs index 35002b49..04713b35 100644 --- a/crates/storage_api2/src/rpc/mod.rs +++ b/crates/storage_api2/src/rpc/mod.rs @@ -40,7 +40,7 @@ impl From for u8 { #[derive(Clone, Copy, Debug)] pub struct Api(PhantomData); -pub mod api_kind { +mod api_kind { #[derive(Clone, Copy, Debug)] pub struct Coordinator; @@ -54,21 +54,21 @@ pub mod api_kind { pub type CoordinatorApi = Api; impl wcn_rpc::Api for CoordinatorApi { - const NAME: ApiName = ApiName::new("StorageApiCoordinator"); + const NAME: ApiName = ApiName::new("Coordinator"); type RpcId = Id; } pub type ReplicaApi = Api; impl wcn_rpc::Api for ReplicaApi { - const NAME: ApiName = ApiName::new("StorageApiReplica"); + const NAME: ApiName = ApiName::new("Replica"); type RpcId = Id; } pub type DatabaseApi = Api; impl wcn_rpc::Api for DatabaseApi { - const NAME: ApiName = ApiName::new("StorageApiDatabase"); + const NAME: ApiName = ApiName::new("Database"); type RpcId = Id; } diff --git a/crates/storage_api2/tests/integration.rs b/crates/storage_api2/tests/integration.rs new file mode 100644 index 00000000..1a51286a --- /dev/null +++ b/crates/storage_api2/tests/integration.rs @@ -0,0 +1,451 @@ +use { + rand::{random, Rng}, + std::{ + net::{Ipv4Addr, SocketAddrV4}, + sync::{Arc, Mutex}, + time::Duration, + }, + tracing_subscriber::EnvFilter, + wc::future::StaticFutureExt, + wcn_rpc::{ + client2::{Api, Client, Connection}, + identity::Keypair, + transport, + }, + wcn_storage_api2::{ + operation, + Bytes, + KeyspaceVersion, + MapEntry, + MapPage, + Namespace, + Operation, + Record, + RecordExpiration, + RecordVersion, + Result, + StorageApi, + }, +}; + +#[tokio::test] +async fn test_rpc() { + let subscriber = tracing_subscriber::FmtSubscriber::builder() + .with_max_level(tracing::Level::INFO) + .with_env_filter(EnvFilter::from_default_env()) + .finish(); + tracing::subscriber::set_global_default(subscriber).unwrap(); + + for _ in 0..10 { + test_rpc_api( + wcn_storage_api2::rpc::server::coordinator, + wcn_storage_api2::rpc::client::coordinator, + ) + .await; + + test_rpc_api( + wcn_storage_api2::rpc::server::replica, + wcn_storage_api2::rpc::client::replica, + ) + .await; + + test_rpc_api( + wcn_storage_api2::rpc::server::database, + wcn_storage_api2::rpc::client::database, + ) + .await; + } +} + +async fn test_rpc_api( + server: impl FnOnce(TestStorage) -> S, + client: impl FnOnce(wcn_rpc::client2::Config) -> wcn_rpc::client2::Result>, +) where + API: Api, + S: wcn_rpc::server2::Server, + Connection: StorageApi, +{ + let storage = TestStorage::default(); + + let server_port = find_available_port(); + let server_keypair = Keypair::generate_ed25519(); + let server_peer_id = server_keypair.public().to_peer_id(); + let server_cfg = wcn_rpc::server2::Config { + name: "test", + port: server_port, + keypair: server_keypair, + connection_timeout: Duration::from_secs(10), + max_connections: 1, + max_connections_per_ip: 1, + max_connection_rate_per_ip: 1, + max_concurrent_rpcs: 10, + priority: transport::Priority::High, + }; + + let server_handle = server(storage.clone()).serve(server_cfg).unwrap().spawn(); + + let client_config = wcn_rpc::client2::Config { + keypair: Keypair::generate_ed25519(), + connection_timeout: Duration::from_secs(10), + reconnect_interval: Duration::from_secs(1), + max_concurrent_rpcs: 10, + priority: transport::Priority::High, + }; + + let client = client(client_config).unwrap(); + + let server_addr = SocketAddrV4::new(Ipv4Addr::LOCALHOST, server_port); + let client_conn = client + .connect(server_addr, &server_peer_id, ()) + .await + .unwrap(); + + let ctx = &TestContext { + storage, + client_conn, + }; + + ctx.test_operations().await; + + server_handle.abort(); +} + +struct TestContext { + storage: TestStorage, + client_conn: Connection, +} + +impl TestContext +where + Connection: StorageApi, +{ + async fn test_operations(&self) { + self.test_get().await; + self.test_set().await; + self.test_del().await; + self.test_get_exp().await; + self.test_set_exp().await; + + self.test_hget().await; + self.test_hset().await; + self.test_hdel().await; + self.test_hget_exp().await; + self.test_hset_exp().await; + + self.test_hcard().await; + self.test_hscan().await; + } + + async fn test_get(&self) { + let op = operation::Get { + namespace: namespace(), + key: bytes(), + keyspace_version: keyspace_version(), + }; + + let res = Ok(opt(record)); + + self.storage + .assert_next(&op, &res, |a, b| assert_eq!(Operation::Get(&a), b)); + assert_eq!(self.client_conn.get(&op).await.map(Into::into), res); + } + + async fn test_set(&self) { + let op = operation::Set { + namespace: namespace(), + key: bytes(), + record: record(), + keyspace_version: keyspace_version(), + }; + + let res = Ok(()); + + self.storage + .assert_next(&op, &res, |a, b| assert_eq!(Operation::Set(&a), b)); + assert_eq!(self.client_conn.set(&op).await.map(Into::into), res); + } + + async fn test_del(&self) { + let op = operation::Del { + namespace: namespace(), + key: bytes(), + version: RecordVersion::now(), + keyspace_version: keyspace_version(), + }; + + let res = Ok(()); + + self.storage + .assert_next(&op, &res, |a, b| assert_eq!(Operation::Del(&a), b)); + assert_eq!(self.client_conn.del(&op).await.map(Into::into), res); + } + + async fn test_get_exp(&self) { + let op = operation::GetExp { + namespace: namespace(), + key: bytes(), + keyspace_version: keyspace_version(), + }; + + let res = Ok(opt(record_expiration)); + + self.storage + .assert_next(&op, &res, |a, b| assert_eq!(Operation::GetExp(&a), b)); + assert_eq!(self.client_conn.get_exp(&op).await.map(Into::into), res); + } + + async fn test_set_exp(&self) { + let op = operation::SetExp { + namespace: namespace(), + key: bytes(), + expiration: record_expiration(), + version: RecordVersion::now(), + keyspace_version: keyspace_version(), + }; + + let res = Ok(()); + + self.storage + .assert_next(&op, &res, |a, b| assert_eq!(Operation::SetExp(&a), b)); + assert_eq!(self.client_conn.set_exp(&op).await.map(Into::into), res); + } + + async fn test_hget(&self) { + let op = operation::HGet { + namespace: namespace(), + key: bytes(), + field: bytes(), + keyspace_version: keyspace_version(), + }; + + let res = Ok(opt(record)); + + self.storage + .assert_next(&op, &res, |a, b| assert_eq!(Operation::HGet(&a), b)); + assert_eq!(self.client_conn.hget(&op).await.map(Into::into), res); + } + + async fn test_hset(&self) { + let op = operation::HSet { + namespace: namespace(), + key: bytes(), + entry: map_entry(), + keyspace_version: keyspace_version(), + }; + + let res = Ok(()); + + self.storage + .assert_next(&op, &res, |a, b| assert_eq!(Operation::HSet(&a), b)); + assert_eq!(self.client_conn.hset(&op).await.map(Into::into), res); + } + + async fn test_hdel(&self) { + let op = operation::HDel { + namespace: namespace(), + key: bytes(), + field: bytes(), + version: RecordVersion::now(), + keyspace_version: keyspace_version(), + }; + + let res = Ok(()); + + self.storage + .assert_next(&op, &res, |a, b| assert_eq!(Operation::HDel(&a), b)); + assert_eq!(self.client_conn.hdel(&op).await.map(Into::into), res); + } + + async fn test_hget_exp(&self) { + let op = operation::HGetExp { + namespace: namespace(), + key: bytes(), + field: bytes(), + keyspace_version: keyspace_version(), + }; + + let res = Ok(opt(record_expiration)); + + self.storage + .assert_next(&op, &res, |a, b| assert_eq!(Operation::HGetExp(&a), b)); + assert_eq!(self.client_conn.hget_exp(&op).await.map(Into::into), res); + } + + async fn test_hset_exp(&self) { + let op = operation::HSetExp { + namespace: namespace(), + key: bytes(), + field: bytes(), + expiration: record_expiration(), + version: RecordVersion::now(), + keyspace_version: keyspace_version(), + }; + + let res = Ok(()); + + self.storage + .assert_next(&op, &res, |a, b| assert_eq!(Operation::HSetExp(&a), b)); + assert_eq!(self.client_conn.hset_exp(&op).await.map(Into::into), res); + } + + async fn test_hcard(&self) { + let op = operation::HCard { + namespace: namespace(), + key: bytes(), + keyspace_version: keyspace_version(), + }; + + let res = Ok(random::()); + + self.storage + .assert_next(&op, &res, |a, b| assert_eq!(Operation::HCard(&a), b)); + assert_eq!(self.client_conn.hcard(&op).await.map(Into::into), res); + } + + async fn test_hscan(&self) { + let op = operation::HScan { + namespace: namespace(), + key: bytes(), + count: random(), + cursor: opt(bytes), + keyspace_version: keyspace_version(), + }; + + let res = Ok(map_page()); + + self.storage + .assert_next(&op, &res, |a, b| assert_eq!(Operation::HScan(&a), b)); + assert_eq!(self.client_conn.hscan(&op).await.map(Into::into), res); + } +} + +fn namespace() -> Namespace { + let operator_id = rand::random::<[u8; 20]>(); + let id = rand::random::(); + + let operator_id = const_hex::encode(&operator_id); + format!("{operator_id}/{id}").parse().unwrap() +} + +fn keyspace_version() -> Option { + if random() { + Some(random()) + } else { + None + } +} + +fn record() -> Record<'static> { + Record { + value: bytes(), + expiration: record_expiration(), + version: RecordVersion::now(), + } +} + +fn map_entry() -> MapEntry<'static> { + MapEntry { + field: bytes(), + record: record(), + } +} + +fn map_page() -> MapPage<'static> { + let mut rng = rand::thread_rng(); + + let len = rng.gen_range(1..=1000); + let mut buf = Vec::with_capacity(len); + for _ in 0..len { + buf.push(map_entry()); + } + + MapPage { + entries: buf, + has_next: random(), + } +} + +fn opt(f: fn() -> T) -> Option { + if random() { + Some(f()) + } else { + None + } +} + +fn bytes() -> Bytes<'static> { + let mut rng = rand::thread_rng(); + + let mut buf = vec![0u8; rng.gen_range(1..=4096)]; + rng.fill(&mut buf[..]); + buf.into() +} + +fn record_expiration() -> RecordExpiration { + let secs = rand::thread_rng().gen_range(30..=60 * 60 * 24 * 30); + Duration::from_secs(secs).into() +} + +fn find_available_port() -> u16 { + use std::{ + net::UdpSocket, + sync::atomic::{AtomicU16, Ordering}, + }; + + static NEXT_PORT: AtomicU16 = AtomicU16::new(48100); + + loop { + let port = NEXT_PORT.fetch_add(1, Ordering::Relaxed); + assert!(port != u16::MAX, "failed to find a free port"); + + if UdpSocket::bind((Ipv4Addr::LOCALHOST, port)).is_ok() { + return port; + } + } +} + +#[derive(Clone, Default)] +struct TestStorage { + expect_fn: Arc>>>, +} + +pub trait TestStorageFn: + for<'a> FnOnce(Operation<'a>) -> Result> + Send + 'static +{ +} + +impl TestStorageFn for F where + F: for<'a> FnOnce(Operation<'a>) -> Result> + Send + 'static +{ +} + +impl TestStorage { + fn assert_next(&self, op: &Op, result: &Result, assert_fn: F) + where + Op: Clone + Send + 'static, + Out: Clone + Into>, + F: for<'a> FnOnce(Op, Operation<'a>) + Send + 'static, + { + let op = op.clone(); + let res = result.clone().map(Into::into); + + let _ = self + .expect_fn + .lock() + .unwrap() + .insert(Box::new(move |operation| { + assert_fn(op, operation); + res + })); + } +} + +impl StorageApi for TestStorage { + async fn execute<'a>( + &'a self, + operation: impl Into> + Send + 'a, + ) -> Result> { + let expect_fn = self.expect_fn.lock().unwrap().take().unwrap(); + expect_fn(operation.into()) + } +} From c543fa8a1c563ccd749526e9f8f7f6341dba620c Mon Sep 17 00:00:00 2001 From: Darksome Date: Mon, 30 Jun 2025 20:09:45 +0000 Subject: [PATCH 69/79] fix: remove unused #[allow] --- crates/storage_api2/src/rpc/client.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/storage_api2/src/rpc/client.rs b/crates/storage_api2/src/rpc/client.rs index 42e406f2..c110ec99 100644 --- a/crates/storage_api2/src/rpc/client.rs +++ b/crates/storage_api2/src/rpc/client.rs @@ -1,5 +1,3 @@ -#![allow(private_interfaces)] - pub use wcn_rpc::client2::Config; use { super::*, From 65a4a1d416e6a28257f4cfc07c1090b9e4b587a6 Mon Sep 17 00:00:00 2001 From: Darksome Date: Mon, 30 Jun 2025 20:13:25 +0000 Subject: [PATCH 70/79] fix: clippy --- crates/storage_api2/tests/integration.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/crates/storage_api2/tests/integration.rs b/crates/storage_api2/tests/integration.rs index 1a51286a..67cf797a 100644 --- a/crates/storage_api2/tests/integration.rs +++ b/crates/storage_api2/tests/integration.rs @@ -147,7 +147,7 @@ where self.storage .assert_next(&op, &res, |a, b| assert_eq!(Operation::Get(&a), b)); - assert_eq!(self.client_conn.get(&op).await.map(Into::into), res); + assert_eq!(self.client_conn.get(&op).await, res); } async fn test_set(&self) { @@ -162,7 +162,7 @@ where self.storage .assert_next(&op, &res, |a, b| assert_eq!(Operation::Set(&a), b)); - assert_eq!(self.client_conn.set(&op).await.map(Into::into), res); + assert_eq!(self.client_conn.set(&op).await, res); } async fn test_del(&self) { @@ -177,7 +177,7 @@ where self.storage .assert_next(&op, &res, |a, b| assert_eq!(Operation::Del(&a), b)); - assert_eq!(self.client_conn.del(&op).await.map(Into::into), res); + assert_eq!(self.client_conn.del(&op).await, res); } async fn test_get_exp(&self) { @@ -191,7 +191,7 @@ where self.storage .assert_next(&op, &res, |a, b| assert_eq!(Operation::GetExp(&a), b)); - assert_eq!(self.client_conn.get_exp(&op).await.map(Into::into), res); + assert_eq!(self.client_conn.get_exp(&op).await, res); } async fn test_set_exp(&self) { @@ -207,7 +207,7 @@ where self.storage .assert_next(&op, &res, |a, b| assert_eq!(Operation::SetExp(&a), b)); - assert_eq!(self.client_conn.set_exp(&op).await.map(Into::into), res); + assert_eq!(self.client_conn.set_exp(&op), res); } async fn test_hget(&self) { @@ -222,7 +222,7 @@ where self.storage .assert_next(&op, &res, |a, b| assert_eq!(Operation::HGet(&a), b)); - assert_eq!(self.client_conn.hget(&op).await.map(Into::into), res); + assert_eq!(self.client_conn.hget(&op).await, res); } async fn test_hset(&self) { @@ -237,7 +237,7 @@ where self.storage .assert_next(&op, &res, |a, b| assert_eq!(Operation::HSet(&a), b)); - assert_eq!(self.client_conn.hset(&op).await.map(Into::into), res); + assert_eq!(self.client_conn.hset(&op).await, res); } async fn test_hdel(&self) { @@ -253,7 +253,7 @@ where self.storage .assert_next(&op, &res, |a, b| assert_eq!(Operation::HDel(&a), b)); - assert_eq!(self.client_conn.hdel(&op).await.map(Into::into), res); + assert_eq!(self.client_conn.hdel(&op).await, res); } async fn test_hget_exp(&self) { @@ -268,7 +268,7 @@ where self.storage .assert_next(&op, &res, |a, b| assert_eq!(Operation::HGetExp(&a), b)); - assert_eq!(self.client_conn.hget_exp(&op).await.map(Into::into), res); + assert_eq!(self.client_conn.hget_exp(&op).await, res); } async fn test_hset_exp(&self) { @@ -285,7 +285,7 @@ where self.storage .assert_next(&op, &res, |a, b| assert_eq!(Operation::HSetExp(&a), b)); - assert_eq!(self.client_conn.hset_exp(&op).await.map(Into::into), res); + assert_eq!(self.client_conn.hset_exp(&op).await, res); } async fn test_hcard(&self) { @@ -299,7 +299,7 @@ where self.storage .assert_next(&op, &res, |a, b| assert_eq!(Operation::HCard(&a), b)); - assert_eq!(self.client_conn.hcard(&op).await.map(Into::into), res); + assert_eq!(self.client_conn.hcard(&op).await, res); } async fn test_hscan(&self) { @@ -315,7 +315,7 @@ where self.storage .assert_next(&op, &res, |a, b| assert_eq!(Operation::HScan(&a), b)); - assert_eq!(self.client_conn.hscan(&op).await.map(Into::into), res); + assert_eq!(self.client_conn.hscan(&op).await, res); } } From 1f4d65a6862ca446f6d203df4858e4a03a9dc3b8 Mon Sep 17 00:00:00 2001 From: Darksome Date: Mon, 30 Jun 2025 20:21:19 +0000 Subject: [PATCH 71/79] fix: missing .await --- crates/storage_api2/tests/integration.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/storage_api2/tests/integration.rs b/crates/storage_api2/tests/integration.rs index 67cf797a..f5ca50dd 100644 --- a/crates/storage_api2/tests/integration.rs +++ b/crates/storage_api2/tests/integration.rs @@ -207,7 +207,7 @@ where self.storage .assert_next(&op, &res, |a, b| assert_eq!(Operation::SetExp(&a), b)); - assert_eq!(self.client_conn.set_exp(&op), res); + assert_eq!(self.client_conn.set_exp(&op).await, res); } async fn test_hget(&self) { From cdb1a1e8b5681aad7ea717022b87a0d623650726 Mon Sep 17 00:00:00 2001 From: Darksome Date: Mon, 30 Jun 2025 20:27:08 +0000 Subject: [PATCH 72/79] fix: clippy --- crates/storage_api2/tests/integration.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/storage_api2/tests/integration.rs b/crates/storage_api2/tests/integration.rs index f5ca50dd..9833897f 100644 --- a/crates/storage_api2/tests/integration.rs +++ b/crates/storage_api2/tests/integration.rs @@ -323,7 +323,7 @@ fn namespace() -> Namespace { let operator_id = rand::random::<[u8; 20]>(); let id = rand::random::(); - let operator_id = const_hex::encode(&operator_id); + let operator_id = const_hex::encode(operator_id); format!("{operator_id}/{id}").parse().unwrap() } From 85393234b042bb662bf49b4751ce2b5e1c2e8cea Mon Sep 17 00:00:00 2001 From: Darksome Date: Tue, 1 Jul 2025 15:29:46 +0000 Subject: [PATCH 73/79] feat(wcn_rpc): client load balancer --- crates/rpc/src/client2.rs | 44 ++++++++++++++++++++++++++- crates/storage_api2/src/lib.rs | 2 +- crates/storage_api2/src/rpc/client.rs | 32 ++++++++++++++++++- crates/storage_api2/src/rpc/server.rs | 12 ++++---- 4 files changed, 81 insertions(+), 9 deletions(-) diff --git a/crates/rpc/src/client2.rs b/crates/rpc/src/client2.rs index 208b8991..540483d7 100644 --- a/crates/rpc/src/client2.rs +++ b/crates/rpc/src/client2.rs @@ -24,7 +24,10 @@ use { future::Future, io, net::{SocketAddr, SocketAddrV4}, - sync::Arc, + sync::{ + atomic::{self, AtomicUsize}, + Arc, + }, time::Duration, }, strum::{EnumDiscriminants, IntoDiscriminant, IntoStaticStr}, @@ -568,3 +571,42 @@ impl metrics::Enum for ErrorKind { } // TODO: Vec Load Balancer + +/// [`Connection`] Load balancer. +/// +/// Load balancer [`Connection::send`] across a list of [`Connection`]s using a +/// round-robin strategy. +pub struct LoadBalancer { + /// List of [`Connections`] of this [`LoadBalancer`]. + /// + /// Can be safely modified at any point. + pub connections: Vec>, + + counter: AtomicUsize, +} + +impl LoadBalancer { + /// Creates a new [`LoadBalancer`]. + pub fn new(connections: impl IntoIterator>) -> Self { + Self { + connections: connections.into_iter().collect(), + // overflows and starts from `0` + counter: usize::MAX.into(), + } + } + + /// Sends the provided RPC using this [`LoadBalancer`]. + /// + /// Doesn't automatically retry errors, you can call this fn again if you + /// want to retry. + pub fn send<'a, RPC: RpcV2>( + &'a self, + input: &'a RpcHandlerInput<'a, API::RpcHandler, RPC>, + ) -> Result>> + Send + 'a> + where + API::RpcHandler: HandleRpc, + { + let n = self.counter.fetch_add(1, atomic::Ordering::Relaxed); + self.connections[n % self.connections.len()].send(input) + } +} diff --git a/crates/storage_api2/src/lib.rs b/crates/storage_api2/src/lib.rs index 0d23500e..1982f34c 100644 --- a/crates/storage_api2/src/lib.rs +++ b/crates/storage_api2/src/lib.rs @@ -55,7 +55,7 @@ pub type KeyspaceVersion = u64; /// servers). /// - Replicas use it to finally execute the operations on their local WCN /// Database instances. -pub trait StorageApi: Clone + Send + Sync + 'static { +pub trait StorageApi: Send + Sync + 'static { /// Executes the provided [`operation::Get`]. fn get<'a>( &'a self, diff --git a/crates/storage_api2/src/rpc/client.rs b/crates/storage_api2/src/rpc/client.rs index c110ec99..dca0f786 100644 --- a/crates/storage_api2/src/rpc/client.rs +++ b/crates/storage_api2/src/rpc/client.rs @@ -2,7 +2,7 @@ pub use wcn_rpc::client2::Config; use { super::*, crate::{operation, MapPage, Operation, Record, Result, StorageApi}, - wcn_rpc::client2::{Client, Connection, ConnectionHandler, RpcHandler}, + wcn_rpc::client2::{Client, Connection, ConnectionHandler, LoadBalancer, RpcHandler}, }; /// RPC [`Client`] of [`CoordinatorApi`]. @@ -124,6 +124,36 @@ where } } +impl StorageApi for LoadBalancer +where + API: wcn_rpc::client2::Api< + ConnectionParameters = (), + ConnectionHandler = ConnectionHandler, + RpcHandler = RpcHandler, + >, + Connection: StorageApi, +{ + async fn execute<'a>( + &'a self, + operation: impl Into> + Send + 'a, + ) -> Result> { + Ok(match operation.into() { + Operation::Get(op) => self.send::(op)?.await??.into(), + Operation::Set(op) => self.send::(op)?.await??.into(), + Operation::Del(op) => self.send::(op)?.await??.into(), + Operation::GetExp(op) => self.send::(op)?.await??.into(), + Operation::SetExp(op) => self.send::(op)?.await??.into(), + Operation::HGet(op) => self.send::(op)?.await??.into(), + Operation::HSet(op) => self.send::(op)?.await??.into(), + Operation::HDel(op) => self.send::(op)?.await??.into(), + Operation::HGetExp(op) => self.send::(op)?.await??.into(), + Operation::HSetExp(op) => self.send::(op)?.await??.into(), + Operation::HCard(op) => self.send::(op)?.await??.into(), + Operation::HScan(op) => self.send::(op)?.await??.into(), + }) + } +} + impl From for crate::Error { fn from(err: wcn_rpc::client2::Error) -> Self { Self::new( diff --git a/crates/storage_api2/src/rpc/server.rs b/crates/storage_api2/src/rpc/server.rs index 645c3571..f1a63093 100644 --- a/crates/storage_api2/src/rpc/server.rs +++ b/crates/storage_api2/src/rpc/server.rs @@ -9,21 +9,21 @@ use { }; /// Creates a new [`CoordinatorApi`] RPC server. -pub fn coordinator(storage_api: impl StorageApi) -> impl wcn_rpc::server2::Server { +pub fn coordinator(storage_api: impl StorageApi + Clone) -> impl wcn_rpc::server2::Server { new::(storage_api) } /// Creates a new [`ReplicaApi`] RPC server. -pub fn replica(storage_api: impl StorageApi) -> impl wcn_rpc::server2::Server { +pub fn replica(storage_api: impl StorageApi + Clone) -> impl wcn_rpc::server2::Server { new::(storage_api) } /// Creates a new [`DatabaseApi`] RPC server. -pub fn database(storage_api: impl StorageApi) -> impl wcn_rpc::server2::Server { +pub fn database(storage_api: impl StorageApi + Clone) -> impl wcn_rpc::server2::Server { new::(storage_api) } -fn new(storage_api: impl StorageApi) -> impl wcn_rpc::server2::Server +fn new(storage_api: impl StorageApi + Clone) -> impl wcn_rpc::server2::Server where Kind: Clone + Send + Sync + 'static, Api: wcn_rpc::Api, @@ -35,14 +35,14 @@ where } #[derive(Clone)] -struct ConnectionHandler { +struct ConnectionHandler { rpc_handler: RpcHandler, _marker: PhantomData, } impl HandleConnection for ConnectionHandler where - S: StorageApi, + S: StorageApi + Clone, Kind: Clone + Send + Sync + 'static, Api: wcn_rpc::Api, { From 99ed0bbfdb3212b7ab3f0e0190e1f08965310e7b Mon Sep 17 00:00:00 2001 From: Darksome Date: Tue, 1 Jul 2025 15:34:39 +0000 Subject: [PATCH 74/79] use LB in integration tests --- crates/storage_api2/tests/integration.rs | 46 +++++++++++++----------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/crates/storage_api2/tests/integration.rs b/crates/storage_api2/tests/integration.rs index 9833897f..ba530b0b 100644 --- a/crates/storage_api2/tests/integration.rs +++ b/crates/storage_api2/tests/integration.rs @@ -8,7 +8,7 @@ use { tracing_subscriber::EnvFilter, wc::future::StaticFutureExt, wcn_rpc::{ - client2::{Api, Client, Connection}, + client2::{Api, Client, LoadBalancer}, identity::Keypair, transport, }, @@ -63,7 +63,7 @@ async fn test_rpc_api( ) where API: Api, S: wcn_rpc::server2::Server, - Connection: StorageApi, + LoadBalancer: StorageApi, { let storage = TestStorage::default(); @@ -75,9 +75,9 @@ async fn test_rpc_api( port: server_port, keypair: server_keypair, connection_timeout: Duration::from_secs(10), - max_connections: 1, - max_connections_per_ip: 1, - max_connection_rate_per_ip: 1, + max_connections: 2, + max_connections_per_ip: 2, + max_connection_rate_per_ip: 2, max_concurrent_rpcs: 10, priority: transport::Priority::High, }; @@ -95,14 +95,18 @@ async fn test_rpc_api( let client = client(client_config).unwrap(); let server_addr = SocketAddrV4::new(Ipv4Addr::LOCALHOST, server_port); - let client_conn = client + let client_conn1 = client + .connect(server_addr, &server_peer_id, ()) + .await + .unwrap(); + let client_conn2 = client .connect(server_addr, &server_peer_id, ()) .await .unwrap(); let ctx = &TestContext { storage, - client_conn, + lb: LoadBalancer::new([client_conn1, client_conn2]), }; ctx.test_operations().await; @@ -112,12 +116,12 @@ async fn test_rpc_api( struct TestContext { storage: TestStorage, - client_conn: Connection, + lb: LoadBalancer, } impl TestContext where - Connection: StorageApi, + LoadBalancer: StorageApi, { async fn test_operations(&self) { self.test_get().await; @@ -147,7 +151,7 @@ where self.storage .assert_next(&op, &res, |a, b| assert_eq!(Operation::Get(&a), b)); - assert_eq!(self.client_conn.get(&op).await, res); + assert_eq!(self.lb.get(&op).await, res); } async fn test_set(&self) { @@ -162,7 +166,7 @@ where self.storage .assert_next(&op, &res, |a, b| assert_eq!(Operation::Set(&a), b)); - assert_eq!(self.client_conn.set(&op).await, res); + assert_eq!(self.lb.set(&op).await, res); } async fn test_del(&self) { @@ -177,7 +181,7 @@ where self.storage .assert_next(&op, &res, |a, b| assert_eq!(Operation::Del(&a), b)); - assert_eq!(self.client_conn.del(&op).await, res); + assert_eq!(self.lb.del(&op).await, res); } async fn test_get_exp(&self) { @@ -191,7 +195,7 @@ where self.storage .assert_next(&op, &res, |a, b| assert_eq!(Operation::GetExp(&a), b)); - assert_eq!(self.client_conn.get_exp(&op).await, res); + assert_eq!(self.lb.get_exp(&op).await, res); } async fn test_set_exp(&self) { @@ -207,7 +211,7 @@ where self.storage .assert_next(&op, &res, |a, b| assert_eq!(Operation::SetExp(&a), b)); - assert_eq!(self.client_conn.set_exp(&op).await, res); + assert_eq!(self.lb.set_exp(&op).await, res); } async fn test_hget(&self) { @@ -222,7 +226,7 @@ where self.storage .assert_next(&op, &res, |a, b| assert_eq!(Operation::HGet(&a), b)); - assert_eq!(self.client_conn.hget(&op).await, res); + assert_eq!(self.lb.hget(&op).await, res); } async fn test_hset(&self) { @@ -237,7 +241,7 @@ where self.storage .assert_next(&op, &res, |a, b| assert_eq!(Operation::HSet(&a), b)); - assert_eq!(self.client_conn.hset(&op).await, res); + assert_eq!(self.lb.hset(&op).await, res); } async fn test_hdel(&self) { @@ -253,7 +257,7 @@ where self.storage .assert_next(&op, &res, |a, b| assert_eq!(Operation::HDel(&a), b)); - assert_eq!(self.client_conn.hdel(&op).await, res); + assert_eq!(self.lb.hdel(&op).await, res); } async fn test_hget_exp(&self) { @@ -268,7 +272,7 @@ where self.storage .assert_next(&op, &res, |a, b| assert_eq!(Operation::HGetExp(&a), b)); - assert_eq!(self.client_conn.hget_exp(&op).await, res); + assert_eq!(self.lb.hget_exp(&op).await, res); } async fn test_hset_exp(&self) { @@ -285,7 +289,7 @@ where self.storage .assert_next(&op, &res, |a, b| assert_eq!(Operation::HSetExp(&a), b)); - assert_eq!(self.client_conn.hset_exp(&op).await, res); + assert_eq!(self.lb.hset_exp(&op).await, res); } async fn test_hcard(&self) { @@ -299,7 +303,7 @@ where self.storage .assert_next(&op, &res, |a, b| assert_eq!(Operation::HCard(&a), b)); - assert_eq!(self.client_conn.hcard(&op).await, res); + assert_eq!(self.lb.hcard(&op).await, res); } async fn test_hscan(&self) { @@ -315,7 +319,7 @@ where self.storage .assert_next(&op, &res, |a, b| assert_eq!(Operation::HScan(&a), b)); - assert_eq!(self.client_conn.hscan(&op).await, res); + assert_eq!(self.lb.hscan(&op).await, res); } } From e154b2a64272b26e1796f37f51a91f5b336df94c Mon Sep 17 00:00:00 2001 From: Github Bot Date: Tue, 1 Jul 2025 15:38:11 +0000 Subject: [PATCH 75/79] Bump VERSION to 250701.0 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index b46821fd..85cda3d4 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -250630.0 +250701.0 From 66652d2e7af86ebd60434d18468c32e48b133d06 Mon Sep 17 00:00:00 2001 From: Darksome Date: Tue, 1 Jul 2025 15:40:29 +0000 Subject: [PATCH 76/79] fix: comment --- crates/rpc/src/client2.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/rpc/src/client2.rs b/crates/rpc/src/client2.rs index 540483d7..b6466a28 100644 --- a/crates/rpc/src/client2.rs +++ b/crates/rpc/src/client2.rs @@ -574,7 +574,7 @@ impl metrics::Enum for ErrorKind { /// [`Connection`] Load balancer. /// -/// Load balancer [`Connection::send`] across a list of [`Connection`]s using a +/// Load balances [`Connection::send`] across a list of [`Connection`]s using a /// round-robin strategy. pub struct LoadBalancer { /// List of [`Connections`] of this [`LoadBalancer`]. From 4e55c46c513c2faa488504418a096b192b671765 Mon Sep 17 00:00:00 2001 From: Github Bot Date: Thu, 3 Jul 2025 14:57:13 +0000 Subject: [PATCH 77/79] Bump VERSION to 250703.0 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 443a1952..476e973b 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -250702.0 +250703.0 From 97552be8cee125832c304d6b1fc2650b9c5352df Mon Sep 17 00:00:00 2001 From: Darksome Date: Thu, 3 Jul 2025 14:59:23 +0000 Subject: [PATCH 78/79] fix: clippy --- crates/storage_api2/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/storage_api2/src/lib.rs b/crates/storage_api2/src/lib.rs index af54887e..722fa9e1 100644 --- a/crates/storage_api2/src/lib.rs +++ b/crates/storage_api2/src/lib.rs @@ -443,7 +443,7 @@ impl LoadBalancer { if self.apis.len() == 0 { return Err(Error::new( ErrorKind::Internal, - Some(format!("LoadBalancer::apis is empty")), + Some("LoadBalancer::apis is empty".to_string()), )); } From c11526ae4bed37433d1e59a4d31505893c9747bc Mon Sep 17 00:00:00 2001 From: Darksome Date: Thu, 3 Jul 2025 15:01:54 +0000 Subject: [PATCH 79/79] fix: clippy --- crates/storage_api2/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/storage_api2/src/lib.rs b/crates/storage_api2/src/lib.rs index 722fa9e1..a281294a 100644 --- a/crates/storage_api2/src/lib.rs +++ b/crates/storage_api2/src/lib.rs @@ -440,7 +440,7 @@ impl LoadBalancer { } fn next_api(&self) -> Result<&S> { - if self.apis.len() == 0 { + if self.apis.is_empty() { return Err(Error::new( ErrorKind::Internal, Some("LoadBalancer::apis is empty".to_string()),