Skip to content

Commit 7be1922

Browse files
committed
aaaaaaaaaaa #2
1 parent ed2c807 commit 7be1922

File tree

2 files changed

+125
-10
lines changed

2 files changed

+125
-10
lines changed

src/cli/commands.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -992,6 +992,10 @@ enum VerificationsCliAction {
992992
#[arg(long)]
993993
request_offer: Option<String>,
994994

995+
/// Address to send funds from verification request offer to
996+
#[arg(long)]
997+
request_offer_recipient: Option<String>,
998+
995999
/// Signatures (comma-separated list)
9961000
#[arg(long)]
9971001
sigs: String,
@@ -1600,6 +1604,7 @@ pub async fn run_cli() {
16001604
asset_id,
16011605
comment,
16021606
request_offer,
1607+
request_offer_recipient,
16031608
sigs,
16041609
testnet11,
16051610
fee,
@@ -1609,6 +1614,7 @@ pub async fn run_cli() {
16091614
asset_id,
16101615
comment,
16111616
request_offer,
1617+
request_offer_recipient,
16121618
sigs,
16131619
testnet11,
16141620
fee,

src/cli/verifications/broadcast_launch.rs

Lines changed: 119 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,42 @@
11
use bech32::Variant;
22
use chia::{
3-
protocol::{Bytes, Bytes32, SpendBundle},
3+
clvm_utils::ToTreeHash,
4+
protocol::{Bytes, Bytes32, Coin, SpendBundle},
45
traits::Streamable,
56
};
7+
use chia_puzzle_types::{
8+
cat::CatArgs,
9+
offer::{NotarizedPayment, Payment},
10+
};
11+
use chia_puzzles::{CAT_PUZZLE_HASH, SETTLEMENT_PAYMENT_HASH};
612
use chia_wallet_sdk::{
7-
driver::{decompress_offer_bytes, DriverError, Launcher, OfferError},
8-
types::Conditions,
13+
driver::{decompress_offer_bytes, Launcher, Puzzle},
14+
types::{announcement_id, Condition, Conditions},
15+
utils::Address,
916
};
1017
use clvm_traits::clvm_quote;
1118
use clvmr::{serde::node_from_bytes, NodePtr};
1219

1320
use crate::{
1421
get_constants, get_latest_data_for_asset_id, hex_string_to_bytes32,
15-
multisig_broadcast_thing_finish, multisig_broadcast_thing_start, CliError, MedievalVault,
16-
Verification, VerificationInfo, VerificationLauncherKVList, VerifiedData,
22+
multisig_broadcast_thing_finish, multisig_broadcast_thing_start, yes_no_prompt, CliError,
23+
MedievalVault, Verification, VerificationAsserter, VerificationLauncherKVList, VerifiedData,
1724
};
1825

1926
pub async fn verifications_broadcast_launch(
2027
launcher_id_str: String,
2128
asset_id_str: String,
2229
comment: String,
2330
request_offer: Option<String>,
31+
request_offer_recipient: Option<String>,
2432
signatures_str: String,
2533
testnet11: bool,
2634
fee_str: String,
2735
) -> Result<(), CliError> {
2836
let launcher_id = hex_string_to_bytes32(&launcher_id_str)?;
2937
let asset_id = hex_string_to_bytes32(&asset_id_str)?;
3038

31-
let (signature_from_signers, pubkeys, client, mut ctx, medieval_vault) =
39+
let (mut signature_from_signers, pubkeys, client, mut ctx, medieval_vault) =
3240
multisig_broadcast_thing_start(signatures_str, launcher_id_str, testnet11).await?;
3341

3442
println!(
@@ -109,11 +117,112 @@ pub async fn verifications_broadcast_launch(
109117
}
110118
let spend_bundle = SpendBundle::from_bytes(&spend_bundle_bytes).unwrap();
111119

112-
// todo: find payment and send it to recipient
113-
// todo: find verification asserter
114-
// todo: spend verification asserter
120+
let verification_asserter = VerificationAsserter::from(
121+
launcher_id,
122+
verified_data.version,
123+
verified_data.asset_id.tree_hash(),
124+
verified_data.data_hash.tree_hash(),
125+
);
126+
let verification_asserter_puzzle_hash: Bytes32 = verification_asserter.tree_hash().into();
127+
128+
let mut payment_sent = false;
129+
let mut verification_asserter_spent = false;
130+
let mut conds = Conditions::new();
131+
for coin_spend in spend_bundle.coin_spends.into_iter() {
132+
let recipient_puzzle_hash =
133+
Address::decode(&request_offer_recipient.ok_or(CliError::Custom(
134+
"Verification offer provided but recipient not specified".to_string(),
135+
))?)?
136+
.puzzle_hash;
137+
138+
let puzzle_ptr = ctx.alloc(&coin_spend.puzzle_reveal)?;
139+
let solution_ptr = ctx.alloc(&coin_spend.solution)?;
140+
let output = ctx.run(puzzle_ptr, solution_ptr)?;
141+
let output = ctx.extract::<Conditions>(output)?;
142+
143+
let puzzle = Puzzle::parse(&ctx, puzzle_ptr);
144+
match puzzle {
145+
Puzzle::Curried(puzzle) => {
146+
if puzzle.mod_hash == CAT_PUZZLE_HASH.into() {
147+
let payment_cat_asset_id =
148+
ctx.extract::<CatArgs<NodePtr>>(puzzle.args)?.asset_id;
149+
let offer_puzzle_hash: Bytes32 = CatArgs::curry_tree_hash(
150+
payment_cat_asset_id,
151+
SETTLEMENT_PAYMENT_HASH.into(),
152+
)
153+
.into();
154+
155+
if let Some(cc) = output.iter().find_map(|c| match c {
156+
Condition::CreateCoin(cc) => {
157+
if cc.puzzle_hash == offer_puzzle_hash {
158+
Some(cc)
159+
} else {
160+
None
161+
}
162+
}
163+
_ => None,
164+
}) {
165+
yes_no_prompt(format!("{} CAT mojos (asset id: {}) will be transferred to the specified recipient. Continue?", cc.amount, hex::encode(payment_cat_asset_id)).as_str())?;
166+
let notarized_payment = NotarizedPayment {
167+
nonce: coin_spend.coin.coin_id(),
168+
payments: vec![Payment::with_memos(
169+
recipient_puzzle_hash,
170+
cc.amount,
171+
vec![recipient_puzzle_hash.into()],
172+
)],
173+
};
174+
175+
// todo: spend CAT
176+
177+
payment_sent = true;
178+
let msg: Bytes32 = notarized_payment.tree_hash().into();
179+
conds = conds.assert_puzzle_announcement(announcement_id(
180+
offer_puzzle_hash,
181+
&msg,
182+
));
183+
}
184+
}
185+
}
186+
Puzzle::Raw(_puzzle) => {
187+
if let Some(cc) = output.iter().find_map(|c| match c {
188+
Condition::CreateCoin(cc) => {
189+
if cc.puzzle_hash == verification_asserter_puzzle_hash {
190+
Some(cc)
191+
} else {
192+
None
193+
}
194+
}
195+
_ => None,
196+
}) {
197+
verification_asserter.spend(
198+
&mut ctx,
199+
Coin::new(coin_spend.coin.coin_id(), cc.puzzle_hash, cc.amount),
200+
verifier_proof,
201+
0,
202+
comment,
203+
);
204+
verification_asserter_spent = true;
205+
}
206+
}
207+
};
208+
209+
ctx.insert(coin_spend);
210+
}
211+
212+
if !payment_sent {
213+
return Err(CliError::Custom(
214+
"Payment in offer could not be found".to_string(),
215+
));
216+
}
217+
if !verification_asserter_spent {
218+
return Err(CliError::Custom(
219+
"Verification asserter could not be found in offer - it is likely invalid"
220+
.to_string(),
221+
));
222+
}
115223

116-
Some(Conditions::new()) // todo
224+
signature_from_signers += &spend_bundle.aggregated_signature;
225+
Some(conds)
117226
} else {
118227
None
119228
};

0 commit comments

Comments
 (0)