Repository: LNP-BP/client_side_validation (language: rust)

Issue:
Two anchors randomly fail to merge with ~10% probability
Details: https://github.com/RGB-WG/rgb-node/issues/208


Discussion / hints:

Fix patch:
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
index 97c7dedf..d309edc6 100644
--- a/.github/FUNDING.yml
+++ b/.github/FUNDING.yml
@@ -1,3 +1,3 @@
 # These are supported funding model platforms
 
-github: [dr-orlovsky]
+github: [lnp-bp, dr-orlovsky]
diff --git a/Cargo.lock b/Cargo.lock
index 0025e6f7..031e7219 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -40,9 +40,9 @@ dependencies = [
 
 [[package]]
 name = "amplify_derive"
-version = "2.11.2"
+version = "2.11.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bcd9d6315c0fb32fb125a50992f64bca686a7012e8b897316cb8e30b0294315c"
+checksum = "1c3de270e75f27a4468a7c344070109046656e85cb522141f7d40ab4b83803ac"
 dependencies = [
  "amplify_syn",
  "proc-macro2",
@@ -81,25 +81,15 @@ dependencies = [
 
 [[package]]
 name = "anyhow"
-version = "1.0.65"
+version = "1.0.66"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "98161a4e3e2184da77bb14f02184cdd111e83bbbcc9979dfee3c44b9a85f5602"
-
-[[package]]
-name = "arrayvec"
-version = "0.3.25"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "06f59fe10306bb78facd90d28c2038ad23ffaaefa85bac43c8a434cde383334f"
-dependencies = [
- "nodrop",
- "odds",
-]
+checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6"
 
 [[package]]
 name = "async-trait"
-version = "0.1.57"
+version = "0.1.58"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "76464446b8bc32758d7e88ee1a804d9914cd9b1cb264c029899680b0be29826f"
+checksum = "1e805d94e6b5001b651426cf4cd446b1ab5f319d27bab5c644f61de0a804360c"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -129,9 +119,9 @@ checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445"
 
 [[package]]
 name = "bitcoin"
-version = "0.29.1"
+version = "0.29.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9cb36de3b18ad25f396f9168302e36fb7e1e8923298ab3127da252d288d5af9d"
+checksum = "0694ea59225b0c5f3cb405ff3f670e4828358ed26aec49dc352f730f0cb1a8a3"
 dependencies = [
  "bech32",
  "bitcoin_hashes",
@@ -153,20 +143,11 @@ version = "1.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
 
-[[package]]
-name = "block-buffer"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
-dependencies = [
- "generic-array",
-]
-
 [[package]]
 name = "bumpalo"
-version = "3.11.0"
+version = "3.11.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d"
+checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba"
 
 [[package]]
 name = "byteorder"
@@ -176,9 +157,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
 
 [[package]]
 name = "cc"
-version = "1.0.73"
+version = "1.0.76"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
+checksum = "76a284da2e6fe2092f2353e51713435363112dfd60030e22add80be333fb928f"
 
 [[package]]
 name = "cfg-if"
@@ -188,9 +169,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
 [[package]]
 name = "chrono"
-version = "0.4.22"
+version = "0.4.23"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bfd4d1b31faaa3a89d7934dbded3111da0d2ef28e3ebccdb4f0179f5929d1ef1"
+checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f"
 dependencies = [
  "iana-time-zone",
  "js-sys",
@@ -203,31 +184,31 @@ dependencies = [
 
 [[package]]
 name = "client_side_validation"
-version = "0.9.0"
+version = "0.9.0-rc.1"
 dependencies = [
- "async-trait",
  "commit_verify",
  "single_use_seals",
  "strict_encoding",
 ]
 
 [[package]]
-name = "cloudabi"
-version = "0.0.3"
+name = "codespan-reporting"
+version = "0.11.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
+checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e"
 dependencies = [
- "bitflags",
+ "termcolor",
+ "unicode-width",
 ]
 
 [[package]]
 name = "commit_verify"
-version = "0.9.0"
+version = "0.9.0-rc.1"
 dependencies = [
  "amplify",
  "bitcoin_hashes",
- "grin_secp256k1zkp",
- "rand 0.8.5",
+ "lnpbp_secp256k1zkp",
+ "rand",
  "serde",
  "serde_with",
  "strict_encoding",
@@ -261,15 +242,6 @@ version = "0.8.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
 
-[[package]]
-name = "cpufeatures"
-version = "0.2.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320"
-dependencies = [
- "libc",
-]
-
 [[package]]
 name = "crunchy"
 version = "0.2.2"
@@ -289,6 +261,50 @@ dependencies = [
  "zeroize",
 ]
 
+[[package]]
+name = "cxx"
+version = "1.0.81"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97abf9f0eca9e52b7f81b945524e76710e6cb2366aead23b7d4fbf72e281f888"
+dependencies = [
+ "cc",
+ "cxxbridge-flags",
+ "cxxbridge-macro",
+ "link-cplusplus",
+]
+
+[[package]]
+name = "cxx-build"
+version = "1.0.81"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7cc32cc5fea1d894b77d269ddb9f192110069a8a9c1f1d441195fba90553dea3"
+dependencies = [
+ "cc",
+ "codespan-reporting",
+ "once_cell",
+ "proc-macro2",
+ "quote",
+ "scratch",
+ "syn",
+]
+
+[[package]]
+name = "cxxbridge-flags"
+version = "1.0.81"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ca220e4794c934dc6b1207c3b42856ad4c302f2df1712e9f8d2eec5afaacf1f"
+
+[[package]]
+name = "cxxbridge-macro"
+version = "1.0.81"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b846f081361125bfc8dc9d3940c84e1fd83ba54bbca7b17cd29483c828be0704"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
 [[package]]
 name = "darling"
 version = "0.13.4"
@@ -360,32 +376,9 @@ dependencies = [
  "winapi",
 ]
 
-[[package]]
-name = "ed25519"
-version = "1.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e9c280362032ea4203659fc489832d0204ef09f247a0506f170dafcac08c369"
-dependencies = [
- "signature",
-]
-
-[[package]]
-name = "ed25519-dalek"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d"
-dependencies = [
- "curve25519-dalek",
- "ed25519",
- "rand 0.7.3",
- "serde",
- "sha2",
- "zeroize",
-]
-
 [[package]]
 name = "encoding_derive_helpers"
-version = "0.9.0"
+version = "0.8.1"
 dependencies = [
  "amplify",
  "proc-macro2",
@@ -395,9 +388,9 @@ dependencies = [
 
 [[package]]
 name = "filetime"
-version = "0.2.17"
+version = "0.2.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e94a7bbaa59354bc20dd75b67f23e2797b4490e9d6928203fb105c79e448c86c"
+checksum = "4b9663d381d07ae25dc88dbdf27df458faa83a9b25336bcac83d5e452b5fc9d3"
 dependencies = [
  "cfg-if",
  "libc",
@@ -412,7 +405,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "cfcf0ed7fe52a17a03854ec54a9f76d6d84508d1c0e66bc1793301c73fc8493c"
 dependencies = [
  "byteorder",
- "rand 0.8.5",
+ "rand",
  "rustc-hex",
  "static_assertions",
 ]
@@ -423,12 +416,6 @@ version = "1.0.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
 
-[[package]]
-name = "fuchsia-cprng"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
-
 [[package]]
 name = "generic-array"
 version = "0.14.6"
@@ -461,31 +448,15 @@ dependencies = [
 
 [[package]]
 name = "getrandom"
-version = "0.2.7"
+version = "0.2.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
+checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
 dependencies = [
  "cfg-if",
  "libc",
  "wasi 0.11.0+wasi-snapshot-preview1",
 ]
 
-[[package]]
-name = "grin_secp256k1zkp"
-version = "0.7.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3af3c4c4829b3e2e7ee1d9a542833e4244912fbb887fabe44682558159b068a7"
-dependencies = [
- "arrayvec",
- "cc",
- "libc",
- "rand 0.5.6",
- "rustc-serialize",
- "serde",
- "serde_json",
- "zeroize",
-]
-
 [[package]]
 name = "half"
 version = "2.1.0"
@@ -533,17 +504,28 @@ checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0"
 
 [[package]]
 name = "iana-time-zone"
-version = "0.1.50"
+version = "0.1.53"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fd911b35d940d2bd0bea0f9100068e5b97b51a1cbe13d13382f132e0365257a0"
+checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765"
 dependencies = [
  "android_system_properties",
  "core-foundation-sys",
+ "iana-time-zone-haiku",
  "js-sys",
  "wasm-bindgen",
  "winapi",
 ]
 
+[[package]]
+name = "iana-time-zone-haiku"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca"
+dependencies = [
+ "cxx",
+ "cxx-build",
+]
+
 [[package]]
 name = "ident_case"
 version = "1.0.1"
@@ -583,9 +565,18 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
 
 [[package]]
 name = "libc"
-version = "0.2.134"
+version = "0.2.137"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89"
+
+[[package]]
+name = "link-cplusplus"
+version = "1.0.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "329c933548736bc49fd575ee68c89e8be4d260064184389a5b77517cddd99ffb"
+checksum = "9272ab7b96c9046fbc5bc56c06c117cb639fe2d509df0c421cad82d2915cf369"
+dependencies = [
+ "cc",
+]
 
 [[package]]
 name = "linked-hash-map"
@@ -593,6 +584,17 @@ version = "0.5.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
 
+[[package]]
+name = "lnpbp_secp256k1zkp"
+version = "0.9.0-rc.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1c6ba83e1b29ed1aca515dab06bdb3a9537101790950847a771069e8e3cb1262"
+dependencies = [
+ "cc",
+ "libc",
+ "rand",
+]
+
 [[package]]
 name = "log"
 version = "0.4.17"
@@ -610,9 +612,9 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
 
 [[package]]
 name = "miniscript"
-version = "8.0.0"
+version = "9.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f4975078076f0b7b914a3044ad7432d2a7fcec38edb855afdc672e24ca35b69"
+checksum = "123a10aae81d0712ecc09b780f6f0ae0b0f506a5c4c912974725760d59ba073e"
 dependencies = [
  "bitcoin",
 ]
@@ -642,12 +644,6 @@ dependencies = [
  "tiny-keccak",
 ]
 
-[[package]]
-name = "nodrop"
-version = "0.1.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb"
-
 [[package]]
 name = "num-integer"
 version = "0.1.45"
@@ -669,31 +665,19 @@ dependencies = [
 
 [[package]]
 name = "num_cpus"
-version = "1.13.1"
+version = "1.14.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
+checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5"
 dependencies = [
  "hermit-abi",
  "libc",
 ]
 
-[[package]]
-name = "odds"
-version = "0.2.26"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4eae0151b9dacf24fcc170d9995e511669a082856a91f958a2fe380bfab3fb22"
-
 [[package]]
 name = "once_cell"
-version = "1.15.0"
+version = "1.16.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1"
-
-[[package]]
-name = "opaque-debug"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
+checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
 
 [[package]]
 name = "paste"
@@ -703,15 +687,15 @@ checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1"
 
 [[package]]
 name = "ppv-lite86"
-version = "0.2.16"
+version = "0.2.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
+checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.46"
+version = "1.0.47"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "94e2ef8dbfc347b10c094890f778ee2e36ca9bb4262e86dc99cd217e35f3470b"
+checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"
 dependencies = [
  "unicode-ident",
 ]
@@ -725,32 +709,6 @@ dependencies = [
  "proc-macro2",
 ]
 
-[[package]]
-name = "rand"
-version = "0.5.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9"
-dependencies = [
- "cloudabi",
- "fuchsia-cprng",
- "libc",
- "rand_core 0.3.1",
- "winapi",
-]
-
-[[package]]
-name = "rand"
-version = "0.7.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
-dependencies = [
- "getrandom 0.1.16",
- "libc",
- "rand_chacha 0.2.2",
- "rand_core 0.5.1",
- "rand_hc",
-]
-
 [[package]]
 name = "rand"
 version = "0.8.5"
@@ -758,20 +716,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
 dependencies = [
  "libc",
- "rand_chacha 0.3.1",
+ "rand_chacha",
  "rand_core 0.6.4",
 ]
 
-[[package]]
-name = "rand_chacha"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
-dependencies = [
- "ppv-lite86",
- "rand_core 0.5.1",
-]
-
 [[package]]
 name = "rand_chacha"
 version = "0.3.1"
@@ -782,21 +730,6 @@ dependencies = [
  "rand_core 0.6.4",
 ]
 
-[[package]]
-name = "rand_core"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
-dependencies = [
- "rand_core 0.4.2",
-]
-
-[[package]]
-name = "rand_core"
-version = "0.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
-
 [[package]]
 name = "rand_core"
 version = "0.5.1"
@@ -812,16 +745,7 @@ version = "0.6.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
 dependencies = [
- "getrandom 0.2.7",
-]
-
-[[package]]
-name = "rand_hc"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
-dependencies = [
- "rand_core 0.5.1",
+ "getrandom 0.2.8",
 ]
 
 [[package]]
@@ -839,16 +763,16 @@ version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
 dependencies = [
- "getrandom 0.2.7",
+ "getrandom 0.2.8",
  "redox_syscall",
  "thiserror",
 ]
 
 [[package]]
 name = "regex"
-version = "1.6.0"
+version = "1.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
+checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a"
 dependencies = [
  "aho-corasick",
  "memchr",
@@ -857,9 +781,9 @@ dependencies = [
 
 [[package]]
 name = "regex-syntax"
-version = "0.6.27"
+version = "0.6.28"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
+checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
 
 [[package]]
 name = "rustc-hex"
@@ -867,12 +791,6 @@ version = "2.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6"
 
-[[package]]
-name = "rustc-serialize"
-version = "0.3.24"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
-
 [[package]]
 name = "rustfix"
 version = "0.6.1"
@@ -897,6 +815,12 @@ version = "1.0.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
 
+[[package]]
+name = "scratch"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c8132065adcfd6e02db789d9285a0deb2f3fcb04002865ab67d5fb103533898"
+
 [[package]]
 name = "sealed"
 version = "0.4.0"
@@ -911,9 +835,9 @@ dependencies = [
 
 [[package]]
 name = "secp256k1"
-version = "0.24.0"
+version = "0.24.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b7649a0b3ffb32636e60c7ce0d70511eda9c52c658cd0634e194d5a19943aeff"
+checksum = "d9512ffd81e3a3503ed401f79c33168b9148c75038956039166cd750eaa037c3"
 dependencies = [
  "bitcoin_hashes",
  "secp256k1-sys",
@@ -921,27 +845,27 @@ dependencies = [
 
 [[package]]
 name = "secp256k1-sys"
-version = "0.6.0"
+version = "0.6.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7058dc8eaf3f2810d7828680320acda0b25a288f6d288e19278e249bbf74226b"
+checksum = "83080e2c2fc1006e625be82e5d1eb6a43b7fd9578b617fcc55814daf286bba4b"
 dependencies = [
  "cc",
 ]
 
 [[package]]
 name = "serde"
-version = "1.0.145"
+version = "1.0.147"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b"
+checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.145"
+version = "1.0.147"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "81fa1584d3d1bcacd84c277a0dfe21f5b0f6accf4a23d04d4c6d61f1af522b4c"
+checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -950,9 +874,9 @@ dependencies = [
 
 [[package]]
 name = "serde_json"
-version = "1.0.85"
+version = "1.0.87"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44"
+checksum = "6ce777b7b150d76b9cf60d28b55f5847135a003f7d7350c6be7a773508ce7d45"
 dependencies = [
  "itoa",
  "ryu",
@@ -1003,28 +927,9 @@ dependencies = [
  "yaml-rust",
 ]
 
-[[package]]
-name = "sha2"
-version = "0.9.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800"
-dependencies = [
- "block-buffer",
- "cfg-if",
- "cpufeatures",
- "digest",
- "opaque-debug",
-]
-
-[[package]]
-name = "signature"
-version = "1.6.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c"
-
 [[package]]
 name = "single_use_seals"
-version = "0.9.0"
+version = "0.9.0-rc.1"
 dependencies = [
  "amplify_derive",
  "async-trait",
@@ -1038,18 +943,17 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
 
 [[package]]
 name = "strict_encoding"
-version = "0.9.0"
+version = "0.9.0-rc.3"
 dependencies = [
  "amplify",
  "bitcoin",
  "bitcoin_hashes",
  "chrono",
- "ed25519-dalek",
- "grin_secp256k1zkp",
  "half",
+ "lnpbp_secp256k1zkp",
  "miniscript",
  "monero",
- "rand 0.7.3",
+ "rand",
  "serde",
  "strict_encoding_derive",
  "strict_encoding_test",
@@ -1071,7 +975,7 @@ dependencies = [
 
 [[package]]
 name = "strict_encoding_test"
-version = "0.9.0"
+version = "0.9.0-rc.1"
 dependencies = [
  "amplify",
  "strict_encoding",
@@ -1101,27 +1005,15 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
 
 [[package]]
 name = "syn"
-version = "1.0.102"
+version = "1.0.103"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3fcd952facd492f9be3ef0d0b7032a6e442ee9b361d4acc2b1d0c4aaa5f613a1"
+checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d"
 dependencies = [
  "proc-macro2",
  "quote",
  "unicode-ident",
 ]
 
-[[package]]
-name = "synstructure"
-version = "0.12.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "unicode-xid",
-]
-
 [[package]]
 name = "term"
 version = "0.7.0"
@@ -1133,6 +1025,15 @@ dependencies = [
  "winapi",
 ]
 
+[[package]]
+name = "termcolor"
+version = "1.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
+dependencies = [
+ "winapi-util",
+]
+
 [[package]]
 name = "tester"
 version = "0.9.0"
@@ -1203,9 +1104,9 @@ checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987"
 
 [[package]]
 name = "unicode-ident"
-version = "1.0.4"
+version = "1.0.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd"
+checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
 
 [[package]]
 name = "unicode-segmentation"
@@ -1219,12 +1120,6 @@ version = "0.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
 
-[[package]]
-name = "unicode-xid"
-version = "0.2.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
-
 [[package]]
 name = "version_check"
 version = "0.9.4"
@@ -1319,6 +1214,15 @@ version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
 
+[[package]]
+name = "winapi-util"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
+dependencies = [
+ "winapi",
+]
+
 [[package]]
 name = "winapi-x86_64-pc-windows-gnu"
 version = "0.4.0"
@@ -1327,46 +1231,60 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
 
 [[package]]
 name = "windows-sys"
-version = "0.36.1"
+version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
+checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
 dependencies = [
+ "windows_aarch64_gnullvm",
  "windows_aarch64_msvc",
  "windows_i686_gnu",
  "windows_i686_msvc",
  "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
  "windows_x86_64_msvc",
 ]
 
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
+
 [[package]]
 name = "windows_aarch64_msvc"
-version = "0.36.1"
+version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
+checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
 
 [[package]]
 name = "windows_i686_gnu"
-version = "0.36.1"
+version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
+checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
 
 [[package]]
 name = "windows_i686_msvc"
-version = "0.36.1"
+version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
+checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
 
 [[package]]
 name = "windows_x86_64_gnu"
-version = "0.36.1"
+version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
+checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
 
 [[package]]
 name = "windows_x86_64_msvc"
-version = "0.36.1"
+version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
+checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"
 
 [[package]]
 name = "yaml-rust"
@@ -1382,18 +1300,3 @@ name = "zeroize"
 version = "1.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd"
-dependencies = [
- "zeroize_derive",
-]
-
-[[package]]
-name = "zeroize_derive"
-version = "1.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f8f187641dad4f680d25c4bfc4225b418165984179f26ca76ec4fb6441d3a17"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "synstructure",
-]
diff --git a/Cargo.toml b/Cargo.toml
index 1e11d972..cbf2829b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "client_side_validation"
-version = "0.9.0"
+version = "0.9.0-rc.1"
 license = "Apache-2.0"
 authors = ["Dr. Maxim Orlovsky <orlovsky@lnp-bp.org>"]
 description = "Client-side validation foundation library"
@@ -18,22 +18,19 @@ name = "client_side_validation"
 path = "src/lib.rs"
 
 [dependencies]
-strict_encoding = { version = "0.9.0", path = "./strict_encoding" }
-commit_verify = { version = "0.9.0", path = "./commit_verify" }
-single_use_seals = { version = "0.9.0", path = "./single_use_seals" }
-
-[dev-dependencies]
-async-trait = "0.1.51"
+strict_encoding = { version = "0.9.0-rc.1", path = "./strict_encoding" }
+commit_verify = { version = "0.9.0-rc.1", path = "./commit_verify" }
+single_use_seals = { version = "0.9.0-rc.1", path = "./single_use_seals" }
 
 [features]
 default = []
 all = ["serde", "rand", "bitcoin", "crypto", "async", "bulletproofs", "float"]
 async = ["single_use_seals/async"]
 rand = ["commit_verify/rand"]
-serde = ["commit_verify/serde"]
+serde = ["commit_verify/serde", "strict_encoding/serde"]
 bitcoin = ["strict_encoding/bitcoin", "strict_encoding/miniscript"]
 crypto = ["strict_encoding/crypto"]
-bulletproofs = ["commit_verify/bulletproofs"]
+bulletproofs = ["commit_verify/bulletproofs", "strict_encoding/lnpbp_secp256k1zkp"]
 float = ["strict_encoding/float"]
 
 [package.metadata.docs.rs]
diff --git a/commit_verify/Cargo.toml b/commit_verify/Cargo.toml
index 1cf0a4ee..24bb94c5 100644
--- a/commit_verify/Cargo.toml
+++ b/commit_verify/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "commit_verify"
-version = "0.9.0"
+version = "0.9.0-rc.1"
 license = "Apache-2.0"
 authors = ["Dr. Maxim Orlovsky <orlovsky@lnp-bp.org>"]
 description = "Commit-verify API for client-side validation"
@@ -19,11 +19,11 @@ path = "src/lib.rs"
 [dependencies]
 amplify = { version = "3.13.0", features = ["hex"] }
 bitcoin_hashes = "0.11.0"
-strict_encoding = { version = "0.9.0", path = "../strict_encoding" }
+strict_encoding = { version = "0.9.0-rc.1", path = "../strict_encoding" }
 rand = { version = "0.8.5", optional = true }
 serde_crate = { version = "1.0", package = "serde", optional = true }
-serde_with = { version = "1.14", optional = true }
-grin_secp256k1zkp = { version = "0.7", optional = true }
+serde_with = { version = "1.14.0", optional = true }
+lnpbp_secp256k1zkp = { version = "0.9.0-alpha.1", optional = true }
 
 [dev-dependencies]
 rand = "0.8.5"
@@ -32,7 +32,7 @@ rand = "0.8.5"
 default = []
 all = ["rand", "serde", "bulletproofs"]
 serde = ["serde_crate", "serde_with", "bitcoin_hashes/serde", "amplify/serde"]
-bulletproofs = ["grin_secp256k1zkp"]
+bulletproofs = ["lnpbp_secp256k1zkp"]
 
 [package.metadata.docs.rs]
 features = [ "all" ]
diff --git a/commit_verify/src/commit_encode.rs b/commit_verify/src/commit_encode.rs
index d3ec5040..bff581ba 100644
--- a/commit_verify/src/commit_encode.rs
+++ b/commit_verify/src/commit_encode.rs
@@ -226,12 +226,12 @@ pub mod strategies {
         type Strategy = UsingStrict;
     }
 
-    #[cfg(feature = "grin_secp256k1zkp")]
+    #[cfg(feature = "lnpbp_secp256k1zkp")]
     impl Strategy for secp256k1zkp::pedersen::Commitment {
         type Strategy = strategies::UsingStrict;
     }
 
-    #[cfg(feature = "grin_secp256k1zkp")]
+    #[cfg(feature = "lnpbp_secp256k1zkp")]
     impl Strategy for secp256k1zkp::pedersen::RangeProof {
         type Strategy = strategies::UsingHash<bitcoin_hashes::sha256::Hash>;
     }
diff --git a/commit_verify/src/convolve_commit.rs b/commit_verify/src/convolve_commit.rs
index 1f07de92..9d572102 100644
--- a/commit_verify/src/convolve_commit.rs
+++ b/commit_verify/src/convolve_commit.rs
@@ -135,7 +135,7 @@ where
 ///
 /// ```
 /// # use bitcoin_hashes::sha256::Midstate;
-/// # use secp256k1zkp::Secp256k1;
+/// # use lnpbp_secp256k1zkp::Secp256k1;
 /// # use commit_verify::CommitmentProtocol;
 ///
 /// // Uninstantiable type
diff --git a/commit_verify/src/embed_commit.rs b/commit_verify/src/embed_commit.rs
index 3d104129..5a2b3818 100644
--- a/commit_verify/src/embed_commit.rs
+++ b/commit_verify/src/embed_commit.rs
@@ -81,7 +81,7 @@ where
 ///
 /// ```
 /// # use bitcoin_hashes::sha256::Midstate;
-/// # use secp256k1zkp::Secp256k1;
+/// # use lnpbp_secp256k1zkp::Secp256k1;
 /// # use commit_verify::CommitmentProtocol;
 ///
 /// // Uninstantiable type
diff --git a/commit_verify/src/lib.rs b/commit_verify/src/lib.rs
index ce87624a..cab1c155 100644
--- a/commit_verify/src/lib.rs
+++ b/commit_verify/src/lib.rs
@@ -31,6 +31,8 @@ extern crate bitcoin_hashes;
 #[cfg(feature = "serde")]
 #[macro_use]
 extern crate serde_crate as serde;
+#[cfg(feature = "lnpbp_secp256k1zkp")]
+extern crate lnpbp_secp256k1zkp as secp256k1zkp;
 #[cfg(feature = "serde")]
 extern crate serde_with;
 
diff --git a/commit_verify/src/lnpbp4.rs b/commit_verify/src/lnpbp4.rs
index 9523df74..350d6418 100644
--- a/commit_verify/src/lnpbp4.rs
+++ b/commit_verify/src/lnpbp4.rs
@@ -44,6 +44,7 @@
 //!
 //! [LNPBP-4]: https://github.com/LNP-BP/LNPBPs/blob/master/lnpbp-0004.md
 
+use std::cmp::Ordering;
 use std::collections::{BTreeMap, BTreeSet};
 use std::fmt::Debug;
 use std::io::Write;
@@ -458,6 +459,10 @@ impl TreeNode {
         self.depth().unwrap_or(tree_depth)
     }
 
+    pub fn is_leaf(&self) -> bool {
+        matches!(self, TreeNode::CommitmentLeaf { .. })
+    }
+
     pub fn merkle_node_with(&self, depth: u8) -> MerkleNode {
         match self {
             TreeNode::ConcealedNode { hash, .. } => *hash,
@@ -794,36 +799,52 @@ impl MerkleBlock {
         let mut last_a = a.next();
         let mut last_b = b.next();
         while let (Some(n1), Some(n2)) = (last_a, last_b) {
-            if n1 == n2 {
-                cross_section.push(n1);
-                last_a = a.next();
-                last_b = b.next();
-            } else if n1.depth_or(self.depth) < n2.depth_or(self.depth) {
-                cross_section.push(n2);
-                cross_section.extend(b.by_ref().take_while(|n| {
-                    if n.depth_or(self.depth) > n1.depth_or(self.depth) {
-                        last_b = None;
-                        true
-                    } else {
-                        last_b = Some(*n);
-                        false
-                    }
-                }));
-                last_a = a.next();
-            } else if n1.depth_or(self.depth) > n2.depth_or(self.depth) {
-                cross_section.push(n1);
-                cross_section.extend(a.by_ref().take_while(|n| {
-                    if n.depth_or(self.depth) > n2.depth_or(self.depth) {
-                        last_a = None;
-                        true
-                    } else {
-                        last_a = Some(*n);
-                        false
+            let n1_depth = n1.depth_or(self.depth);
+            let n2_depth = n2.depth_or(self.depth);
+            match n1_depth.cmp(&n2_depth) {
+                Ordering::Equal if n1 == n2 => {
+                    cross_section.push(n1);
+                    last_a = a.next();
+                    last_b = b.next();
+                }
+                Ordering::Equal => {
+                    match (n1.is_leaf(), n2.is_leaf()) {
+                        (true, false) => cross_section.push(n1),
+                        (false, true) => cross_section.push(n2),
+                        // If two nodes are both leafs or concealed, but not
+                        // equal to each other it means that the provided blocks
+                        // are unrelated
+                        _ => return Err(UnrelatedProof),
                     }
-                }));
-                last_b = b.next();
-            } else {
-                unreachable!("broken merkle block merge-reveal algorithm")
+                    last_a = a.next();
+                    last_b = b.next();
+                }
+                Ordering::Less => {
+                    cross_section.push(n2);
+                    cross_section.extend(b.by_ref().take_while(|n| {
+                        if n.depth_or(self.depth) > n1_depth {
+                            last_b = None;
+                            true
+                        } else {
+                            last_b = Some(*n);
+                            false
+                        }
+                    }));
+                    last_a = a.next();
+                }
+                Ordering::Greater => {
+                    cross_section.push(n1);
+                    cross_section.extend(a.by_ref().take_while(|n| {
+                        if n.depth_or(self.depth) > n2_depth {
+                            last_a = None;
+                            true
+                        } else {
+                            last_a = Some(*n);
+                            false
+                        }
+                    }));
+                    last_b = b.next();
+                }
             }
         }
 
@@ -934,6 +955,8 @@ impl MerkleProof {
 
 #[cfg(test)]
 mod test {
+    use std::str::FromStr;
+
     use super::*;
     use crate::TryCommitVerify;
 
@@ -1171,4 +1194,80 @@ mod test {
             .unwrap();
         assert_eq!(orig_block, new_block);
     }
+
+    #[test]
+    fn test_merge_blocks() {
+        let mut block1 = MerkleBlock {
+            depth: 3,
+            cross_section: vec![
+                TreeNode::ConcealedNode {
+                    depth: 3,
+                    hash: MerkleNode::from_str("03e43c730e76e654a40fdc0b62940bb7382ed95d4e8124ba687b4ec470cd1f01").unwrap()
+                },
+                TreeNode::CommitmentLeaf {
+                    protocol_id: ProtocolId::from_str("391cfae9f7b23562826b3260831e92698c7ec43c49e7afeed8e83a1bd75bbce9").unwrap(),
+                    message: Message::from_str("72c7278c8337a0480aa343dae2e6e6e1aee6c7b3df7d88f150a21c82f2b373ac").unwrap()
+                },
+                TreeNode::ConcealedNode {
+                    depth: 2,
+                    hash: MerkleNode::from_str("d42b5b6f1d6cc564fea2258e5147f4dd07735fac5aafa4a8394feb75ed8e366d").unwrap()
+                },
+                TreeNode::ConcealedNode {
+                    depth: 1,
+                    hash: MerkleNode::from_str("5009030a186d268e698e184cf9e32607951ab81c6e3b42ecaf6ccf73a5ca0f2e").unwrap()
+                },
+            ],
+            entropy: None,
+        };
+
+        let block2 = MerkleBlock {
+            depth: 3,
+            cross_section: vec![
+                TreeNode::CommitmentLeaf {
+                    protocol_id: ProtocolId::from_str("f0f2fc11fa38f3fd6132f46d8044612fc73e26b769025edabbe1290af9851897").unwrap(),
+                    message: Message::from_str("c0abbb938d4da7ce3a25e704b5b41dbacc762afe45a536e7d0a962fb1b34413e").unwrap()
+                },
+                TreeNode::ConcealedNode {
+                    depth: 3,
+                    hash: MerkleNode::from_str("8fff224a68c261d62ab33d802182ff09d6332e9079fce71936ea414ed45ee782").unwrap()
+                },
+                TreeNode::ConcealedNode {
+                    depth: 2,
+                    hash: MerkleNode::from_str("d42b5b6f1d6cc564fea2258e5147f4dd07735fac5aafa4a8394feb75ed8e366d").unwrap()
+                },
+                TreeNode::ConcealedNode {
+                    depth: 1,
+                    hash: MerkleNode::from_str("5009030a186d268e698e184cf9e32607951ab81c6e3b42ecaf6ccf73a5ca0f2e").unwrap()
+                },
+            ],
+            entropy: None,
+        };
+
+        let expected = MerkleBlock {
+            depth: 3,
+            cross_section: vec![
+                TreeNode::CommitmentLeaf {
+                    protocol_id: ProtocolId::from_str("f0f2fc11fa38f3fd6132f46d8044612fc73e26b769025edabbe1290af9851897").unwrap(),
+                    message: Message::from_str("c0abbb938d4da7ce3a25e704b5b41dbacc762afe45a536e7d0a962fb1b34413e").unwrap()
+                },
+                TreeNode::CommitmentLeaf {
+                    protocol_id: ProtocolId::from_str("391cfae9f7b23562826b3260831e92698c7ec43c49e7afeed8e83a1bd75bbce9").unwrap(),
+                    message: Message::from_str("72c7278c8337a0480aa343dae2e6e6e1aee6c7b3df7d88f150a21c82f2b373ac").unwrap()
+                },
+                TreeNode::ConcealedNode {
+                    depth: 2,
+                    hash: MerkleNode::from_str("d42b5b6f1d6cc564fea2258e5147f4dd07735fac5aafa4a8394feb75ed8e366d").unwrap()
+                },
+                TreeNode::ConcealedNode {
+                    depth: 1,
+                    hash: MerkleNode::from_str("5009030a186d268e698e184cf9e32607951ab81c6e3b42ecaf6ccf73a5ca0f2e").unwrap()
+                },
+            ],
+            entropy: None,
+        };
+
+        block1.merge_reveal(block2).unwrap();
+
+        assert_eq!(block1, expected);
+    }
 }
diff --git a/single_use_seals/Cargo.toml b/single_use_seals/Cargo.toml
index 3e1d3430..4b7469c5 100644
--- a/single_use_seals/Cargo.toml
+++ b/single_use_seals/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "single_use_seals"
-version = "0.9.0"
+version = "0.9.0-rc.1"
 license = "Apache-2.0"
 authors = ["Dr. Maxim Orlovsky <orlovsky@lnp-bp.org>"]
 description = "Single-use-seals foundation API. For bitcoin-specific implementation check bp-seals"
diff --git a/strict_encoding/Cargo.toml b/strict_encoding/Cargo.toml
index a5f6b9c9..31525b71 100644
--- a/strict_encoding/Cargo.toml
+++ b/strict_encoding/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "strict_encoding"
-version = "0.9.0"
+version = "0.9.0-rc.2"
 license = "Apache-2.0"
 authors = ["Dr. Maxim Orlovsky <orlovsky@lnp-bp.org>"]
 description = "Strict encoding: deterministic binary serialization for networking & client-side validation"
@@ -22,24 +22,24 @@ crate-type = ["rlib", "staticlib"]
 amplify = { version = "3.13.0", features = ["proc_attr"] }
 strict_encoding_derive = { version = "0.9.0", path = "./derive", optional = true }
 bitcoin_hashes = "0.11.0" # We need this separately since bitcoin is an optional dependency
-bitcoin = { version = "0.29.1", optional = true }
-miniscript = { version = "8.0.0", optional = true }
-ed25519-dalek = { version = "1.0", optional = true }
-grin_secp256k1zkp = { version = "0.7", optional = true }
+bitcoin = { version = "0.29.2", optional = true }
+miniscript = { version = "9.0.0", optional = true }
+lnpbp_secp256k1zkp = { version = "0.9.0-rc.1", optional = true }
 chrono = { version = "0.4", optional = true }
 half = { version = "2.1", optional = true }
-serde = { version = "1.0", optional = true }
+serde = { version = "1.0", features = ["derive"], optional = true }
 monero = { version = "0.18", optional = true }
 
 [dev-dependencies]
-rand = "0.7"
+rand = "0.8.5" # We can't use more recent version due to ed25519-dalek limitations
+lnpbp_secp256k1zkp = { version = "0.9.0-rc.1", features = ["rand"] }
 amplify = { version = "3.13.0", features = ["proc_attr", "hex"] }
-strict_encoding_test = { version = "0.9.0", path = "./test_helpers" }
+strict_encoding_test = { version = "0.9.0-rc.1", path = "./test_helpers" }
 
 [features]
 default = ["chrono", "derive", "bitcoin"]
 all = ["float", "miniscript", "crypto", "chrono", "derive", "bitcoin", "serde", "monero"]
-crypto = ["ed25519-dalek", "grin_secp256k1zkp", "bitcoin"]
+crypto = ["lnpbp_secp256k1zkp", "bitcoin"]
 derive = ["strict_encoding_derive"]
 float = ["amplify/apfloat", "half"]
 
diff --git a/strict_encoding/README.md b/strict_encoding/README.md
index 471efe1f..2841af2f 100644
--- a/strict_encoding/README.md
+++ b/strict_encoding/README.md
@@ -76,7 +76,7 @@ feature flags:
 - `miniscript`: types defined in bitcoin Miniscript
 - `crypto`: non-bitcoin cryptographic primitives, which include Ed25519
   curve, X25519 signatures from `ed25519-dalek` library and pedersen
-  commitments + bulletproofs from `grin_secp256k1zkp` library. Encodings for
+  commitments + bulletproofs from `lnpbp_secp256k1zkp` library. Encodings for
   other cryptography-related types, such as Secp256k1 and hashes, are always
   included as a part of the library - see NB below.
 
diff --git a/strict_encoding/derive/Cargo.toml b/strict_encoding/derive/Cargo.toml
index daa4e95d..ae20e3ba 100644
--- a/strict_encoding/derive/Cargo.toml
+++ b/strict_encoding/derive/Cargo.toml
@@ -18,7 +18,7 @@ proc-macro = true
 [dependencies]
 syn = "1"
 proc-macro2 = "1"
-encoding_derive_helpers = { version = "0.9.0", path = "../derive_helpers" }
+encoding_derive_helpers = { version = "0.8.1", path = "../derive_helpers" }
 amplify_syn = "1.1.6"
 
 [dev-dependencies]
diff --git a/strict_encoding/derive_helpers/Cargo.toml b/strict_encoding/derive_helpers/Cargo.toml
index 777df694..290648c3 100644
--- a/strict_encoding/derive_helpers/Cargo.toml
+++ b/strict_encoding/derive_helpers/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "encoding_derive_helpers"
-version = "0.9.0"
+version = "0.8.1"
 license = "Apache-2.0"
 authors = ["Dr. Maxim Orlovsky <orlovsky@lnp-bp.org>"]
 description = "Helper functions for creating different encoding derivation macros"
diff --git a/strict_encoding/derive_helpers/src/decode.rs b/strict_encoding/derive_helpers/src/decode.rs
index 72897e6a..20b093c1 100644
--- a/strict_encoding/derive_helpers/src/decode.rs
+++ b/strict_encoding/derive_helpers/src/decode.rs
@@ -228,7 +228,7 @@ fn decode_enum_impl(
         let ident = &variant.ident;
         let value = match (encoding.value, encoding.by_order) {
             (Some(val), _) => val.to_token_stream(),
-            (None, true) => Index::from(order as usize).to_token_stream(),
+            (None, true) => Index::from(order).to_token_stream(),
             (None, false) => quote! { Self::#ident as #repr },
         };
 
diff --git a/strict_encoding/derive_helpers/src/encode.rs b/strict_encoding/derive_helpers/src/encode.rs
index d4bc9ea6..a2fac44c 100644
--- a/strict_encoding/derive_helpers/src/encode.rs
+++ b/strict_encoding/derive_helpers/src/encode.rs
@@ -251,7 +251,7 @@ fn encode_enum_impl(
         let ident = &variant.ident;
         let value = match (encoding.value, encoding.by_order) {
             (Some(val), _) => val.to_token_stream(),
-            (None, true) => Index::from(order as usize).to_token_stream(),
+            (None, true) => Index::from(order).to_token_stream(),
             (None, false) => quote! { Self::#ident },
         };
 
diff --git a/strict_encoding/src/collections.rs b/strict_encoding/src/collections.rs
index 99ddba12..8e011d3d 100644
--- a/strict_encoding/src/collections.rs
+++ b/strict_encoding/src/collections.rs
@@ -196,7 +196,7 @@ where
     T: StrictEncode,
 {
     fn strict_encode<E: io::Write>(&self, mut e: E) -> Result<usize, Error> {
-        let len = self.len() as usize;
+        let len = self.len();
         // We handle oversize problems at the level of `usize` value
         // serializaton
         let mut encoded = len.strict_encode(&mut e)?;
@@ -504,7 +504,7 @@ where
 {
     fn strict_decode<D: io::Read>(mut d: D) -> Result<Self, Error> {
         let len = usize::strict_decode(&mut d)?;
-        let mut data = Vec::<T>::with_capacity(len as usize);
+        let mut data = Vec::<T>::with_capacity(len);
         for _ in 0..len {
             data.push(T::strict_decode(&mut d)?);
         }
@@ -522,7 +522,7 @@ where
     T: StrictEncode + Eq + Ord + Hash + Debug,
 {
     fn strict_encode<E: io::Write>(&self, mut e: E) -> Result<usize, Error> {
-        let len = self.len() as usize;
+        let len = self.len();
         let mut encoded = len.strict_encode(&mut e)?;
         let mut vec: Vec<&T> = self.iter().collect();
         vec.sort();
@@ -543,7 +543,7 @@ where
 {
     fn strict_decode<D: io::Read>(mut d: D) -> Result<Self, Error> {
         let len = usize::strict_decode(&mut d)?;
-        let mut data = HashSet::<T>::with_capacity(len as usize);
+        let mut data = HashSet::<T>::with_capacity(len);
         for _ in 0..len {
             let val = T::strict_decode(&mut d)?;
             if data.contains(&val) {
@@ -566,7 +566,7 @@ where
     T: StrictEncode + Eq + Ord + Debug,
 {
     fn strict_encode<E: io::Write>(&self, mut e: E) -> Result<usize, Error> {
-        let len = self.len() as usize;
+        let len = self.len();
         let mut encoded = len.strict_encode(&mut e)?;
         let mut vec: Vec<&T> = self.iter().collect();
         vec.sort();
@@ -669,7 +669,7 @@ where
     V: StrictEncode + Clone,
 {
     fn strict_encode<E: io::Write>(&self, mut e: E) -> Result<usize, Error> {
-        let len = self.len() as usize;
+        let len = self.len();
         let encoded = len.strict_encode(&mut e)?;
 
         self.iter().try_fold(encoded, |mut acc, (key, val)| {
diff --git a/strict_encoding/src/crypto.rs b/strict_encoding/src/crypto.rs
index 6664d3fd..49aa3075 100644
--- a/strict_encoding/src/crypto.rs
+++ b/strict_encoding/src/crypto.rs
@@ -59,7 +59,7 @@ impl StrictDecode for ed25519_dalek::Signature {
     }
 }
 
-#[cfg(feature = "grin_secp256k1zkp")]
+#[cfg(feature = "lnpbp_secp256k1zkp")]
 impl StrictEncode for secp256k1zkp::Error {
     #[inline]
     fn strict_encode<E: io::Write>(&self, e: E) -> Result<usize, Error> {
@@ -80,7 +80,7 @@ impl StrictEncode for secp256k1zkp::Error {
     }
 }
 
-#[cfg(feature = "grin_secp256k1zkp")]
+#[cfg(feature = "lnpbp_secp256k1zkp")]
 impl StrictDecode for secp256k1zkp::Error {
     #[inline]
     fn strict_decode<D: io::Read>(d: D) -> Result<Self, Error> {
@@ -106,7 +106,7 @@ impl StrictDecode for secp256k1zkp::Error {
     }
 }
 
-#[cfg(feature = "grin_secp256k1zkp")]
+#[cfg(feature = "lnpbp_secp256k1zkp")]
 impl StrictEncode for secp256k1zkp::pedersen::Commitment {
     #[inline]
     fn strict_encode<E: io::Write>(&self, mut e: E) -> Result<usize, Error> {
@@ -114,7 +114,7 @@ impl StrictEncode for secp256k1zkp::pedersen::Commitment {
     }
 }
 
-#[cfg(feature = "grin_secp256k1zkp")]
+#[cfg(feature = "lnpbp_secp256k1zkp")]
 impl StrictDecode for secp256k1zkp::pedersen::Commitment {
     #[inline]
     fn strict_decode<D: io::Read>(mut d: D) -> Result<Self, Error> {
@@ -124,7 +124,7 @@ impl StrictDecode for secp256k1zkp::pedersen::Commitment {
     }
 }
 
-#[cfg(feature = "grin_secp256k1zkp")]
+#[cfg(feature = "lnpbp_secp256k1zkp")]
 impl StrictEncode for secp256k1zkp::pedersen::RangeProof {
     #[inline]
     fn strict_encode<E: io::Write>(&self, e: E) -> Result<usize, Error> {
@@ -132,7 +132,7 @@ impl StrictEncode for secp256k1zkp::pedersen::RangeProof {
     }
 }
 
-#[cfg(feature = "grin_secp256k1zkp")]
+#[cfg(feature = "lnpbp_secp256k1zkp")]
 impl StrictDecode for secp256k1zkp::pedersen::RangeProof {
     #[inline]
     fn strict_decode<D: io::Read>(d: D) -> Result<Self, Error> {
@@ -190,7 +190,7 @@ mod test {
     }
 
     #[test]
-    #[cfg(all(feature = "grin_secp256k1zkp", feature = "bitcoin"))]
+    #[cfg(all(feature = "lnpbp_secp256k1zkp", feature = "bitcoin"))]
     fn pedersen() {
         use std::str::FromStr;
 
@@ -215,7 +215,7 @@ mod test {
     }
 
     #[test]
-    #[cfg(feature = "grin_secp256k1zkp")]
+    #[cfg(feature = "lnpbp_secp256k1zkp")]
     fn bulletproof() {
         let secp = secp256k1zkp::Secp256k1::new();
         let blind = secp256k1zkp::SecretKey::new(
@@ -240,9 +240,9 @@ mod test {
         );
     }
 
-    /* TODO: #25 Uncomment this test once `grin_secp256k1zkp::Error` impl `Ord`
+    /* TODO: #25 Uncomment this test once `lnpbp_secp256k1zkp::Error` impl `Ord`
     #[test]
-    #[cfg(feature = "grin_secp256k1zkp")]
+    #[cfg(feature = "lnpbp_secp256k1zkp")]
     fn error_encoding() {
         test_encoding_enum_u8_exhaustive!(crate => secp256k1zkp::Error;
             secp256k1zkp::Error::IncapableContext => 0u8,
diff --git a/strict_encoding/src/lib.rs b/strict_encoding/src/lib.rs
index 5e23c19b..e6a90bc3 100644
--- a/strict_encoding/src/lib.rs
+++ b/strict_encoding/src/lib.rs
@@ -44,9 +44,9 @@
 //! - `miniscript`: types defined in bitcoin Miniscript
 //! - `crypto`: non-bitcoin cryptographic primitives, which include Ed25519
 //!   curve, X25519 signatures from `ed25519-dalek` library and pedersen
-//!   commitments + bulletproofs from `grin_secp256k1zkp` library. Encodings for
-//!   other cryptography-related types, such as Secp256k1 and hashes, are always
-//!   included as a part of the library - see NB below.
+//!   commitments + bulletproofs from `lnpbp_secp256k1zkp` library. Encodings
+//!   for other cryptography-related types, such as Secp256k1 and hashes, are
+//!   always included as a part of the library - see NB below.
 //!
 //! NB: this crate requires `bitcoin` as an upstream dependency since many of
 //!     strict-encoded formats are standardized as using *bitcoin consensus
@@ -65,6 +65,8 @@ extern crate strict_encoding_test;
 #[cfg(feature = "serde")]
 #[macro_use]
 extern crate serde;
+#[cfg(feature = "lnpbp_secp256k1zkp")]
+extern crate lnpbp_secp256k1zkp as secp256k1zkp;
 
 #[macro_use]
 mod macros;
diff --git a/strict_encoding/src/miniscript.rs b/strict_encoding/src/miniscript.rs
index 6fd1f98b..73f7c96e 100644
--- a/strict_encoding/src/miniscript.rs
+++ b/strict_encoding/src/miniscript.rs
@@ -193,8 +193,8 @@ where
                 let vec1 = Vec::<u8>::strict_decode(&mut d)?;
                 let vec2 = Vec::<u8>::strict_decode(&mut d)?;
                 Ok(TapTree::Tree(
-                    Arc::new(TapTree::strict_deserialize(&vec1)?),
-                    Arc::new(TapTree::strict_deserialize(&vec2)?),
+                    Arc::new(TapTree::strict_deserialize(vec1)?),
+                    Arc::new(TapTree::strict_deserialize(vec2)?),
                 ))
             }
             wrong => Err(Error::EnumValueNotKnown("TapTree", wrong as usize)),
diff --git a/strict_encoding/src/pointers.rs b/strict_encoding/src/pointers.rs
index fc88c94e..96390b5c 100644
--- a/strict_encoding/src/pointers.rs
+++ b/strict_encoding/src/pointers.rs
@@ -160,7 +160,7 @@ pub mod test {
     fn test_encode_decode() {
         gen_strings().into_iter().for_each(|s| {
             let r = strict_serialize(&s).unwrap();
-            let p: String = strict_deserialize(&r).unwrap();
+            let p: String = strict_deserialize(r).unwrap();
             assert_eq!(s, p);
         })
     }
@@ -171,7 +171,7 @@ pub mod test {
         gen_strings().into_iter().for_each(|s| {
             let mut r = strict_serialize(&s).unwrap();
             r.extend_from_slice("data".as_ref());
-            let _: String = strict_deserialize(&r).unwrap();
+            let _: String = strict_deserialize(r).unwrap();
         })
     }
 
diff --git a/strict_encoding/src/primitives.rs b/strict_encoding/src/primitives.rs
index d87e1ce0..9b328d30 100644
--- a/strict_encoding/src/primitives.rs
+++ b/strict_encoding/src/primitives.rs
@@ -308,7 +308,12 @@ mod _chrono {
     impl StrictDecode for NaiveDateTime {
         #[inline]
         fn strict_decode<D: io::Read>(d: D) -> Result<Self, Error> {
-            Ok(Self::from_timestamp(i64::strict_decode(d)?, 0))
+            let secs = i64::strict_decode(d)?;
+            Self::from_timestamp_opt(secs, 0).ok_or_else(|| {
+                Error::DataIntegrityError(s!(
+                    "number of seconds in timestamp exceeds UNIX limit"
+                ))
+            })
         }
     }
 
@@ -474,7 +479,8 @@ pub mod test {
         assert_eq!(ser.len(), 8);
 
         let naive = utc.naive_utc();
-        let naive = NaiveDateTime::from_timestamp(naive.timestamp(), 0);
+        let naive =
+            NaiveDateTime::from_timestamp_opt(naive.timestamp(), 0).unwrap();
         assert_eq!(strict_deserialize(&ser), Ok(naive));
 
         let ser = naive.strict_serialize().unwrap();


Test patch:
diff --git a/strict_encoding/test_helpers/Cargo.toml b/strict_encoding/test_helpers/Cargo.toml
index 933f42b1..ca671fae 100644
--- a/strict_encoding/test_helpers/Cargo.toml
+++ b/strict_encoding/test_helpers/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "strict_encoding_test"
-version = "0.9.0"
+version = "0.9.0-rc.1"
 license = "Apache-2.0"
 authors = ["Dr. Maxim Orlovsky <orlovsky@lnp-bp.org>"]
 description = "Helper functions for testing strict encodings"
@@ -16,4 +16,4 @@ rust-version = "1.59.0"
 
 [dependencies]
 amplify = "3.13.0"
-strict_encoding = { version = "0.9.0", path = ".." }
+strict_encoding = { version = "0.9.0-rc.1", path = ".." }