Skip to content
This repository was archived by the owner on Dec 9, 2023. It is now read-only.

Commit fcdf41f

Browse files
committed
allow many transfers by cli
1 parent 770ce83 commit fcdf41f

File tree

14 files changed

+138
-314
lines changed

14 files changed

+138
-314
lines changed

cli/src/command.rs

+28-19
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@
88
// You should have received a copy of the MIT License along with this software.
99
// If not, see <https://opensource.org/licenses/MIT>.
1010

11-
use std::collections::BTreeSet;
11+
use std::collections::{BTreeMap, BTreeSet};
1212
use std::{fs, io};
1313

14+
use crate::opts::{ContractCommand, OutpointCommand, TransferCommand};
15+
use crate::{Command, Opts};
1416
use amplify::IoError;
1517
use bitcoin::consensus;
1618
use bitcoin::psbt::serialize::{Deserialize, Serialize};
@@ -20,13 +22,10 @@ use microservices::shell::Exec;
2022
use psbt::Psbt;
2123
use rgb::blank::BlankBundle;
2224
use rgb::psbt::{RgbExt, RgbInExt};
23-
use rgb::{Node, StateTransfer, Transition, TransitionBundle};
25+
use rgb::{Node, SealEndpoint, StateTransfer, Transition, TransitionBundle};
2426
use rgb_rpc::{Client, ContractValidity};
2527
use strict_encoding::{StrictDecode, StrictEncode};
2628

27-
use crate::opts::{ContractCommand, OutpointCommand, TransferCommand};
28-
use crate::{Command, Opts};
29-
3029
#[derive(Debug, Display, Error, From)]
3130
#[display(inner)]
3231
pub enum Error {
@@ -93,10 +92,7 @@ impl TransferCommand {
9392
format!("Composing consignment for state transfer for contract {}", contract_id)
9493
}
9594
Self::Combine { .. } => s!("Preparing PSBT for the state transfer"),
96-
Self::Finalize {
97-
send: Some(addr), ..
98-
} => format!("Finalizing state transfer and sending it to {}", addr),
99-
Self::Finalize { send: None, .. } => s!("Finalizing state transfer"),
95+
Self::Finalize { .. } => s!("Finalizing state transfers"),
10096
Self::Consume { .. } => s!("Verifying and consuming state transfer"),
10197
}
10298
}
@@ -261,23 +257,36 @@ impl Exec for Opts {
261257
}
262258

263259
TransferCommand::Finalize {
260+
endseal,
264261
psbt: psbt_in,
265-
consignment_in,
266-
consignment_out,
267-
endseals,
268-
send,
269262
psbt_out,
270263
} => {
271264
let psbt_bytes = fs::read(&psbt_in)?;
272265
let psbt = Psbt::deserialize(&psbt_bytes)?;
273-
let consignment = StateTransfer::strict_file_load(&consignment_in)?;
274-
let transfer = client.transfer(consignment, endseals, psbt, send, progress)?;
275266

276-
transfer
277-
.consignment
278-
.strict_file_save(consignment_out.unwrap_or(consignment_in))?;
267+
let mut consig_paths = BTreeMap::new();
268+
let transfers: Vec<(StateTransfer, Vec<SealEndpoint>)> = endseal
269+
.into_iter()
270+
.map(|b| -> (StateTransfer, Vec<SealEndpoint>) {
271+
let consignment =
272+
StateTransfer::strict_file_load(b.consignment.clone())
273+
.expect("Valid consignment file");
274+
consig_paths.insert(consignment.contract_id(), b.consignment);
275+
(consignment, b.endseals)
276+
})
277+
.collect();
278+
279+
let transfers = client.finalize_transfers(transfers, psbt, progress)?;
280+
for transfer in transfers.consignments {
281+
if consig_paths.contains_key(&transfer.contract_id()) {
282+
let path = consig_paths
283+
.get(&transfer.contract_id())
284+
.expect("Invalid consignment path");
285+
let _ = transfer.strict_file_save(path);
286+
}
287+
}
279288

280-
let psbt_bytes = transfer.psbt.serialize();
289+
let psbt_bytes = transfers.psbt.serialize();
281290
fs::write(psbt_out.unwrap_or(psbt_in), psbt_bytes)?;
282291
}
283292

cli/src/opts.rs

+10-15
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@
1111
use std::path::PathBuf;
1212

1313
use bitcoin::OutPoint;
14-
use internet2::addr::{NodeAddr, ServiceAddr};
14+
use internet2::addr::ServiceAddr;
1515
use lnpbp::chain::Chain;
1616
use rgb::schema::TransitionType;
17-
use rgb::{Contract, ContractId, SealEndpoint};
18-
use rgb_rpc::{Reveal, RGB_NODE_RPC_ENDPOINT};
17+
use rgb::{Contract, ContractId};
18+
use rgb_rpc::{NewTransfer, Reveal, RGB_NODE_RPC_ENDPOINT};
1919

2020
/// Command-line tool for working with RGB node
2121
#[derive(Parser, Clone, PartialEq, Eq, Debug)]
@@ -151,14 +151,10 @@ pub enum TransferCommand {
151151
/// (LNP Node).
152152
#[display("finalize ...")]
153153
Finalize {
154-
/// Bifrost server to send state transfer to
155-
#[clap(short, long)]
156-
send: Option<NodeAddr>,
157-
158154
/// Beneficiary blinded TXO seal - or witness transaction output numbers
159155
/// containing allocations for the beneficiary.
160156
#[clap(short, long = "endseal", required = true)]
161-
endseals: Vec<SealEndpoint>,
157+
endseal: Vec<NewTransfer>,
162158

163159
/// The final PSBT (not modified).
164160
psbt: PathBuf,
@@ -167,13 +163,12 @@ pub enum TransferCommand {
167163
/// information. If not given, the source PSBT file is overwritten.
168164
#[clap(short = 'o', long = "out")]
169165
psbt_out: Option<PathBuf>,
166+
// /// State transfer consignment draft file prepared with `compose` command.
167+
// consignment_in: PathBuf,
170168

171-
/// State transfer consignment draft file prepared with `compose` command.
172-
consignment_in: PathBuf,
173-
174-
/// Output file to save the final consignment. If not given, the source
175-
/// consignment file is overwritten.
176-
consignment_out: Option<PathBuf>,
169+
// /// Output file to save the final consignment. If not given, the source
170+
// /// consignment file is overwritten.
171+
// consignment_out: Option<PathBuf>,
177172
},
178173

179174
/// Validate incoming transfer consignment and consume it into the stash.
@@ -194,7 +189,7 @@ pub enum TransferCommand {
194189
/// Examples:
195190
///
196191
/// tapret1st@<outpoint>#<blinding_factor>
197-
/// opret1st@<outpoint>#<blinding_factor>
192+
/// opret1st@<outpoint>#<blinding_factor>
198193
#[clap(short, long)]
199194
reveal: Option<Reveal>,
200195
},

rpc/src/client.rs

+3-26
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use std::thread::sleep;
1313
use std::time::Duration;
1414

1515
use bitcoin::{OutPoint, Txid};
16-
use internet2::addr::{NodeAddr, ServiceAddr};
16+
use internet2::addr::ServiceAddr;
1717
use internet2::ZmqSocketType;
1818
use lnpbp::chain::Chain;
1919
use microservices::esb::{self, BusId, ClientId};
@@ -22,10 +22,10 @@ use psbt::Psbt;
2222
use rgb::schema::TransitionType;
2323
use rgb::{Contract, ContractId, ContractState, ContractStateMap, SealEndpoint, StateTransfer};
2424

25-
use crate::messages::{FinalizeTransfersRes, HelloReq, TransferFinalize, TransfersReq};
25+
use crate::messages::{FinalizeTransfersRes, HelloReq, TransfersReq};
2626
use crate::{
2727
AcceptReq, BusMsg, ComposeReq, ContractValidity, Error, FailureCode, OutpointFilter, Reveal,
28-
RpcMsg, ServiceId, TransferReq,
28+
RpcMsg, ServiceId,
2929
};
3030

3131
// We have just a single service bus (RPC), so we can use any id
@@ -218,29 +218,6 @@ impl Client {
218218
}
219219
}
220220

221-
pub fn transfer(
222-
&mut self,
223-
consignment: StateTransfer,
224-
endseals: Vec<SealEndpoint>,
225-
psbt: Psbt,
226-
beneficiary: Option<NodeAddr>,
227-
progress: impl Fn(String),
228-
) -> Result<TransferFinalize, Error> {
229-
self.request(RpcMsg::Transfer(TransferReq {
230-
consignment,
231-
endseals,
232-
psbt,
233-
beneficiary,
234-
}))?;
235-
loop {
236-
match self.response()?.failure_to_error()? {
237-
RpcMsg::StateTransferFinalize(transfer) => return Ok(transfer),
238-
RpcMsg::Progress(info) => progress(info),
239-
_ => return Err(Error::UnexpectedServerResponse),
240-
}
241-
}
242-
}
243-
244221
pub fn finalize_transfers(
245222
&mut self,
246223
transfers: Vec<(StateTransfer, Vec<SealEndpoint>)>,

rpc/src/lib.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,16 @@ pub mod client;
3636
mod error;
3737
mod messages;
3838
mod service_id;
39-
mod reveal;
39+
mod structs;
4040

4141
pub use client::Client;
4242
pub use error::{Error, FailureCode};
4343
pub(crate) use messages::BusMsg;
4444
pub use messages::{
4545
AcceptReq, ComposeReq, ContractValidity, FinalizeTransfersRes, HelloReq, OutpointFilter,
46-
RpcMsg, TransferFinalize, TransferReq, TransfersReq,
46+
RpcMsg, TransfersReq,
4747
};
48-
pub use reveal::Reveal;
4948
pub use service_id::ServiceId;
49+
pub use structs::{NewTransfer, Reveal};
5050

5151
pub const RGB_NODE_RPC_ENDPOINT: &str = "0.0.0.0:63963";

rpc/src/messages.rs

-25
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
use std::collections::BTreeSet;
1212

1313
use bitcoin::{OutPoint, Txid};
14-
use internet2::addr::NodeAddr;
1514
use internet2::presentation;
1615
use lnpbp::chain::Chain;
1716
use microservices::rpc;
@@ -71,9 +70,6 @@ pub enum RpcMsg {
7170
#[display("process_disclosure({0})")]
7271
ProcessDisclosure(Txid),
7372

74-
#[display(inner)]
75-
Transfer(TransferReq),
76-
7773
#[display(inner)]
7874
FinalizeTransfers(TransfersReq),
7975

@@ -97,9 +93,6 @@ pub enum RpcMsg {
9793
#[display("state_transfer(...)")]
9894
StateTransfer(StateTransfer),
9995

100-
#[display("state_transfer_finalize(...)")]
101-
StateTransferFinalize(TransferFinalize),
102-
10396
#[display("state_transfer_finalize(...)")]
10497
FinalizedTransfers(FinalizeTransfersRes),
10598

@@ -190,24 +183,6 @@ pub struct ComposeReq {
190183
pub outpoints: OutpointFilter,
191184
}
192185

193-
#[derive(Clone, PartialEq, Eq, Debug, Display)]
194-
#[derive(NetworkEncode, NetworkDecode)]
195-
#[display("transfer(...)")]
196-
pub struct TransferReq {
197-
pub consignment: StateTransfer,
198-
pub endseals: Vec<SealEndpoint>,
199-
pub psbt: Psbt,
200-
pub beneficiary: Option<NodeAddr>,
201-
}
202-
203-
#[derive(Clone, PartialEq, Eq, Debug, Display)]
204-
#[derive(NetworkEncode, NetworkDecode)]
205-
#[display("transfer_complete(...)")]
206-
pub struct TransferFinalize {
207-
pub consignment: StateTransfer,
208-
pub psbt: Psbt,
209-
}
210-
211186
#[derive(Clone, PartialEq, Eq, Debug, Display)]
212187
#[derive(NetworkEncode, NetworkDecode)]
213188
#[display("transfers_req(...)")]

rpc/src/reveal.rs rpc/src/structs.rs

+82
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
use bitcoin::OutPoint;
1212
use bp::seals::txout::CloseMethod;
13+
use rgb::SealEndpoint;
1314

1415
#[derive(From, PartialEq, Eq, Debug, Clone, StrictEncode, StrictDecode)]
1516
pub struct Reveal {
@@ -115,3 +116,84 @@ impl ::std::error::Error for ParseRevealError {
115116
}
116117
}
117118
}
119+
120+
#[derive(From, PartialEq, Eq, Debug, Clone, StrictEncode, StrictDecode)]
121+
pub struct NewTransfer {
122+
/// Beneficiary blinded TXO seal - or witness transaction output numbers
123+
/// containing allocations for the beneficiary.
124+
pub endseals: Vec<SealEndpoint>,
125+
126+
/// State transfer consignment draft file prepared with `compose` command.
127+
pub consignment: String,
128+
}
129+
130+
/// An error in parsing an OutPoint.
131+
#[derive(Clone, PartialEq, Eq, Debug)]
132+
pub enum ParseNewTransferError {
133+
/// Error in seal endpoint part.
134+
SealEndpoint,
135+
/// Error in consignment part.
136+
Consignment,
137+
/// Error in general format.
138+
Format,
139+
}
140+
141+
impl std::fmt::Display for ParseNewTransferError {
142+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
143+
match *self {
144+
ParseNewTransferError::SealEndpoint => write!(f, "error parsing SealEndpoint"),
145+
ParseNewTransferError::Consignment => write!(f, "error parsing Consignment"),
146+
ParseNewTransferError::Format => todo!(),
147+
}
148+
}
149+
}
150+
151+
impl std::fmt::Display for NewTransfer {
152+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
153+
let endseals: Vec<String> =
154+
self.endseals.clone().into_iter().map(|e| e.to_string()).collect();
155+
let endseals = endseals.join(",");
156+
write!(f, "{}:{}", endseals, self.consignment)
157+
}
158+
}
159+
160+
impl ::core::str::FromStr for NewTransfer {
161+
type Err = ParseNewTransferError;
162+
163+
fn from_str(s: &str) -> Result<Self, Self::Err> {
164+
let find_consig = s.find(':');
165+
let index_consig = match find_consig {
166+
Some(index) => index,
167+
_ => return Err(ParseNewTransferError::Format),
168+
};
169+
170+
println!("{}", "passou aqui");
171+
if index_consig == 0 || index_consig == s.len() - 1 {
172+
return Err(ParseNewTransferError::Format);
173+
}
174+
175+
let find_endseals = s.find(',');
176+
let endseals = match find_endseals {
177+
Some(_) => s[..index_consig]
178+
.split(',')
179+
.into_iter()
180+
.map(|e| SealEndpoint::from_str(e).expect("Error in SealEndpoint part"))
181+
.collect(),
182+
_ => {
183+
vec![SealEndpoint::from_str(&s[..index_consig]).expect("Error in SealEndpoint part")]
184+
}
185+
};
186+
187+
Ok(NewTransfer {
188+
endseals,
189+
consignment: match String::try_from(&s[index_consig + 1..]) {
190+
Ok(it) => it,
191+
Err(_) => return Err(ParseNewTransferError::Consignment),
192+
},
193+
})
194+
}
195+
}
196+
197+
impl ::std::error::Error for ParseNewTransferError {
198+
fn cause(&self) -> Option<&dyn ::std::error::Error> { None }
199+
}

shell/_rgb-cli

+2-6
Original file line numberDiff line numberDiff line change
@@ -247,10 +247,8 @@ _arguments "${_arguments_options[@]}" \
247247
;;
248248
(finalize)
249249
_arguments "${_arguments_options[@]}" \
250-
'-s+[Bifrost server to send state transfer to]:SEND: ' \
251-
'--send=[Bifrost server to send state transfer to]:SEND: ' \
252-
'*-e+[Beneficiary blinded TXO seal - or witness transaction output numbers containing allocations for the beneficiary]:ENDSEALS: ' \
253-
'*--endseal=[Beneficiary blinded TXO seal - or witness transaction output numbers containing allocations for the beneficiary]:ENDSEALS: ' \
250+
'*-e+[Beneficiary blinded TXO seal - or witness transaction output numbers containing allocations for the beneficiary]:ENDSEAL: ' \
251+
'*--endseal=[Beneficiary blinded TXO seal - or witness transaction output numbers containing allocations for the beneficiary]:ENDSEAL: ' \
254252
'-o+[Output file to save the PSBT updated with state transition(s) information. If not given, the source PSBT file is overwritten]:PSBT_OUT: ' \
255253
'--out=[Output file to save the PSBT updated with state transition(s) information. If not given, the source PSBT file is overwritten]:PSBT_OUT: ' \
256254
'-R+[ZMQ socket for connecting daemon RPC interface]:CONNECT: ' \
@@ -262,8 +260,6 @@ _arguments "${_arguments_options[@]}" \
262260
'*-v[Set verbosity level]' \
263261
'*--verbose[Set verbosity level]' \
264262
':psbt -- The final PSBT (not modified):' \
265-
':consignment-in -- State transfer consignment draft file prepared with `compose` command:' \
266-
'::consignment-out -- Output file to save the final consignment. If not given, the source consignment file is overwritten:' \
267263
&& ret=0
268264
;;
269265
(consume)

shell/_rgb-cli.ps1

-2
Original file line numberDiff line numberDiff line change
@@ -203,8 +203,6 @@ Register-ArgumentCompleter -Native -CommandName 'rgb-cli' -ScriptBlock {
203203
break
204204
}
205205
'rgb-cli;transfer;finalize' {
206-
[CompletionResult]::new('-s', 's', [CompletionResultType]::ParameterName, 'Bifrost server to send state transfer to')
207-
[CompletionResult]::new('--send', 'send', [CompletionResultType]::ParameterName, 'Bifrost server to send state transfer to')
208206
[CompletionResult]::new('-e', 'e', [CompletionResultType]::ParameterName, 'Beneficiary blinded TXO seal - or witness transaction output numbers containing allocations for the beneficiary')
209207
[CompletionResult]::new('--endseal', 'endseal', [CompletionResultType]::ParameterName, 'Beneficiary blinded TXO seal - or witness transaction output numbers containing allocations for the beneficiary')
210208
[CompletionResult]::new('-o', 'o', [CompletionResultType]::ParameterName, 'Output file to save the PSBT updated with state transition(s) information. If not given, the source PSBT file is overwritten')

0 commit comments

Comments
 (0)