1use std::borrow::Borrow;
2
3pub use crate::solidity_types::Envelope;
4use crate::{
5 Service, ServiceManagerEnvelope, ServiceManagerSignatureData, SignatureAlgorithm,
6 SignatureData, SignatureKind, SignaturePrefix, TriggerAction, TriggerData, WorkflowId,
7};
8use alloy_primitives::{eip191_hash_message, keccak256, FixedBytes, SignatureError};
9use alloy_signer::Signer;
10use alloy_signer_local::PrivateKeySigner;
11use alloy_sol_types::SolValue;
12use async_trait::async_trait;
13use ripemd::Ripemd160;
14use serde::{Deserialize, Serialize};
15use sha2::Digest;
16use thiserror::Error;
17use utoipa::ToSchema;
18
19#[derive(Serialize, Deserialize, Clone, Debug, ToSchema)]
20#[serde(rename_all = "snake_case")]
21pub struct Packet {
22 pub service: Service,
23 pub workflow_id: WorkflowId,
24 #[schema(value_type = Object)]
25 pub envelope: Envelope,
26 pub signature: EnvelopeSignature,
27 pub trigger_data: TriggerData,
28}
29
30#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
31#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
32pub trait EnvelopeExt: Borrow<Envelope> {
33 fn prefix_eip191_hash(&self) -> FixedBytes<32> {
34 let envelope_bytes = self.borrow().abi_encode();
35 eip191_hash_message(keccak256(&envelope_bytes))
36 }
37
38 fn unprefixed_hash(&self) -> FixedBytes<32> {
39 let envelope_bytes = self.borrow().abi_encode();
40 keccak256(&envelope_bytes)
41 }
42
43 async fn sign(
44 &self,
45 signer: &PrivateKeySigner,
46 kind: SignatureKind,
47 ) -> anyhow::Result<EnvelopeSignature> {
48 let hash = match kind.algorithm {
49 SignatureAlgorithm::Secp256k1 => match kind.prefix {
50 Some(SignaturePrefix::Eip191) => self.prefix_eip191_hash(),
51 None => self.unprefixed_hash(),
52 },
53 };
54
55 Ok(signer
56 .sign_hash(&hash)
57 .await
58 .map(|signature| EnvelopeSignature {
59 data: signature.into(),
60 kind,
61 })
62 .map_err(|e| anyhow::anyhow!("Failed to sign envelope: {e:?}"))?)
63 }
64
65 fn signature_data(
66 &self,
67 signatures: Vec<EnvelopeSignature>,
68 block_height: u64,
69 ) -> std::result::Result<SignatureData, EnvelopeError> {
70 let mut signers_and_signatures: Vec<(alloy_primitives::Address, alloy_primitives::Bytes)> =
71 signatures
72 .into_iter()
73 .map(|sig| {
74 sig.evm_signer_address(self.borrow())
75 .map(|addr| (addr, sig.data.into()))
76 })
77 .collect::<Result<_, _>>()?;
78
79 signers_and_signatures.sort_by_key(|(addr, _)| *addr);
81
82 let (signers, signatures): (Vec<alloy_primitives::Address>, Vec<alloy_primitives::Bytes>) =
84 signers_and_signatures.into_iter().unzip();
85
86 Ok(SignatureData {
87 signers,
88 signatures,
89 referenceBlock: block_height as u32,
90 })
91 }
92}
93
94impl<T: Borrow<Envelope> + ?Sized> EnvelopeExt for T {}
96
97impl From<Envelope> for ServiceManagerEnvelope {
98 fn from(envelope: Envelope) -> Self {
99 ServiceManagerEnvelope {
100 eventId: envelope.eventId,
101 ordering: envelope.ordering,
102 payload: envelope.payload,
103 }
104 }
105}
106
107impl From<SignatureData> for ServiceManagerSignatureData {
108 fn from(signature_data: SignatureData) -> Self {
109 ServiceManagerSignatureData {
110 signers: signature_data.signers,
111 signatures: signature_data.signatures,
112 referenceBlock: signature_data.referenceBlock,
113 }
114 }
115}
116
117#[derive(Serialize, Deserialize, Clone, Debug, ToSchema)]
118#[serde(rename_all = "snake_case")]
119pub struct EnvelopeSignature {
120 pub data: Vec<u8>,
121 pub kind: SignatureKind,
122}
123
124impl EnvelopeSignature {
125 pub fn evm_signer_address(
126 &self,
127 envelope: &Envelope,
128 ) -> std::result::Result<alloy_primitives::Address, EnvelopeError> {
129 match self.kind.algorithm {
130 SignatureAlgorithm::Secp256k1 => {
131 let signature = alloy_primitives::Signature::from_raw(&self.data)
132 .map_err(EnvelopeError::RecoverSignerAddress)?;
133
134 match self.kind.prefix {
135 Some(SignaturePrefix::Eip191) => signature
136 .recover_address_from_prehash(&envelope.prefix_eip191_hash())
137 .map_err(EnvelopeError::RecoverSignerAddress),
138 None => signature
139 .recover_address_from_prehash(&envelope.unprefixed_hash())
140 .map_err(EnvelopeError::RecoverSignerAddress),
141 }
142 }
143 }
144 }
145}
146
147impl Packet {
148 pub fn event_id(&self) -> EventId {
149 self.envelope.eventId.into()
150 }
151}
152
153#[derive(
154 Serialize,
155 Deserialize,
156 Clone,
157 Eq,
158 PartialEq,
159 Debug,
160 Hash,
161 bincode::Decode,
162 bincode::Encode,
163 Ord,
164 PartialOrd,
165)]
166#[serde(transparent)]
167pub struct EventId([u8; 20]);
168
169impl From<FixedBytes<20>> for EventId {
170 fn from(value: FixedBytes<20>) -> Self {
171 Self(value.0)
172 }
173}
174
175impl From<EventId> for FixedBytes<20> {
176 fn from(value: EventId) -> Self {
177 FixedBytes(value.0)
178 }
179}
180
181impl TryFrom<(&Service, &TriggerAction)> for EventId {
182 type Error = anyhow::Error;
183
184 fn try_from(
185 (service, trigger_action): (&Service, &TriggerAction),
186 ) -> std::result::Result<EventId, Self::Error> {
187 let service_digest = service.hash()?;
188 let action_bytes = bincode::encode_to_vec(trigger_action, bincode::config::standard())?;
189
190 let mut hasher = Ripemd160::new();
191 hasher.update(&service_digest);
192 hasher.update(&action_bytes);
193 let result = hasher.finalize();
194
195 Ok(EventId(result.into()))
196 }
197}
198
199impl std::fmt::Display for EventId {
200 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
201 write!(f, "{}", const_hex::encode(self.0))
202 }
203}
204
205impl AsRef<[u8]> for EventId {
206 fn as_ref(&self) -> &[u8] {
207 &self.0
208 }
209}
210
211#[derive(Serialize, Deserialize, Clone)]
212#[serde(transparent)]
213pub struct EventOrder([u8; 12]);
214
215impl EventOrder {
216 pub fn new_u64(value: u64) -> Self {
217 let mut bytes = [0; 12];
218 bytes[0..8].copy_from_slice(&value.to_be_bytes());
219 Self(bytes)
220 }
221}
222
223impl From<FixedBytes<12>> for EventOrder {
224 fn from(value: FixedBytes<12>) -> Self {
225 Self(value.0)
226 }
227}
228
229impl From<EventOrder> for FixedBytes<12> {
230 fn from(value: EventOrder) -> Self {
231 FixedBytes(value.0)
232 }
233}
234
235impl std::fmt::Display for EventOrder {
236 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
237 write!(f, "{}", const_hex::encode(self.0))
238 }
239}
240
241impl AsRef<[u8]> for EventOrder {
242 fn as_ref(&self) -> &[u8] {
243 &self.0
244 }
245}
246
247#[derive(Debug, Error)]
248pub enum EnvelopeError {
249 #[error("Unable to recover signer address: {0:?}")]
250 RecoverSignerAddress(SignatureError),
251}