plutus_mint: thread additional_signers into tx body's required_signers
On Babbage+, Plutus's TxInfo.signatories is populated only from the tx body's required_signers field — vkey witnesses alone don't surface in the script context. Without this, any Agora script that calls pauthorizedBy/txSignedBy fails. Stake-bootstrap on preprod erred because the owner pkh wasn't in signatories despite the wallet signing the tx. MCP layer always passes [wallet_pkh]; callers can append cosigner pkhs for multi-sig flows.
This commit is contained in:
parent
1e20b71cc9
commit
6fa93a3c68
2 changed files with 21 additions and 0 deletions
|
|
@ -95,6 +95,16 @@ pub struct PlutusMintArgs<'a> {
|
||||||
/// Optional inline datum on the recipient output. Required for
|
/// Optional inline datum on the recipient output. Required for
|
||||||
/// any send to a Plutus script address.
|
/// any send to a Plutus script address.
|
||||||
pub dest_inline_datum_cbor: Option<&'a [u8]>,
|
pub dest_inline_datum_cbor: Option<&'a [u8]>,
|
||||||
|
/// PKH hashes to add to the tx body's `required_signers` field.
|
||||||
|
/// On Babbage+, Plutus's `TxInfo.signatories` is populated ONLY
|
||||||
|
/// from `required_signers` — VKey witnesses alone are not enough
|
||||||
|
/// for any `pauthorizedBy` / `txSignedBy` check inside a script.
|
||||||
|
/// MCP layer always passes this wallet's payment-key pkh; pass
|
||||||
|
/// extra entries for cosigners. Empty slice = scripts that don't
|
||||||
|
/// check signatories (e.g. Agora's GST policy).
|
||||||
|
/// Caught 2026-05-07 on Agora's stake-policy bootstrap on preprod
|
||||||
|
/// — script erred because owner pkh was absent from signatories.
|
||||||
|
pub additional_signers: &'a [Hash<28>],
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_address(bech32: &str) -> Result<PallasAddress, WalletError> {
|
fn parse_address(bech32: &str) -> Result<PallasAddress, WalletError> {
|
||||||
|
|
@ -586,6 +596,10 @@ fn prepare_plutus_mint(
|
||||||
.fee(fee)
|
.fee(fee)
|
||||||
.network_id(network_id);
|
.network_id(network_id);
|
||||||
|
|
||||||
|
for pkh in args.additional_signers {
|
||||||
|
staging = staging.disclosed_signer(*pkh);
|
||||||
|
}
|
||||||
|
|
||||||
// Plutus V1/V2/V3 each need their cost-model wired via
|
// Plutus V1/V2/V3 each need their cost-model wired via
|
||||||
// language_view so pallas computes script_data_hash on the tx
|
// language_view so pallas computes script_data_hash on the tx
|
||||||
// body. Without it, chain rejects with PPViewHashesDontMatch.
|
// body. Without it, chain rejects with PPViewHashesDontMatch.
|
||||||
|
|
@ -785,6 +799,7 @@ mod tests {
|
||||||
dest_lovelace: 3_000_000,
|
dest_lovelace: 3_000_000,
|
||||||
dest_extra_assets: &[],
|
dest_extra_assets: &[],
|
||||||
dest_inline_datum_cbor: Some(&UNIT_DATUM_CBOR),
|
dest_inline_datum_cbor: Some(&UNIT_DATUM_CBOR),
|
||||||
|
additional_signers: &[],
|
||||||
};
|
};
|
||||||
let err = build_signed_plutus_mint(
|
let err = build_signed_plutus_mint(
|
||||||
&payment,
|
&payment,
|
||||||
|
|
@ -816,6 +831,7 @@ mod tests {
|
||||||
dest_lovelace: 3_000_000,
|
dest_lovelace: 3_000_000,
|
||||||
dest_extra_assets: &[],
|
dest_extra_assets: &[],
|
||||||
dest_inline_datum_cbor: Some(&UNIT_DATUM_CBOR),
|
dest_inline_datum_cbor: Some(&UNIT_DATUM_CBOR),
|
||||||
|
additional_signers: &[],
|
||||||
};
|
};
|
||||||
let err = build_signed_plutus_mint(
|
let err = build_signed_plutus_mint(
|
||||||
&payment,
|
&payment,
|
||||||
|
|
@ -857,6 +873,7 @@ mod tests {
|
||||||
dest_lovelace: 3_000_000,
|
dest_lovelace: 3_000_000,
|
||||||
dest_extra_assets: &[],
|
dest_extra_assets: &[],
|
||||||
dest_inline_datum_cbor: Some(&UNIT_DATUM_CBOR),
|
dest_inline_datum_cbor: Some(&UNIT_DATUM_CBOR),
|
||||||
|
additional_signers: &[],
|
||||||
};
|
};
|
||||||
let err = build_signed_plutus_mint(
|
let err = build_signed_plutus_mint(
|
||||||
&payment,
|
&payment,
|
||||||
|
|
@ -895,6 +912,7 @@ mod tests {
|
||||||
dest_lovelace: 3_000_000,
|
dest_lovelace: 3_000_000,
|
||||||
dest_extra_assets: &[],
|
dest_extra_assets: &[],
|
||||||
dest_inline_datum_cbor: Some(&UNIT_DATUM_CBOR),
|
dest_inline_datum_cbor: Some(&UNIT_DATUM_CBOR),
|
||||||
|
additional_signers: &[],
|
||||||
};
|
};
|
||||||
// V3 cost model is required for staging language_view; test
|
// V3 cost model is required for staging language_view; test
|
||||||
// ProtocolParams::default() should provide one for preprod.
|
// ProtocolParams::default() should provide one for preprod.
|
||||||
|
|
|
||||||
|
|
@ -1654,6 +1654,8 @@ impl WalletService {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let wallet_pkh = self.inner.payment_key.public_key_hash();
|
||||||
|
let signers = [wallet_pkh];
|
||||||
let core_args = CorePlutusMintArgs {
|
let core_args = CorePlutusMintArgs {
|
||||||
required_inputs: &required,
|
required_inputs: &required,
|
||||||
policy_cbor: &policy_cbor,
|
policy_cbor: &policy_cbor,
|
||||||
|
|
@ -1665,6 +1667,7 @@ impl WalletService {
|
||||||
dest_lovelace,
|
dest_lovelace,
|
||||||
dest_extra_assets: &core_extras,
|
dest_extra_assets: &core_extras,
|
||||||
dest_inline_datum_cbor: datum_bytes.as_deref(),
|
dest_inline_datum_cbor: datum_bytes.as_deref(),
|
||||||
|
additional_signers: &signers,
|
||||||
};
|
};
|
||||||
|
|
||||||
let unsigned = build_unsigned_plutus_mint(
|
let unsigned = build_unsigned_plutus_mint(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue