mirror of
https://github.com/jwinterm/grin-wallet.git
synced 2026-11-12 18:43:53 +01:00
[CONTRACTS] Contracts branch update for 1.80 (#718)
* Simple contracts restructured v3 (#675) * Add prototype contract implementation Lacks: - Payment proofs (add early payment proofs) - Tests - Better structure * Separate contract utilities * Simplify the main setup/sign code flow * Remove commented initial_sec_key assignment * Simplify sign::compute function * Add logic for "removal" of secret keys from the context * Further simplify a bit sign and setup * No need for mutable context when adding outputs * Refactor the commented code (lol) * Refactor a bit * tmp --------- Co-authored-by: oryhp <gtrphyro@gmail.com> * contract test fixes (#676) * [Contracts] Experimental Slate v5 (#677) * beginning to add and modify slate version 5 * completion of conversions from V5 to V4 Slate * timestamp and memo fields * upgrade/downgrade serialization of v5 slates * add v5 binary slate versions + start of tests * add bin slate ser/deser to tests * ensure serialization of timestamp always excludes milliseconds * start to update v5 tests, update v5 documentation * add fn to generate populated internal slate for conversion testing * add basic tests to convert all slate versions * update * commit cargo.lock * [WIP] [Contracts] Early payment proofs (#681) * add types and beginnings of signature utils * add proof serialization * serialisation of proof data + signature operation * add serialization type for invoice proof + separate bin wrapper version * add witness data + serializion to invoice payment proof, insert verfication functions in place in order to begin verification testing * tests and infrastructure in place for validation * verification of promise sig * added verification of promise signature, infrastructure up to the point where a signature must be subtracted * attempting to figure out differences between recipient nonce that's getting stored and calculated recipient nonce * implementation of witness verification function, retrieve relevant values and re-validate derived recipient partial signature * move stored portion of invoice proof into core types for storage, need to rename invoice proof * define/refine the stored portion of payment proofs type 2? * Folding all proof data into tx log entry storage * back to importing master * remove cargo files from diffs * remove a lot of extra debug output * return proof witness as part of proof retrieval, define json serialization of invoice proof + witness fields * finish adding verification steps to foreign API * remove redundant promise sig field * move lcation of sign/verify calls * Replace Azure Pipelines with Github Actions (#688) * Update CI Badge on README.MD (#690) * Trigger CI on push and pull request (#693) * Update versioning to 5.2.0-beta.1 against grin 5.2.0-beta.3 (#691) * update versioning to 5.2.0-beta.1 against grin 5.2.0-beta.3 * tweak for CI trigger --------- Co-authored-by: Quentin Le Sceller <q.lesceller@gmail.com> --------- Co-authored-by: Quentin Le Sceller <q.lesceller@gmail.com> * fix Cargo.lock * Contracts - Test fixes + warning cleanups (#694) * clean up warnings in libwallet crate * clean up warnings in controller crate * update all contract tests with awareness of new proof structure * added explicit payment proof tests for both rsr and srs (#695) * Basic mwmixnet send (#696) * integrating onion library * updates and changes to support newly included mwmixnet types * add (incorrect) owner api function * turn off test for now * switch working grin branch to master * fix doctests for build * update cargo lock in attempt to fix croaring build on CI server * update cargo lock with upstream thiserror crate * update test dependency for croaring * [Contracts] Add self spend transaction state (#697) * Add self spend transaction state * subtle errors with output states and tx lookups - fixes * [Contracts] Slatepack v5 Deserialization fix (#698) * add V5 deserialization test + fixes * clarify comment * upwrap fix during v4 deserialization * further unwrap removal * update cargo lock, use latest grin packages * addition of self-spend cancel + tests (#699) * add tests + legacy self send cancel (#702) * [Contracts] Cancel self-spend TX Pt. 2 (#703) * add tests + legacy self send cancel * add missing file * Update grin to latest master, change versioning label to include contracts (#712) * Add owner_api_listen_interface as hidden configuration field (#714) * updates for rust 1.80 * updates for rust 1.80 --------- Co-authored-by: oryhp <gtrphyro@gmail.com> Co-authored-by: Quentin Le Sceller <q.lesceller@gmail.com>
This commit is contained in:
co-authored by
oryhp
Quentin Le Sceller
parent
765f11b168
commit
cdd63fb565
@@ -446,3 +446,149 @@ subcommands:
|
||||
- input:
|
||||
help: Filename of a proof file
|
||||
index: 1
|
||||
- contract:
|
||||
subcommands:
|
||||
- new:
|
||||
about: Create a new contract with initial setup
|
||||
args:
|
||||
- encrypt-for:
|
||||
help: The counter party grin address
|
||||
short: e
|
||||
long: encrypt-for
|
||||
takes_value: true
|
||||
# index: 1
|
||||
- receive:
|
||||
help: How much you want to receive
|
||||
short: r
|
||||
long: receive
|
||||
takes_value: true
|
||||
- send:
|
||||
help: How much you want to send
|
||||
short: s
|
||||
long: send
|
||||
takes_value: true
|
||||
- num-participants:
|
||||
help: How many participants are involved? (can be 1 or 2)
|
||||
short: n
|
||||
long: num-participants
|
||||
takes_value: true
|
||||
default_value: "2"
|
||||
- as-json:
|
||||
help: Show result as JSON
|
||||
short: j
|
||||
long: as-json
|
||||
takes_value: false
|
||||
- no-payjoin:
|
||||
help: Don't make it a payjoin (if receiver)
|
||||
long: no-payjoin
|
||||
takes_value: false
|
||||
- add-outputs:
|
||||
help: Defines whether we should pick inputs/outputs in the first step.
|
||||
short: a
|
||||
long: add-outputs
|
||||
takes_value: false
|
||||
- use-inputs:
|
||||
help: Which inputs you want to use (provide comma separated commitments)
|
||||
short: i
|
||||
long: use-inputs
|
||||
takes_value: true
|
||||
- make-outputs:
|
||||
help: Which outputs should we create? (provide comma separated amounts)
|
||||
short: o
|
||||
long: make-outputs
|
||||
takes_value: true
|
||||
# - setup:
|
||||
# about: Perform a key setup on a contract
|
||||
# args:
|
||||
# - encrypt-for:
|
||||
# help: The counter party grin address
|
||||
# short: e
|
||||
# long: encrypt-for
|
||||
# takes_value: true
|
||||
# # index: 1
|
||||
# - receive:
|
||||
# help: How much you want to receive
|
||||
# short: r
|
||||
# long: receive
|
||||
# takes_value: true
|
||||
# - send:
|
||||
# help: How much you want to send
|
||||
# short: s
|
||||
# long: send
|
||||
# takes_value: true
|
||||
# - as-json:
|
||||
# help: Show result as JSON
|
||||
# short: j
|
||||
# long: as-json
|
||||
# takes_value: false
|
||||
# - no-payjoin:
|
||||
# help: Don't make it a payjoin (if receiver)
|
||||
# long: no-payjoin
|
||||
# takes_value: false
|
||||
# - add-outputs:
|
||||
# help: Defines whether we should pick inputs/outputs in the setup step.
|
||||
# short: a
|
||||
# long: add-outputs
|
||||
# takes_value: false
|
||||
# - use-inputs:
|
||||
# help: Which inputs you want to use (provide comma separated commitments)
|
||||
# short: i
|
||||
# long: use-inputs
|
||||
# takes_value: true
|
||||
# - make-outputs:
|
||||
# help: Which outputs should we create? (provide comma separated amounts)
|
||||
# short: o
|
||||
# long: make-outputs
|
||||
# takes_value: true
|
||||
- sign:
|
||||
about: Sign a contract
|
||||
args:
|
||||
- encrypt-for:
|
||||
help: The counter party grin address
|
||||
short: e
|
||||
long: encrypt-for
|
||||
takes_value: true
|
||||
# index: 1
|
||||
- receive:
|
||||
help: How much you want to receive
|
||||
short: r
|
||||
long: receive
|
||||
takes_value: true
|
||||
- send:
|
||||
help: How much you want to send
|
||||
short: s
|
||||
long: send
|
||||
takes_value: true
|
||||
- as-json:
|
||||
help: Show result as JSON
|
||||
short: j
|
||||
long: as-json
|
||||
takes_value: false
|
||||
- no-payjoin:
|
||||
help: Don't make it a payjoin (if receiver)
|
||||
long: no-payjoin
|
||||
takes_value: false
|
||||
- use-inputs:
|
||||
help: Which inputs you want to use (provide comma separated commitments)
|
||||
short: i
|
||||
long: use-inputs
|
||||
takes_value: true
|
||||
- make-outputs:
|
||||
help: Which outputs should we create? (provide comma separated amounts)
|
||||
short: o
|
||||
long: make-outputs
|
||||
takes_value: true
|
||||
- no-broadcast:
|
||||
help: Don't broadcast the transaction if it was finalized
|
||||
long: no-broadcast
|
||||
takes_value: false
|
||||
- view:
|
||||
about: View a contract
|
||||
- revoke:
|
||||
about: Attempt to revoke a contract
|
||||
args:
|
||||
- tx-id:
|
||||
help: Id of a transaction we want to cancel
|
||||
short: i
|
||||
long: tx-id
|
||||
takes_value: true
|
||||
|
||||
+1
-4
@@ -39,13 +39,10 @@ fn main() {
|
||||
}
|
||||
|
||||
// build and versioning information
|
||||
let mut opts = built::Options::default();
|
||||
opts.set_dependencies(true);
|
||||
let out_dir_path = format!("{}{}", env::var("OUT_DIR").unwrap(), "/built.rs");
|
||||
// don't fail the build if something's missing, may just be cargo release
|
||||
let _ = built::write_built_file_with_opts(
|
||||
&opts,
|
||||
Path::new(env!("CARGO_MANIFEST_DIR")),
|
||||
Some(Path::new(env!("CARGO_MANIFEST_DIR"))),
|
||||
Path::new(&out_dir_path),
|
||||
);
|
||||
}
|
||||
|
||||
+169
-1
@@ -12,13 +12,14 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/// Argument parsing and error handling for wallet commands
|
||||
use self::core::consensus;
|
||||
use crate::api::TLSConfig;
|
||||
use crate::cli::command_loop;
|
||||
use crate::config::GRIN_WALLET_DIR;
|
||||
use crate::util::file::get_first_line;
|
||||
use crate::util::secp::key::SecretKey;
|
||||
use crate::util::{Mutex, ZeroingString};
|
||||
/// Argument parsing and error handling for wallet commands
|
||||
use clap::ArgMatches;
|
||||
use grin_core as core;
|
||||
use grin_core::core::amount_to_hr_string;
|
||||
@@ -965,6 +966,148 @@ pub fn parse_verify_proof_args(args: &ArgMatches) -> Result<command::ProofVerify
|
||||
})
|
||||
}
|
||||
|
||||
// TODO: parse args
|
||||
pub fn parse_contract_new_args(
|
||||
args: &ArgMatches,
|
||||
account: &String,
|
||||
) -> Result<command::ContractNewArgs, ParseError> {
|
||||
let counterparty_addr = args.value_of("encrypt-for").unwrap();
|
||||
|
||||
// TODO: Make sure the values are in some expected bounds.
|
||||
// TODO: How to deal with decimals and precision? we probably want users to express the value in Grin.
|
||||
// Parse receive and send params and convert them to nano grin
|
||||
let receive = match args.value_of("receive") {
|
||||
Some(g) => Some((g.parse::<f64>().unwrap() * consensus::GRIN_BASE as f64) as u64),
|
||||
None => None,
|
||||
};
|
||||
let send = match args.value_of("send") {
|
||||
Some(g) => Some((g.parse::<f64>().unwrap() * consensus::GRIN_BASE as f64) as u64),
|
||||
None => None,
|
||||
};
|
||||
if receive.is_some() && send.is_some() {
|
||||
return Err(ParseError::ArgumentError(String::from(
|
||||
"You can only specify receive or send, not both.",
|
||||
)));
|
||||
};
|
||||
// TODO: verify this is correct e.g. which values are passed here by default etc.
|
||||
let src_acct_name = Some(String::from(account));
|
||||
let add_outputs = args.is_present("add-outputs");
|
||||
let as_json = args.is_present("as-json");
|
||||
let no_payjoin = args.is_present("no-payjoin");
|
||||
let use_inputs = match args.value_of("use-inputs") {
|
||||
Some(v) => {
|
||||
if no_payjoin {
|
||||
panic!("Can't use --no-payjoin with --use-inputs.");
|
||||
}
|
||||
Some(String::from(v))
|
||||
}
|
||||
None => {
|
||||
if no_payjoin {
|
||||
None
|
||||
} else {
|
||||
// Some("any") means pick 1 random input to contribute (payjoin)
|
||||
Some(String::from("any"))
|
||||
}
|
||||
}
|
||||
};
|
||||
let make_outputs = match args.value_of("make-outputs") {
|
||||
Some(v) => Some(String::from(v)),
|
||||
None => None,
|
||||
};
|
||||
|
||||
let num_participants = args
|
||||
.value_of("num-participants")
|
||||
.unwrap()
|
||||
.parse::<u8>()
|
||||
.unwrap();
|
||||
|
||||
Ok(command::ContractNewArgs {
|
||||
counterparty_addr: String::from(counterparty_addr),
|
||||
receive: receive,
|
||||
send: send,
|
||||
src_acct_name: src_acct_name,
|
||||
num_participants: num_participants,
|
||||
as_json: as_json,
|
||||
add_outputs: add_outputs,
|
||||
use_inputs: use_inputs,
|
||||
make_outputs: make_outputs,
|
||||
// TODO: Future features below
|
||||
fee_rate: None,
|
||||
outfile: None,
|
||||
})
|
||||
}
|
||||
|
||||
// TODO: parse args
|
||||
pub fn parse_contract_setup_args(
|
||||
args: &ArgMatches,
|
||||
) -> Result<command::ContractSetupArgs, ParseError> {
|
||||
// TODO: Make sure the values are in some expected bounds.
|
||||
// TODO: How to deal with decimals and precision? we probably want users to express the value in Grin.
|
||||
let counterparty_addr = match args.value_of("encrypt-for") {
|
||||
Some(v) => Some(String::from(v)),
|
||||
None => None,
|
||||
};
|
||||
// Parse receive and send params and convert them to nano grin
|
||||
let receive = match args.value_of("receive") {
|
||||
Some(g) => Some((g.parse::<f64>().unwrap() * consensus::GRIN_BASE as f64) as u64),
|
||||
None => None,
|
||||
};
|
||||
let send = match args.value_of("send") {
|
||||
Some(g) => Some((g.parse::<f64>().unwrap() * consensus::GRIN_BASE as f64) as u64),
|
||||
None => None,
|
||||
};
|
||||
if receive.is_some() && send.is_some() {
|
||||
return Err(ParseError::ArgumentError(String::from(
|
||||
"You can only specify receive or send, not both.",
|
||||
)));
|
||||
};
|
||||
let as_json = args.is_present("as-json");
|
||||
let no_payjoin = args.is_present("no-payjoin");
|
||||
let use_inputs = match args.value_of("use-inputs") {
|
||||
Some(v) => {
|
||||
if no_payjoin {
|
||||
panic!("Can't use --no-payjoin with --use-inputs.");
|
||||
}
|
||||
Some(String::from(v))
|
||||
}
|
||||
None => {
|
||||
if no_payjoin {
|
||||
None
|
||||
} else {
|
||||
// Some("any") means pick 1 random input to contribute (payjoin)
|
||||
Some(String::from("any"))
|
||||
}
|
||||
}
|
||||
};
|
||||
let make_outputs = match args.value_of("make-outputs") {
|
||||
Some(v) => Some(String::from(v)),
|
||||
None => None,
|
||||
};
|
||||
// TODO: should we catch if the person calls "--receive=5" when it should be "--send=5"?
|
||||
// Perhaps we could detect this from the slate state e.g. S1 -> receive, I1 -> send?
|
||||
|
||||
Ok(command::ContractSetupArgs {
|
||||
counterparty_addr: counterparty_addr,
|
||||
receive: receive,
|
||||
send: send,
|
||||
as_json: as_json,
|
||||
add_outputs: false,
|
||||
use_inputs: use_inputs,
|
||||
make_outputs: make_outputs,
|
||||
// TODO: Future features below
|
||||
fee_rate: None,
|
||||
outfile: None,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn parse_contract_revoke_args(
|
||||
args: &ArgMatches,
|
||||
) -> Result<command::ContractRevokeArgs, ParseError> {
|
||||
let tx_id = args.value_of("tx-id").unwrap().parse::<u32>().unwrap();
|
||||
|
||||
Ok(command::ContractRevokeArgs { tx_id: tx_id })
|
||||
}
|
||||
|
||||
pub fn wallet_command<C, F>(
|
||||
wallet_args: &ArgMatches,
|
||||
mut wallet_config: WalletConfig,
|
||||
@@ -1295,6 +1438,31 @@ where
|
||||
// for CLI mode only, should be handled externally
|
||||
Ok(())
|
||||
}
|
||||
("contract", Some(args)) => match args.subcommand() {
|
||||
("new", Some(new_args)) => {
|
||||
let account = &global_wallet_args.account;
|
||||
let a = arg_parse!(parse_contract_new_args(&new_args, account));
|
||||
command::contract_new(owner_api, km, a)
|
||||
}
|
||||
// ("setup", Some(setup_args)) => {
|
||||
// let a = arg_parse!(parse_contract_setup_args(&setup_args));
|
||||
// command::contract_setup(owner_api, km, a)
|
||||
// }
|
||||
("sign", Some(sign_args)) => {
|
||||
// Sign command takes setup_args so we use the same parser
|
||||
let setup_args = arg_parse!(parse_contract_setup_args(&sign_args));
|
||||
let broadcast_tx = !sign_args.is_present("no-broadcast");
|
||||
command::contract_sign(owner_api, km, setup_args, broadcast_tx)
|
||||
}
|
||||
("view", Some(view_args)) => {
|
||||
Err(Error::ArgumentError(String::from("Not implemented")).into())
|
||||
}
|
||||
("revoke", Some(revoke_args)) => {
|
||||
let a = arg_parse!(parse_contract_revoke_args(&revoke_args));
|
||||
command::contract_revoke(owner_api, km, a)
|
||||
}
|
||||
_ => Err(Error::ArgumentError(String::from("Unknown contract subcommand.")).into()),
|
||||
},
|
||||
_ => {
|
||||
let msg = format!("Unknown wallet command, use 'grin-wallet help' for details");
|
||||
return Err(Error::ArgumentError(msg));
|
||||
|
||||
Reference in New Issue
Block a user