From 59fab61dd225ec64ca2b258f938ce546cf69bf3c Mon Sep 17 00:00:00 2001 From: Sebastien Guillemot Date: Tue, 20 Apr 2021 02:58:52 +0900 Subject: [PATCH] Add namespace to script hashing (#142) --- rust/pkg/cardano_serialization_lib.js.flow | 21 +++++++++++-------- rust/src/lib.rs | 24 ++++++++++++++-------- 2 files changed, 28 insertions(+), 17 deletions(-) diff --git a/rust/pkg/cardano_serialization_lib.js.flow b/rust/pkg/cardano_serialization_lib.js.flow index 893f7b03..b29c6fab 100644 --- a/rust/pkg/cardano_serialization_lib.js.flow +++ b/rust/pkg/cardano_serialization_lib.js.flow @@ -198,6 +198,17 @@ declare export var NativeScriptKind: {| +TimelockExpiry: 5, // 5 |}; +/** + * Each new language uses a different namespace for hashing its script + * This is because you could have a language where the same bytes have different semantics + * So this avoids scripts in different languages mapping to the same hash + * Note that the enum value here is different than the enum value for deciding the cost model of a script + */ + +declare export var ScriptHashNamespace: {| + +NativeScript: 0, // 0 +|}; + /** */ @@ -2091,16 +2102,10 @@ declare export class NativeScript { static from_bytes(bytes: Uint8Array): NativeScript; /** + * @param {number} namespace * @returns {Ed25519KeyHash} */ - hash(): Ed25519KeyHash; - - /** - * like hash(), but prefixes 0x00 in the pre-image bytes, to match the specs - * followed by cardano-cli. See https://github.com/input-output-hk/cardano-node/issues/2593 - * @returns {Ed25519KeyHash} - */ - script_hash(): Ed25519KeyHash; + hash(namespace: number): Ed25519KeyHash; /** * @param {ScriptPubkey} script_pubkey diff --git a/rust/src/lib.rs b/rust/src/lib.rs index acc434ec..bf0344fb 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -1452,17 +1452,21 @@ pub struct NativeScript(NativeScriptEnum); to_from_bytes!(NativeScript); +/// Each new language uses a different namespace for hashing its script +/// This is because you could have a language where the same bytes have different semantics +/// So this avoids scripts in different languages mapping to the same hash +/// Note that the enum value here is different than the enum value for deciding the cost model of a script #[wasm_bindgen] -impl NativeScript { - pub fn hash(&self) -> Ed25519KeyHash { - Ed25519KeyHash::from(blake2b224(self.to_bytes().as_ref())) - } +#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] +pub enum ScriptHashNamespace { + NativeScript, +} - /// like hash(), but prefixes 0x00 in the pre-image bytes, to match the specs - /// followed by cardano-cli. See https://github.com/input-output-hk/cardano-node/issues/2593 - pub fn script_hash(&self) -> Ed25519KeyHash { +#[wasm_bindgen] +impl NativeScript { + pub fn hash(&self, namespace: ScriptHashNamespace) -> Ed25519KeyHash { let mut bytes = Vec::with_capacity(self.to_bytes().len() + 1); - bytes.extend_from_slice(&vec![00]); + bytes.extend_from_slice(&vec![namespace as u8]); bytes.extend_from_slice(&self.to_bytes()); Ed25519KeyHash::from(blake2b224(bytes.as_ref())) } @@ -2439,7 +2443,9 @@ mod tests { let script = NativeScript::new_script_pubkey(&ScriptPubkey::new(&hash)); - let script_hash = ScriptHash::from_bytes(script.script_hash().to_bytes()).unwrap(); + let script_hash = ScriptHash::from_bytes( + script.hash(ScriptHashNamespace::NativeScript).to_bytes() + ).unwrap(); assert_eq!(hex::encode(&script_hash.to_bytes()), "187b8d3ddcb24013097c003da0b8d8f7ddcf937119d8f59dccd05a0f"); }