feat(mcp): add policy_cbor_path arg to wallet_plutus_mint_unsigned
Mirrors the reference_script_path workaround already on wallet_send. Lets the caller hand aldabra a path to a hex-CBOR file inside the container instead of pasting the hex inline as a JSON-RPC arg, which lets us bypass the 2026-05-07 MCP large-string transport bug (>~ 4500 char hex strings get a 1-byte truncation between Claude Code and aldabra's stdio reader, surfacing as 'odd length' decode errors and blocking debug-build minting policies). policy_cbor_hex becomes Option<String>; new policy_cbor_path: Option<String> sits next to it. New resolver helper resolve_policy_cbor_bytes mirrors resolve_ref_script_bytes — at most one of the two may be set, exactly one must be set. Whitespace is stripped from file contents so the file may have trailing newlines. Unblocks Track #33 / preprod_test3: debug-build validators that overshoot the transport ceiling can now be minted via path arg.
This commit is contained in:
parent
1b9968cf3b
commit
e679874939
1 changed files with 64 additions and 4 deletions
|
|
@ -103,6 +103,48 @@ fn resolve_ref_script_bytes(
|
|||
}
|
||||
}
|
||||
|
||||
/// Resolve the Plutus minting-policy CBOR from EITHER an inline
|
||||
/// hex argument OR a file path inside the container. Caller passes
|
||||
/// both raw options; this fn enforces the "exactly one" rule and
|
||||
/// reads the file when path is set.
|
||||
///
|
||||
/// Mirrors [`resolve_ref_script_bytes`] — same workaround for the
|
||||
/// 2026-05-07 MCP transport bug where hex strings >~ 4500 chars
|
||||
/// get a 1-byte truncation between Claude Code and aldabra's stdio
|
||||
/// reader, surfacing as "odd length" hex decode errors and blocking
|
||||
/// debug-build minting policies. Reading from a file inside the
|
||||
/// container bypasses the JSON-RPC arg path entirely.
|
||||
fn resolve_policy_cbor_bytes(
|
||||
cbor_hex: Option<&str>,
|
||||
path: Option<&str>,
|
||||
) -> Result<Vec<u8>, String> {
|
||||
match (cbor_hex, path) {
|
||||
(Some(_), Some(_)) => Err(
|
||||
"set at most one of policy_cbor_hex / policy_cbor_path".into(),
|
||||
),
|
||||
(Some(s), None) => {
|
||||
let cleaned: String = s.chars().filter(|c| !c.is_whitespace()).collect();
|
||||
hex_decode(&cleaned).map_err(|e| format!("decode policy_cbor_hex: {e}"))
|
||||
}
|
||||
(None, Some(p)) => {
|
||||
let raw = std::fs::read_to_string(p)
|
||||
.map_err(|e| format!("read policy_cbor_path '{p}': {e}"))?;
|
||||
let cleaned: String = raw.chars().filter(|c| !c.is_whitespace()).collect();
|
||||
if cleaned.is_empty() {
|
||||
return Err(format!(
|
||||
"policy_cbor_path '{p}' contained no hex characters"
|
||||
));
|
||||
}
|
||||
hex_decode(&cleaned).map_err(|e| {
|
||||
format!("decode policy_cbor_path '{p}' contents: {e}")
|
||||
})
|
||||
}
|
||||
(None, None) => {
|
||||
Err("must set exactly one of policy_cbor_hex / policy_cbor_path".into())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse a user-supplied script-kind string ("PlutusV1" / "PlutusV2"
|
||||
/// / "PlutusV3" / "Native") into the pallas `ScriptKind` enum used
|
||||
/// by the reference-script attachment helper. Case-insensitive,
|
||||
|
|
@ -398,7 +440,22 @@ pub struct PolicyCreateArgs {
|
|||
pub struct PlutusMintUnsignedArgs {
|
||||
/// Plutus minting policy script CBOR (hex). 28-byte blake2b
|
||||
/// hash with the version tag becomes the policy_id.
|
||||
pub policy_cbor_hex: String,
|
||||
/// At most one of `policy_cbor_hex` or `policy_cbor_path` may
|
||||
/// be set; exactly one must be set.
|
||||
#[serde(default)]
|
||||
pub policy_cbor_hex: Option<String>,
|
||||
/// Path INSIDE THE ALDABRA CONTAINER to a file containing
|
||||
/// hex-encoded Plutus policy CBOR. Use INSTEAD of
|
||||
/// `policy_cbor_hex` for scripts >~ 4500 chars to bypass the
|
||||
/// MCP large-string transport bug (caught 2026-05-07: hex strings
|
||||
/// > ~4500 chars get a 1-byte truncation + structural rearrangement
|
||||
/// somewhere between Claude Code and aldabra's stdio reader,
|
||||
/// surfacing as "odd length" hex decode errors). File contents
|
||||
/// may include leading/trailing whitespace; only hex chars are
|
||||
/// decoded. At most one of `policy_cbor_hex` or `policy_cbor_path`
|
||||
/// may be set; exactly one must be set.
|
||||
#[serde(default)]
|
||||
pub policy_cbor_path: Option<String>,
|
||||
/// Plutus version: "v1", "v2", or "v3".
|
||||
pub policy_version: String,
|
||||
/// PlutusData CBOR redeemer (hex) for the mint redeemer entry.
|
||||
|
|
@ -1612,12 +1669,13 @@ impl WalletService {
|
|||
|
||||
#[tool(
|
||||
name = "wallet_plutus_mint_unsigned",
|
||||
description = "Build (no sign) a Plutus-policy mint with custom output. Distinct from wallet_mint (native script only). Args: policy_cbor_hex + policy_version (v1/v2/v3) + redeemer_cbor_hex + ex_units (mem+steps), mint_assets (array of {asset_name_hex, quantity}), dest_address + dest_lovelace + dest_extra_assets + dest_inline_datum_cbor_hex (req for script addrs), required_input_refs (array of 'txhash#index' UTxOs that MUST be spent — e.g. gstOutRef for parameterized policies). Returns JSON {cbor_hex, summary}. Pass through wallet_sign_partial → wallet_submit_signed_tx. Designed for Agora-style DAO bringup: governor bootstrap, stake bootstrap, proposal create."
|
||||
description = "Build (no sign) a Plutus-policy mint with custom output. Distinct from wallet_mint (native script only). Args: policy_cbor_hex OR policy_cbor_path (use path for >~4500-char scripts to bypass the MCP large-string transport bug) + policy_version (v1/v2/v3) + redeemer_cbor_hex + ex_units (mem+steps), mint_assets (array of {asset_name_hex, quantity}), dest_address + dest_lovelace + dest_extra_assets + dest_inline_datum_cbor_hex (req for script addrs), required_input_refs (array of 'txhash#index' UTxOs that MUST be spent — e.g. gstOutRef for parameterized policies). Returns JSON {cbor_hex, summary}. Pass through wallet_sign_partial → wallet_submit_signed_tx. Designed for Agora-style DAO bringup: governor bootstrap, stake bootstrap, proposal create."
|
||||
)]
|
||||
async fn wallet_plutus_mint_unsigned(
|
||||
&self,
|
||||
#[tool(aggr)] PlutusMintUnsignedArgs {
|
||||
policy_cbor_hex,
|
||||
policy_cbor_path,
|
||||
policy_version,
|
||||
redeemer_cbor_hex,
|
||||
mint_assets,
|
||||
|
|
@ -1639,8 +1697,10 @@ impl WalletService {
|
|||
));
|
||||
}
|
||||
|
||||
let policy_cbor =
|
||||
hex_decode(&policy_cbor_hex).map_err(|e| format!("decode policy_cbor: {e}"))?;
|
||||
let policy_cbor = resolve_policy_cbor_bytes(
|
||||
policy_cbor_hex.as_deref(),
|
||||
policy_cbor_path.as_deref(),
|
||||
)?;
|
||||
let redeemer_cbor =
|
||||
hex_decode(&redeemer_cbor_hex).map_err(|e| format!("decode redeemer: {e}"))?;
|
||||
let policy_ver = match policy_version.trim().to_ascii_lowercase().as_str() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue