,
tx_maker: M,
lane: LaneId,
instance: InstanceId,
_marker: PhantomData,
}
/// Substrate transactions maker.
#[async_trait]
pub trait SubstrateTransactionMaker: Clone + Send + Sync {
/// Signed transaction type.
type SignedTransaction: Send + Sync + Encode;
/// Make messages delivery transaction.
async fn make_messages_delivery_transaction(
&self,
generated_at_header: SourceHeaderIdOf,
nonces: RangeInclusive,
proof: P::MessagesProof,
) -> Result;
}
impl SubstrateMessagesTarget {
/// Create new Substrate headers target.
pub fn new(client: Client, tx_maker: M, lane: LaneId, instance: InstanceId) -> Self {
SubstrateMessagesTarget {
client,
tx_maker,
lane,
instance,
_marker: Default::default(),
}
}
}
impl Clone for SubstrateMessagesTarget {
fn clone(&self) -> Self {
Self {
client: self.client.clone(),
tx_maker: self.tx_maker.clone(),
lane: self.lane,
instance: self.instance,
_marker: Default::default(),
}
}
}
#[async_trait]
impl TargetClient for SubstrateMessagesTarget
where
C: Chain,
C::Header: DeserializeOwned,
C::Index: DeserializeOwned,
::Number: Into,
P: MessageLane<
MessagesReceivingProof = (HashOf, StorageProof, LaneId),
TargetHeaderNumber = ::Number,
TargetHeaderHash = ::Hash,
>,
P::SourceHeaderNumber: Decode,
P::SourceHeaderHash: Decode,
M: SubstrateTransactionMaker,
{
type Error = SubstrateError;
async fn reconnect(mut self) -> Result {
let new_client = self.client.clone().reconnect().await?;
self.client = new_client;
Ok(self)
}
async fn state(&self) -> Result, Self::Error> {
read_client_state::<_, P::SourceHeaderHash, P::SourceHeaderNumber>(&self.client, P::SOURCE_NAME).await
}
async fn latest_received_nonce(
&self,
id: TargetHeaderIdOf,
) -> Result<(TargetHeaderIdOf
, MessageNonce), Self::Error> {
let encoded_response = self
.client
.state_call(
// TODO: https://github.com/paritytech/parity-bridges-common/issues/457
"InboundLaneApi_latest_received_nonce".into(),
Bytes(self.lane.encode()),
Some(id.1),
)
.await?;
let latest_received_nonce: MessageNonce =
Decode::decode(&mut &encoded_response.0[..]).map_err(SubstrateError::ResponseParseFailed)?;
Ok((id, latest_received_nonce))
}
async fn latest_confirmed_received_nonce(
&self,
id: TargetHeaderIdOf
,
) -> Result<(TargetHeaderIdOf
, MessageNonce), Self::Error> {
let encoded_response = self
.client
.state_call(
// TODO: https://github.com/paritytech/parity-bridges-common/issues/457
"OutboundLaneApi_latest_received_nonce".into(),
Bytes(self.lane.encode()),
Some(id.1),
)
.await?;
let latest_received_nonce: MessageNonce =
Decode::decode(&mut &encoded_response.0[..]).map_err(SubstrateError::ResponseParseFailed)?;
Ok((id, latest_received_nonce))
}
async fn prove_messages_receiving(
&self,
id: TargetHeaderIdOf
,
) -> Result<(TargetHeaderIdOf
, P::MessagesReceivingProof), Self::Error> {
let proof = self
.client
.prove_messages_delivery(self.instance, self.lane, id.1)
.await?;
let proof = (id.1, proof, self.lane);
Ok((id, proof))
}
async fn submit_messages_proof(
&self,
generated_at_header: SourceHeaderIdOf
,
nonces: RangeInclusive,
proof: P::MessagesProof,
) -> Result, Self::Error> {
let tx = self
.tx_maker
.make_messages_delivery_transaction(generated_at_header, nonces.clone(), proof)
.await?;
self.client.submit_extrinsic(Bytes(tx.encode())).await?;
Ok(nonces)
}
}