Migrate legacy delegation data (#771)
* Skip ReadOnlyBucket deserialization errors * empty migration * clippy * cargo schema * Drop invalid delegation data * Dont drop old data * Add todo * Unify on type param * gateways are different * cargo fmt Co-authored-by: Drazen Urch <durch@users.noreply.guthub.com>
This commit is contained in:
Generated
+2
-2
@@ -727,9 +727,9 @@ checksum = "1e81da0851ada1f3e9d4312c704aa4f8806f0f9d69faaf8df2f3464b4a9437c2"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.60"
|
||||
version = "1.0.65"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c700597eca8a5a762beb35753ef6b94df201c81cca676604f547495a0d7f0081"
|
||||
checksum = "f3a1d708c221c5a612956ef9f75b37e454e88d1f7b899fbd3a18d4252012d663"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
||||
@@ -0,0 +1,349 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "ExecuteMsg",
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"bond_mixnode"
|
||||
],
|
||||
"properties": {
|
||||
"bond_mixnode": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"mix_node"
|
||||
],
|
||||
"properties": {
|
||||
"mix_node": {
|
||||
"$ref": "#/definitions/MixNode"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"unbond_mixnode"
|
||||
],
|
||||
"properties": {
|
||||
"unbond_mixnode": {
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"bond_gateway"
|
||||
],
|
||||
"properties": {
|
||||
"bond_gateway": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"gateway"
|
||||
],
|
||||
"properties": {
|
||||
"gateway": {
|
||||
"$ref": "#/definitions/Gateway"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"unbond_gateway"
|
||||
],
|
||||
"properties": {
|
||||
"unbond_gateway": {
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"update_state_params"
|
||||
],
|
||||
"properties": {
|
||||
"update_state_params": {
|
||||
"$ref": "#/definitions/StateParams"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"delegate_to_mixnode"
|
||||
],
|
||||
"properties": {
|
||||
"delegate_to_mixnode": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"mix_identity"
|
||||
],
|
||||
"properties": {
|
||||
"mix_identity": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"undelegate_from_mixnode"
|
||||
],
|
||||
"properties": {
|
||||
"undelegate_from_mixnode": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"mix_identity"
|
||||
],
|
||||
"properties": {
|
||||
"mix_identity": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"delegate_to_gateway"
|
||||
],
|
||||
"properties": {
|
||||
"delegate_to_gateway": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"gateway_identity"
|
||||
],
|
||||
"properties": {
|
||||
"gateway_identity": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"undelegate_from_gateway"
|
||||
],
|
||||
"properties": {
|
||||
"undelegate_from_gateway": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"gateway_identity"
|
||||
],
|
||||
"properties": {
|
||||
"gateway_identity": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"reward_mixnode"
|
||||
],
|
||||
"properties": {
|
||||
"reward_mixnode": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"identity",
|
||||
"uptime"
|
||||
],
|
||||
"properties": {
|
||||
"identity": {
|
||||
"type": "string"
|
||||
},
|
||||
"uptime": {
|
||||
"type": "integer",
|
||||
"format": "uint32",
|
||||
"minimum": 0.0
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"reward_gateway"
|
||||
],
|
||||
"properties": {
|
||||
"reward_gateway": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"identity",
|
||||
"uptime"
|
||||
],
|
||||
"properties": {
|
||||
"identity": {
|
||||
"type": "string"
|
||||
},
|
||||
"uptime": {
|
||||
"type": "integer",
|
||||
"format": "uint32",
|
||||
"minimum": 0.0
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
],
|
||||
"definitions": {
|
||||
"Decimal": {
|
||||
"description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 340282366920938463463.374607431768211455 (which is (2^128 - 1) / 10^18)",
|
||||
"type": "string"
|
||||
},
|
||||
"Gateway": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"clients_port",
|
||||
"host",
|
||||
"identity_key",
|
||||
"location",
|
||||
"mix_port",
|
||||
"sphinx_key",
|
||||
"version"
|
||||
],
|
||||
"properties": {
|
||||
"clients_port": {
|
||||
"type": "integer",
|
||||
"format": "uint16",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"host": {
|
||||
"type": "string"
|
||||
},
|
||||
"identity_key": {
|
||||
"description": "Base58 encoded ed25519 EdDSA public key of the gateway used to derive shared keys with clients",
|
||||
"type": "string"
|
||||
},
|
||||
"location": {
|
||||
"type": "string"
|
||||
},
|
||||
"mix_port": {
|
||||
"type": "integer",
|
||||
"format": "uint16",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"sphinx_key": {
|
||||
"type": "string"
|
||||
},
|
||||
"version": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"MixNode": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"host",
|
||||
"http_api_port",
|
||||
"identity_key",
|
||||
"mix_port",
|
||||
"sphinx_key",
|
||||
"verloc_port",
|
||||
"version"
|
||||
],
|
||||
"properties": {
|
||||
"host": {
|
||||
"type": "string"
|
||||
},
|
||||
"http_api_port": {
|
||||
"type": "integer",
|
||||
"format": "uint16",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"identity_key": {
|
||||
"description": "Base58 encoded ed25519 EdDSA public key.",
|
||||
"type": "string"
|
||||
},
|
||||
"mix_port": {
|
||||
"type": "integer",
|
||||
"format": "uint16",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"sphinx_key": {
|
||||
"type": "string"
|
||||
},
|
||||
"verloc_port": {
|
||||
"type": "integer",
|
||||
"format": "uint16",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"version": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"StateParams": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"epoch_length",
|
||||
"gateway_bond_reward_rate",
|
||||
"gateway_delegation_reward_rate",
|
||||
"minimum_gateway_bond",
|
||||
"minimum_mixnode_bond",
|
||||
"mixnode_active_set_size",
|
||||
"mixnode_bond_reward_rate",
|
||||
"mixnode_delegation_reward_rate"
|
||||
],
|
||||
"properties": {
|
||||
"epoch_length": {
|
||||
"type": "integer",
|
||||
"format": "uint32",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"gateway_bond_reward_rate": {
|
||||
"$ref": "#/definitions/Decimal"
|
||||
},
|
||||
"gateway_delegation_reward_rate": {
|
||||
"$ref": "#/definitions/Decimal"
|
||||
},
|
||||
"minimum_gateway_bond": {
|
||||
"$ref": "#/definitions/Uint128"
|
||||
},
|
||||
"minimum_mixnode_bond": {
|
||||
"$ref": "#/definitions/Uint128"
|
||||
},
|
||||
"mixnode_active_set_size": {
|
||||
"type": "integer",
|
||||
"format": "uint32",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"mixnode_bond_reward_rate": {
|
||||
"$ref": "#/definitions/Decimal"
|
||||
},
|
||||
"mixnode_delegation_reward_rate": {
|
||||
"$ref": "#/definitions/Decimal"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Uint128": {
|
||||
"description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,134 +0,0 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "HandleMsg",
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"register_mixnode"
|
||||
],
|
||||
"properties": {
|
||||
"register_mixnode": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"mix_node"
|
||||
],
|
||||
"properties": {
|
||||
"mix_node": {
|
||||
"$ref": "#/definitions/MixNode"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"un_register_mixnode"
|
||||
],
|
||||
"properties": {
|
||||
"un_register_mixnode": {
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"bond_gateway"
|
||||
],
|
||||
"properties": {
|
||||
"bond_gateway": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"gateway"
|
||||
],
|
||||
"properties": {
|
||||
"gateway": {
|
||||
"$ref": "#/definitions/Gateway"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"unbond_gateway"
|
||||
],
|
||||
"properties": {
|
||||
"unbond_gateway": {
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"definitions": {
|
||||
"Gateway": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"clients_host",
|
||||
"identity_key",
|
||||
"location",
|
||||
"mix_host",
|
||||
"sphinx_key",
|
||||
"version"
|
||||
],
|
||||
"properties": {
|
||||
"clients_host": {
|
||||
"type": "string"
|
||||
},
|
||||
"identity_key": {
|
||||
"description": "Base58 encoded ed25519 EdDSA public key of the gateway used to derive shared keys with clients",
|
||||
"type": "string"
|
||||
},
|
||||
"location": {
|
||||
"type": "string"
|
||||
},
|
||||
"mix_host": {
|
||||
"type": "string"
|
||||
},
|
||||
"sphinx_key": {
|
||||
"type": "string"
|
||||
},
|
||||
"version": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"MixNode": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"host",
|
||||
"identity_key",
|
||||
"layer",
|
||||
"location",
|
||||
"sphinx_key",
|
||||
"version"
|
||||
],
|
||||
"properties": {
|
||||
"host": {
|
||||
"type": "string"
|
||||
},
|
||||
"identity_key": {
|
||||
"description": "Base58 encoded ed25519 EdDSA public key.",
|
||||
"type": "string"
|
||||
},
|
||||
"layer": {
|
||||
"type": "integer",
|
||||
"format": "uint64",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"location": {
|
||||
"type": "string"
|
||||
},
|
||||
"sphinx_key": {
|
||||
"type": "string"
|
||||
},
|
||||
"version": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "InitMsg",
|
||||
"title": "InstantiateMsg",
|
||||
"type": "object"
|
||||
}
|
||||
@@ -3,25 +3,40 @@
|
||||
"title": "MixNodeBond",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"amount",
|
||||
"bond_amount",
|
||||
"layer",
|
||||
"mix_node",
|
||||
"owner"
|
||||
"owner",
|
||||
"total_delegation"
|
||||
],
|
||||
"properties": {
|
||||
"amount": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/Coin"
|
||||
}
|
||||
"block_height": {
|
||||
"default": 0,
|
||||
"type": "integer",
|
||||
"format": "uint64",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"bond_amount": {
|
||||
"$ref": "#/definitions/Coin"
|
||||
},
|
||||
"layer": {
|
||||
"$ref": "#/definitions/Layer"
|
||||
},
|
||||
"mix_node": {
|
||||
"$ref": "#/definitions/MixNode"
|
||||
},
|
||||
"owner": {
|
||||
"$ref": "#/definitions/HumanAddr"
|
||||
"$ref": "#/definitions/Addr"
|
||||
},
|
||||
"total_delegation": {
|
||||
"$ref": "#/definitions/Coin"
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"Addr": {
|
||||
"description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.",
|
||||
"type": "string"
|
||||
},
|
||||
"Coin": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
@@ -37,44 +52,59 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"HumanAddr": {
|
||||
"type": "string"
|
||||
"Layer": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Gateway",
|
||||
"One",
|
||||
"Two",
|
||||
"Three"
|
||||
]
|
||||
},
|
||||
"MixNode": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"host",
|
||||
"http_api_port",
|
||||
"identity_key",
|
||||
"layer",
|
||||
"location",
|
||||
"mix_port",
|
||||
"sphinx_key",
|
||||
"verloc_port",
|
||||
"version"
|
||||
],
|
||||
"properties": {
|
||||
"host": {
|
||||
"type": "string"
|
||||
},
|
||||
"http_api_port": {
|
||||
"type": "integer",
|
||||
"format": "uint16",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"identity_key": {
|
||||
"description": "Base58 encoded ed25519 EdDSA public key.",
|
||||
"type": "string"
|
||||
},
|
||||
"layer": {
|
||||
"mix_port": {
|
||||
"type": "integer",
|
||||
"format": "uint64",
|
||||
"format": "uint16",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"location": {
|
||||
"type": "string"
|
||||
},
|
||||
"sphinx_key": {
|
||||
"type": "string"
|
||||
},
|
||||
"verloc_port": {
|
||||
"type": "integer",
|
||||
"format": "uint16",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"version": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Uint128": {
|
||||
"description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,18 +20,15 @@
|
||||
"minimum": 0.0
|
||||
},
|
||||
"start_after": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/HumanAddr"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
@@ -50,10 +47,96 @@
|
||||
"format": "uint32",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"start_after": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"owns_mixnode"
|
||||
],
|
||||
"properties": {
|
||||
"owns_mixnode": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"address"
|
||||
],
|
||||
"properties": {
|
||||
"address": {
|
||||
"$ref": "#/definitions/Addr"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"owns_gateway"
|
||||
],
|
||||
"properties": {
|
||||
"owns_gateway": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"address"
|
||||
],
|
||||
"properties": {
|
||||
"address": {
|
||||
"$ref": "#/definitions/Addr"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"state_params"
|
||||
],
|
||||
"properties": {
|
||||
"state_params": {
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"get_mix_delegations"
|
||||
],
|
||||
"properties": {
|
||||
"get_mix_delegations": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"mix_identity"
|
||||
],
|
||||
"properties": {
|
||||
"limit": {
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
],
|
||||
"format": "uint32",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"mix_identity": {
|
||||
"type": "string"
|
||||
},
|
||||
"start_after": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/HumanAddr"
|
||||
"$ref": "#/definitions/Addr"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
@@ -62,11 +145,179 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"get_reverse_mix_delegations"
|
||||
],
|
||||
"properties": {
|
||||
"get_reverse_mix_delegations": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"delegation_owner"
|
||||
],
|
||||
"properties": {
|
||||
"delegation_owner": {
|
||||
"$ref": "#/definitions/Addr"
|
||||
},
|
||||
"limit": {
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
],
|
||||
"format": "uint32",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"start_after": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"get_mix_delegation"
|
||||
],
|
||||
"properties": {
|
||||
"get_mix_delegation": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"address",
|
||||
"mix_identity"
|
||||
],
|
||||
"properties": {
|
||||
"address": {
|
||||
"$ref": "#/definitions/Addr"
|
||||
},
|
||||
"mix_identity": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"get_gateway_delegations"
|
||||
],
|
||||
"properties": {
|
||||
"get_gateway_delegations": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"gateway_identity"
|
||||
],
|
||||
"properties": {
|
||||
"gateway_identity": {
|
||||
"type": "string"
|
||||
},
|
||||
"limit": {
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
],
|
||||
"format": "uint32",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"start_after": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Addr"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"get_reverse_gateway_delegations"
|
||||
],
|
||||
"properties": {
|
||||
"get_reverse_gateway_delegations": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"delegation_owner"
|
||||
],
|
||||
"properties": {
|
||||
"delegation_owner": {
|
||||
"$ref": "#/definitions/Addr"
|
||||
},
|
||||
"limit": {
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
],
|
||||
"format": "uint32",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"start_after": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"get_gateway_delegation"
|
||||
],
|
||||
"properties": {
|
||||
"get_gateway_delegation": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"address",
|
||||
"gateway_identity"
|
||||
],
|
||||
"properties": {
|
||||
"address": {
|
||||
"$ref": "#/definitions/Addr"
|
||||
},
|
||||
"gateway_identity": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"layer_distribution"
|
||||
],
|
||||
"properties": {
|
||||
"layer_distribution": {
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
],
|
||||
"definitions": {
|
||||
"HumanAddr": {
|
||||
"Addr": {
|
||||
"description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,15 +3,91 @@
|
||||
"title": "State",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"owner"
|
||||
"gateway_epoch_bond_reward",
|
||||
"gateway_epoch_delegation_reward",
|
||||
"mixnode_epoch_bond_reward",
|
||||
"mixnode_epoch_delegation_reward",
|
||||
"network_monitor_address",
|
||||
"owner",
|
||||
"params"
|
||||
],
|
||||
"properties": {
|
||||
"gateway_epoch_bond_reward": {
|
||||
"$ref": "#/definitions/Decimal"
|
||||
},
|
||||
"gateway_epoch_delegation_reward": {
|
||||
"$ref": "#/definitions/Decimal"
|
||||
},
|
||||
"mixnode_epoch_bond_reward": {
|
||||
"$ref": "#/definitions/Decimal"
|
||||
},
|
||||
"mixnode_epoch_delegation_reward": {
|
||||
"$ref": "#/definitions/Decimal"
|
||||
},
|
||||
"network_monitor_address": {
|
||||
"$ref": "#/definitions/Addr"
|
||||
},
|
||||
"owner": {
|
||||
"$ref": "#/definitions/HumanAddr"
|
||||
"$ref": "#/definitions/Addr"
|
||||
},
|
||||
"params": {
|
||||
"$ref": "#/definitions/StateParams"
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"HumanAddr": {
|
||||
"Addr": {
|
||||
"description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.",
|
||||
"type": "string"
|
||||
},
|
||||
"Decimal": {
|
||||
"description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 340282366920938463463.374607431768211455 (which is (2^128 - 1) / 10^18)",
|
||||
"type": "string"
|
||||
},
|
||||
"StateParams": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"epoch_length",
|
||||
"gateway_bond_reward_rate",
|
||||
"gateway_delegation_reward_rate",
|
||||
"minimum_gateway_bond",
|
||||
"minimum_mixnode_bond",
|
||||
"mixnode_active_set_size",
|
||||
"mixnode_bond_reward_rate",
|
||||
"mixnode_delegation_reward_rate"
|
||||
],
|
||||
"properties": {
|
||||
"epoch_length": {
|
||||
"type": "integer",
|
||||
"format": "uint32",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"gateway_bond_reward_rate": {
|
||||
"$ref": "#/definitions/Decimal"
|
||||
},
|
||||
"gateway_delegation_reward_rate": {
|
||||
"$ref": "#/definitions/Decimal"
|
||||
},
|
||||
"minimum_gateway_bond": {
|
||||
"$ref": "#/definitions/Uint128"
|
||||
},
|
||||
"minimum_mixnode_bond": {
|
||||
"$ref": "#/definitions/Uint128"
|
||||
},
|
||||
"mixnode_active_set_size": {
|
||||
"type": "integer",
|
||||
"format": "uint32",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"mixnode_bond_reward_rate": {
|
||||
"$ref": "#/definitions/Decimal"
|
||||
},
|
||||
"mixnode_delegation_reward_rate": {
|
||||
"$ref": "#/definitions/Decimal"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Uint128": {
|
||||
"description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,9 @@ use cosmwasm_std::{
|
||||
entry_point, to_binary, Addr, Decimal, Deps, DepsMut, Env, MessageInfo, QueryResponse,
|
||||
Response, Uint128,
|
||||
};
|
||||
use mixnet_contract::{ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg, StateParams};
|
||||
use mixnet_contract::{
|
||||
ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg, RawDelegationData, StateParams,
|
||||
};
|
||||
|
||||
pub const INITIAL_DEFAULT_EPOCH_LENGTH: u32 = 2;
|
||||
|
||||
@@ -205,31 +207,68 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> Result<QueryResponse, Cont
|
||||
}
|
||||
|
||||
#[entry_point]
|
||||
pub fn migrate(deps: DepsMut, env: Env, _msg: MigrateMsg) -> Result<Response, ContractError> {
|
||||
use crate::storage::{gateways, gateways_read, mixnodes, mixnodes_read};
|
||||
pub fn migrate(mut deps: DepsMut, _env: Env, _msg: MigrateMsg) -> Result<Response, ContractError> {
|
||||
use crate::storage::{
|
||||
gateway_delegations, gateway_delegations_read, gateway_delegations_read_old, gateways_read,
|
||||
mix_delegations, mix_delegations_read, mix_delegations_read_old, mixnodes_read,
|
||||
};
|
||||
use crate::transactions::delegations;
|
||||
use cosmwasm_std::{Order, StdResult};
|
||||
use mixnet_contract::CURRENT_BLOCK_HEIGHT;
|
||||
use mixnet_contract::{GatewayBond, MixNodeBond};
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
CURRENT_BLOCK_HEIGHT.store(env.block.height, Ordering::Relaxed);
|
||||
// Read existing delegations data, drop invalid values, and rewrite delegations data with valid data only
|
||||
fn overwrite_mixnode_delegations_data(
|
||||
identity: &str,
|
||||
deps: &mut DepsMut,
|
||||
) -> Result<(), ContractError> {
|
||||
let delegations_bucket = mix_delegations_read(deps.storage, identity);
|
||||
let old_delegations_bucket = mix_delegations_read_old(deps.storage, identity);
|
||||
let mut delegations_vec = delegations(delegations_bucket)?;
|
||||
let old_delegations = delegations::<Uint128>(old_delegations_bucket)?;
|
||||
for delegation in old_delegations {
|
||||
delegations_vec.push((delegation.0, RawDelegationData::new(delegation.1, 1)))
|
||||
}
|
||||
|
||||
let bonds = mixnodes_read(deps.storage)
|
||||
for (key, delegation) in delegations_vec {
|
||||
mix_delegations(deps.storage, identity).save(&key, &delegation)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn overwrite_gateway_delegations_data(
|
||||
identity: &str,
|
||||
deps: &mut DepsMut,
|
||||
) -> Result<(), ContractError> {
|
||||
let delegations_bucket = gateway_delegations_read(deps.storage, identity);
|
||||
let old_delegations_bucket = gateway_delegations_read_old(deps.storage, identity);
|
||||
let mut delegations_vec = delegations(delegations_bucket)?;
|
||||
let old_delegations = delegations::<Uint128>(old_delegations_bucket)?;
|
||||
for delegation in old_delegations {
|
||||
delegations_vec.push((delegation.0, RawDelegationData::new(delegation.1, 1)))
|
||||
}
|
||||
|
||||
for (key, delegation) in delegations_vec {
|
||||
gateway_delegations(deps.storage, identity).save(&key, &delegation)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
let mixnet_bonds = mixnodes_read(deps.storage)
|
||||
.range(None, None, Order::Ascending)
|
||||
.map(|res| res.map(|item| item.1))
|
||||
.collect::<StdResult<Vec<MixNodeBond>>>()?;
|
||||
|
||||
for bond in bonds {
|
||||
mixnodes(deps.storage).save(bond.identity().as_bytes(), &bond)?;
|
||||
for bond in mixnet_bonds {
|
||||
overwrite_mixnode_delegations_data(bond.identity(), &mut deps)?;
|
||||
}
|
||||
|
||||
let bonds = gateways_read(deps.storage)
|
||||
let gateway_bonds = gateways_read(deps.storage)
|
||||
.range(None, None, Order::Ascending)
|
||||
.map(|res| res.map(|item| item.1))
|
||||
.collect::<StdResult<Vec<GatewayBond>>>()?;
|
||||
|
||||
for bond in bonds {
|
||||
gateways(deps.storage).save(bond.identity().as_bytes(), &bond)?;
|
||||
for bond in gateway_bonds {
|
||||
overwrite_gateway_delegations_data(bond.identity(), &mut deps)?;
|
||||
}
|
||||
|
||||
Ok(Default::default())
|
||||
|
||||
@@ -36,6 +36,8 @@ const PREFIX_REVERSE_GATEWAY_DELEGATION: &[u8] = b"dg";
|
||||
|
||||
// Contract-level stuff
|
||||
|
||||
// TODO Unify bucket and mixnode storage functions
|
||||
|
||||
pub fn config(storage: &mut dyn Storage) -> Singleton<State> {
|
||||
singleton(storage, CONFIG_KEY)
|
||||
}
|
||||
@@ -316,6 +318,14 @@ pub fn mix_delegations_read<'a>(
|
||||
ReadonlyBucket::multilevel(storage, &[PREFIX_MIX_DELEGATION, mix_identity.as_bytes()])
|
||||
}
|
||||
|
||||
// https://github.com/nymtech/nym/blob/122f5d9f2e5c1ced96e3b9ba0c74ef8b7dbde2c7/contracts/mixnet/src/storage.rs
|
||||
pub fn mix_delegations_read_old<'a>(
|
||||
storage: &'a dyn Storage,
|
||||
mix_identity: IdentityKeyRef,
|
||||
) -> ReadonlyBucket<'a, Uint128> {
|
||||
ReadonlyBucket::multilevel(storage, &[PREFIX_MIX_DELEGATION, mix_identity.as_bytes()])
|
||||
}
|
||||
|
||||
pub fn reverse_mix_delegations<'a>(storage: &'a mut dyn Storage, owner: &Addr) -> Bucket<'a, ()> {
|
||||
Bucket::multilevel(storage, &[PREFIX_REVERSE_MIX_DELEGATION, owner.as_bytes()])
|
||||
}
|
||||
@@ -347,6 +357,16 @@ pub fn gateway_delegations_read<'a>(
|
||||
)
|
||||
}
|
||||
|
||||
pub fn gateway_delegations_read_old<'a>(
|
||||
storage: &'a dyn Storage,
|
||||
gateway_identity: IdentityKeyRef,
|
||||
) -> ReadonlyBucket<'a, Uint128> {
|
||||
ReadonlyBucket::multilevel(
|
||||
storage,
|
||||
&[PREFIX_GATEWAY_DELEGATION, gateway_identity.as_bytes()],
|
||||
)
|
||||
}
|
||||
|
||||
pub fn reverse_gateway_delegations<'a>(
|
||||
storage: &'a mut dyn Storage,
|
||||
owner: &Addr,
|
||||
|
||||
@@ -14,6 +14,8 @@ use cosmwasm_storage::ReadonlyBucket;
|
||||
use mixnet_contract::{
|
||||
Gateway, GatewayBond, IdentityKey, Layer, MixNode, MixNodeBond, RawDelegationData, StateParams,
|
||||
};
|
||||
use serde::de::DeserializeOwned;
|
||||
use serde::Serialize;
|
||||
|
||||
const OLD_DELEGATIONS_CHUNK_SIZE: usize = 500;
|
||||
pub(crate) const MINIMUM_BLOCK_AGE_FOR_REWARDING: u64 = 17280;
|
||||
@@ -25,12 +27,15 @@ pub(crate) const MINIMUM_BLOCK_AGE_FOR_REWARDING: u64 = 17280;
|
||||
// 3. The node unbonds
|
||||
// 4. Some of the addresses that delegated in the past have not removed the delegation yet
|
||||
// 5. The node rebonds with the same identity
|
||||
fn find_old_delegations(delegations_bucket: ReadonlyBucket<RawDelegationData>) -> StdResult<Coin> {
|
||||
pub fn delegations<T: DeserializeOwned + Serialize>(
|
||||
delegations_bucket: ReadonlyBucket<T>,
|
||||
) -> StdResult<Vec<(Vec<u8>, T)>> {
|
||||
// I think it's incredibly unlikely to ever read more than that
|
||||
// but in case we do, we should guard ourselves against possible
|
||||
// out of memory errors (wasm contracts can only allocate at most 2MB
|
||||
// of RAM, so we don't want to box the entire iterator)
|
||||
let mut total_delegation = Coin::new(0, DENOM);
|
||||
let mut delegations = Vec::new();
|
||||
// let mut total_delegation = Coin::new(0, DENOM);
|
||||
let mut start = None;
|
||||
loop {
|
||||
let iterator = delegations_bucket
|
||||
@@ -39,16 +44,23 @@ fn find_old_delegations(delegations_bucket: ReadonlyBucket<RawDelegationData>) -
|
||||
|
||||
let mut iterated = 0;
|
||||
|
||||
for delegation in iterator {
|
||||
for result_tuple in iterator {
|
||||
iterated += 1;
|
||||
if iterated == OLD_DELEGATIONS_CHUNK_SIZE + 1 {
|
||||
// we reached start of next chunk, don't process it, mark it for the next iteration of the loop
|
||||
start = Some(delegation?.0);
|
||||
continue;
|
||||
match result_tuple {
|
||||
Ok((position, delegation)) => {
|
||||
// We might skip some values due to deserializatio errors
|
||||
if iterated > OLD_DELEGATIONS_CHUNK_SIZE {
|
||||
// we reached start of next chunk, don't process it, mark it for the next iteration of the loop
|
||||
start = Some(position);
|
||||
continue;
|
||||
}
|
||||
delegations.push((position, delegation))
|
||||
}
|
||||
Err(_e) => {
|
||||
// Skip errors
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
let value = delegation?.1.amount;
|
||||
total_delegation.amount += value;
|
||||
}
|
||||
|
||||
if iterated <= OLD_DELEGATIONS_CHUNK_SIZE {
|
||||
@@ -57,7 +69,17 @@ fn find_old_delegations(delegations_bucket: ReadonlyBucket<RawDelegationData>) -
|
||||
}
|
||||
}
|
||||
|
||||
Ok(total_delegation)
|
||||
Ok(delegations)
|
||||
}
|
||||
|
||||
fn total_delegations(delegations_bucket: ReadonlyBucket<RawDelegationData>) -> StdResult<Coin> {
|
||||
match delegations(delegations_bucket) {
|
||||
Ok(delegations) => Ok(Coin::new(
|
||||
delegations.iter().fold(0, |acc, x| acc + x.1.amount.u128()),
|
||||
"upunk",
|
||||
)),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
|
||||
fn validate_mixnode_bond(bond: &[Coin], minimum_bond: Uint128) -> Result<(), ContractError> {
|
||||
@@ -138,7 +160,7 @@ pub(crate) fn try_add_mixnode(
|
||||
|
||||
// this might potentially require more gas if a significant number of delegations was there
|
||||
let delegations_bucket = mix_delegations_read(deps.storage, &bond.mix_node.identity_key);
|
||||
let existing_delegation = find_old_delegations(delegations_bucket)?;
|
||||
let existing_delegation = total_delegations(delegations_bucket)?;
|
||||
bond.total_delegation = existing_delegation;
|
||||
|
||||
let identity = bond.identity();
|
||||
@@ -270,7 +292,7 @@ pub(crate) fn try_add_gateway(
|
||||
|
||||
// this might potentially require more gas if a significant number of delegations was there
|
||||
let delegations_bucket = gateway_delegations_read(deps.storage, &bond.gateway.identity_key);
|
||||
let existing_delegation = find_old_delegations(delegations_bucket)?;
|
||||
let existing_delegation = total_delegations(delegations_bucket)?;
|
||||
bond.total_delegation = existing_delegation;
|
||||
|
||||
let identity = bond.identity();
|
||||
@@ -3928,7 +3950,7 @@ pub mod tests {
|
||||
let node_identity: IdentityKey = "nodeidentity".into();
|
||||
|
||||
let read_bucket = mix_delegations_read(&deps.storage, &node_identity);
|
||||
let old_delegations = find_old_delegations(read_bucket).unwrap();
|
||||
let old_delegations = total_delegations(read_bucket).unwrap();
|
||||
|
||||
assert_eq!(Coin::new(0, DENOM), old_delegations);
|
||||
}
|
||||
@@ -3945,14 +3967,14 @@ pub mod tests {
|
||||
OLD_DELEGATIONS_CHUNK_SIZE * 3 + 1,
|
||||
];
|
||||
|
||||
for total_delegations in num_delegations {
|
||||
for delegations in num_delegations {
|
||||
let mut deps = helpers::init_contract();
|
||||
|
||||
let node_identity: IdentityKey = "nodeidentity".into();
|
||||
|
||||
// delegate some stake
|
||||
let mut write_bucket = mix_delegations(&mut deps.storage, &node_identity);
|
||||
for i in 1..=total_delegations {
|
||||
for i in 1..=delegations {
|
||||
let delegator = Addr::unchecked(format!("delegator{}", i));
|
||||
let delegation = raw_delegation_fixture(i as u128);
|
||||
write_bucket
|
||||
@@ -3961,9 +3983,9 @@ pub mod tests {
|
||||
}
|
||||
|
||||
let read_bucket = mix_delegations_read(&deps.storage, &node_identity);
|
||||
let old_delegations = find_old_delegations(read_bucket).unwrap();
|
||||
let old_delegations = total_delegations(read_bucket).unwrap();
|
||||
|
||||
let total_delegation = (1..=total_delegations as u128).into_iter().sum();
|
||||
let total_delegation = (1..=delegations as u128).into_iter().sum();
|
||||
assert_eq!(Coin::new(total_delegation, DENOM), old_delegations);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user