[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:
Yeastplume
2024-08-27 12:30:22 +01:00
committed by GitHub
co-authored by oryhp Quentin Le Sceller
parent 765f11b168
commit cdd63fb565
78 changed files with 10170 additions and 220 deletions
+146
View File
@@ -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
View File
@@ -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
View File
@@ -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));