Skip to content

Commit

Permalink
Merge pull request #86 from KeystoneHQ/feat/ada-integration-v2
Browse files Browse the repository at this point in the history
Feat/ada integration v2
  • Loading branch information
soralit authored Jun 28, 2024
2 parents 3d98980 + 5db682a commit 6d7f981
Show file tree
Hide file tree
Showing 7 changed files with 285 additions and 0 deletions.
2 changes: 2 additions & 0 deletions libs/ur-parse-lib/src/keystone_ur_decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ mod tests {
use crate::keystone_ur_decoder::{probe_decode, MultiURParseResult, URParseResult};
use alloc::string::ToString;
use ur_registry::crypto_psbt::CryptoPSBT;
use ur_registry::cardano::cardano_sign_data_request::CardanoSignDataRequest;

use ur_registry::ethereum::eth_sign_request::EthSignRequest;

#[test]
Expand Down
107 changes: 107 additions & 0 deletions libs/ur-registry/src/cardano/cardano_sign_data_request.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
use crate::cbor::cbor_map;
use crate::crypto_key_path::CryptoKeyPath;
use crate::error::{URError, URResult};
use crate::registry_types::{RegistryType, CRYPTO_KEYPATH, CARDANO_SIGN_DATA_REQUEST, UUID};
use crate::traits::{From as FromCbor, RegistryItem, To, MapSize};
use crate::types::Bytes;
use alloc::format;
use crate::impl_template_struct;
use alloc::string::{String, ToString};
use alloc::vec::Vec;
use minicbor::data::{Int, Tag};
use minicbor::encode::Write;
use minicbor::{Decoder, Encoder};

const REQUEST_ID: u8 = 1;
const SIGN_DATA: u8 = 2;
const DERIVATION_PATH: u8 = 3;
const ORIGIN: u8 = 4;

impl_template_struct!(CardanoSignDataRequest {request_id: Option<Bytes>, sign_data: Bytes, derivation_path: CryptoKeyPath, origin: Option<String>});

impl MapSize for CardanoSignDataRequest {
fn map_size(&self) -> u64 {
let mut size = 2;
if self.request_id.is_some() {
size += 1;
}
if self.origin.is_some() {
size += 1;
}
size
}
}

impl RegistryItem for CardanoSignDataRequest {
fn get_registry_type() -> RegistryType<'static> {
CARDANO_SIGN_DATA_REQUEST
}
}

impl<C> minicbor::Encode<C> for CardanoSignDataRequest {
fn encode<W: Write>(
&self,
e: &mut Encoder<W>,
_ctx: &mut C,
) -> Result<(), minicbor::encode::Error<W::Error>> {
e.map(self.map_size())?;
if let Some(request_id) = &self.request_id {
e.int(Int::from(REQUEST_ID))?
.tag(Tag::Unassigned(UUID.get_tag()))?
.bytes(request_id)?;
}

e.int(Int::from(SIGN_DATA))?.bytes(&self.sign_data)?;

e.int(Int::from(DERIVATION_PATH))?;
e.tag(Tag::Unassigned(CRYPTO_KEYPATH.get_tag()))?;
CryptoKeyPath::encode(&self.derivation_path, e, _ctx)?;

if let Some(origin) = &self.origin {
e.int(Int::from(ORIGIN))?.str(origin)?;
}

Ok(())
}
}

impl<'b, C> minicbor::Decode<'b, C> for CardanoSignDataRequest {
fn decode(d: &mut Decoder<'b>, _ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
let mut result: CardanoSignDataRequest = CardanoSignDataRequest::default();
cbor_map(d, &mut result, |key, obj, d: &mut Decoder| {
let key =
u8::try_from(key).map_err(|e| minicbor::decode::Error::message(e.to_string()))?;
match key {
REQUEST_ID => {
d.tag()?;
obj.set_request_id(Some(d.bytes()?.to_vec()));
}
SIGN_DATA => {
obj.set_sign_data(d.bytes()?.to_vec());
}
DERIVATION_PATH => {
d.tag()?;
obj.derivation_path = CryptoKeyPath::decode(d, _ctx)?;
}
ORIGIN => {
obj.origin = Some(d.str()?.to_string());
}
_ => {}
}
Ok(())
})?;
Ok(result)
}
}

impl To for CardanoSignDataRequest {
fn to_bytes(&self) -> URResult<Vec<u8>> {
minicbor::to_vec(self.clone()).map_err(|e| URError::CborEncodeError(e.to_string()))
}
}

impl FromCbor<CardanoSignDataRequest> for CardanoSignDataRequest {
fn from_cbor(bytes: Vec<u8>) -> URResult<CardanoSignDataRequest> {
minicbor::decode(&bytes).map_err(|e| URError::CborDecodeError(e.to_string()))
}
}
78 changes: 78 additions & 0 deletions libs/ur-registry/src/cardano/cardano_sign_data_signature.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
use crate::cbor::cbor_map;
use crate::impl_template_struct;
use crate::registry_types::{CARDANO_SIGN_DATA_SIGNATURE, RegistryType, UUID};
use crate::traits::{MapSize, RegistryItem};
use crate::types::Bytes;
use alloc::string::ToString;
use minicbor::data::{Int, Tag};
use minicbor::encode::{Error, Write};
use minicbor::{Decoder, Encoder};

const REQUEST_ID: u8 = 1;
const SIGNATURE: u8 = 2;
const PUBLIC_KEY: u8 = 3;

impl_template_struct!(CardanoSignDataSignature {
request_id: Option<Bytes>,
signature: Bytes,
public_key: Bytes
});

impl RegistryItem for CardanoSignDataSignature {
fn get_registry_type() -> RegistryType<'static> {
CARDANO_SIGN_DATA_SIGNATURE
}
}

impl MapSize for CardanoSignDataSignature {
fn map_size(&self) -> u64 {
let mut size = 2;
if self.request_id.is_some() {
size += 1;
}
size
}
}

impl<C> minicbor::Encode<C> for CardanoSignDataSignature {
fn encode<W: Write>(&self, e: &mut Encoder<W>, _ctx: &mut C) -> Result<(), Error<W::Error>> {
e.map(self.map_size())?;

if let Some(id) = &self.request_id {
e.int(Int::from(REQUEST_ID))?
.tag(Tag::Unassigned(UUID.get_tag()))?
.bytes(id)?;
}

e.int(Int::from(SIGNATURE))?.bytes(&self.signature)?;

e.int(Int::from(PUBLIC_KEY))?.bytes(&self.public_key)?;

Ok(())
}
}

impl<'b, C> minicbor::Decode<'b, C> for CardanoSignDataSignature {
fn decode(d: &mut Decoder<'b>, _ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
let mut cardano_sign_data_signature = CardanoSignDataSignature::default();
cbor_map(d, &mut cardano_sign_data_signature, |key, obj, d| {
let key =
u8::try_from(key).map_err(|e| minicbor::decode::Error::message(e.to_string()))?;
match key {
REQUEST_ID => {
d.tag()?;
obj.set_request_id(Some(d.bytes()?.to_vec()));
}
SIGNATURE => {
obj.set_signature(d.bytes()?.to_vec());
}
PUBLIC_KEY => {
obj.set_public_key(d.bytes()?.to_vec());
}
_ => {}
}
Ok(())
})?;
Ok(cardano_sign_data_signature)
}
}
86 changes: 86 additions & 0 deletions libs/ur-registry/src/cardano/cardano_sign_structure.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
use crate::cbor::cbor_array;
use crate::crypto_key_path::CryptoKeyPath;
use crate::error::{URError, URResult};
use crate::registry_types::{CARDANO_CERT_KEY, CRYPTO_KEYPATH, RegistryType};
use crate::traits::{From as FromCbor, MapSize, RegistryItem, To};
use crate::types::Bytes;

use alloc::string::{String, ToString};
use alloc::vec::Vec;
use prost::Message;
use core::convert::From;
use minicbor::data::{Int, Tag};
use minicbor::encode::{Error, Write};
use minicbor::{Decoder, Encoder};

const KEY_CONTEXT: u8 = 0;
const KEY_PROTECTED_HEADER: u8 = 1;
const KEY_EXTERNAL_AAD: u8 = 2;
const KEY_PAYLOAD: u8 = 3;

use crate::impl_template_struct;

impl_template_struct!(CardanoSignStructure {
context: Bytes,
protected_header: Bytes,
external_aad: Bytes,
payload: String
});

impl MapSize for CardanoSignStructure {
fn map_size(&self) -> u64 {
4
}
}

impl<'b, C> minicbor::Decode<'b, C> for CardanoSignStructure {
fn decode(d: &mut Decoder<'b>, _ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
let mut cardano_sign_structure = CardanoSignStructure::default();
cbor_array(d, &mut cardano_sign_structure, |_index, obj, d| {
let _index =
u8::try_from(_index).map_err(|e| minicbor::decode::Error::message(e.to_string()))?;

match _index {
KEY_CONTEXT => {
obj.context = d.str()?.to_string().encode_to_vec()
}
KEY_PROTECTED_HEADER => {
obj.protected_header = d.bytes()?.to_vec()
}
KEY_EXTERNAL_AAD => {
obj.external_aad = d.bytes()?.to_vec()
}
KEY_PAYLOAD => {
obj.payload = hex::encode(d.bytes()?);
}
_ => {
d.skip()?;
}
}
Ok(())
})?;
Ok(cardano_sign_structure)
}
}

impl FromCbor<CardanoSignStructure> for CardanoSignStructure {
fn from_cbor(bytes: Vec<u8>) -> URResult<CardanoSignStructure> {
minicbor::decode(&bytes).map_err(|e| URError::CborDecodeError(e.to_string()))
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_decode_sign_structure() {
let sign_structure_str = "846a5369676e617475726531582aa201276761646472657373581de133a4f1f468454744b2ff3644b2ab79d48e76a3187f902fe8a1bcfaad4058857b22707572706f7365223a224b6f696f73204163636f756e7420566572696669636174696f6e222c226163636f756e74223a2265313333613466316634363834353437343462326666333634346232616237396434386537366133313837663930326665386131626366616164222c226e6f6e6365223a313731393533383936383333347d";
let sign_structure_bytes = hex::decode(sign_structure_str).unwrap();

let sign_structure = CardanoSignStructure::from_cbor(sign_structure_bytes).unwrap();
let payload = hex::decode(sign_structure.payload).unwrap();
let payload = String::from_utf8(payload).unwrap();
assert_eq!(payload, "{\"purpose\":\"Koios Account Verification\",\"account\":\"e133a4f1f468454744b2ff3644b2ab79d48e76a3187f902fe8a1bcfaad\",\"nonce\":1719538968334}");
}
}
3 changes: 3 additions & 0 deletions libs/ur-registry/src/cardano/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
pub mod cardano_cert_key;
pub mod cardano_sign_request;
pub mod cardano_sign_data_request;
pub mod cardano_signature;
pub mod cardano_sign_data_signature;
pub mod cardano_utxo;
pub mod cardano_sign_structure;
4 changes: 4 additions & 0 deletions libs/ur-registry/src/macros_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ use crate::bytes::Bytes;
use crate::cardano::{
cardano_cert_key::CardanoCertKey, cardano_sign_request::CardanoSignRequest,
cardano_signature::CardanoSignature, cardano_utxo::CardanoUTXO,
cardano_sign_data_request::CardanoSignDataRequest,
cardano_sign_data_signature::CardanoSignDataSignature,
};
use crate::cosmos::{cosmos_sign_request::CosmosSignRequest, cosmos_signature::CosmosSignature};
use crate::cosmos::{evm_sign_request::EvmSignRequest, evm_signature::EvmSignature};
Expand Down Expand Up @@ -50,6 +52,8 @@ impl_cbor_bytes!(
CardanoSignature,
CardanoUTXO,
CardanoSignRequest,
CardanoSignDataRequest,
CardanoSignDataSignature,
CardanoCertKey,
AptosSignRequest,
AptosSignature,
Expand Down
5 changes: 5 additions & 0 deletions libs/ur-registry/src/registry_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub enum URType {
ArweaveSignRequest(String),
AptosSignRequest(String),
CardanoSignRequest(String),
CardanoSignDataRequest(String),
CosmosSignRequest(String),
EvmSignRequest(String),
SuiSignRequest(String),
Expand Down Expand Up @@ -42,6 +43,7 @@ impl URType {
"aptos-sign-request" => Ok(URType::AptosSignRequest(type_str.to_string())),
"sui-sign-request" => Ok(URType::SuiSignRequest(type_str.to_string())),
"cardano-sign-request" => Ok(URType::CardanoSignRequest(type_str.to_string())),
"cardano-sign-data-request" => Ok(URType::CardanoSignDataRequest(type_str.to_string())),
"qr-hardware-call" => Ok(URType::QRHardwareCall(type_str.to_string())),
"ton-sign-request" => Ok(URType::TonSignRequest(type_str.to_string())),
_ => Err(URError::NotSupportURTypeError(type_str.to_string())),
Expand All @@ -63,6 +65,7 @@ impl URType {
URType::ArweaveSignRequest(type_str) => type_str.to_string(),
URType::AptosSignRequest(type_str) => type_str.to_string(),
URType::CardanoSignRequest(type_str) => type_str.to_string(),
URType::CardanoSignDataRequest(type_str) => type_str.to_string(),
URType::SuiSignRequest(type_str) => type_str.to_string(),
URType::CosmosSignRequest(type_str) => type_str.to_string(),
URType::EvmSignRequest(type_str) => type_str.to_string(),
Expand Down Expand Up @@ -135,6 +138,8 @@ pub const CARDANO_UTXO: RegistryType = RegistryType("cardano-utxo", Some(2201));
pub const CARDANO_SIGN_REQUEST: RegistryType = RegistryType("cardano-sign-request", Some(2202));
pub const CARDANO_SIGNATURE: RegistryType = RegistryType("cardano-signature", Some(2203));
pub const CARDANO_CERT_KEY: RegistryType = RegistryType("cardano-cert-key", Some(2204));
pub const CARDANO_SIGN_DATA_REQUEST: RegistryType = RegistryType("cardano-sign-data-request", Some(2205));
pub const CARDANO_SIGN_DATA_SIGNATURE: RegistryType = RegistryType("cardano-sign-data-signature", Some(2206));
// Sui
pub const SUI_SIGN_REQUEST: RegistryType = RegistryType("sui-sign-request", Some(7101));
pub const SUI_SIGNATURE: RegistryType = RegistryType("sui-signature", Some(7102));
Expand Down

0 comments on commit 6d7f981

Please sign in to comment.