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

Issue:
Implement resolve_seal_issues
https://github.com/LNP-BP/client_side_validation/blob/5e872055dc8563b24055913a4bb23eb707ae0226/src/api.rs#L239-L251


Discussion / hints:

Fix patch:
diff --git a/Cargo.lock b/Cargo.lock
index a1a68089..c5c3c6dc 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -103,6 +103,15 @@ version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
 
+[[package]]
+name = "base64-compat"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a8d4d2746f89841e49230dd26917df1876050f95abafafbe34f47cb534b88d7"
+dependencies = [
+ "byteorder",
+]
+
 [[package]]
 name = "bech32"
 version = "0.8.1"
@@ -115,6 +124,7 @@ version = "0.28.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "05bba324e6baf655b882df672453dbbc527bc938cadd27750ae510aaccc3a66a"
 dependencies = [
+ "base64-compat",
  "bech32",
  "bitcoin_hashes",
  "secp256k1",
@@ -129,6 +139,48 @@ dependencies = [
  "serde",
 ]
 
+[[package]]
+name = "bitcoin_hd"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d080f88bdc1827e569d305765bc407a7cc9b5d464d25e1d36fe2294f274507f"
+dependencies = [
+ "amplify",
+ "bitcoin",
+ "miniscript",
+ "slip132",
+ "strict_encoding 1.8.11 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "bitcoin_onchain"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7e9453484e54cffe3f9f0075b0ee862950621185475aecae8b2eef97ad4ff9d2"
+dependencies = [
+ "amplify",
+ "bitcoin",
+ "bitcoin_hd",
+ "chrono",
+ "descriptors",
+ "miniscript",
+ "strict_encoding 1.8.11 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "bitcoin_scripts"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dcfdf7d9a0b3af94a35b92daa2e3f1c5b02b7293b5938a4cd4cc426852e52249"
+dependencies = [
+ "amplify",
+ "bitcoin",
+ "miniscript",
+ "secp256k1",
+ "stability",
+ "strict_encoding 1.8.11 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "bitflags"
 version = "1.3.2"
@@ -182,7 +234,7 @@ dependencies = [
  "async-trait",
  "commit_verify",
  "single_use_seals",
- "strict_encoding",
+ "strict_encoding 1.8.11",
 ]
 
 [[package]]
@@ -201,10 +253,11 @@ dependencies = [
  "amplify",
  "bitcoin_hashes",
  "grin_secp256k1zkp",
+ "psbt",
  "rand 0.8.5",
  "serde",
  "serde_with",
- "strict_encoding",
+ "strict_encoding 1.8.11",
 ]
 
 [[package]]
@@ -286,6 +339,21 @@ dependencies = [
  "syn",
 ]
 
+[[package]]
+name = "descriptors"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "36afa2baa98f5205560c4e194c0f943546682b943bc96adbec54ed7e1bbf5cab"
+dependencies = [
+ "amplify",
+ "bitcoin",
+ "bitcoin_hd",
+ "bitcoin_scripts",
+ "chrono",
+ "miniscript",
+ "strict_encoding 1.8.11 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "diff"
 version = "0.1.12"
@@ -355,6 +423,18 @@ dependencies = [
  "syn",
 ]
 
+[[package]]
+name = "encoding_derive_helpers"
+version = "1.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc4ba8a88067b85c8714922db6e5f2af47b894d63b771dbb0c4d31d6607e9057"
+dependencies = [
+ "amplify",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
 [[package]]
 name = "filetime"
 version = "0.2.16"
@@ -598,6 +678,22 @@ dependencies = [
  "unicode-ident",
 ]
 
+[[package]]
+name = "psbt"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eebee19795c9b0e04dc3c34f77173b3715e21ae57cd9ec22bf17a08a90ffe004"
+dependencies = [
+ "amplify",
+ "bitcoin",
+ "bitcoin_hd",
+ "bitcoin_onchain",
+ "bitcoin_scripts",
+ "descriptors",
+ "miniscript",
+ "strict_encoding 1.8.11 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "quote"
 version = "1.0.18"
@@ -887,12 +983,32 @@ checksum = "f054c6c1a6e95179d6f23ed974060dcefb2d9388bb7256900badad682c499de4"
 
 [[package]]
 name = "single_use_seals"
-version = "0.7.0"
+version = "0.8.0"
 dependencies = [
  "amplify_derive",
  "async-trait",
 ]
 
+[[package]]
+name = "slip132"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "086f81f7be78373eb07e9879fa77e49d52416bde18778f675698c5c7da6b296c"
+dependencies = [
+ "amplify",
+ "bitcoin",
+]
+
+[[package]]
+name = "stability"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ebd1b177894da2a2d9120208c3386066af06a488255caabc5de8ddca22dbc3ce"
+dependencies = [
+ "quote",
+ "syn",
+]
+
 [[package]]
 name = "strict_encoding"
 version = "0.8.0"
@@ -907,10 +1023,24 @@ dependencies = [
  "miniscript",
  "rand 0.7.3",
  "serde",
- "strict_encoding_derive",
+ "strict_encoding_derive 1.7.6",
  "strict_encoding_test",
 ]
 
+[[package]]
+name = "strict_encoding"
+version = "1.8.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "acd582d614348ea8ff707ab58b145e8cb504a929219f3efc2492bed62d27c4bb"
+dependencies = [
+ "amplify",
+ "bitcoin",
+ "bitcoin_hashes",
+ "chrono",
+ "miniscript",
+ "strict_encoding_derive 1.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "strict_encoding_derive"
 version = "0.8.0"
@@ -918,19 +1048,31 @@ dependencies = [
  "amplify",
  "amplify_syn",
  "compiletest_rs",
- "encoding_derive_helpers",
+ "encoding_derive_helpers 1.7.6",
  "proc-macro2",
- "strict_encoding",
+ "strict_encoding 1.8.11",
  "strict_encoding_test",
  "syn",
 ]
 
+[[package]]
+name = "strict_encoding_derive"
+version = "1.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3bc7b868cb00c8861784b7f463c984c4b2ad20d1f23cec5997ad9cb41e559239"
+dependencies = [
+ "amplify_syn",
+ "encoding_derive_helpers 1.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2",
+ "syn",
+]
+
 [[package]]
 name = "strict_encoding_test"
 version = "0.8.0"
 dependencies = [
  "amplify",
- "strict_encoding",
+ "strict_encoding 1.8.11",
 ]
 
 [[package]]
diff --git a/Cargo.toml b/Cargo.toml
index 28629672..bed8ea9c 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -19,7 +19,7 @@ path = "src/lib.rs"
 [dependencies]
 strict_encoding = { version = "0.8.0", path = "./strict_encoding" }
 commit_verify = { version = "0.8.0", path = "./commit_verify" }
-single_use_seals = { version = "0.7.0", path = "./single_use_seals" }
+single_use_seals = { version = "0.8.0", path = "./single_use_seals" }
 
 [dev-dependencies]
 async-trait = "0.1.51"
diff --git a/README.md b/README.md
index e359ead9..5a77a193 100644
--- a/README.md
+++ b/README.md
@@ -116,7 +116,7 @@ libraries:
   [Pandora Core](https://pandoracore.com) – a very early prototypes and proofs 
   of concept applying client-side-validation to mimblewimble-types of 
   blockchains.
-- [Pandora timechain](https://github.com/pandora-network/timechain), an 
+- [Pandora sealchain](https://github.com/pandora-network/sealchain-rs), an 
   experimental blockchain of [Pandora Network](https://pandora.network), 
   playing with client-side-validation using modified bitcoin consensus rules, 
   extended with eltoo- and covenants-related functionality and with removed 
diff --git a/single_use_seals/Cargo.toml b/single_use_seals/Cargo.toml
index 66596213..d30cc563 100644
--- a/single_use_seals/Cargo.toml
+++ b/single_use_seals/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "single_use_seals"
-version = "0.7.0"
+version = "0.8.0"
 license = "Apache-2.0"
 authors = ["Dr. Maxim Orlovsky <orlovsky@pandoracore.com>"]
 description = "Single-use-seals foundation API. For bitcoin-specific implementation check bp-seals"
diff --git a/single_use_seals/README.md b/single_use_seals/README.md
index f98da76d..b9b738cd 100644
--- a/single_use_seals/README.md
+++ b/single_use_seals/README.md
@@ -10,20 +10,18 @@
 [![unsafe forbidden](https://img.shields.io/badge/unsafe-forbidden-success.svg)](https://github.com/rust-secure-code/safety-dance/)
 [![Apache-2 licensed](https://img.shields.io/crates/l/single_use_seals)](./LICENSE)
 
-This is an implementation of [LNPBP-4] multi-commitment standard and [LNPBP-9] 
-standard, defining to cryptographic commitment schemes used in 
-client-side-validation. It is a part of more generic [`client_side_validation`] 
-library covering other client-side-validation standards.
+This is an implementation of [LNPBP-8] single-use-seal abstraction. 
+Specifically, it provides a set of traits that allow to implement Peter's Todd 
+**single-use seal** paradigm. Information in this file partially contains 
+extracts from Peter's works listed in "Further reading" section.
 
-Client-side-validation is a paradigm for distributed computing, based on top of
-proof-of-publication/commitment medium layer, which may be a bitcoin blockchain
-or other type of distributed consensus system.
+The library is a part of more generic [`client_side_validation`] library 
+covering other client-side-validation standards. Client-side-validation is a 
+paradigm for distributed computing, based on top of proof-of-publication/
+commitment medium layer, which may be a bitcoin blockchain or other type of 
+distributed consensus system.
 
 The development of the library is supported by [LNP/BP Standards Association](https://lnp-bp.org).
-The original idea of client-side-validation was proposed by Peter Todd with its
-possible applications designed by Giacomo Zucco. It was shaped into a protocol-
-level design by Dr Maxim Orlovsky with a big input from the community and
-implemented by him as this set of libraries.
 
 
 ## Documentation
@@ -38,7 +36,7 @@ and [LNP/BP tech talks videos](https://www.youtube.com/channel/UCK_Q3xcQ-H3ERwAr
 
 ## Usage
 
-To use the library, you just need to reference a latest version, in 
+To use the library, you just need to reference the latest version, in 
 `[dependencies]` section of your project `Cargo.toml`.
 
 ```toml
@@ -52,6 +50,81 @@ including the current one.
 The library does not expose any feature flags and have only a single dependency
 on `amplify_derive` crate, also created and supported by the LNP/BP Association.
 
+## More information
+
+### Single-use-seals definition
+
+Analogous to the real-world, physical, single-use-seals used to secure
+shipping containers, a single-use-seal primitive is a unique object that can
+be closed over a message exactly once. In short, a single-use-seal is an
+abstract mechanism to prevent double-spends.
+
+A single-use-seal implementation supports two fundamental operations:
+* `Close(l,m) → w` — Close seal l over message m, producing a witness `w`.
+* `Verify(l,w,m) → bool` — Verify that the seal l was closed over message `m`.
+
+A single-use-seal implementation is secure if it is impossible for an
+attacker to cause the Verify function to return true for two distinct
+messages m1, m2, when applied to the same seal (it is acceptable, although
+non-ideal, for there to exist multiple witnesses for the same seal/message
+pair).
+
+Practical single-use-seal implementations will also obviously require some
+way of generating new single-use-seals:
+* `Gen(p)→l` — Generate a new seal basing on some seal definition data `p`.
+
+### Terminology
+
+**Single-use-seal**: a commitment to commit to some (potentially unknown)
+  message. The first commitment (i.e. single-use-seal) must be a
+  well-defined (i.e. fully specified and unequally identifiable
+  in some space, like in time/place or within a given formal informational
+  system).
+**Closing of a single-use-seal over message**: a fulfilment of the first
+  commitment: creation of the actual commitment to some message in a form
+  unequally defined by the seal.
+**Witness**: data produced with closing of a single use seal which are
+  required and sufficient for an independent party to verify that the seal
+  was indeed closed over a given message (i.e. the commitment to the message
+  had being created according to the seal definition).
+
+NB: It's important to note, that while its possible to deterministically
+  define was a given seal closed it yet may be not possible to find out
+  if the seal is open; i.e. seal status may be either "closed over message"
+  or "unknown". Some specific implementations of single-use-seals may define
+  procedure to deterministically prove that a given seal is not closed (i.e.
+  opened), however this is not a part of the specification and we should
+  not rely on the existence of such possibility in all cases.
+
+### Trait structure
+
+The module defines trait `SealProtocol` that can be used for
+implementation of single-use-seals with methods for seal close and
+verification. A type implementing this trait operates only with messages
+(which is represented by any type that implements `AsRef<[u8]>`,i.e. can be
+represented as a sequence of bytes) and witnesses (which is represented by
+an associated type `SealProtocol::Witness`). At the same time,
+`SealProtocol` can't define seals by itself.
+
+Seal protocol operates with a *seal medium *: a proof of publication medium
+on which the seals are defined.
+
+The module provides two options of implementing such medium: synchronous
+`SealProtocol` and asynchronous `SealProtocolAsync`.
+
+### Sample implementation
+
+Examples of implementations can be found in `bp::seals` module of `bp-core`
+crate.
+
+### Further reading
+
+* Peter Todd. Preventing Consensus Fraud with Commitments and
+  Single-Use-Seals.
+  <https://petertodd.org/2016/commitments-and-single-use-seals>.
+* Peter Todd. Scalable Semi-Trustless Asset Transfer via Single-Use-Seals
+  and Proof-of-Publication. 1. Single-Use-Seal Definition.
+  <https://petertodd.org/2017/scalable-single-use-seal-asset-transfer>
 
 ## Contributing
 
@@ -64,3 +137,4 @@ The libraries are distributed on the terms of Apache 2.0 opensource license.
 See [LICENCE](LICENSE) file for the license details.
 
 [`client_side_validation`]: https://crates.io/crates/client_side_validation
+[LNPBP-8]: https://github.com/LNP-BP/LNPBPs/blob/master/lnpbp-0008.md
diff --git a/single_use_seals/src/lib.rs b/single_use_seals/src/lib.rs
index 905c6898..6e9120b1 100644
--- a/single_use_seals/src/lib.rs
+++ b/single_use_seals/src/lib.rs
@@ -90,7 +90,8 @@
 //!
 //! ## Sample implementation
 //!
-//! Examples of implementations can be found in `bp::seals`.
+//! Examples of implementations can be found in `bp::seals` module of `bp-core`
+//! crate.
 //!
 //! ## Further reading
 //!
@@ -177,7 +178,7 @@ pub trait SealProtocol<Seal> {
 }
 
 /// Adds support for the seal close operation to [`SealProtocol`].
-pub trait SealClose<Seal>: SealProtocol<Seal> {
+pub trait CloseSeal<Seal>: SealProtocol<Seal> {
     /// Closes seal over a message, producing *witness*.
     ///
     /// NB: Closing of the seal MUST not change the internal state of the
@@ -185,21 +186,72 @@ pub trait SealClose<Seal>: SealProtocol<Seal> {
     /// into the returned Witness type.
     ///
     /// The witness _is not_ published by this method to the seal medium.
-    fn close(
+    fn close_seal(
         &mut self,
         seal: &Seal,
         over: &Self::Message,
     ) -> Result<Self::Witness, Self::Error>;
+
+    /// Closes number of related seals over the same message, producing a single
+    /// *witness*.
+    ///
+    /// NB: Closing of the seal MUST not change the internal state of the
+    /// seal itself; all the data produced by the process must be placed
+    /// into the returned Witness type.
+    ///
+    /// The witness _is not_ published by this method to the seal medium.
+    fn close_all_seals<'seal>(
+        &mut self,
+        seals: impl IntoIterator<Item = &'seal Seal>,
+        over: &Self::Message,
+    ) -> Result<Self::Witness, Self::Error>
+    where
+        Seal: 'seal;
+}
+
+/// Adds support to [`SealProtocol`] for merging seal close operation into an
+/// existing witness data (closing some other seals).
+pub trait MergeCloseSeal<Seal>: SealProtocol<Seal> {
+    /// Closes seal over a message, adding witness to some existing *witness*
+    /// container.
+    ///
+    /// NB: Closing of the seal MUST not change the internal state of the
+    /// seal itself; all the data produced by the process must be placed
+    /// into the returned Witness type.
+    ///
+    /// The witness _is not_ published by this method to the seal medium.
+    fn merge_close_seal(
+        &mut self,
+        seal: &Seal,
+        over: &Self::Message,
+        witness_proto: Self::Witness,
+    ) -> Result<Self::Witness, Self::Error>;
+
+    /// Closes number of related seals over the same message, adding witness to
+    /// some existing *witness* container.
+    ///
+    /// NB: Closing of the seal MUST not change the internal state of the
+    /// seal itself; all the data produced by the process must be placed
+    /// into the returned Witness type.
+    ///
+    /// The witness _is not_ published by this method to the seal medium.
+    fn merge_close_all_seals<'seal>(
+        &mut self,
+        seals: impl IntoIterator<Item = &'seal Seal>,
+        over: &Self::Message,
+    ) -> Result<Self::Witness, Self::Error>
+    where
+        Seal: 'seal;
 }
 
 /// Adds support for the seal verify operation to [`SealProtocol`].
-pub trait SealVerify<'seal, Seal>: SealProtocol<Seal>
+pub trait VerifySeal<'seal, Seal>: SealProtocol<Seal>
 where
     Seal: 'seal,
 {
     /// Verifies that the seal was indeed closed over the message with the
     /// provided seal closure witness.
-    fn verify(
+    fn verify_seal(
         &self,
         seal: &'seal Seal,
         msg: &Self::Message,
@@ -207,16 +259,17 @@ where
     ) -> Result<bool, Self::Error>;
 
     /// Performs batch verification of the seals. Default implementation
-    /// iterates through the seals and calls [`Self::verify`] for each of them,
-    /// returning `false` on first failure (not verifying the rest of seals).
-    fn verify_batch(
+    /// iterates through the seals and calls [`Self::verify_seal`] for each of
+    /// them, returning `false` on first failure (not verifying the rest of
+    /// seals).
+    fn verify_seal_all(
         &self,
         seals: impl IntoIterator<Item = &'seal Seal>,
         msg: &Self::Message,
         witness: &Self::Witness,
     ) -> Result<bool, Self::Error> {
         for seal in seals {
-            if !self.verify(seal, msg, witness)? {
+            if !self.verify_seal(seal, msg, witness)? {
                 return Ok(false);
             }
         }
@@ -289,7 +342,7 @@ where
 /// Adds support for the seal close operation to [`SealProtocolAsync`].
 #[cfg(feature = "async")]
 #[async_trait]
-pub trait SealCloseAsync<Seal>: SealProtocolAsync<Seal>
+pub trait CloseSealAsync<Seal>: SealProtocolAsync<Seal>
 where
     Seal: Sync + Send,
 {
@@ -300,23 +353,79 @@ where
     /// into the returned Witness type.
     ///
     /// The witness _is not_ published by this method to the seal medium.
-    async fn close_async(
+    async fn close_seal_async(
         &mut self,
         seal: &Seal,
         over: &Self::Message,
     ) -> Result<Self::Witness, Self::Error>;
+
+    /// Closes number of related seals over the same message, producing a single
+    /// *witness*.
+    ///
+    /// NB: Closing of the seal MUST not change the internal state of the
+    /// seal itself; all the data produced by the process must be placed
+    /// into the returned Witness type.
+    ///
+    /// The witness _is not_ published by this method to the seal medium.
+    async fn seal_close_all_async<'seal>(
+        &mut self,
+        seals: impl IntoIterator<Item = &'seal Seal>,
+        over: &Self::Message,
+    ) -> Result<Self::Witness, Self::Error>
+    where
+        Seal: 'seal;
+}
+
+/// Adds support to [`SealProtocolAsync`] for merging seal close operation into
+/// an existing witness data (closing some other seals).
+#[cfg(feature = "async")]
+#[async_trait]
+pub trait MergeCloseSealAsync<Seal>: SealProtocolAsync<Seal>
+where
+    Seal: Sync + Send,
+{
+    /// Closes seal over a message, adding witness to some existing *witness*
+    /// container.
+    ///
+    /// NB: Closing of the seal MUST not change the internal state of the
+    /// seal itself; all the data produced by the process must be placed
+    /// into the returned Witness type.
+    ///
+    /// The witness _is not_ published by this method to the seal medium.
+    async fn merge_close_seal_async(
+        &mut self,
+        seal: &Seal,
+        over: &Self::Message,
+        witness_proto: Self::Witness,
+    ) -> Result<Self::Witness, Self::Error>;
+
+    /// Closes number of related seals over the same message, adding witness to
+    /// some existing *witness* container.
+    ///
+    /// NB: Closing of the seal MUST not change the internal state of the
+    /// seal itself; all the data produced by the process must be placed
+    /// into the returned Witness type.
+    ///
+    /// The witness _is not_ published by this method to the seal medium.
+    async fn merge_close_all_seals_async<'seal>(
+        &mut self,
+        seals: impl IntoIterator<Item = &'seal Seal>,
+        over: &Self::Message,
+    ) -> Result<Self::Witness, Self::Error>
+    where
+        Seal: 'seal;
 }
 
 /// Adds support for the seal verify operation to [`SealProtocolAsync`].
 #[cfg(feature = "async")]
 #[async_trait]
-pub trait SealVerifyAsync<'seal, Seal>: SealProtocol<Seal>
+pub trait VerifySealAsync<'seal, Seal>: SealProtocol<Seal>
 where
     Seal: 'seal + Sync + Send,
 {
     /// Verifies that the seal was indeed closed over the message with the
     /// provided seal closure witness.
-    async fn verify_async(
+    async fn verify_seal_async(
         &self,
         seal: &'seal Seal,
         msg: &Self::Message,
@@ -324,10 +433,10 @@ where
     ) -> Result<bool, Self::Error>;
 
     /// Performs batch verification of the seals. Default implementation
-    /// iterates through the seals and calls [`Self::verify_async`] for each of
-    /// them, returning `false` on first failure (not verifying the rest of
-    /// seals).
-    async fn verify_async_batch<I>(
+    /// iterates through the seals and calls [`Self::verify_seal_async`] for
+    /// each of them, returning `false` on first failure (not verifying the
+    /// rest of seals).
+    async fn verify_all_seals_async<I>(
         &self,
         seals: I,
         msg: &Self::Message,
@@ -340,7 +449,7 @@ where
         I::IntoIter: Send,
     {
         for seal in seals {
-            if !self.verify_async(seal, msg, witness).await? {
+            if !self.verify_seal_async(seal, msg, witness).await? {
                 return Ok(false);
             }
         }
diff --git a/src/api.rs b/src/api.rs
index 24fdb90b..b4ec1868 100644
--- a/src/api.rs
+++ b/src/api.rs
@@ -241,20 +241,6 @@ where
             Validity::Valid
         }
     }
-
-    /// Method used to check whether seal resolution issues are resolved, for
-    /// instance allowing to try a different resolver, re-check after restored
-    /// network connectivity or after some time allowing unmined transactions to
-    /// be mined.
-    pub fn resolve_seal_issues<Resolver>(&mut self, _resolver: &mut Resolver)
-    where
-        Resolver: SealResolver<
-            <R::SealIssue as SealIssue>::Seal,
-            Error = R::SealIssue,
-        >,
-    {
-        todo!("#34 resolve_seal_issues")
-    }
 }
 
 /// This simple trait MUST be used by all top-level data structures implementing
@@ -263,9 +249,9 @@ where
 /// represented or accessed through a single structure; and MUST be able to
 /// deterministically validate this set giving an external validation function,
 /// that is able to provide validator with
-pub trait ClientSideValidate<'a>: ClientData
+pub trait ClientSideValidate<'client_data>: ClientData<'client_data>
 where
-    Self::ValidationItem: 'a,
+    Self::ValidationItem: 'client_data,
 {
     /// Data type for data sub-entries contained withing the current
     /// client-side-validated data item.
@@ -274,13 +260,16 @@ where
     /// entries, this may be a special enum type with a per-data-type variant.
     ///
     /// If the data do not contain internal data, set this type to `()`.
-    type ValidationItem: ClientData<ValidationReport = Self::ValidationReport>;
+    type ValidationItem: ClientData<
+        'client_data,
+        ValidationReport = Self::ValidationReport,
+    >;
 
     /// Iterator over the list of specific validation items.
     ///
     /// If the client-side-validated data contain different types of internal
     /// entries, this may be a special enum type with a per-data-type variant.
-    type ValidationIter: Iterator<Item = &'a Self::ValidationItem>;
+    type ValidationIter: Iterator<Item = &'client_data Self::ValidationItem>;
 
     /// The mein method performing client-side-validation for the whole block of
     /// client-side-validated data.
@@ -299,20 +288,20 @@ where
     /// reported issues withing [`Status`] object, returned by the function at
     /// the end.
     fn client_side_validate<Resolver>(
-        &'a self,
-        resolver: &'a mut Resolver,
+        &'client_data self,
+        resolver: &'client_data mut Resolver,
     ) -> Status<Self::ValidationReport>
     where
         Resolver: SealResolver<
-            <<<Self as ClientData>::ValidationReport as ValidationReport>::SealIssue as SealIssue>::Seal,
-            Error = <<Self as ClientData>::ValidationReport as ValidationReport>::SealIssue,
+            <<<Self as ClientData<'client_data>>::ValidationReport as ValidationReport>::SealIssue as SealIssue>::Seal,
+            Error = <<Self as ClientData<'client_data>>::ValidationReport as ValidationReport>::SealIssue,
         >,
     {
         let mut status = Status::new();
 
         status += self.validate_internal_consistency();
         for item in self.validation_iter() {
-            if let Some(seal) = item.single_use_seal() {
+            for seal in item.single_use_seals() {
                 let _ = resolver
                     .resolve_trust(seal)
                     .map_err(|issue| status.add_seal_issue(issue));
@@ -325,11 +314,14 @@ where
 
     /// Returns iterator over hierarchy of individual data items inside
     /// client-side-validation data.
-    fn validation_iter(&'a self) -> Self::ValidationIter;
+    fn validation_iter(&'client_data self) -> Self::ValidationIter;
 }
 
 /// Marker trait for client-side-validation data at any level of data hierarchy.
-pub trait ClientData {
+pub trait ClientData<'client_data>
+where
+    Self: 'client_data,
+{
     /// Data type that stores validation report configuration for the validation
     /// [`Status`] object.
     ///
@@ -337,15 +329,12 @@ pub trait ClientData {
     /// [`ValidationReport::SealIssue`]`<Seal>`.
     type ValidationReport: ValidationReport;
 
-    /// Method returning single-use-seal reference which corresponds to the
-    /// current piece of client-side-validated data. Should return `None` if the
-    /// client-side-validation data does not associated with any single-use-seal
-    /// at this level of data hierarchy.
-    fn single_use_seal(
-        &self,
-    ) -> Option<
-        &<<Self::ValidationReport as ValidationReport>::SealIssue as SealIssue>::Seal,
-    >;
+    /// Iterator over single-use-seals belonging to a specific validation item.
+    type SealIterator: Iterator<Item = &'client_data <<Self::ValidationReport as ValidationReport>::SealIssue as SealIssue>::Seal>;
+
+    /// Method returning iterator over single-use-seal references corresponding
+    /// to the current piece of client-side-validated data.
+    fn single_use_seals(&'client_data self) -> Self::SealIterator;
 
     /// Validates internal consistency of the current client-side-validated data
     /// item. Must not validate any single-use-seals or commitments against
@@ -356,7 +345,9 @@ pub trait ClientData {
     /// single current item. The iteration is performed at higher levels,
     /// normally as a part of [`ClientSideValidate::client_side_validate`]
     /// method logic.
-    fn validate_internal_consistency(&self) -> Status<Self::ValidationReport>;
+    fn validate_internal_consistency(
+        &'client_data self,
+    ) -> Status<Self::ValidationReport>;
 }
 
 /// Seal resolver validates seal to have `closed` status, or reports
@@ -395,7 +386,7 @@ mod test {
     //! of an array of data items, each of which has a name bound to a certain
     //! bitcoin single-use-seal.
 
-    use single_use_seals::{SealStatus, SealVerify};
+    use single_use_seals::{SealStatus, VerifySeal};
 
     use super::*;
     use crate::single_use_seals::SealProtocol;
@@ -430,8 +421,8 @@ mod test {
             }
         }
 
-        impl SealVerify<'_, Seal> for Protocol {
-            fn verify(
+        impl VerifySeal<'_, Seal> for Protocol {
+            fn verify_seal(
                 &self,
                 _seal: &Seal,
                 _msg: &Self::Message,
@@ -474,13 +465,19 @@ mod test {
 
         #[derive(Default)]
         struct Data {
-            seal: Seal,
+            seals: Vec<Seal>,
         }
 
-        impl ClientData for Data {
+        impl<'a> ClientData<'a> for Data
+        where
+            Data: 'a,
+        {
             type ValidationReport = Report;
+            type SealIterator = std::slice::Iter<'a, Seal>;
 
-            fn single_use_seal(&self) -> Option<&Seal> { Some(&self.seal) }
+            fn single_use_seals(&'a self) -> Self::SealIterator {
+                self.seals.iter()
+            }
 
             fn validate_internal_consistency(
                 &self,
@@ -493,10 +490,11 @@ mod test {
             pub data: Vec<Data>,
         }
 
-        impl ClientData for State {
+        impl<'a> ClientData<'a> for State {
             type ValidationReport = Report;
+            type SealIterator = std::slice::Iter<'a, Seal>;
 
-            fn single_use_seal(&self) -> Option<&Seal> { None }
+            fn single_use_seals(&self) -> Self::SealIterator { [].iter() }
 
             fn validate_internal_consistency(
                 &self,


Test patch: