Files
rippled/src/test/jtx/impl/multisign.cpp
2026-04-07 14:47:47 +02:00

99 lines
2.7 KiB
C++

#include <test/jtx/multisign.h>
#include <test/jtx/utility.h>
#include <xrpl/basics/contract.h>
#include <xrpl/protocol/Sign.h>
#include <xrpl/protocol/jss.h>
#include <optional>
namespace xrpl {
namespace test {
namespace jtx {
Json::Value
signers(Account const& account, std::uint32_t quorum, std::vector<signer> const& v)
{
Json::Value jv;
jv[jss::Account] = account.human();
jv[jss::TransactionType] = jss::SignerListSet;
jv[sfSignerQuorum.getJsonName()] = quorum;
auto& ja = jv[sfSignerEntries.getJsonName()];
for (std::size_t i = 0; i < v.size(); ++i)
{
auto const& e = v[i];
auto& je = ja[i][sfSignerEntry.getJsonName()];
je[jss::Account] = e.account.human();
je[sfSignerWeight.getJsonName()] = e.weight;
if (e.tag)
je[sfWalletLocator.getJsonName()] = to_string(*e.tag);
}
return jv;
}
Json::Value
signers(Account const& account, none_t)
{
Json::Value jv;
jv[jss::Account] = account.human();
jv[jss::TransactionType] = jss::SignerListSet;
jv[sfSignerQuorum.getJsonName()] = 0;
return jv;
}
//------------------------------------------------------------------------------
void
msig::operator()(Env& env, JTx& jt) const
{
auto const mySigners = signers;
auto callback = [subField = subField, mySigners, &env](Env&, JTx& jtx) {
// Where to put the signature. Supports sfCounterPartySignature.
auto& sigObject = subField ? jtx[*subField] : jtx.jv;
// The signing pub key is only required at the top level.
if (!subField)
{
sigObject[sfSigningPubKey] = "";
}
else if (sigObject.isNull())
{
sigObject = Json::Value(Json::objectValue);
}
std::optional<STObject> st;
try
{
st = parse(jtx.jv);
}
catch (parse_error const&)
{
env.test.log << pretty(jtx.jv) << std::endl;
Rethrow();
}
auto& js = sigObject[sfSigners];
for (std::size_t i = 0; i < mySigners.size(); ++i)
{
auto const& e = mySigners[i];
auto& jo = js[i][sfSigner.getJsonName()];
jo[jss::Account] = e.acct.human();
jo[jss::SigningPubKey] = strHex(e.sig.pk().slice());
Serializer const ss{buildMultiSigningData(*st, e.acct.id())};
auto const sig = xrpl::sign(*publicKeyType(e.sig.pk().slice()), e.sig.sk(), ss.slice());
jo[sfTxnSignature.getJsonName()] = strHex(Slice{sig.data(), sig.size()});
}
};
if (subField == nullptr)
{
jt.mainSigners.emplace_back(callback);
}
else
{
jt.postSigners.emplace_back(callback);
}
}
} // namespace jtx
} // namespace test
} // namespace xrpl