[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
+8 -8
View File
@@ -1,6 +1,6 @@
[package]
name = "grin_wallet_api"
version = "5.4.0-alpha.1"
version = "5.4.0-contracts.0"
authors = ["Grin Developers <mimblewimble@lists.launchpad.net>"]
description = "Grin Wallet API"
license = "Apache-2.0"
@@ -22,17 +22,17 @@ ring = "0.16"
base64 = "0.12"
ed25519-dalek = "1.0.0-pre.4"
grin_wallet_libwallet = { path = "../libwallet", version = "5.4.0-alpha.1" }
grin_wallet_config = { path = "../config", version = "5.4.0-alpha.1" }
grin_wallet_impls = { path = "../impls", version = "5.4.0-alpha.1" }
grin_wallet_util = { path = "../util", version = "5.4.0-alpha.1" }
grin_wallet_libwallet = { path = "../libwallet", version = "5.4.0-contracts.0" }
grin_wallet_config = { path = "../config", version = "5.4.0-contracts.0" }
grin_wallet_impls = { path = "../impls", version = "5.4.0-contracts.0" }
grin_wallet_util = { path = "../util", version = "5.4.0-contracts.0" }
##### Grin Imports
# For Release
# grin_core = "5.4.0-alpha.1"
# grin_keychain = "5.4.0-alpha.1"
# grin_util = "5.4.0-alpha.1"
# grin_core = "5.4.0-contracts.0"
# grin_keychain = "5.4.0-contracts.0"
# grin_util = "5.4.0-contracts.0"
# For beta release
+40
View File
@@ -17,6 +17,8 @@
use crate::config::TorConfig;
use crate::keychain::Keychain;
use crate::libwallet::api_impl::foreign;
use crate::libwallet::contract::proofs::InvoiceProof;
use crate::libwallet::contract::types::{ContractNewArgsAPI, ContractSetupArgsAPI};
use crate::libwallet::{
BlockFees, CbData, Error, NodeClient, NodeVersionInfo, Slate, VersionInfo, WalletInst,
WalletLCProvider,
@@ -24,6 +26,7 @@ use crate::libwallet::{
use crate::try_slatepack_sync_workflow;
use crate::util::secp::key::SecretKey;
use crate::util::Mutex;
use ed25519_dalek::PublicKey as DalekPublicKey;
use std::sync::Arc;
/// ForeignAPI Middleware Check callback
@@ -450,6 +453,43 @@ where
post_automatically,
)
}
// Below is a foreign wrapper around owner calls to 'new' and 'sign' which are only executed
// if this is a receiving contract. This preserves the ability to receive on a foreign interface.
/// TODO
pub fn contract_new(
&self,
keychain_mask: Option<&SecretKey>,
args: &ContractNewArgsAPI,
) -> Result<Slate, Error> {
let mut w_lock = self.wallet_inst.lock();
let w = w_lock.lc_provider()?.wallet_inst()?;
// TODO: self.doctest_mode ?
foreign::contract_new(&mut **w, keychain_mask, &args)
}
/// TODO
pub fn contract_sign(
&self,
keychain_mask: Option<&SecretKey>,
slate: &Slate,
args: &ContractSetupArgsAPI,
) -> Result<Slate, Error> {
let mut w_lock = self.wallet_inst.lock();
let w = w_lock.lc_provider()?.wallet_inst()?;
foreign::contract_sign(&mut **w, keychain_mask, &args, &slate)
}
/// TODO
pub fn verify_payment_proof_invoice(
&self,
recipient_address: &DalekPublicKey,
proof: &InvoiceProof,
) -> Result<(), Error> {
let mut w_lock = self.wallet_inst.lock();
let w = w_lock.lc_provider()?.wallet_inst()?;
foreign::verify_payment_proof_invoice(&mut **w, recipient_address, proof)
}
}
#[doc(hidden)]
+5 -4
View File
@@ -52,6 +52,7 @@ pub trait ForeignRpc {
"Ok": {
"foreign_api_version": 2,
"supported_slate_versions": [
"V5",
"V4"
]
}
@@ -141,7 +142,7 @@ pub trait ForeignRpc {
}
],
"sta": "S1",
"ver": "4:2"
"ver": "5:2"
},
null,
null
@@ -176,7 +177,7 @@ pub trait ForeignRpc {
}
],
"sta": "S2",
"ver": "4:2"
"ver": "5:2"
}
}
}
@@ -205,7 +206,7 @@ pub trait ForeignRpc {
"method": "finalize_tx",
"id": 1,
"params": [{
"ver": "4:2",
"ver": "5:2",
"id": "0436430c-2b02-624c-2032-570501212b00",
"sta": "I2",
"off": "383bc9df0dd332629520a0a72f8dd7f0e97d579dccb4dbdc8592aa3d424c846c",
@@ -275,7 +276,7 @@ pub trait ForeignRpc {
}
],
"sta": "I3",
"ver": "4:2"
"ver": "5:2"
}
}
}
+103
View File
@@ -16,6 +16,7 @@
use chrono::prelude::*;
use ed25519_dalek::SecretKey as DalekSecretKey;
use grin_wallet_libwallet::contract::proofs::InvoiceProof;
use grin_wallet_libwallet::RetrieveTxQueryArgs;
use uuid::Uuid;
@@ -27,6 +28,10 @@ use crate::impls::SlateSender as _;
use crate::keychain::{Identifier, Keychain};
use crate::libwallet::api_impl::owner_updater::{start_updater_log_thread, StatusMessage};
use crate::libwallet::api_impl::{owner, owner_updater};
use crate::libwallet::contract::types::{
ContractNewArgsAPI, ContractRevokeArgsAPI, ContractSetupArgsAPI,
};
use crate::libwallet::mwmixnet::types::{MixnetReqCreationParams, SwapReq};
use crate::libwallet::{
AcctPathMapping, BuiltOutput, Error, InitTxArgs, IssueInvoiceTxArgs, NodeClient,
NodeHeightResult, OutputCommitMapping, PaymentProof, Slate, Slatepack, SlatepackAddress,
@@ -766,6 +771,78 @@ where
owner::issue_invoice_tx(&mut **w, keychain_mask, args, self.doctest_mode)
}
/// TODO
pub fn contract_new(
&self,
keychain_mask: Option<&SecretKey>,
args: &ContractNewArgsAPI,
) -> Result<Slate, Error> {
let mut w_lock = self.wallet_inst.lock();
let w = w_lock.lc_provider()?.wallet_inst()?;
// TODO: self.doctest_mode ?
owner::contract_new(&mut **w, keychain_mask, &args)
}
// /// TODO
// pub fn contract_setup(
// &self,
// keychain_mask: Option<&SecretKey>,
// slate: &Slate,
// args: &ContractSetupArgsAPI,
// ) -> Result<Slate, Error> {
// let mut w_lock = self.wallet_inst.lock();
// let w = w_lock.lc_provider()?.wallet_inst()?;
// // TODO: self.doctest_mode ?
// owner::contract_setup(&mut **w, keychain_mask, &args, &slate)
// }
/// TODO
pub fn contract_sign(
&self,
keychain_mask: Option<&SecretKey>,
slate: &Slate,
args: &ContractSetupArgsAPI,
) -> Result<Slate, Error> {
let mut w_lock = self.wallet_inst.lock();
let w = w_lock.lc_provider()?.wallet_inst()?;
owner::contract_sign(&mut **w, keychain_mask, &args, &slate)
}
/// TODO
pub fn get_slate_index_matching_my_context(
&self,
keychain_mask: Option<&SecretKey>,
slate: &Slate,
) -> Result<usize, Error> {
let mut w_lock = self.wallet_inst.lock();
let w = w_lock.lc_provider()?.wallet_inst()?;
owner::get_slate_index_matching_my_context(&mut **w, keychain_mask, &slate)
}
/// TODO
pub fn contract_revoke(
&self,
keychain_mask: Option<&SecretKey>,
args: &ContractRevokeArgsAPI,
) -> Result<Option<Slate>, Error> {
let mut w_lock = self.wallet_inst.lock();
let w = w_lock.lc_provider()?.wallet_inst()?;
owner::contract_revoke(&mut **w, keychain_mask, &args)
}
/// Create MXMixnet request
pub fn create_mwmixnet_req(
&self,
keychain_mask: Option<&SecretKey>,
params: &MixnetReqCreationParams,
slate: &Slate,
// use_test_rng: bool,
) -> Result<SwapReq, Error> {
let mut w_lock = self.wallet_inst.lock();
let w = w_lock.lc_provider()?.wallet_inst()?;
owner::create_mwmixnet_req(&mut **w, keychain_mask, params, slate)
}
/// Processes an invoice tranaction created by another party, essentially
/// a `request for payment`. The incoming slate should contain a requested
/// amount, an output created by the invoicer convering the amount, and
@@ -2355,6 +2432,32 @@ where
)
}
/// TODO: Temporary, likely should merge with above
pub fn retrieve_payment_proof_invoice(
&self,
keychain_mask: Option<&SecretKey>,
refresh_from_node: bool,
tx_id: Option<u32>,
tx_slate_id: Option<Uuid>,
) -> Result<InvoiceProof, Error> {
let tx = {
let t = self.status_tx.lock();
t.clone()
};
let refresh_from_node = match self.updater_running.load(Ordering::Relaxed) {
true => false,
false => refresh_from_node,
};
owner::retrieve_payment_proof_invoice(
self.wallet_inst.clone(),
keychain_mask,
&tx,
refresh_from_node,
tx_id,
tx_slate_id,
)
}
/// Verifies a [PaymentProof](../grin_wallet_libwallet/api_impl/types/struct.PaymentProof.html)
/// This process entails:
///
+106 -3
View File
@@ -20,6 +20,9 @@ use crate::config::{TorConfig, WalletConfig};
use crate::core::core::OutputFeatures;
use crate::core::global;
use crate::keychain::{Identifier, Keychain};
use crate::libwallet::contract::types::{
ContractNewArgsAPI, ContractRevokeArgsAPI, ContractSetupArgsAPI,
};
use crate::libwallet::{
AcctPathMapping, Amount, BuiltOutput, Error, InitTxArgs, IssueInvoiceTxArgs, NodeClient,
NodeHeightResult, OutputCommitMapping, PaymentProof, Slate, SlateVersion, Slatepack,
@@ -501,7 +504,7 @@ pub trait OwnerRpc {
}
],
"sta": "S1",
"ver": "4:2"
"ver": "5:2"
}
}
}
@@ -510,8 +513,49 @@ pub trait OwnerRpc {
```
*/
/**
TODO: Full docs once API has stabilised
*/
fn init_send_tx(&self, token: Token, args: InitTxArgs) -> Result<VersionedSlate, Error>;
/**
TODO: Implement
*/
// fn contract_setup(
// &self,
// token: Token,
// slate: VersionedSlate,
// args: ContractSetupArgsAPI,
// ) -> Result<VersionedSlate, Error>;
/**
TODO: Full docs once API has stabilised
*/
fn contract_new(&self, token: Token, args: ContractNewArgsAPI)
-> Result<VersionedSlate, Error>;
/**
TODO: Full docs once API has stabilised
*/
fn contract_sign(
&self,
token: Token,
slate: VersionedSlate,
args: ContractSetupArgsAPI,
) -> Result<VersionedSlate, Error>;
/**
TODO: Full docs once API has stabilised
*/
fn contract_revoke(
&self,
token: Token,
args: ContractRevokeArgsAPI,
) -> Result<Option<VersionedSlate>, Error>;
/**
;Networked version of [Owner::issue_invoice_tx](struct.Owner.html#method.issue_invoice_tx).
@@ -548,7 +592,7 @@ pub trait OwnerRpc {
}
],
"sta": "I1",
"ver": "4:2"
"ver": "5:2"
}
}
}
@@ -919,7 +963,7 @@ pub trait OwnerRpc {
"id": "0436430c-2b02-624c-2032-570501212b00",
"sigs": [],
"sta": "S3",
"ver": "4:3"
"ver": "5:3"
}
}
}
@@ -2052,6 +2096,65 @@ where
VersionedSlate::into_version(slate, version)
}
fn contract_new(
&self,
token: Token,
args: ContractNewArgsAPI,
) -> Result<VersionedSlate, Error> {
let slate = Owner::contract_new(self, (&token.keychain_mask).as_ref(), &args)?;
let version = SlateVersion::V4;
VersionedSlate::into_version(slate, version)
}
// fn contract_setup(
// &self,
// token: Token,
// in_slate: VersionedSlate,
// args: ContractSetupArgsAPI,
// ) -> Result<VersionedSlate, Error> {
// let slate = Owner::contract_setup(
// self,
// (&token.keychain_mask).as_ref(),
// &Slate::from(in_slate),
// &args,
// )?;
// let version = SlateVersion::V4;
// VersionedSlate::into_version(slate, version)
// }
fn contract_sign(
&self,
token: Token,
in_slate: VersionedSlate,
args: ContractSetupArgsAPI,
) -> Result<VersionedSlate, Error> {
let slate = Owner::contract_sign(
self,
(&token.keychain_mask).as_ref(),
&Slate::from(in_slate),
&args,
)?;
let version = SlateVersion::V4;
VersionedSlate::into_version(slate, version)
}
fn contract_revoke(
&self,
token: Token,
args: ContractRevokeArgsAPI,
) -> Result<Option<VersionedSlate>, Error> {
let slate_opt = Owner::contract_revoke(self, (&token.keychain_mask).as_ref(), &args)?;
let version = SlateVersion::V4;
// We return a slate only when we had to perform a self-spend safe cancel
if slate_opt.is_some() {
return Ok(Some(VersionedSlate::into_version(
slate_opt.unwrap(),
version,
)?));
}
Ok(None)
}
fn issue_invoice_tx(
&self,
token: Token,