Skip to content

Commit

Permalink
fixed plutus script encoding
Browse files Browse the repository at this point in the history
  • Loading branch information
alessandrokonrad committed Jan 18, 2025
1 parent f836955 commit 6bc52c8
Show file tree
Hide file tree
Showing 10 changed files with 169 additions and 18 deletions.
1 change: 1 addition & 0 deletions src/core/libs/lucid_core/pkg/lucid_core.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,5 +206,6 @@ export class Utils {
free(): void;
static applyParamsToScript(params: string, script: string): string;
static encodeBech32(hrp: string, data: string): string;
static applySingleCborEncoding(script: string): string;
static applyDoubleCborEncoding(script: string): string;
}
24 changes: 24 additions & 0 deletions src/core/libs/lucid_core/pkg/lucid_core_bg.js
Original file line number Diff line number Diff line change
Expand Up @@ -1151,6 +1151,30 @@ export class Utils {
wasm.__wbindgen_free(deferred4_0, deferred4_1, 1);
}
}
/**
* @param {string} script
* @returns {string}
*/
static applySingleCborEncoding(script) {
let deferred3_0;
let deferred3_1;
try {
const ptr0 = passStringToWasm0(script, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
const len0 = WASM_VECTOR_LEN;
const ret = wasm.utils_applySingleCborEncoding(ptr0, len0);
var ptr2 = ret[0];
var len2 = ret[1];
if (ret[3]) {
ptr2 = 0; len2 = 0;
throw takeFromExternrefTable0(ret[2]);
}
deferred3_0 = ptr2;
deferred3_1 = len2;
return getStringFromWasm0(ptr2, len2);
} finally {
wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);
}
}
/**
* @param {string} script
* @returns {string}
Expand Down
Binary file modified src/core/libs/lucid_core/pkg/lucid_core_bg.wasm
Binary file not shown.
1 change: 1 addition & 0 deletions src/core/libs/lucid_core/pkg/lucid_core_bg.wasm.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export const instructionsigner_getPartialWitnessSet: (a: number) => [number, num
export const instructionsigner_commit: (a: number) => [number, number];
export const utils_applyParamsToScript: (a: number, b: number, c: number, d: number) => [number, number, number, number];
export const utils_encodeBech32: (a: number, b: number, c: number, d: number) => [number, number, number, number];
export const utils_applySingleCborEncoding: (a: number, b: number) => [number, number, number, number];
export const utils_applyDoubleCborEncoding: (a: number, b: number) => [number, number, number, number];
export const __wbg_codec_free: (a: number, b: number) => void;
export const __wbg_hasher_free: (a: number, b: number) => void;
Expand Down
27 changes: 23 additions & 4 deletions src/core/libs/lucid_core/src/codec.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use crate::utils::Utils;

use super::{
addresses::{Addresses, Credential},
error::{CoreErr, CoreError, CoreResult},
Expand All @@ -21,7 +23,7 @@ use std::{
str::FromStr,
};
use tsify::Tsify;
use wasm_bindgen::{prelude::wasm_bindgen, UnwrapThrowExt};
use wasm_bindgen::prelude::wasm_bindgen;

#[wasm_bindgen]
pub struct Codec;
Expand Down Expand Up @@ -347,6 +349,23 @@ pub enum Script {
PlutusV3 { script: String },
}

impl Script {
pub fn try_double_cbor(&self) -> CoreResult<Script> {
Ok(match self {
Self::PlutusV1 { script } => Script::PlutusV1 {
script: Utils::apply_double_cbor_encoding(&script)?,
},
Self::PlutusV2 { script } => Script::PlutusV2 {
script: Utils::apply_double_cbor_encoding(&script)?,
},
Self::PlutusV3 { script } => Script::PlutusV3 {
script: Utils::apply_double_cbor_encoding(&script)?,
},
native => native.clone(),
})
}
}

#[derive(Tsify, Serialize, Deserialize, Debug, Clone, PartialEq)]
#[tsify(into_wasm_abi, from_wasm_abi)]
pub struct Assets(HashMap<String, i128>);
Expand Down Expand Up @@ -614,9 +633,9 @@ impl TryFrom<Assets> for Mint {
continue;
}
let unit_vec = hex::decode(unit).map_err(CoreError::msg)?;
let (policy_id, asset_name) = unit_vec
.split_at_checked(28)
.expect_throw("Unit needs to be at least 28 bytes (length of policy id)");
let (policy_id, asset_name) = unit_vec.split_at_checked(28).ok_or(CoreError::msg(
"Unit needs to be at least 28 bytes (length of policy id)",
))?;
value
.entry(policy_id.to_vec())
.or_default()
Expand Down
3 changes: 3 additions & 0 deletions src/core/libs/lucid_core/src/hasher.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use crate::utils::Utils;

use super::{
codec::Script,
error::{CoreError, CoreResult},
Expand Down Expand Up @@ -76,6 +78,7 @@ impl Hasher {

#[wasm_bindgen(js_name = hashScript)]
pub fn hash_script(script: Script) -> CoreResult<String> {
let script = script.try_double_cbor()?;
Ok(match script {
Script::Native { script } => {
NativeScript::decode_fragment(&hex::decode(script).map_err(CoreError::msg)?)
Expand Down
41 changes: 40 additions & 1 deletion src/core/libs/lucid_core/src/instruction_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use super::{
instruction_signer::InstructionSigner,
};
use crate::error::CoreError;
use crate::utils::Utils;
use num_integer::Roots;
use pallas_addresses::Address;
use pallas_primitives::{
Expand Down Expand Up @@ -560,6 +561,8 @@ impl InstructionBuilder {
.insert(label, Either::Right(value));
}
Instruction::AttachScript { script } => {
let script = script.try_double_cbor()?;

self.add_language_or_keys(&script)?;

let hash: ScriptHash = Hasher::hash_script(script.clone())?.parse().unwrap();
Expand Down Expand Up @@ -2176,7 +2179,7 @@ mod tests {
use uplc::{Constr, Fragment, PlutusData};

use super::{
Change, Instruction, InstructionBuilder, Instructions, RelevantProtocolParameters,
Change, DatumVariant, Instruction, InstructionBuilder, Instructions, RelevantProtocolParameters
};
use crate::{
addresses::{Addresses, Network},
Expand Down Expand Up @@ -2658,4 +2661,40 @@ mod tests {
assert!(tx.transaction_body.auxiliary_data_hash.is_some());
assert!(tx.transaction_body.script_data_hash.is_none());
}

#[test]
fn test_nebula_create_royalty() {
let builder = setup_builder(None);


let redeemer = hex::encode(
PlutusData::Constr(Constr::from_index(0, vec![]))
.encode_fragment()
.unwrap(),
);


let signer = builder
.commit(Instructions(vec![
Instruction::CollectFrom { utxos: vec![
Utxo {tx_hash: "3b06c12f0df26630dc5b454a3738bfbf318d3caba5754dc9096e01094d2e2e46".to_string(),
output_index: 4,
address: ADDRESS_OTHER.to_string(),
assets: Assets::from([("afcaf4f8dc27c51ada41ace7008ccef79b7d3a71d4a7c995adfd7cd0000de1404275643332".to_string(), 1),
("afcaf4f8dc27c51ada41ace7008ccef79b7d3a71d4a7c995adfd7cd0000de14042756430".to_string(), 1),
("afcaf4f8dc27c51ada41ace7008ccef79b7d3a71d4a7c995adfd7cd0000de1404275643235".to_string(), 1),
("lovelace".to_string(), 1314550),
("afcaf4f8dc27c51ada41ace7008ccef79b7d3a71d4a7c995adfd7cd0000de14042756431313131".to_string(),1)]),
datum: None,
datum_hash: None,
script_ref: None}
], redeemer: None },
Instruction::Mint { assets: Assets::from_unit("62d864f576a29db34bc681a44d06639f593d71751453c5f2fcb9d663001f4d70526f79616c7479".to_string(), 1), redeemer: Some(redeemer.clone()) },
Instruction::PayTo { assets: Assets::from_unit("62d864f576a29db34bc681a44d06639f593d71751453c5f2fcb9d663001f4d70526f79616c7479".to_string(), 1), address: ADDRESS.to_string(), datum_variant: Some(DatumVariant::Inline("d8798383d87984d87982d87981581c1a3d2cd7e9f8a05714ba8c4a0d96f7e1f60d5455956bfe74de7b157fd87a80190271d879811a00061a80d87a80d87984d87982d87981581ca9516d49d80c2deb7a9029ef421ca8b5e5b9e0b28dbd6fc2c6726fa7d87a801909c4d87a80d87a80d87984d87982d87981581cde467543f7cee91138085797279a458e74020c30be0b325ceada11d2d87a801909c4d87a80d879811a0016e36001d87980".to_string())), script_ref: None },
Instruction::AttachScript { script: Script::PlutusV2 { script: "5836583458e3010030034c0129d87982d8798158203b06c12f0df26630dc5b454a3738bfbf318d3caba5754dc9096e01094d2e2e46040001".to_string() } }
]))
.unwrap();

// let tx = signer.get_tx();
}
}
53 changes: 45 additions & 8 deletions src/core/libs/lucid_core/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ impl Utils {
pub fn apply_params_to_script(params: &str, script: &str) -> CoreResult<String> {
let params_bytes = hex::decode(params).map_err(CoreError::msg)?;
let script_bytes =
hex::decode(Utils::apply_double_cbor_encoding(script)?).map_err(CoreError::msg)?;
hex::decode(Utils::apply_single_cbor_encoding(script)?).map_err(CoreError::msg)?;
let result = uplc::tx::apply_params_to_script(&params_bytes, &script_bytes)
.map_err(CoreError::msg)?;
Ok(hex::encode(result))
Expand All @@ -26,27 +26,64 @@ impl Utils {
Ok(result)
}

#[wasm_bindgen(js_name = applySingleCborEncoding)]
pub fn apply_single_cbor_encoding(script: &str) -> CoreResult<String> {
let script_bytes: Bytes = hex::decode(script).map_err(CoreError::msg)?.into();
match pallas_codec::minicbor::decode::<Bytes>(&script_bytes) {
Ok(script_bytes_decoded) => {
match pallas_codec::minicbor::decode::<Bytes>(&script_bytes_decoded) {
Ok(_) => return Ok(hex::encode(script_bytes_decoded.to_vec())),
Err(_) => return Ok(script.to_string()),
}
}
Err(_) => {
return Err(CoreError::msg(
"Plutus script does not have any cbor wrapper",
))
}
}
}

#[wasm_bindgen(js_name = applyDoubleCborEncoding)]
pub fn apply_double_cbor_encoding(script: &str) -> CoreResult<String> {
let script_bytes: Bytes = hex::decode(script).map_err(CoreError::msg)?.into();
match pallas_codec::minicbor::decode::<Bytes>(&script_bytes) {
Ok(script_bytes_decoded) => {
match pallas_codec::minicbor::decode::<Bytes>(&script_bytes_decoded) {
Ok(_) => return Ok(script.to_string()),
_ => {}
Ok(_) => Ok(script.to_string()),
Err(_) => {
let mut buffer = Vec::new();
pallas_codec::minicbor::encode(&script_bytes, &mut buffer)
.map_err(CoreError::msg)?;
Ok(hex::encode(buffer))
}
}
}
_ => return Err(CoreError::msg("Cannot cbor encode script")),
};
let mut buffer = Vec::new();
pallas_codec::minicbor::encode(&script_bytes, &mut buffer).map_err(CoreError::msg)?;
Ok(hex::encode(buffer))
Err(_) => {
return Err(CoreError::msg(
"Plutus script does not have any cbor wrapper",
))
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_apply_single_cbor_encoding() {
assert_eq!(
Utils::apply_single_cbor_encoding("49480100002221200101").unwrap(),
"480100002221200101"
);
assert_eq!(
Utils::apply_single_cbor_encoding("480100002221200101").unwrap(),
"480100002221200101"
);
assert!(Utils::apply_single_cbor_encoding("0100002221200101").is_err(),);
}

#[test]
fn test_apply_double_cbor_encoding() {
assert_eq!(
Expand Down
6 changes: 1 addition & 5 deletions src/utils/script_utility.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
Lucid,
NativeScript,
Script,
Utils,
} from "../mod.ts";

export class ScriptUtility<T extends unknown[] = Data[]> {
Expand All @@ -32,10 +31,7 @@ export class ScriptUtility<T extends unknown[] = Data[]> {
);
this.script = { type: script.type, script: scriptWithParams };
} else {
this.script = {
type: script.type,
script: Utils.applyDoubleCborEncoding(script.script),
};
this.script = script;
}
} else {
this.script = {
Expand Down
31 changes: 31 additions & 0 deletions tests/emulator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -239,3 +239,34 @@ Deno.test("Check required signer", async () => {
await tx.partialSign();
await lucid.awaitTx(await tx.commit().then((tx) => tx.submit()));
});

Deno.test("Evaluate matching numbers contract", async () => {
const matchingNumber = lucid.newScript({
type: "PlutusV1",
script:
"59099a59099701000033233223322323233322232333222323333333322222222323332223233332222323233223233322232333222323233223322323233333222223322332233223322332233222222323253353031333006375a00a6eb4010cccd5cd19b8735573aa004900011980499191919191919191919191999ab9a3370e6aae754029200023333333333017335025232323333573466e1cd55cea8012400046603a60706ae854008c0a8d5d09aba250022350573530583357389201035054310005949926135573ca00226ea8004d5d0a80519a8128131aba150093335502c75ca0566ae854020ccd540b1d728159aba1500733502504135742a00c66a04a66aa0a4094eb4d5d0a8029919191999ab9a3370e6aae7540092000233501f3232323333573466e1cd55cea80124000466a04e66a080eb4d5d0a80118229aba135744a00446a0b66a60b866ae712401035054310005d49926135573ca00226ea8004d5d0a8011919191999ab9a3370e6aae7540092000233502533504075a6ae854008c114d5d09aba2500223505b35305c3357389201035054310005d49926135573ca00226ea8004d5d09aba250022350573530583357389201035054310005949926135573ca00226ea8004d5d0a80219a812bae35742a00666a04a66aa0a4eb88004d5d0a801181b9aba135744a00446a0a66a60a866ae71241035054310005549926135744a00226ae8940044d5d1280089aba25001135744a00226ae8940044d5d1280089aba25001135573ca00226ea8004d5d0a8011919191999ab9a3370ea00290031180e181c9aba135573ca00646666ae68cdc3a801240084603660866ae84d55cf280211999ab9a3370ea00690011180d98171aba135573ca00a46666ae68cdc3a802240004603c6eb8d5d09aab9e500623504e35304f3357389201035054310005049926499264984d55cea80089baa001357426ae8940088d411cd4c120cd5ce2490350543100049499261048135046353047335738920103505435000484984d55cf280089baa0012212330010030022001222222222212333333333300100b00a00900800700600500400300220012212330010030022001122123300100300212001122123300100300212001122123300100300212001212222300400521222230030052122223002005212222300100520011232230023758002640026aa068446666aae7c004940388cd4034c010d5d080118019aba200203323232323333573466e1cd55cea801a4000466600e6464646666ae68cdc39aab9d5002480008cc034c0c4d5d0a80119a8098169aba135744a00446a06c6a606e66ae712401035054310003849926135573ca00226ea8004d5d0a801999aa805bae500a35742a00466a01eeb8d5d09aba25002235032353033335738921035054310003449926135744a00226aae7940044dd50009110919980080200180110009109198008018011000899aa800bae75a224464460046eac004c8004d540b888c8cccd55cf80112804919a80419aa81898031aab9d5002300535573ca00460086ae8800c0b84d5d08008891001091091198008020018900089119191999ab9a3370ea002900011a80418029aba135573ca00646666ae68cdc3a801240044a01046a0526a605466ae712401035054310002b499264984d55cea80089baa001121223002003112200112001232323333573466e1cd55cea8012400046600c600e6ae854008dd69aba135744a00446a0466a604866ae71241035054310002549926135573ca00226ea80048848cc00400c00880048c8cccd5cd19b8735573aa002900011bae357426aae7940088d407cd4c080cd5ce24810350543100021499261375400224464646666ae68cdc3a800a40084a00e46666ae68cdc3a8012400446a014600c6ae84d55cf280211999ab9a3370ea00690001280511a8111a981199ab9c490103505431000244992649926135573aa00226ea8004484888c00c0104488800844888004480048c8cccd5cd19b8750014800880188cccd5cd19b8750024800080188d4068d4c06ccd5ce249035054310001c499264984d55ce9baa0011220021220012001232323232323333573466e1d4005200c200b23333573466e1d4009200a200d23333573466e1d400d200823300b375c6ae854014dd69aba135744a00a46666ae68cdc3a8022400c46601a6eb8d5d0a8039bae357426ae89401c8cccd5cd19b875005480108cc048c050d5d0a8049bae357426ae8940248cccd5cd19b875006480088c050c054d5d09aab9e500b23333573466e1d401d2000230133016357426aae7940308d407cd4c080cd5ce2481035054310002149926499264992649926135573aa00826aae79400c4d55cf280109aab9e500113754002424444444600e01044244444446600c012010424444444600a010244444440082444444400644244444446600401201044244444446600201201040024646464646666ae68cdc3a800a400446660106eb4d5d0a8021bad35742a0066eb4d5d09aba2500323333573466e1d400920002300a300b357426aae7940188d4040d4c044cd5ce2490350543100012499264984d55cea80189aba25001135573ca00226ea80048488c00800c888488ccc00401401000c80048c8c8cccd5cd19b875001480088c018dd71aba135573ca00646666ae68cdc3a80124000460106eb8d5d09aab9e500423500a35300b3357389201035054310000c499264984d55cea80089baa001212230020032122300100320011122232323333573466e1cd55cea80124000466aa016600c6ae854008c014d5d09aba25002235007353008335738921035054310000949926135573ca00226ea8004498480048004448848cc00400c008448004448c8c00400488cc00cc008008004ccc888ccc888cccccccc88888888cc88ccccc88888cccc8888ccc888cc88cc88cc88ccc888cc88cc88ccc888cc88cc88cc88cc88888ccd5cd19b8700300201e01d2212330010030022001222222222212333333333300100b00a00900800700600500400300220012212330010030022001222123330010040030022001112200212212233001004003120011122123300100300211200122123300100300220011212230020031122001120011221233001003002120011221233001003002120011221233001003002120011220021220012001121222300300411222002112220011200121222230040052122223003005212222300200521222230010052001221233001003002200121222222230070082212222222330060090082122222223005008122222220041222222200322122222223300200900822122222223300100900820012122300200322212233300100500400320012122300200321223001003200101",
});

const matchingNumberAddress = matchingNumber.toAddress();

const tx = await lucid
.newTx()
.payToContract(matchingNumberAddress, Data.to(33n), { lovelace: 2000000n })
.commit();

const signedTx = await tx.sign().commit();

await lucid.awaitTx(await signedTx.submit());

const [utxo] = await lucid.utxosAt(matchingNumberAddress);

const txRedeem = await lucid
.newTx()
.collectFrom([utxo], Data.to(33n))
.attachScript(matchingNumber.script)
.commit();

const signedTxRedeem = await txRedeem.sign().commit();

await lucid.awaitTx(await signedTxRedeem.submit());
});

0 comments on commit 6bc52c8

Please sign in to comment.