Get Counterparty signing working

This commit is contained in:
Ed Hennis
2025-04-25 18:05:34 -04:00
parent 7823c8b186
commit 0a4c0a555d
5 changed files with 44 additions and 20 deletions

View File

@@ -59,7 +59,8 @@ class Loan_test : public beast::unit_test::suite
Env env(*this, features); Env env(*this, features);
Account const alice{"alice"}; Account const alice{"alice"};
env.fund(XRP(10000), alice); Account const bob{"bob"};
env.fund(XRP(10000), alice, bob);
auto const keylet = keylet::loanbroker(alice, env.seq(alice)); auto const keylet = keylet::loanbroker(alice, env.seq(alice));
@@ -67,14 +68,16 @@ class Loan_test : public beast::unit_test::suite
using namespace loan; using namespace loan;
// counter party signature is required on LoanSet // counter party signature is required on LoanSet
env(set(alice, keylet.key, Number(10000), env.now() + 720h), auto setTx = env.jt(
set(alice, keylet.key, Number(10000), env.now() + 720h),
ter(temMALFORMED)); ter(temMALFORMED));
env(setTx);
// All loan transactions are disabled. // All loan transactions are disabled.
// 1. LoanSet // 1. LoanSet
env(set(alice, keylet.key, Number(10000), env.now() + 720h), setTx = env.jt(
sig(sfCounterpartySignature, alice), setTx, sig(sfCounterpartySignature, bob), ter(temDISABLED));
ter(temDISABLED)); env(setTx);
auto const loanKeylet = auto const loanKeylet =
keylet::loan(alice.id(), keylet.key, env.seq(alice)); keylet::loan(alice.id(), keylet.key, env.seq(alice));
#if 0 #if 0

View File

@@ -54,7 +54,11 @@ struct JTx
bool fill_sig = true; bool fill_sig = true;
bool fill_netid = true; bool fill_netid = true;
std::shared_ptr<STTx const> stx; std::shared_ptr<STTx const> stx;
std::vector<std::function<void(Env&, JTx&)>> signers; // Functions that sign the transaction from the Account
std::vector<std::function<void(Env&, JTx&)>> mainSigners;
// Functions that sign something else after the mainSigners, such as
// sfCounterpartySignature
std::vector<std::function<void(Env&, JTx&)>> postSigners;
JTx() = default; JTx() = default;
JTx(JTx const&) = default; JTx(JTx const&) = default;

View File

@@ -35,6 +35,7 @@
#include <xrpl/basics/Slice.h> #include <xrpl/basics/Slice.h>
#include <xrpl/basics/contract.h> #include <xrpl/basics/contract.h>
#include <xrpl/basics/scope.h>
#include <xrpl/json/to_string.h> #include <xrpl/json/to_string.h>
#include <xrpl/protocol/ErrorCodes.h> #include <xrpl/protocol/ErrorCodes.h>
#include <xrpl/protocol/Indexes.h> #include <xrpl/protocol/Indexes.h>
@@ -481,13 +482,25 @@ void
Env::autofill_sig(JTx& jt) Env::autofill_sig(JTx& jt)
{ {
auto& jv = jt.jv; auto& jv = jt.jv;
if (!jt.signers.empty())
{ scope_success success([&]() {
for (auto const& signer : jt.signers) // Call all the post-signers after the main signers or autofill are done
for (auto const& signer : jt.postSigners)
signer(*this, jt); signer(*this, jt);
});
// Call all the main signers
if (!jt.mainSigners.empty())
{
for (auto const& signer : jt.mainSigners)
signer(*this, jt);
return;
} }
// If the sig is still needed, get it here.
if (!jt.fill_sig) if (!jt.fill_sig)
return; return;
auto const account = lookup(jv[jss::Account].asString()); auto const account = lookup(jv[jss::Account].asString());
if (!app().checkSigs()) if (!app().checkSigs())
{ {
@@ -552,9 +565,8 @@ Env::st(JTx const& jt)
{ {
return sterilize(STTx{std::move(*obj)}); return sterilize(STTx{std::move(*obj)});
} }
catch (std::exception const& e) catch (std::exception const&)
{ {
test.log << e.what() << std::endl;
} }
return nullptr; return nullptr;
} }

View File

@@ -81,12 +81,9 @@ void
msig::operator()(Env& env, JTx& jt) const msig::operator()(Env& env, JTx& jt) const
{ {
auto const mySigners = signers; auto const mySigners = signers;
jt.signers.emplace_back([subField = subField, mySigners, &env]( auto callback = [subField = subField, mySigners, &env](Env&, JTx& jtx) {
Env&, JTx& jtx) {
// Where to put the signature. Supports sfCounterPartySignature. // Where to put the signature. Supports sfCounterPartySignature.
auto& sigObject = subField ? jtx[*subField] : jtx.jv; auto& sigObject = subField ? jtx[*subField] : jtx.jv;
if (jtx.fill_sig && !subField)
jtx.fill_sig = false;
sigObject[sfSigningPubKey] = ""; sigObject[sfSigningPubKey] = "";
std::optional<STObject> st; std::optional<STObject> st;
@@ -113,7 +110,11 @@ msig::operator()(Env& env, JTx& jt) const
jo[sfTxnSignature.getJsonName()] = jo[sfTxnSignature.getJsonName()] =
strHex(Slice{sig.data(), sig.size()}); strHex(Slice{sig.data(), sig.size()});
} }
}); };
if (!subField)
jt.mainSigners.emplace_back(callback);
else
jt.postSigners.emplace_back(callback);
} }
} // namespace jtx } // namespace jtx

View File

@@ -29,18 +29,22 @@ sig::operator()(Env&, JTx& jt) const
{ {
if (!manual_) if (!manual_)
return; return;
if (!subField)
jt.fill_sig = false;
if (account_) if (account_)
{ {
// VFALCO Inefficient pre-C++14 // VFALCO Inefficient pre-C++14
auto const account = *account_; auto const account = *account_;
jt.signers.emplace_back([subField = subField, account](Env&, JTx& jtx) { auto callback = [subField = subField, account](Env&, JTx& jtx) {
// Where to put the signature. Supports sfCounterPartySignature. // Where to put the signature. Supports sfCounterPartySignature.
auto& sigObject = subField ? jtx[*subField] : jtx.jv; auto& sigObject = subField ? jtx[*subField] : jtx.jv;
if (jtx.fill_sig && !subField)
jtx.fill_sig = false;
jtx::sign(jtx.jv, account, sigObject); jtx::sign(jtx.jv, account, sigObject);
}); };
if (!subField)
jt.mainSigners.emplace_back(callback);
else
jt.postSigners.emplace_back(callback);
} }
} }