diff --git a/.github/workflows/local-tests.yml b/.github/workflows/local-tests.yml index dd4787a8..4876710b 100644 --- a/.github/workflows/local-tests.yml +++ b/.github/workflows/local-tests.yml @@ -23,3 +23,11 @@ jobs: - uses: actions/checkout@v4.1.0 - name: Build contracts, check formats, and run unit tests (full validation) run: cargo test --lib --features full-validation + local-build-test-full-validation: + runs-on: ubuntu-latest + container: + image: rust:1.78.0 + steps: + - uses: actions/checkout@v4.1.0 + - name: Build contracts, check formats, and run unit tests (BTC light client) + run: cargo test --lib --features btc-lc diff --git a/contracts/babylon/Cargo.toml b/contracts/babylon/Cargo.toml index e911f8d5..a1cc97ea 100644 --- a/contracts/babylon/Cargo.toml +++ b/contracts/babylon/Cargo.toml @@ -9,6 +9,14 @@ publish = false # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[package.metadata.optimizer] +default-build = true +builds = [ + { name = "btc-lc", features = [ + "btc-lc", + ], default-features = false } +] + [lib] crate-type = ["cdylib", "rlib"] # See https://bheisler.github.io/criterion.rs/book/faq.html#cargo-bench-gives-unrecognized-option-errors-for-valid-command-line-options @@ -22,14 +30,16 @@ bench = false test = false [features] -# Add feature "cranelift" to default if you need 32 bit or ARM support +# Add feature "cranelift" to default if you need 32 bits or ARM support default = [] -# Use cranelift backend instead of singlepass. This is required for development on 32 bit or ARM machines. +# Use cranelift backend instead of singlepass. This is required for development on 32 bits or ARM machines. cranelift = ["cosmwasm-vm/cranelift"] # for quicker tests, cargo test --lib library = [] # feature for enabling the full validation full-validation = [ "btc-staking/full-validation" ] +# Feature for enabling the Bitcoin light client +btc-lc = [] [dependencies] babylon-apis = { path = "../../packages/apis" } @@ -69,3 +79,4 @@ thousands = { workspace = true } [[bench]] name = "main" harness = false +required-features = ["btc-lc"] diff --git a/contracts/babylon/schema/babylon-contract.json b/contracts/babylon/schema/babylon-contract.json index 21cf91de..8d52f01d 100644 --- a/contracts/babylon/schema/babylon-contract.json +++ b/contracts/babylon/schema/babylon-contract.json @@ -118,31 +118,6 @@ "$schema": "http://json-schema.org/draft-07/schema#", "title": "ExecuteMsg", "oneOf": [ - { - "type": "object", - "required": [ - "btc_headers" - ], - "properties": { - "btc_headers": { - "type": "object", - "required": [ - "headers" - ], - "properties": { - "headers": { - "description": "`headers` is a list of BTC headers. Typically: - A given delta of headers a user wants to add to the tip or fork of the BTC chain.", - "type": "array", - "items": { - "$ref": "#/definitions/BtcHeader" - } - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, { "description": "`slashing` is a slashing event from the BTC staking contract.\n\nThis will be forwarded over IBC to the Babylon side for propagation to other Consumers, and Babylon itself", "type": "object", @@ -167,51 +142,6 @@ } ], "definitions": { - "BtcHeader": { - "description": "Bitcoin header.\n\nContains all the block's information except the actual transactions, but including a root of a [merkle tree] committing to all transactions in the block.\n\nThis struct is for use in RPC requests and responses. It has convenience trait impls to convert to the internal representation (`BlockHeader`), and to the Babylon extended representation (`BtcHeaderInfo`). Adapted from `BlockHeader`.", - "type": "object", - "required": [ - "bits", - "merkle_root", - "nonce", - "prev_blockhash", - "time", - "version" - ], - "properties": { - "bits": { - "description": "The target value below which the blockhash must lie, encoded as a a float (with well-defined rounding, of course).", - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - "merkle_root": { - "description": "The root hash of the merkle tree of transactions in the block. Encoded as a (byte-reversed) hex string.", - "type": "string" - }, - "nonce": { - "description": "The nonce, selected to obtain a low enough blockhash.", - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - "prev_blockhash": { - "description": "Reference to the previous block in the chain. Encoded as a (byte-reversed) hex string.", - "type": "string" - }, - "time": { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - "version": { - "description": "Originally protocol version, but repurposed for soft-fork signaling.\n\n### Relevant BIPs\n\n* [BIP9 - Version bits with timeout and delay](https://github.com/bitcoin/bips/blob/master/bip-0009.mediawiki) (current usage) * [BIP34 - Block v2, Height in Coinbase](https://github.com/bitcoin/bips/blob/master/bip-0034.mediawiki)", - "type": "integer", - "format": "int32" - } - }, - "additionalProperties": false - }, "Evidence": { "description": "Evidence is the evidence that a finality provider has signed finality signatures with correct public randomness on two conflicting Babylon headers", "type": "object", @@ -308,194 +238,6 @@ }, "additionalProperties": false }, - { - "description": "BtcBaseHeader returns the base BTC header stored in the contract", - "type": "object", - "required": [ - "btc_base_header" - ], - "properties": { - "btc_base_header": { - "type": "object", - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "BtcTipHeader returns the tip BTC header stored in the contract", - "type": "object", - "required": [ - "btc_tip_header" - ], - "properties": { - "btc_tip_header": { - "type": "object", - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "BtcHeader returns the BTC header information stored in the contract, by BTC height.", - "type": "object", - "required": [ - "btc_header" - ], - "properties": { - "btc_header": { - "type": "object", - "required": [ - "height" - ], - "properties": { - "height": { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "BtcHeaderByHash returns the BTC header information stored in the contract, by BTC hash.\n\n`hash` is the (byte-reversed) hex-encoded hash of the BTC header", - "type": "object", - "required": [ - "btc_header_by_hash" - ], - "properties": { - "btc_header_by_hash": { - "type": "object", - "required": [ - "hash" - ], - "properties": { - "hash": { - "type": "string" - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "BtcHeaders returns the canonical BTC chain stored in the contract.\n\n`start_after` is the height of the header to start after, or `None` to start from the base", - "type": "object", - "required": [ - "btc_headers" - ], - "properties": { - "btc_headers": { - "type": "object", - "properties": { - "limit": { - "type": [ - "integer", - "null" - ], - "format": "uint32", - "minimum": 0.0 - }, - "reverse": { - "type": [ - "boolean", - "null" - ] - }, - "start_after": { - "type": [ - "integer", - "null" - ], - "format": "uint32", - "minimum": 0.0 - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "BabylonBaseEpoch returns the base Babylon epoch stored in the contract", - "type": "object", - "required": [ - "babylon_base_epoch" - ], - "properties": { - "babylon_base_epoch": { - "type": "object", - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "BabylonLastEpoch returns the last babylon finalized epoch stored in the contract", - "type": "object", - "required": [ - "babylon_last_epoch" - ], - "properties": { - "babylon_last_epoch": { - "type": "object", - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "BabylonEpoch returns the Babylon epoch stored in the contract, by epoch number.", - "type": "object", - "required": [ - "babylon_epoch" - ], - "properties": { - "babylon_epoch": { - "type": "object", - "required": [ - "epoch_number" - ], - "properties": { - "epoch_number": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "BabylonCheckpoint returns the Babylon checkpoint stored in the contract, by epoch number.", - "type": "object", - "required": [ - "babylon_checkpoint" - ], - "properties": { - "babylon_checkpoint": { - "type": "object", - "required": [ - "epoch_number" - ], - "properties": { - "epoch_number": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, { "description": "CzLastHeader returns the last CZ epoch stored in the contract", "type": "object", @@ -545,739 +287,6 @@ }, "sudo": null, "responses": { - "babylon_base_epoch": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "EpochResponse", - "description": "Babylon epoch.\n\nThis struct is for use in RPC requests and responses. It has convenience helpers to convert to and from the internal representation (`Epoch`). Adapted from `Epoch`.", - "type": "object", - "required": [ - "current_epoch_interval", - "epoch_number", - "first_block_height", - "sealer_app_hash", - "sealer_block_hash" - ], - "properties": { - "current_epoch_interval": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "epoch_number": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "first_block_height": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "last_block_time": { - "description": "last_block_time is the time of the last block in this epoch. Babylon needs to remember the last header's time of each epoch to complete unbonding validators/delegations when a previous epoch's checkpoint is finalised. The last_block_time field is nil in the epoch's beginning, and is set upon the end of this epoch", - "anyOf": [ - { - "$ref": "#/definitions/Timestamp" - }, - { - "type": "null" - } - ] - }, - "sealer_app_hash": { - "description": "sealer is the last block of the sealed epoch. sealer_app_hash points to the sealer but stored in the first header of the next epoch. Hex-encoded string", - "type": "string" - }, - "sealer_block_hash": { - "description": "sealer_block_hash is the hash of the sealer. The validator set has generated a BLS multisig on the hash, i.e. the hash of the last block in the epoch. Hex-encoded string", - "type": "string" - } - }, - "additionalProperties": false, - "definitions": { - "Timestamp": { - "description": "A point in time in nanosecond precision.\n\nThis type can represent times from 1970-01-01T00:00:00Z to 2554-07-21T23:34:33Z.\n\n## Examples\n\n``` # use cosmwasm_std::Timestamp; let ts = Timestamp::from_nanos(1_000_000_202); assert_eq!(ts.nanos(), 1_000_000_202); assert_eq!(ts.seconds(), 1); assert_eq!(ts.subsec_nanos(), 202);\n\nlet ts = ts.plus_seconds(2); assert_eq!(ts.nanos(), 3_000_000_202); assert_eq!(ts.seconds(), 3); assert_eq!(ts.subsec_nanos(), 202); ```", - "allOf": [ - { - "$ref": "#/definitions/Uint64" - } - ] - }, - "Uint64": { - "description": "A thin wrapper around u64 that is using strings for JSON encoding/decoding, such that the full u64 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 `u64` to get the value out:\n\n``` # use cosmwasm_std::Uint64; let a = Uint64::from(42u64); assert_eq!(a.u64(), 42);\n\nlet b = Uint64::from(70u32); assert_eq!(b.u64(), 70); ```", - "type": "string" - } - } - }, - "babylon_checkpoint": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "EpochResponse", - "description": "Babylon epoch.\n\nThis struct is for use in RPC requests and responses. It has convenience helpers to convert to and from the internal representation (`Epoch`). Adapted from `Epoch`.", - "type": "object", - "required": [ - "current_epoch_interval", - "epoch_number", - "first_block_height", - "sealer_app_hash", - "sealer_block_hash" - ], - "properties": { - "current_epoch_interval": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "epoch_number": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "first_block_height": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "last_block_time": { - "description": "last_block_time is the time of the last block in this epoch. Babylon needs to remember the last header's time of each epoch to complete unbonding validators/delegations when a previous epoch's checkpoint is finalised. The last_block_time field is nil in the epoch's beginning, and is set upon the end of this epoch", - "anyOf": [ - { - "$ref": "#/definitions/Timestamp" - }, - { - "type": "null" - } - ] - }, - "sealer_app_hash": { - "description": "sealer is the last block of the sealed epoch. sealer_app_hash points to the sealer but stored in the first header of the next epoch. Hex-encoded string", - "type": "string" - }, - "sealer_block_hash": { - "description": "sealer_block_hash is the hash of the sealer. The validator set has generated a BLS multisig on the hash, i.e. the hash of the last block in the epoch. Hex-encoded string", - "type": "string" - } - }, - "additionalProperties": false, - "definitions": { - "Timestamp": { - "description": "A point in time in nanosecond precision.\n\nThis type can represent times from 1970-01-01T00:00:00Z to 2554-07-21T23:34:33Z.\n\n## Examples\n\n``` # use cosmwasm_std::Timestamp; let ts = Timestamp::from_nanos(1_000_000_202); assert_eq!(ts.nanos(), 1_000_000_202); assert_eq!(ts.seconds(), 1); assert_eq!(ts.subsec_nanos(), 202);\n\nlet ts = ts.plus_seconds(2); assert_eq!(ts.nanos(), 3_000_000_202); assert_eq!(ts.seconds(), 3); assert_eq!(ts.subsec_nanos(), 202); ```", - "allOf": [ - { - "$ref": "#/definitions/Uint64" - } - ] - }, - "Uint64": { - "description": "A thin wrapper around u64 that is using strings for JSON encoding/decoding, such that the full u64 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 `u64` to get the value out:\n\n``` # use cosmwasm_std::Uint64; let a = Uint64::from(42u64); assert_eq!(a.u64(), 42);\n\nlet b = Uint64::from(70u32); assert_eq!(b.u64(), 70); ```", - "type": "string" - } - } - }, - "babylon_epoch": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "EpochResponse", - "description": "Babylon epoch.\n\nThis struct is for use in RPC requests and responses. It has convenience helpers to convert to and from the internal representation (`Epoch`). Adapted from `Epoch`.", - "type": "object", - "required": [ - "current_epoch_interval", - "epoch_number", - "first_block_height", - "sealer_app_hash", - "sealer_block_hash" - ], - "properties": { - "current_epoch_interval": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "epoch_number": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "first_block_height": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "last_block_time": { - "description": "last_block_time is the time of the last block in this epoch. Babylon needs to remember the last header's time of each epoch to complete unbonding validators/delegations when a previous epoch's checkpoint is finalised. The last_block_time field is nil in the epoch's beginning, and is set upon the end of this epoch", - "anyOf": [ - { - "$ref": "#/definitions/Timestamp" - }, - { - "type": "null" - } - ] - }, - "sealer_app_hash": { - "description": "sealer is the last block of the sealed epoch. sealer_app_hash points to the sealer but stored in the first header of the next epoch. Hex-encoded string", - "type": "string" - }, - "sealer_block_hash": { - "description": "sealer_block_hash is the hash of the sealer. The validator set has generated a BLS multisig on the hash, i.e. the hash of the last block in the epoch. Hex-encoded string", - "type": "string" - } - }, - "additionalProperties": false, - "definitions": { - "Timestamp": { - "description": "A point in time in nanosecond precision.\n\nThis type can represent times from 1970-01-01T00:00:00Z to 2554-07-21T23:34:33Z.\n\n## Examples\n\n``` # use cosmwasm_std::Timestamp; let ts = Timestamp::from_nanos(1_000_000_202); assert_eq!(ts.nanos(), 1_000_000_202); assert_eq!(ts.seconds(), 1); assert_eq!(ts.subsec_nanos(), 202);\n\nlet ts = ts.plus_seconds(2); assert_eq!(ts.nanos(), 3_000_000_202); assert_eq!(ts.seconds(), 3); assert_eq!(ts.subsec_nanos(), 202); ```", - "allOf": [ - { - "$ref": "#/definitions/Uint64" - } - ] - }, - "Uint64": { - "description": "A thin wrapper around u64 that is using strings for JSON encoding/decoding, such that the full u64 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 `u64` to get the value out:\n\n``` # use cosmwasm_std::Uint64; let a = Uint64::from(42u64); assert_eq!(a.u64(), 42);\n\nlet b = Uint64::from(70u32); assert_eq!(b.u64(), 70); ```", - "type": "string" - } - } - }, - "babylon_last_epoch": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "EpochResponse", - "description": "Babylon epoch.\n\nThis struct is for use in RPC requests and responses. It has convenience helpers to convert to and from the internal representation (`Epoch`). Adapted from `Epoch`.", - "type": "object", - "required": [ - "current_epoch_interval", - "epoch_number", - "first_block_height", - "sealer_app_hash", - "sealer_block_hash" - ], - "properties": { - "current_epoch_interval": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "epoch_number": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "first_block_height": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "last_block_time": { - "description": "last_block_time is the time of the last block in this epoch. Babylon needs to remember the last header's time of each epoch to complete unbonding validators/delegations when a previous epoch's checkpoint is finalised. The last_block_time field is nil in the epoch's beginning, and is set upon the end of this epoch", - "anyOf": [ - { - "$ref": "#/definitions/Timestamp" - }, - { - "type": "null" - } - ] - }, - "sealer_app_hash": { - "description": "sealer is the last block of the sealed epoch. sealer_app_hash points to the sealer but stored in the first header of the next epoch. Hex-encoded string", - "type": "string" - }, - "sealer_block_hash": { - "description": "sealer_block_hash is the hash of the sealer. The validator set has generated a BLS multisig on the hash, i.e. the hash of the last block in the epoch. Hex-encoded string", - "type": "string" - } - }, - "additionalProperties": false, - "definitions": { - "Timestamp": { - "description": "A point in time in nanosecond precision.\n\nThis type can represent times from 1970-01-01T00:00:00Z to 2554-07-21T23:34:33Z.\n\n## Examples\n\n``` # use cosmwasm_std::Timestamp; let ts = Timestamp::from_nanos(1_000_000_202); assert_eq!(ts.nanos(), 1_000_000_202); assert_eq!(ts.seconds(), 1); assert_eq!(ts.subsec_nanos(), 202);\n\nlet ts = ts.plus_seconds(2); assert_eq!(ts.nanos(), 3_000_000_202); assert_eq!(ts.seconds(), 3); assert_eq!(ts.subsec_nanos(), 202); ```", - "allOf": [ - { - "$ref": "#/definitions/Uint64" - } - ] - }, - "Uint64": { - "description": "A thin wrapper around u64 that is using strings for JSON encoding/decoding, such that the full u64 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 `u64` to get the value out:\n\n``` # use cosmwasm_std::Uint64; let a = Uint64::from(42u64); assert_eq!(a.u64(), 42);\n\nlet b = Uint64::from(70u32); assert_eq!(b.u64(), 70); ```", - "type": "string" - } - } - }, - "btc_base_header": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "BtcHeaderResponse", - "description": "Bitcoin header response.\n\nThis struct is for use in RPC requests and responses. It has convenience helpers to convert from the internal representation (`BtcHeaderInfo`), and to the Babylon extended representation\n\nAdapted from `BtcHeaderInfo`.", - "type": "object", - "required": [ - "cum_work", - "hash", - "header", - "height" - ], - "properties": { - "cum_work": { - "description": "The cumulative total work of this block and all of its ancestors.", - "allOf": [ - { - "$ref": "#/definitions/Uint256" - } - ] - }, - "hash": { - "description": "`hash` is the hash of the BTC header. Encoded as a (byte-reversed) hex string.", - "type": "string" - }, - "header": { - "description": "The Bitcoin header.", - "allOf": [ - { - "$ref": "#/definitions/BtcHeader" - } - ] - }, - "height": { - "description": "The height of the block in the BTC blockchain.", - "type": "integer", - "format": "uint32", - "minimum": 0.0 - } - }, - "additionalProperties": false, - "definitions": { - "BtcHeader": { - "description": "Bitcoin header.\n\nContains all the block's information except the actual transactions, but including a root of a [merkle tree] committing to all transactions in the block.\n\nThis struct is for use in RPC requests and responses. It has convenience trait impls to convert to the internal representation (`BlockHeader`), and to the Babylon extended representation (`BtcHeaderInfo`). Adapted from `BlockHeader`.", - "type": "object", - "required": [ - "bits", - "merkle_root", - "nonce", - "prev_blockhash", - "time", - "version" - ], - "properties": { - "bits": { - "description": "The target value below which the blockhash must lie, encoded as a a float (with well-defined rounding, of course).", - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - "merkle_root": { - "description": "The root hash of the merkle tree of transactions in the block. Encoded as a (byte-reversed) hex string.", - "type": "string" - }, - "nonce": { - "description": "The nonce, selected to obtain a low enough blockhash.", - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - "prev_blockhash": { - "description": "Reference to the previous block in the chain. Encoded as a (byte-reversed) hex string.", - "type": "string" - }, - "time": { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - "version": { - "description": "Originally protocol version, but repurposed for soft-fork signaling.\n\n### Relevant BIPs\n\n* [BIP9 - Version bits with timeout and delay](https://github.com/bitcoin/bips/blob/master/bip-0009.mediawiki) (current usage) * [BIP34 - Block v2, Height in Coinbase](https://github.com/bitcoin/bips/blob/master/bip-0034.mediawiki)", - "type": "integer", - "format": "int32" - } - }, - "additionalProperties": false - }, - "Uint256": { - "description": "An implementation of u256 that is using strings for JSON encoding/decoding, such that the full u256 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 out of primitive uint types or `new` to provide big endian bytes:\n\n``` # use cosmwasm_std::Uint256; let a = Uint256::from(258u128); let b = Uint256::new([ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 2u8, ]); assert_eq!(a, b); ```", - "type": "string" - } - } - }, - "btc_header": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "BtcHeaderResponse", - "description": "Bitcoin header response.\n\nThis struct is for use in RPC requests and responses. It has convenience helpers to convert from the internal representation (`BtcHeaderInfo`), and to the Babylon extended representation\n\nAdapted from `BtcHeaderInfo`.", - "type": "object", - "required": [ - "cum_work", - "hash", - "header", - "height" - ], - "properties": { - "cum_work": { - "description": "The cumulative total work of this block and all of its ancestors.", - "allOf": [ - { - "$ref": "#/definitions/Uint256" - } - ] - }, - "hash": { - "description": "`hash` is the hash of the BTC header. Encoded as a (byte-reversed) hex string.", - "type": "string" - }, - "header": { - "description": "The Bitcoin header.", - "allOf": [ - { - "$ref": "#/definitions/BtcHeader" - } - ] - }, - "height": { - "description": "The height of the block in the BTC blockchain.", - "type": "integer", - "format": "uint32", - "minimum": 0.0 - } - }, - "additionalProperties": false, - "definitions": { - "BtcHeader": { - "description": "Bitcoin header.\n\nContains all the block's information except the actual transactions, but including a root of a [merkle tree] committing to all transactions in the block.\n\nThis struct is for use in RPC requests and responses. It has convenience trait impls to convert to the internal representation (`BlockHeader`), and to the Babylon extended representation (`BtcHeaderInfo`). Adapted from `BlockHeader`.", - "type": "object", - "required": [ - "bits", - "merkle_root", - "nonce", - "prev_blockhash", - "time", - "version" - ], - "properties": { - "bits": { - "description": "The target value below which the blockhash must lie, encoded as a a float (with well-defined rounding, of course).", - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - "merkle_root": { - "description": "The root hash of the merkle tree of transactions in the block. Encoded as a (byte-reversed) hex string.", - "type": "string" - }, - "nonce": { - "description": "The nonce, selected to obtain a low enough blockhash.", - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - "prev_blockhash": { - "description": "Reference to the previous block in the chain. Encoded as a (byte-reversed) hex string.", - "type": "string" - }, - "time": { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - "version": { - "description": "Originally protocol version, but repurposed for soft-fork signaling.\n\n### Relevant BIPs\n\n* [BIP9 - Version bits with timeout and delay](https://github.com/bitcoin/bips/blob/master/bip-0009.mediawiki) (current usage) * [BIP34 - Block v2, Height in Coinbase](https://github.com/bitcoin/bips/blob/master/bip-0034.mediawiki)", - "type": "integer", - "format": "int32" - } - }, - "additionalProperties": false - }, - "Uint256": { - "description": "An implementation of u256 that is using strings for JSON encoding/decoding, such that the full u256 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 out of primitive uint types or `new` to provide big endian bytes:\n\n``` # use cosmwasm_std::Uint256; let a = Uint256::from(258u128); let b = Uint256::new([ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 2u8, ]); assert_eq!(a, b); ```", - "type": "string" - } - } - }, - "btc_header_by_hash": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "BtcHeaderResponse", - "description": "Bitcoin header response.\n\nThis struct is for use in RPC requests and responses. It has convenience helpers to convert from the internal representation (`BtcHeaderInfo`), and to the Babylon extended representation\n\nAdapted from `BtcHeaderInfo`.", - "type": "object", - "required": [ - "cum_work", - "hash", - "header", - "height" - ], - "properties": { - "cum_work": { - "description": "The cumulative total work of this block and all of its ancestors.", - "allOf": [ - { - "$ref": "#/definitions/Uint256" - } - ] - }, - "hash": { - "description": "`hash` is the hash of the BTC header. Encoded as a (byte-reversed) hex string.", - "type": "string" - }, - "header": { - "description": "The Bitcoin header.", - "allOf": [ - { - "$ref": "#/definitions/BtcHeader" - } - ] - }, - "height": { - "description": "The height of the block in the BTC blockchain.", - "type": "integer", - "format": "uint32", - "minimum": 0.0 - } - }, - "additionalProperties": false, - "definitions": { - "BtcHeader": { - "description": "Bitcoin header.\n\nContains all the block's information except the actual transactions, but including a root of a [merkle tree] committing to all transactions in the block.\n\nThis struct is for use in RPC requests and responses. It has convenience trait impls to convert to the internal representation (`BlockHeader`), and to the Babylon extended representation (`BtcHeaderInfo`). Adapted from `BlockHeader`.", - "type": "object", - "required": [ - "bits", - "merkle_root", - "nonce", - "prev_blockhash", - "time", - "version" - ], - "properties": { - "bits": { - "description": "The target value below which the blockhash must lie, encoded as a a float (with well-defined rounding, of course).", - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - "merkle_root": { - "description": "The root hash of the merkle tree of transactions in the block. Encoded as a (byte-reversed) hex string.", - "type": "string" - }, - "nonce": { - "description": "The nonce, selected to obtain a low enough blockhash.", - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - "prev_blockhash": { - "description": "Reference to the previous block in the chain. Encoded as a (byte-reversed) hex string.", - "type": "string" - }, - "time": { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - "version": { - "description": "Originally protocol version, but repurposed for soft-fork signaling.\n\n### Relevant BIPs\n\n* [BIP9 - Version bits with timeout and delay](https://github.com/bitcoin/bips/blob/master/bip-0009.mediawiki) (current usage) * [BIP34 - Block v2, Height in Coinbase](https://github.com/bitcoin/bips/blob/master/bip-0034.mediawiki)", - "type": "integer", - "format": "int32" - } - }, - "additionalProperties": false - }, - "Uint256": { - "description": "An implementation of u256 that is using strings for JSON encoding/decoding, such that the full u256 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 out of primitive uint types or `new` to provide big endian bytes:\n\n``` # use cosmwasm_std::Uint256; let a = Uint256::from(258u128); let b = Uint256::new([ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 2u8, ]); assert_eq!(a, b); ```", - "type": "string" - } - } - }, - "btc_headers": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "BtcHeadersResponse", - "description": "Bitcoin header responses.\n\nVector of `BtcHeaderResponse`.", - "type": "object", - "required": [ - "headers" - ], - "properties": { - "headers": { - "description": "The Bitcoin headers.", - "type": "array", - "items": { - "$ref": "#/definitions/BtcHeaderResponse" - } - } - }, - "additionalProperties": false, - "definitions": { - "BtcHeader": { - "description": "Bitcoin header.\n\nContains all the block's information except the actual transactions, but including a root of a [merkle tree] committing to all transactions in the block.\n\nThis struct is for use in RPC requests and responses. It has convenience trait impls to convert to the internal representation (`BlockHeader`), and to the Babylon extended representation (`BtcHeaderInfo`). Adapted from `BlockHeader`.", - "type": "object", - "required": [ - "bits", - "merkle_root", - "nonce", - "prev_blockhash", - "time", - "version" - ], - "properties": { - "bits": { - "description": "The target value below which the blockhash must lie, encoded as a a float (with well-defined rounding, of course).", - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - "merkle_root": { - "description": "The root hash of the merkle tree of transactions in the block. Encoded as a (byte-reversed) hex string.", - "type": "string" - }, - "nonce": { - "description": "The nonce, selected to obtain a low enough blockhash.", - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - "prev_blockhash": { - "description": "Reference to the previous block in the chain. Encoded as a (byte-reversed) hex string.", - "type": "string" - }, - "time": { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - "version": { - "description": "Originally protocol version, but repurposed for soft-fork signaling.\n\n### Relevant BIPs\n\n* [BIP9 - Version bits with timeout and delay](https://github.com/bitcoin/bips/blob/master/bip-0009.mediawiki) (current usage) * [BIP34 - Block v2, Height in Coinbase](https://github.com/bitcoin/bips/blob/master/bip-0034.mediawiki)", - "type": "integer", - "format": "int32" - } - }, - "additionalProperties": false - }, - "BtcHeaderResponse": { - "description": "Bitcoin header response.\n\nThis struct is for use in RPC requests and responses. It has convenience helpers to convert from the internal representation (`BtcHeaderInfo`), and to the Babylon extended representation\n\nAdapted from `BtcHeaderInfo`.", - "type": "object", - "required": [ - "cum_work", - "hash", - "header", - "height" - ], - "properties": { - "cum_work": { - "description": "The cumulative total work of this block and all of its ancestors.", - "allOf": [ - { - "$ref": "#/definitions/Uint256" - } - ] - }, - "hash": { - "description": "`hash` is the hash of the BTC header. Encoded as a (byte-reversed) hex string.", - "type": "string" - }, - "header": { - "description": "The Bitcoin header.", - "allOf": [ - { - "$ref": "#/definitions/BtcHeader" - } - ] - }, - "height": { - "description": "The height of the block in the BTC blockchain.", - "type": "integer", - "format": "uint32", - "minimum": 0.0 - } - }, - "additionalProperties": false - }, - "Uint256": { - "description": "An implementation of u256 that is using strings for JSON encoding/decoding, such that the full u256 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 out of primitive uint types or `new` to provide big endian bytes:\n\n``` # use cosmwasm_std::Uint256; let a = Uint256::from(258u128); let b = Uint256::new([ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 2u8, ]); assert_eq!(a, b); ```", - "type": "string" - } - } - }, - "btc_tip_header": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "BtcHeaderResponse", - "description": "Bitcoin header response.\n\nThis struct is for use in RPC requests and responses. It has convenience helpers to convert from the internal representation (`BtcHeaderInfo`), and to the Babylon extended representation\n\nAdapted from `BtcHeaderInfo`.", - "type": "object", - "required": [ - "cum_work", - "hash", - "header", - "height" - ], - "properties": { - "cum_work": { - "description": "The cumulative total work of this block and all of its ancestors.", - "allOf": [ - { - "$ref": "#/definitions/Uint256" - } - ] - }, - "hash": { - "description": "`hash` is the hash of the BTC header. Encoded as a (byte-reversed) hex string.", - "type": "string" - }, - "header": { - "description": "The Bitcoin header.", - "allOf": [ - { - "$ref": "#/definitions/BtcHeader" - } - ] - }, - "height": { - "description": "The height of the block in the BTC blockchain.", - "type": "integer", - "format": "uint32", - "minimum": 0.0 - } - }, - "additionalProperties": false, - "definitions": { - "BtcHeader": { - "description": "Bitcoin header.\n\nContains all the block's information except the actual transactions, but including a root of a [merkle tree] committing to all transactions in the block.\n\nThis struct is for use in RPC requests and responses. It has convenience trait impls to convert to the internal representation (`BlockHeader`), and to the Babylon extended representation (`BtcHeaderInfo`). Adapted from `BlockHeader`.", - "type": "object", - "required": [ - "bits", - "merkle_root", - "nonce", - "prev_blockhash", - "time", - "version" - ], - "properties": { - "bits": { - "description": "The target value below which the blockhash must lie, encoded as a a float (with well-defined rounding, of course).", - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - "merkle_root": { - "description": "The root hash of the merkle tree of transactions in the block. Encoded as a (byte-reversed) hex string.", - "type": "string" - }, - "nonce": { - "description": "The nonce, selected to obtain a low enough blockhash.", - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - "prev_blockhash": { - "description": "Reference to the previous block in the chain. Encoded as a (byte-reversed) hex string.", - "type": "string" - }, - "time": { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - "version": { - "description": "Originally protocol version, but repurposed for soft-fork signaling.\n\n### Relevant BIPs\n\n* [BIP9 - Version bits with timeout and delay](https://github.com/bitcoin/bips/blob/master/bip-0009.mediawiki) (current usage) * [BIP34 - Block v2, Height in Coinbase](https://github.com/bitcoin/bips/blob/master/bip-0034.mediawiki)", - "type": "integer", - "format": "int32" - } - }, - "additionalProperties": false - }, - "Uint256": { - "description": "An implementation of u256 that is using strings for JSON encoding/decoding, such that the full u256 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 out of primitive uint types or `new` to provide big endian bytes:\n\n``` # use cosmwasm_std::Uint256; let a = Uint256::from(258u128); let b = Uint256::new([ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 2u8, ]); assert_eq!(a, b); ```", - "type": "string" - } - } - }, "config": { "$schema": "http://json-schema.org/draft-07/schema#", "title": "Config", diff --git a/contracts/babylon/schema/raw/execute.json b/contracts/babylon/schema/raw/execute.json index ebc3604f..5cce2657 100644 --- a/contracts/babylon/schema/raw/execute.json +++ b/contracts/babylon/schema/raw/execute.json @@ -2,31 +2,6 @@ "$schema": "http://json-schema.org/draft-07/schema#", "title": "ExecuteMsg", "oneOf": [ - { - "type": "object", - "required": [ - "btc_headers" - ], - "properties": { - "btc_headers": { - "type": "object", - "required": [ - "headers" - ], - "properties": { - "headers": { - "description": "`headers` is a list of BTC headers. Typically: - A given delta of headers a user wants to add to the tip or fork of the BTC chain.", - "type": "array", - "items": { - "$ref": "#/definitions/BtcHeader" - } - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, { "description": "`slashing` is a slashing event from the BTC staking contract.\n\nThis will be forwarded over IBC to the Babylon side for propagation to other Consumers, and Babylon itself", "type": "object", @@ -51,51 +26,6 @@ } ], "definitions": { - "BtcHeader": { - "description": "Bitcoin header.\n\nContains all the block's information except the actual transactions, but including a root of a [merkle tree] committing to all transactions in the block.\n\nThis struct is for use in RPC requests and responses. It has convenience trait impls to convert to the internal representation (`BlockHeader`), and to the Babylon extended representation (`BtcHeaderInfo`). Adapted from `BlockHeader`.", - "type": "object", - "required": [ - "bits", - "merkle_root", - "nonce", - "prev_blockhash", - "time", - "version" - ], - "properties": { - "bits": { - "description": "The target value below which the blockhash must lie, encoded as a a float (with well-defined rounding, of course).", - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - "merkle_root": { - "description": "The root hash of the merkle tree of transactions in the block. Encoded as a (byte-reversed) hex string.", - "type": "string" - }, - "nonce": { - "description": "The nonce, selected to obtain a low enough blockhash.", - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - "prev_blockhash": { - "description": "Reference to the previous block in the chain. Encoded as a (byte-reversed) hex string.", - "type": "string" - }, - "time": { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - "version": { - "description": "Originally protocol version, but repurposed for soft-fork signaling.\n\n### Relevant BIPs\n\n* [BIP9 - Version bits with timeout and delay](https://github.com/bitcoin/bips/blob/master/bip-0009.mediawiki) (current usage) * [BIP34 - Block v2, Height in Coinbase](https://github.com/bitcoin/bips/blob/master/bip-0034.mediawiki)", - "type": "integer", - "format": "int32" - } - }, - "additionalProperties": false - }, "Evidence": { "description": "Evidence is the evidence that a finality provider has signed finality signatures with correct public randomness on two conflicting Babylon headers", "type": "object", diff --git a/contracts/babylon/schema/raw/query.json b/contracts/babylon/schema/raw/query.json index e4991b84..451c16a3 100644 --- a/contracts/babylon/schema/raw/query.json +++ b/contracts/babylon/schema/raw/query.json @@ -16,194 +16,6 @@ }, "additionalProperties": false }, - { - "description": "BtcBaseHeader returns the base BTC header stored in the contract", - "type": "object", - "required": [ - "btc_base_header" - ], - "properties": { - "btc_base_header": { - "type": "object", - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "BtcTipHeader returns the tip BTC header stored in the contract", - "type": "object", - "required": [ - "btc_tip_header" - ], - "properties": { - "btc_tip_header": { - "type": "object", - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "BtcHeader returns the BTC header information stored in the contract, by BTC height.", - "type": "object", - "required": [ - "btc_header" - ], - "properties": { - "btc_header": { - "type": "object", - "required": [ - "height" - ], - "properties": { - "height": { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "BtcHeaderByHash returns the BTC header information stored in the contract, by BTC hash.\n\n`hash` is the (byte-reversed) hex-encoded hash of the BTC header", - "type": "object", - "required": [ - "btc_header_by_hash" - ], - "properties": { - "btc_header_by_hash": { - "type": "object", - "required": [ - "hash" - ], - "properties": { - "hash": { - "type": "string" - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "BtcHeaders returns the canonical BTC chain stored in the contract.\n\n`start_after` is the height of the header to start after, or `None` to start from the base", - "type": "object", - "required": [ - "btc_headers" - ], - "properties": { - "btc_headers": { - "type": "object", - "properties": { - "limit": { - "type": [ - "integer", - "null" - ], - "format": "uint32", - "minimum": 0.0 - }, - "reverse": { - "type": [ - "boolean", - "null" - ] - }, - "start_after": { - "type": [ - "integer", - "null" - ], - "format": "uint32", - "minimum": 0.0 - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "BabylonBaseEpoch returns the base Babylon epoch stored in the contract", - "type": "object", - "required": [ - "babylon_base_epoch" - ], - "properties": { - "babylon_base_epoch": { - "type": "object", - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "BabylonLastEpoch returns the last babylon finalized epoch stored in the contract", - "type": "object", - "required": [ - "babylon_last_epoch" - ], - "properties": { - "babylon_last_epoch": { - "type": "object", - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "BabylonEpoch returns the Babylon epoch stored in the contract, by epoch number.", - "type": "object", - "required": [ - "babylon_epoch" - ], - "properties": { - "babylon_epoch": { - "type": "object", - "required": [ - "epoch_number" - ], - "properties": { - "epoch_number": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "BabylonCheckpoint returns the Babylon checkpoint stored in the contract, by epoch number.", - "type": "object", - "required": [ - "babylon_checkpoint" - ], - "properties": { - "babylon_checkpoint": { - "type": "object", - "required": [ - "epoch_number" - ], - "properties": { - "epoch_number": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, { "description": "CzLastHeader returns the last CZ epoch stored in the contract", "type": "object", diff --git a/contracts/babylon/src/contract.rs b/contracts/babylon/src/contract.rs index 38b82683..4c6dca80 100644 --- a/contracts/babylon/src/contract.rs +++ b/contracts/babylon/src/contract.rs @@ -12,6 +12,7 @@ use crate::error::ContractError; use crate::ibc::{ibc_packet, IBC_CHANNEL}; use crate::msg::contract::{ContractMsg, ExecuteMsg, InstantiateMsg, QueryMsg}; use crate::queries; +#[cfg(feature = "btc-lc")] use crate::state::btc_light_client; use crate::state::config::{Config, CONFIG}; @@ -170,12 +171,17 @@ fn reply_init_finality_callback( pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> Result { match msg { QueryMsg::Config {} => Ok(to_json_binary(&queries::config(deps)?)?), + #[cfg(feature = "btc-lc")] QueryMsg::BtcBaseHeader {} => Ok(to_json_binary(&queries::btc_base_header(deps)?)?), + #[cfg(feature = "btc-lc")] QueryMsg::BtcTipHeader {} => Ok(to_json_binary(&queries::btc_tip_header(deps)?)?), + #[cfg(feature = "btc-lc")] QueryMsg::BtcHeader { height } => Ok(to_json_binary(&queries::btc_header(deps, height)?)?), + #[cfg(feature = "btc-lc")] QueryMsg::BtcHeaderByHash { hash } => { Ok(to_json_binary(&queries::btc_header_by_hash(deps, &hash)?)?) } + #[cfg(feature = "btc-lc")] QueryMsg::BtcHeaders { start_after, limit, @@ -186,12 +192,16 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> Result Ok(to_json_binary(&queries::babylon_base_epoch(deps)?)?), + #[cfg(feature = "btc-lc")] QueryMsg::BabylonLastEpoch {} => Ok(to_json_binary(&queries::babylon_last_epoch(deps)?)?), + #[cfg(feature = "btc-lc")] QueryMsg::BabylonEpoch { epoch_number } => Ok(to_json_binary(&queries::babylon_epoch( deps, epoch_number, )?)?), + #[cfg(feature = "btc-lc")] QueryMsg::BabylonCheckpoint { epoch_number } => Ok(to_json_binary( &queries::babylon_checkpoint(deps, epoch_number)?, )?), @@ -216,6 +226,7 @@ pub fn execute( msg: ExecuteMsg, ) -> Result, ContractError> { match msg { + #[cfg(feature = "btc-lc")] ExecuteMsg::BtcHeaders { headers: btc_headers, } => { diff --git a/contracts/babylon/src/ibc.rs b/contracts/babylon/src/ibc.rs index 3a780feb..51f55276 100644 --- a/contracts/babylon/src/ibc.rs +++ b/contracts/babylon/src/ibc.rs @@ -1,7 +1,7 @@ use crate::error::ContractError; use babylon_bindings::BabylonMsg; use babylon_proto::babylon::zoneconcierge::v1::{ - zoneconcierge_packet_data::Packet, BtcTimestamp, ZoneconciergePacketData, + zoneconcierge_packet_data::Packet, ZoneconciergePacketData, }; use crate::state::config::CONFIG; @@ -134,7 +134,12 @@ pub fn ibc_packet_receive( .packet .ok_or(StdError::generic_err("empty IBC packet"))?; match zc_packet { + #[cfg(feature = "btc-lc")] Packet::BtcTimestamp(btc_ts) => ibc_packet::handle_btc_timestamp(deps, caller, &btc_ts), + #[cfg(not(feature = "btc-lc"))] + Packet::BtcTimestamp(_) => Err(StdError::generic_err( + "BTC light client feature is not enabled", + )), Packet::BtcStaking(btc_staking) => { ibc_packet::handle_btc_staking(deps, caller, &btc_staking) } @@ -164,9 +169,12 @@ pub(crate) mod ibc_packet { use babylon_apis::finality_api::Evidence; use babylon_proto::babylon::btcstaking::v1::BtcStakingIbcPacket; use babylon_proto::babylon::zoneconcierge::v1::zoneconcierge_packet_data::Packet::ConsumerSlashing; + #[cfg(feature = "btc-lc")] + use babylon_proto::babylon::zoneconcierge::v1::BtcTimestamp; use babylon_proto::babylon::zoneconcierge::v1::ConsumerSlashingIbcPacket; use cosmwasm_std::{to_json_binary, IbcChannel, IbcMsg, WasmMsg}; + #[cfg(feature = "btc-lc")] pub fn handle_btc_timestamp( deps: DepsMut, _caller: String, diff --git a/contracts/babylon/src/lib.rs b/contracts/babylon/src/lib.rs index dd7414f3..5fad6d39 100644 --- a/contracts/babylon/src/lib.rs +++ b/contracts/babylon/src/lib.rs @@ -12,6 +12,7 @@ use crate::error::ContractError; pub use crate::msg::contract::ExecuteMsg; use crate::msg::contract::InstantiateMsg; +#[cfg(feature = "btc-lc")] mod bindings; pub mod contract; pub mod error; diff --git a/contracts/babylon/src/msg/contract.rs b/contracts/babylon/src/msg/contract.rs index b094f0c8..f528bdc0 100644 --- a/contracts/babylon/src/msg/contract.rs +++ b/contracts/babylon/src/msg/contract.rs @@ -3,13 +3,14 @@ use cosmwasm_std::{Binary, StdError, StdResult}; use babylon_apis::finality_api::Evidence; -use crate::msg::btc_header::BtcHeader; #[cfg(not(target_arch = "wasm32"))] -use { - crate::msg::btc_header::{BtcHeaderResponse, BtcHeadersResponse}, - crate::msg::cz_header::CzHeaderResponse, - crate::msg::epoch::EpochResponse, - crate::state::config::Config, +use crate::{msg::cz_header::CzHeaderResponse, state::config::Config}; + +#[cfg(feature = "btc-lc")] +use crate::msg::{ + btc_header::BtcHeader, + btc_header::{BtcHeaderResponse, BtcHeadersResponse}, + epoch::EpochResponse, }; const BABYLON_TAG_BYTES: usize = 4; @@ -98,6 +99,7 @@ impl ContractMsg for InstantiateMsg { #[cw_serde] pub enum ExecuteMsg { + #[cfg(feature = "btc-lc")] BtcHeaders { /// `headers` is a list of BTC headers. Typically: /// - A given delta of headers a user wants to add to the tip or fork of the BTC chain. @@ -117,22 +119,27 @@ pub enum QueryMsg { #[returns(Config)] Config {}, /// BtcBaseHeader returns the base BTC header stored in the contract + #[cfg(feature = "btc-lc")] #[returns(BtcHeaderResponse)] BtcBaseHeader {}, /// BtcTipHeader returns the tip BTC header stored in the contract + #[cfg(feature = "btc-lc")] #[returns(BtcHeaderResponse)] BtcTipHeader {}, /// BtcHeader returns the BTC header information stored in the contract, by BTC height. + #[cfg(feature = "btc-lc")] #[returns(BtcHeaderResponse)] BtcHeader { height: u32 }, /// BtcHeaderByHash returns the BTC header information stored in the contract, by BTC hash. /// /// `hash` is the (byte-reversed) hex-encoded hash of the BTC header + #[cfg(feature = "btc-lc")] #[returns(BtcHeaderResponse)] BtcHeaderByHash { hash: String }, /// BtcHeaders returns the canonical BTC chain stored in the contract. /// /// `start_after` is the height of the header to start after, or `None` to start from the base + #[cfg(feature = "btc-lc")] #[returns(BtcHeadersResponse)] BtcHeaders { start_after: Option, @@ -140,15 +147,19 @@ pub enum QueryMsg { reverse: Option, }, /// BabylonBaseEpoch returns the base Babylon epoch stored in the contract + #[cfg(feature = "btc-lc")] #[returns(EpochResponse)] BabylonBaseEpoch {}, /// BabylonLastEpoch returns the last babylon finalized epoch stored in the contract + #[cfg(feature = "btc-lc")] #[returns(EpochResponse)] BabylonLastEpoch {}, /// BabylonEpoch returns the Babylon epoch stored in the contract, by epoch number. + #[cfg(feature = "btc-lc")] #[returns(EpochResponse)] BabylonEpoch { epoch_number: u64 }, /// BabylonCheckpoint returns the Babylon checkpoint stored in the contract, by epoch number. + #[cfg(feature = "btc-lc")] #[returns(EpochResponse)] BabylonCheckpoint { epoch_number: u64 }, /// CzLastHeader returns the last CZ epoch stored in the contract diff --git a/contracts/babylon/src/queries/mod.rs b/contracts/babylon/src/queries/mod.rs index c28791fa..92aa588a 100644 --- a/contracts/babylon/src/queries/mod.rs +++ b/contracts/babylon/src/queries/mod.rs @@ -1,38 +1,50 @@ -use crate::error::{BTCLightclientError, BabylonEpochChainError, CZHeaderChainError}; -use crate::msg::btc_header::{BtcHeaderResponse, BtcHeadersResponse}; +use crate::error::CZHeaderChainError; use crate::msg::cz_header::CzHeaderResponse; -use crate::msg::epoch::{CheckpointResponse, EpochResponse}; +#[cfg(feature = "btc-lc")] use crate::state::babylon_epoch_chain::{ get_base_epoch, get_checkpoint, get_epoch, get_last_finalized_epoch, }; +#[cfg(feature = "btc-lc")] use crate::state::btc_light_client::{ get_base_header, get_header, get_header_by_hash, get_headers, get_tip, }; use crate::state::config::{Config, CONFIG}; use crate::state::cz_header_chain::{get_cz_header, get_last_cz_header}; -use babylon_bitcoin::BlockHash; use cosmwasm_std::{Deps, StdResult}; -use std::str::FromStr; + +#[cfg(feature = "btc-lc")] +use { + crate::error::{BTCLightclientError, BabylonEpochChainError}, + crate::msg::btc_header::BtcHeaderResponse, + crate::msg::btc_header::BtcHeadersResponse, + crate::msg::epoch::{CheckpointResponse, EpochResponse}, + babylon_bitcoin::BlockHash, + std::str::FromStr, +}; pub fn config(deps: Deps) -> StdResult { CONFIG.load(deps.storage) } +#[cfg(feature = "btc-lc")] pub fn btc_base_header(deps: Deps) -> Result { let btc_header_info = get_base_header(deps.storage)?; BtcHeaderResponse::try_from(&btc_header_info) } +#[cfg(feature = "btc-lc")] pub fn btc_tip_header(_deps: Deps) -> Result { let btc_header_info = get_tip(_deps.storage)?; BtcHeaderResponse::try_from(&btc_header_info) } +#[cfg(feature = "btc-lc")] pub fn btc_header(deps: Deps, height: u32) -> Result { let btc_header_info = get_header(deps.storage, height)?; BtcHeaderResponse::try_from(&btc_header_info) } +#[cfg(feature = "btc-lc")] pub fn btc_header_by_hash( deps: Deps, hash: &str, @@ -42,6 +54,7 @@ pub fn btc_header_by_hash( BtcHeaderResponse::try_from(&btc_header_info) } +#[cfg(feature = "btc-lc")] pub fn btc_headers( deps: Deps, start_after: Option, @@ -58,16 +71,19 @@ pub fn btc_headers( }) } +#[cfg(feature = "btc-lc")] pub fn babylon_base_epoch(deps: Deps) -> Result { let epoch = get_base_epoch(deps.storage)?; Ok(EpochResponse::from(&epoch)) } +#[cfg(feature = "btc-lc")] pub fn babylon_last_epoch(deps: Deps) -> Result { let epoch = get_last_finalized_epoch(deps.storage)?; Ok(EpochResponse::from(&epoch)) } +#[cfg(feature = "btc-lc")] pub fn babylon_epoch( deps: Deps, epoch_number: u64, @@ -76,6 +92,7 @@ pub fn babylon_epoch( Ok(EpochResponse::from(&epoch)) } +#[cfg(feature = "btc-lc")] pub fn babylon_checkpoint( deps: Deps, epoch_number: u64, @@ -94,13 +111,16 @@ pub(crate) fn cz_header(deps: Deps, height: u64) -> Result Vec { // https://github.com/babylonlabs-io/babylon/blob/8638c950fd2de1ac5dc69a8b9f710c1fa720c155/x/epoching/types/keys.go#L21 let mut epoch_info_key = [0x11].to_vec(); @@ -16,6 +20,7 @@ pub fn get_epoch_info_key(epoch_number: u64) -> Vec { epoch_info_key } +#[cfg(feature = "btc-lc")] pub fn get_valset_key(epoch_number: u64) -> Vec { // https://github.com/babylonlabs-io/babylon/blob/8638c950fd2de1ac5dc69a8b9f710c1fa720c155/x/checkpointing/types/keys.go#L28 let mut epoch_valset_key = [0x03].to_vec(); diff --git a/contracts/babylon/src/utils/mod.rs b/contracts/babylon/src/utils/mod.rs index 7a2c58f5..c8124a29 100644 --- a/contracts/babylon/src/utils/mod.rs +++ b/contracts/babylon/src/utils/mod.rs @@ -1,8 +1,12 @@ +#[cfg(feature = "btc-lc")] mod bitcoin; +#[cfg(feature = "btc-lc")] mod bls; mod cosmos_store; mod ics23_commitment; +#[cfg(feature = "btc-lc")] pub mod babylon_epoch_chain; +#[cfg(feature = "btc-lc")] pub mod btc_light_client; pub mod cz_header_chain; diff --git a/contracts/babylon/tests/integration.rs b/contracts/babylon/tests/integration.rs index dbe78dde..a6074306 100644 --- a/contracts/babylon/tests/integration.rs +++ b/contracts/babylon/tests/integration.rs @@ -16,19 +16,24 @@ //! //... //! }); //! 4. Anywhere you see query(&deps, ...) you must replace it with query(&mut deps, ...) +#[cfg(feature = "btc-lc")] +use cosmwasm_std::from_json; use cosmwasm_std::testing::{message_info, mock_ibc_channel_open_try}; -use cosmwasm_std::{from_json, Addr, ContractResult, IbcOrder, Response}; +use cosmwasm_std::{Addr, ContractResult, IbcOrder, Response}; use cosmwasm_vm::testing::{ - execute, ibc_channel_open, instantiate, mock_env, mock_info, mock_instance, - mock_instance_with_gas_limit, query, MockApi, MockQuerier, MockStorage, + ibc_channel_open, instantiate, mock_env, mock_instance, mock_instance_with_gas_limit, MockApi, + MockQuerier, MockStorage, }; use cosmwasm_vm::Instance; -use test_utils::{get_btc_lc_fork_msg, get_btc_lc_mainchain_resp}; +#[cfg(feature = "btc-lc")] +use test_utils::get_btc_lc_fork_msg; +use test_utils::get_btc_lc_mainchain_resp; -use babylon_bindings::BabylonMsg; use babylon_contract::ibc::IBC_VERSION; -use babylon_contract::msg::btc_header::{BtcHeader, BtcHeadersResponse}; -use babylon_contract::msg::contract::{ExecuteMsg, InstantiateMsg}; +use babylon_contract::msg::btc_header::BtcHeader; +#[cfg(feature = "btc-lc")] +use babylon_contract::msg::contract::ExecuteMsg; +use babylon_contract::msg::contract::InstantiateMsg; static BABYLON_CONTRACT_WASM: &[u8] = include_bytes!("../../../artifacts/babylon_contract.wasm"); /// Wasm size limit: https://github.com/CosmWasm/wasmd/blob/main/x/wasm/types/validation.go#L24-L25 @@ -70,10 +75,12 @@ pub fn get_main_msg_test_headers() -> Vec { } #[track_caller] +#[cfg(feature = "btc-lc")] fn get_fork_msg_test_headers() -> Vec { let testdata = get_btc_lc_fork_msg(); let resp: ExecuteMsg = from_json(testdata).unwrap(); match resp { + #[cfg(feature = "btc-lc")] ExecuteMsg::BtcHeaders { headers } => headers, ExecuteMsg::Slashing { .. } => unreachable!("unexpected slashing message"), } @@ -128,6 +135,7 @@ fn enforce_version_in_handshake() { } #[test] +#[cfg(feature = "btc-lc")] fn btc_headers_works() { let mut deps = setup(); let env = mock_env(); @@ -143,6 +151,7 @@ fn btc_headers_works() { } #[test] +#[cfg(feature = "btc-lc")] fn btc_headers_fork_works() { let mut deps = setup(); let env = mock_env(); @@ -168,6 +177,7 @@ fn btc_headers_fork_works() { } #[test] +#[cfg(feature = "btc-lc")] fn btc_headers_query_works() { let mut deps = setup(); let env = mock_env(); diff --git a/contracts/btc-finality/Cargo.toml b/contracts/btc-finality/Cargo.toml index 45e700ee..26769a72 100644 --- a/contracts/btc-finality/Cargo.toml +++ b/contracts/btc-finality/Cargo.toml @@ -27,6 +27,7 @@ cranelift = ["cosmwasm-vm/cranelift"] library = [] # feature for enabling the full validation full-validation = [ "btc-staking/full-validation" ] +btc-lc = ["babylon-contract/btc-lc" ] [dependencies] babylon-apis = { path = "../../packages/apis" } diff --git a/contracts/btc-staking/Cargo.toml b/contracts/btc-staking/Cargo.toml index f0e0486d..5940c0da 100644 --- a/contracts/btc-staking/Cargo.toml +++ b/contracts/btc-staking/Cargo.toml @@ -35,6 +35,7 @@ cranelift = ["cosmwasm-vm/cranelift"] library = [] # feature for enabling the full validation full-validation = [] +btc-lc = ["babylon-contract/btc-lc" ] [dependencies] babylon-apis = { path = "../../packages/apis" } diff --git a/contracts/btc-staking/src/staking.rs b/contracts/btc-staking/src/staking.rs index d8e8d1a5..0b63c5fd 100644 --- a/contracts/btc-staking/src/staking.rs +++ b/contracts/btc-staking/src/staking.rs @@ -23,8 +23,9 @@ use babylon_apis::btc_staking_api::{ use babylon_apis::Validate; use babylon_bindings::BabylonMsg; +#[cfg(feature = "btc-lc")] use babylon_contract::msg::btc_header::BtcHeaderResponse; - +#[cfg(feature = "btc-lc")] use babylon_contract::msg::contract::QueryMsg as BabylonQueryMsg; /// handle_btc_staking handles the BTC staking operations @@ -367,7 +368,15 @@ pub(crate) fn slash_finality_provider( // Set BTC slashing height (if available from the babylon contract) // FIXME: Turn this into a hard error // return fmt.Errorf("failed to get current BTC tip") - let btc_height = get_btc_tip_height(&deps).unwrap_or_default(); + let btc_height; + #[cfg(feature = "btc-lc")] + { + btc_height = get_btc_tip_height(&deps).unwrap_or_default(); + } + #[cfg(not(feature = "btc-lc"))] + { + btc_height = 1; // Unsupported BTC light client. Just set to non-zero value + } fp.slashed_btc_height = btc_height; // Record slashed event. The next `BeginBlock` will consume this event for updating the active @@ -388,8 +397,9 @@ pub(crate) fn slash_finality_provider( } /// get_btc_tip_height queries the Babylon contract for the latest BTC tip height +#[cfg(feature = "btc-lc")] fn get_btc_tip_height(deps: &DepsMut) -> Result { - // Get the BTC tip from the babylon contract through a raw query + // Get the BTC tip from the babylon contract through a query let babylon_addr = CONFIG.load(deps.storage)?.babylon; // Query the Babylon contract