Skip to content

Commit

Permalink
Merge pull request dcSpark#251 from dcSpark/cip36-update
Browse files Browse the repository at this point in the history
Update CIP36 to changes to spec
  • Loading branch information
gostkin authored Sep 27, 2023
2 parents 758ef89 + 02c11d7 commit dcd2ad2
Show file tree
Hide file tree
Showing 7 changed files with 251 additions and 114 deletions.
2 changes: 1 addition & 1 deletion cip36/rust/src/cbor_encodings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ pub struct KeyRegistrationEncoding {
pub delegation_key_encoding: Option<cbor_event::Sz>,
pub stake_credential_encoding: StringEncoding,
pub stake_credential_key_encoding: Option<cbor_event::Sz>,
pub reward_address_key_encoding: Option<cbor_event::Sz>,
pub address_key_encoding: Option<cbor_event::Sz>,
pub nonce_encoding: Option<cbor_event::Sz>,
pub nonce_key_encoding: Option<cbor_event::Sz>,
pub voting_purpose_encoding: Option<cbor_event::Sz>,
Expand Down
88 changes: 49 additions & 39 deletions cip36/rust/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pub use cml_core::{
serialization::{Deserialize, LenEncoding, Serialize, StringEncoding},
};

pub use cml_chain::{address::RewardAddress, NetworkId};
pub use cml_chain::{address::Address, NetworkId};

use std::convert::From;

Expand Down Expand Up @@ -136,7 +136,7 @@ pub struct KeyDeregistration {
pub struct KeyRegistration {
pub delegation: DelegationDistribution,
pub stake_credential: StakeCredential,
pub reward_address: RewardAddress,
pub payment_address: Address,
pub nonce: Nonce,
pub voting_purpose: VotingPurpose,
#[serde(skip)]
Expand Down Expand Up @@ -187,63 +187,73 @@ mod tests {
// .derive(0)
// .derive(0);
// let catalyst_prv_key = hex::decode("4820f7ce221e177c8eae2b2ee5c1f1581a0d88ca5c14329d8f2389e77a465655c27662621bfb99cb9445bf8114cc2a630afd2dd53bc88c08c5f2aed8e9c7cb89").unwrap();
let stake_cred = PublicKey::from_raw_hex(
"86870efc99c453a873a16492ce87738ec79a0ebd064379a62e2c9cf4e119219e",
)
// test case says: 0036ef3e1f0d3f5989e2d155ea54bdb2a72c4c456ccb959af4c94868f473f5a0
// but the CBOR differs, so we use the ones in the CBOR for the test case.
// Is this being derived or why does it not match?
let stake_cred = PublicKey::from_raw_bytes(&[
227, 205, 36, 4, 200, 77, 230, 95, 150, 145, 143, 24, 213, 180, 69, 188, 185, 51, 167,
205, 161, 142, 237, 237, 121, 69, 221, 25, 30, 67, 35, 105,
])
.unwrap();
// let stake_cred = StakeCredential::from(staking_derived_prv.to_public().to_raw_key());
let reward_address = RewardAddress::from_address(
&Address::from_bech32(
"stake_test1uzhr5zn6akj2affzua8ylcm8t872spuf5cf6tzjrvnmwemcehgcjm",
)
.unwrap(),
)
.unwrap();
let nonce = 1234;

// legacy format
// legacy cip-15 format
// test case says: addr_test1qprhw4s70k0vzyhvxp6h97hvrtlkrlcvlmtgmaxdtjz87xrjkctk27ypuv9dzlzxusqse89naweygpjn5dxnygvus05sdq9h07
// but the CBOR differs, so we use the ones in the CBOR for the test case.
// Is this being derived or why does it not match?
let legacy_address = Address::from_raw_bytes(&[
224, 114, 182, 23, 101, 120, 129, 227, 10, 209, 124, 70, 228, 1, 12, 156, 179, 235,
178, 68, 6, 83, 163, 77, 50, 33, 156, 131, 233,
])
.unwrap();
let legacy_reg = KeyRegistration::new(
DelegationDistribution::new_legacy(
LegacyKeyRegistration::from_raw_hex(
"a6a3c0447aeb9cc54cf6422ba32b294e5e1c3ef6d782f2acff4a70694c4d1663",
)
LegacyKeyRegistration::from_raw_bytes(&[
0, 54, 239, 62, 31, 13, 63, 89, 137, 226, 209, 85, 234, 84, 189, 178, 167, 44,
76, 69, 108, 203, 149, 154, 244, 201, 72, 104, 244, 115, 245, 160,
])
.unwrap(),
),
stake_cred.clone(),
reward_address.clone(),
legacy_address,
nonce,
);
let legacy_sign_data_hash = legacy_reg.hash_to_sign(false).unwrap();
assert_eq!(
"872bcb4a9e2b110a06fd5de04be5924b6c659c28a1665ecc75def13ebca6dfd8",
"9946e71b5f6c16150cf431910a0f7dbb8084a992577847802e60d32becb3d6be",
hex::encode(legacy_sign_data_hash)
);

// weighted
// cip-36 format
// test case says: addr_test1qprhw4s70k0vzyhvxp6h97hvrtlkrlcvlmtgmaxdtjz87xrjkctk27ypuv9dzlzxusqse89naweygpjn5dxnygvus05sdq9h07
// but the CBOR differs, so we use the ones in the CBOR for the test case.
// Is this being derived or why does it not match? It doesn't match the legacy one either
let new_address = Address::from_raw_bytes(&[
0, 71, 119, 86, 30, 125, 158, 193, 18, 236, 48, 117, 114, 250, 236, 26, 255, 97, 255,
12, 254, 214, 141, 244, 205, 92, 132, 127, 24, 114, 182, 23, 101, 120, 129, 227, 10,
209, 124, 70, 228, 1, 12, 156, 179, 235, 178, 68, 6, 83, 163, 77, 50, 33, 156, 131,
233,
])
.unwrap();
let weighted_reg = KeyRegistration::new(
DelegationDistribution::new_weighted(vec![
Delegation::new(
VotingPubKey::from_raw_hex(
"a6a3c0447aeb9cc54cf6422ba32b294e5e1c3ef6d782f2acff4a70694c4d1663",
)
.unwrap(),
1,
),
Delegation::new(
VotingPubKey::from_raw_hex(
"00588e8e1d18cba576a4d35758069fe94e53f638b6faf7c07b8abd2bc5c5cdee",
)
.unwrap(),
3,
),
]),
DelegationDistribution::new_weighted(vec![Delegation::new(
VotingPubKey::from_raw_bytes(&[
0, 54, 239, 62, 31, 13, 63, 89, 137, 226, 209, 85, 234, 84, 189, 178, 167, 44,
76, 69, 108, 203, 149, 154, 244, 201, 72, 104, 244, 115, 245, 160,
])
.unwrap(),
1,
)]),
stake_cred,
reward_address,
new_address,
nonce,
);
let _weighted_sign_data_hash = weighted_reg.hash_to_sign(false).unwrap();
// There are some issues with the CIP-36 test vector here. TODO: figure out whether it's the vector or the spec or us that's wrong.
//assert_eq!("5bc0681f173efd76e1989037a3694b8a7abea22053f5940cbb5cfcdf721007d7", hex::encode(weighted_sign_data_hash));
let weighted_sign_data_hash = weighted_reg.hash_to_sign(false).unwrap();
assert_eq!(
"3110fbad72589a80de7fc174310e92dac35bbfece1690c2dce53c2235a9776fa",
hex::encode(weighted_sign_data_hash)
);

// TODO: deregistration test? there are no official test vectors in CIP36
}
Expand Down
64 changes: 29 additions & 35 deletions cip36/rust/src/serialization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -598,27 +598,10 @@ impl Serialize for KeyRegistration {
serializer: &'se mut Serializer<W>,
force_canonical: bool,
) -> cbor_event::Result<&'se mut Serializer<W>> {
serializer.write_map_sz(
self.encodings
.as_ref()
.map(|encs| encs.len_encoding)
.unwrap_or_default()
.to_len_sz(
4 + if self.voting_purpose != 0
|| self
.encodings
.as_ref()
.map(|encs| encs.voting_purpose_default_present)
.unwrap_or(false)
{
1
} else {
0
},
force_canonical,
),
)?;
let (legacy_format, should_include_voting_purpose) = match self.delegation {
// code hand-edited to deal with including voting purpose or not depending on format
// defaulting to weighted including it is based on the test vectors as it is not well specified
// this seems to have changed as previously it was not included in old test vectors
let (_legacy_format, should_include_voting_purpose) = match self.delegation {
DelegationDistribution::Legacy { .. } => (true, false),
DelegationDistribution::Weighted { .. } => (
false,
Expand All @@ -627,9 +610,19 @@ impl Serialize for KeyRegistration {
.encodings
.as_ref()
.map(|encs| encs.voting_purpose_default_present)
.unwrap_or(false),
.unwrap_or(true),
),
};
serializer.write_map_sz(
self.encodings
.as_ref()
.map(|encs| encs.len_encoding)
.unwrap_or_default()
.to_len_sz(
4 + if should_include_voting_purpose { 1 } else { 0 },
force_canonical,
),
)?;
let deser_order = self
.encodings
.as_ref()
Expand All @@ -640,7 +633,7 @@ impl Serialize for KeyRegistration {
})
.map(|encs| encs.orig_deser_order.clone())
.unwrap_or_else(|| {
if legacy_format {
if should_include_voting_purpose {
vec![0, 1, 2, 3, 4]
} else {
vec![0, 1, 2, 3]
Expand Down Expand Up @@ -693,12 +686,13 @@ impl Serialize for KeyRegistration {
3u64,
self.encodings
.as_ref()
.map(|encs| encs.reward_address_key_encoding)
.map(|encs| encs.address_key_encoding)
.unwrap_or_default(),
force_canonical,
),
)?;
self.reward_address.serialize(serializer, force_canonical)?;
self.payment_address
.serialize(serializer, force_canonical)?;
}
3 => {
serializer.write_unsigned_integer_sz(
Expand Down Expand Up @@ -774,8 +768,8 @@ impl Deserialize for KeyRegistration {
let mut stake_credential_encoding = StringEncoding::default();
let mut stake_credential_key_encoding = None;
let mut stake_credential = None;
let mut reward_address_key_encoding = None;
let mut reward_address = None;
let mut address_key_encoding = None;
let mut payment_address = None;
let mut nonce_encoding = None;
let mut nonce_key_encoding = None;
let mut nonce = None;
Expand Down Expand Up @@ -821,13 +815,13 @@ impl Deserialize for KeyRegistration {
orig_deser_order.push(1);
}
(3, key_enc) => {
if reward_address.is_some() {
if payment_address.is_some() {
return Err(DeserializeFailure::DuplicateKey(Key::Uint(3)).into());
}
let tmp_reward_address = RewardAddress::deserialize(raw)
.map_err(|e: DeserializeError| e.annotate("reward_address"))?;
reward_address = Some(tmp_reward_address);
reward_address_key_encoding = Some(key_enc);
let tmp_payment_address = Address::deserialize(raw)
.map_err(|e: DeserializeError| e.annotate("payment_address"))?;
payment_address = Some(tmp_payment_address);
address_key_encoding = Some(key_enc);
orig_deser_order.push(2);
}
(4, key_enc) => {
Expand Down Expand Up @@ -893,7 +887,7 @@ impl Deserialize for KeyRegistration {
Some(x) => x,
None => return Err(DeserializeFailure::MandatoryFieldMissing(Key::Uint(2)).into()),
};
let reward_address = match reward_address {
let payment_address = match payment_address {
Some(x) => x,
None => return Err(DeserializeFailure::MandatoryFieldMissing(Key::Uint(3)).into()),
};
Expand All @@ -909,7 +903,7 @@ impl Deserialize for KeyRegistration {
Ok(Self {
delegation,
stake_credential,
reward_address,
payment_address,
nonce,
voting_purpose,
encodings: Some(KeyRegistrationEncoding {
Expand All @@ -918,7 +912,7 @@ impl Deserialize for KeyRegistration {
delegation_key_encoding,
stake_credential_key_encoding,
stake_credential_encoding,
reward_address_key_encoding,
address_key_encoding,
nonce_key_encoding,
nonce_encoding,
voting_purpose_key_encoding,
Expand Down
18 changes: 6 additions & 12 deletions cip36/rust/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ pub use cml_core::{
serialization::{Deserialize, LenEncoding, Serialize, StringEncoding},
};

pub use cml_chain::{address::RewardAddress, NetworkId};
pub use cml_chain::{address::Address, NetworkId};

use std::convert::From;

Expand Down Expand Up @@ -67,10 +67,7 @@ impl DeregistrationCbor {

/// Create a CIP36 view from the bytes of a Metadata.
/// The resulting DeregistrationCbor will contain ONLY the relevant fields for CIP36 from the Metadata
pub fn from_metadata_bytes(
&self,
metadata_cbor_bytes: &[u8],
) -> Result<Self, DeserializeError> {
pub fn from_metadata_bytes(metadata_cbor_bytes: &[u8]) -> Result<Self, DeserializeError> {
let mut raw = Deserializer::from(std::io::Cursor::new(metadata_cbor_bytes));
Self::deserialize(&mut raw)
}
Expand Down Expand Up @@ -252,18 +249,18 @@ impl KeyRegistration {
///
/// * `delegation` - Delegation
/// * `stake_credential` - stake address for the network that this transaction is submitted to (to point to the Ada that is being delegated).
/// * `reward_address` - Shelley address discriminated for the same network this transaction is submitted to for receiving awairds.
/// * `payment_address` - Shelley payment address discriminated for the same network this transaction is submitted to for receiving awairds.
/// * `nonce` - Monotonically rising across all transactions with the same staking key. Recommended to just use the slot of this tx.
pub fn new(
delegation: DelegationDistribution,
stake_credential: StakeCredential,
reward_address: RewardAddress,
payment_address: Address,
nonce: Nonce,
) -> Self {
Self {
delegation,
stake_credential,
reward_address,
payment_address,
nonce,
voting_purpose: 0,
encodings: None,
Expand Down Expand Up @@ -340,10 +337,7 @@ impl RegistrationCbor {

/// Create a CIP36 view from the bytes of a Metadata.
/// The resulting RegistrationCbor will contain ONLY the relevant fields for CIP36 from the Metadata
pub fn from_metadata_bytes(
&self,
metadata_cbor_bytes: &[u8],
) -> Result<Self, DeserializeError> {
pub fn from_metadata_bytes(metadata_cbor_bytes: &[u8]) -> Result<Self, DeserializeError> {
let mut raw = Deserializer::from(std::io::Cursor::new(metadata_cbor_bytes));
Self::deserialize(&mut raw)
}
Expand Down
27 changes: 3 additions & 24 deletions cip36/wasm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use wasm_bindgen::prelude::{wasm_bindgen, JsValue};

use cml_core_wasm::{impl_wasm_cbor_json_api, impl_wasm_conversions, impl_wasm_json_api};

use cml_chain_wasm::address::RewardAddress;
use cml_chain_wasm::address::Address;
pub mod utils;

#[derive(Clone, Debug)]
Expand Down Expand Up @@ -210,13 +210,6 @@ impl KeyDeregistration {
pub fn voting_purpose(&self) -> VotingPurpose {
self.0.voting_purpose
}

pub fn new(stake_credential: &StakeCredential, nonce: Nonce) -> Self {
Self(cml_cip36::KeyDeregistration::new(
stake_credential.clone().into(),
nonce,
))
}
}

#[derive(Clone, Debug)]
Expand All @@ -237,8 +230,8 @@ impl KeyRegistration {
self.0.stake_credential.clone().into()
}

pub fn reward_address(&self) -> RewardAddress {
self.0.reward_address.clone().into()
pub fn payment_address(&self) -> Address {
self.0.payment_address.clone().into()
}

pub fn nonce(&self) -> Nonce {
Expand All @@ -252,20 +245,6 @@ impl KeyRegistration {
pub fn voting_purpose(&self) -> VotingPurpose {
self.0.voting_purpose
}

pub fn new(
delegation: &DelegationDistribution,
stake_credential: &StakeCredential,
reward_address: &RewardAddress,
nonce: Nonce,
) -> Self {
Self(cml_cip36::KeyRegistration::new(
delegation.clone().into(),
stake_credential.clone().into(),
reward_address.clone().into(),
nonce,
))
}
}

pub type LegacyKeyRegistration = cml_crypto_wasm::PublicKey;
Expand Down
Loading

0 comments on commit dcd2ad2

Please sign in to comment.