unify proof json, breaking older experimental data

This commit is contained in:
wiesche
2026-09-12 10:38:57 +02:00
parent 73c37fdc89
commit 4c84962bc1
3 changed files with 85 additions and 2 deletions
+2 -2
View File
@@ -597,7 +597,7 @@ pub trait OwnerRpc {
},
"proof_args": {
"suppress_proof": true,
"proof_type": "Invoice",
"proof_type": 1,
"memo": null,
"sender_address": null
}
@@ -685,7 +685,7 @@ pub trait OwnerRpc {
},
"proof_args": {
"suppress_proof": true,
"proof_type": "Invoice",
"proof_type": 1,
"memo": null,
"sender_address": null
}
+24
View File
@@ -95,6 +95,7 @@ pub struct ProofArgs {
/// If net change is positive during this step, whether to suppress the creation of payment proof
pub suppress_proof: bool,
/// Requested early payment proof type
#[serde(with = "crate::slate::payment_proof_type_serde")]
pub proof_type: ProofType,
/// Memo used when this step creates the payment proof
pub memo: Option<PaymentMemo>,
@@ -249,6 +250,29 @@ pub struct ContractRevokeArgsAPI {
mod tests {
use super::*;
#[test]
fn proof_args_json() {
for (proof_type, value) in [
(ProofType::Legacy, 0),
(ProofType::Invoice, 1),
(ProofType::SenderNonce, 2),
] {
let args = ProofArgs {
proof_type,
..Default::default()
};
let json = serde_json::to_value(args).unwrap();
assert_eq!(json["proof_type"], value);
let recovered: ProofArgs = serde_json::from_value(json).unwrap();
assert_eq!(recovered.proof_type, proof_type);
}
let mut json = serde_json::to_value(ProofArgs::default()).unwrap();
for invalid in [serde_json::json!(3), serde_json::json!("Invoice")] {
json["proof_type"] = invalid;
assert!(serde_json::from_value::<ProofArgs>(json.clone()).is_err());
}
}
#[test]
fn selection_args_json() {
let explicit: OutputSelectionArgs = serde_json::from_value(serde_json::json!({
+59
View File
@@ -791,18 +791,41 @@ pub struct StoredProofInfo {
pub sender_signature: Option<DalekSignature>,
// Fields beyond here are specific to early payment proofs
/// Assumed to be 0x00 (Legacy) if missing
#[serde(default, skip_serializing_if = "Option::is_none")]
pub proof_type: Option<u8>,
/// receiver's public nonce from signing
#[serde(
default,
with = "dalek_ser::option_pubkey_serde",
skip_serializing_if = "Option::is_none"
)]
pub receiver_public_nonce: Option<PublicKey>,
/// receiver's public excess from signing
#[serde(
default,
with = "dalek_ser::option_pubkey_serde",
skip_serializing_if = "Option::is_none"
)]
pub receiver_public_excess: Option<PublicKey>,
/// Timestamp provided by recipient when signing
#[serde(default, skip_serializing_if = "Option::is_none")]
pub timestamp: Option<DateTime<Utc>>,
/// Optional payment memo
#[serde(default, skip_serializing_if = "Option::is_none")]
pub memo: Option<PaymentMemo>,
/// Early-proof sender partial signature
#[serde(
default,
with = "secp_ser::option_sig_serde",
skip_serializing_if = "Option::is_none"
)]
pub sender_part_sig: Option<Signature>,
/// Untweaked sender public nonce for a sender-nonce proof
#[serde(
default,
with = "dalek_ser::option_pubkey_serde",
skip_serializing_if = "Option::is_none"
)]
pub sender_public_nonce: Option<PublicKey>,
}
@@ -1098,11 +1121,47 @@ mod tests {
"sender_signature": null
});
let expected = proof.clone();
let proof: StoredProofInfo = serde_json::from_value(proof).unwrap();
assert!(proof.receiver_signature.is_none());
let proof = serde_json::to_value(proof).unwrap();
assert!(proof.get("receiver_signature").is_some());
assert!(proof.get("promise_signature").is_none());
assert_eq!(proof, expected);
}
#[test]
fn stored_proof_json() {
let secp = Secp256k1::new();
let key = SecretKey::from_slice(&secp, &[1; 32]).unwrap();
let public_key = PublicKey::from_secret_key(&secp, &key).unwrap();
let signature = Signature::from_compact(&secp, &[11; 64]).unwrap();
let address = DalekSecretKey::from_bytes(&[1; 32]).verifying_key();
let proof = StoredProofInfo {
proof_type: Some(1),
receiver_public_nonce: Some(public_key),
receiver_public_excess: Some(public_key),
sender_public_nonce: Some(public_key),
sender_part_sig: Some(signature),
..StoredProofInfo::new(address, None, address, 0, None)
};
let value = serde_json::to_value(&proof).unwrap();
for field in [
"receiver_public_nonce",
"receiver_public_excess",
"sender_public_nonce",
] {
assert_eq!(value[field], public_key.serialize_vec(&secp, true).to_hex());
}
assert_eq!(value["sender_part_sig"], [11u8; 64].to_hex());
let recovered: StoredProofInfo = serde_json::from_value(value).unwrap();
assert_eq!(recovered.receiver_public_nonce, proof.receiver_public_nonce);
assert_eq!(
recovered.receiver_public_excess,
proof.receiver_public_excess
);
assert_eq!(recovered.sender_public_nonce, proof.sender_public_nonce);
assert_eq!(recovered.sender_part_sig, proof.sender_part_sig);
}
#[test]