mirror of
https://github.com/XRPLF/rippled.git
synced 2026-06-04 17:27:00 +00:00
use sfSponsorSignature
This commit is contained in:
@@ -249,8 +249,6 @@ public:
|
||||
getFieldObject(SField const& field) const;
|
||||
STArray const&
|
||||
getFieldArray(SField const& field) const;
|
||||
STObject const&
|
||||
getFieldObject(SField const& field) const;
|
||||
STCurrency const&
|
||||
getFieldCurrency(SField const& field) const;
|
||||
STNumber const&
|
||||
|
||||
@@ -115,12 +115,6 @@ public:
|
||||
boost::container::flat_set<AccountID>
|
||||
getMentionedAccounts() const;
|
||||
|
||||
static Blob
|
||||
getSigningData(STObject const& that);
|
||||
|
||||
static Blob
|
||||
getSponsorSigningData(STTx const& that);
|
||||
|
||||
uint256
|
||||
getTransactionID() const;
|
||||
|
||||
@@ -168,11 +162,6 @@ public:
|
||||
RequireFullyCanonicalSig requireCanonicalSig,
|
||||
Rules const& rules) const;
|
||||
|
||||
Expected<void, std::string>
|
||||
checkSponsorSign(
|
||||
RequireFullyCanonicalSig requireCanonicalSig,
|
||||
Rules const& rules) const;
|
||||
|
||||
// SQL Functions with metadata.
|
||||
static std::string const&
|
||||
getMetaSQLInsertReplaceHeader();
|
||||
@@ -208,23 +197,12 @@ private:
|
||||
STObject const& batchSigner,
|
||||
RequireFullyCanonicalSig requireCanonicalSig) const;
|
||||
|
||||
Expected<void, std::string>
|
||||
checkSponsorSingleSign(
|
||||
STObject const& signer,
|
||||
RequireFullyCanonicalSig requireCanonicalSig) const;
|
||||
|
||||
Expected<void, std::string>
|
||||
checkBatchMultiSign(
|
||||
STObject const& batchSigner,
|
||||
RequireFullyCanonicalSig requireCanonicalSig,
|
||||
Rules const& rules) const;
|
||||
|
||||
Expected<void, std::string>
|
||||
checkSponsorMultiSign(
|
||||
STObject const& signer,
|
||||
RequireFullyCanonicalSig requireCanonicalSig,
|
||||
Rules const& rules) const;
|
||||
|
||||
STBase*
|
||||
copy(std::size_t n, void* buf) const override;
|
||||
STBase*
|
||||
@@ -273,46 +251,6 @@ STTx::getTransactionID() const
|
||||
return tid_;
|
||||
}
|
||||
|
||||
/** Return a Serializer suitable for computing a multisigning TxnSignature. */
|
||||
Serializer
|
||||
buildMultiSigningData(STObject const& obj, AccountID const& signingID);
|
||||
|
||||
/** Break the multi-signing hash computation into 2 parts for optimization.
|
||||
|
||||
We can optimize verifying multiple multisignatures by splitting the
|
||||
data building into two parts;
|
||||
o A large part that is shared by all of the computations.
|
||||
o A small part that is unique to each signer in the multisignature.
|
||||
|
||||
The following methods support that optimization:
|
||||
1. startMultiSigningData provides the large part which can be shared.
|
||||
2. finishMultiSigningData caps the passed in serializer with each
|
||||
signer's unique data.
|
||||
*/
|
||||
Serializer
|
||||
startMultiSigningData(STObject const& obj);
|
||||
|
||||
inline void
|
||||
finishMultiSigningData(AccountID const& signingID, Serializer& s)
|
||||
{
|
||||
s.addBitString(signingID);
|
||||
}
|
||||
|
||||
Serializer
|
||||
buildSponsorMultiSigningData(
|
||||
STObject const& obj,
|
||||
AccountID const& signingID,
|
||||
uint32_t flags);
|
||||
|
||||
Serializer
|
||||
startSponsorSigningData(STObject const& obj);
|
||||
|
||||
inline void
|
||||
finishSponsorSigningData(AccountID const& signerID, Serializer& s)
|
||||
{
|
||||
s.addBitString(signerID);
|
||||
}
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
#endif
|
||||
|
||||
@@ -61,6 +61,31 @@ verify(
|
||||
PublicKey const& pk,
|
||||
SF_VL const& sigField = sfSignature);
|
||||
|
||||
/** Return a Serializer suitable for computing a multisigning TxnSignature. */
|
||||
Serializer
|
||||
buildMultiSigningData(STObject const& obj, AccountID const& signingID);
|
||||
|
||||
/** Break the multi-signing hash computation into 2 parts for optimization.
|
||||
|
||||
We can optimize verifying multiple multisignatures by splitting the
|
||||
data building into two parts;
|
||||
o A large part that is shared by all of the computations.
|
||||
o A small part that is unique to each signer in the multisignature.
|
||||
|
||||
The following methods support that optimization:
|
||||
1. startMultiSigningData provides the large part which can be shared.
|
||||
2. finishMultiSigningData caps the passed in serializer with each
|
||||
signer's unique data.
|
||||
*/
|
||||
Serializer
|
||||
startMultiSigningData(STObject const& obj);
|
||||
|
||||
inline void
|
||||
finishMultiSigningData(AccountID const& signingID, Serializer& s)
|
||||
{
|
||||
s.addBitString(signingID);
|
||||
}
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
#endif
|
||||
|
||||
@@ -383,7 +383,8 @@ UNTYPED_SFIELD(sfCredential, OBJECT, 33)
|
||||
UNTYPED_SFIELD(sfRawTransaction, OBJECT, 34)
|
||||
UNTYPED_SFIELD(sfBatchSigner, OBJECT, 35)
|
||||
UNTYPED_SFIELD(sfBook, OBJECT, 36)
|
||||
UNTYPED_SFIELD(sfSponsor, OBJECT, 37, SField::sMD_Default, SField::notSigning)
|
||||
UNTYPED_SFIELD(sfSponsor, OBJECT, 37)
|
||||
UNTYPED_SFIELD(sfSponsorSignature, OBJECT, 38, SField::sMD_Default, SField::notSigning)
|
||||
|
||||
// array of objects (common)
|
||||
// ARRAY/1 is reserved for end of array
|
||||
|
||||
@@ -178,6 +178,11 @@ InnerObjectFormats::InnerObjectFormats()
|
||||
{
|
||||
{sfAccount, soeREQUIRED},
|
||||
{sfFlags, soeREQUIRED},
|
||||
});
|
||||
|
||||
add(sfSponsorSignature.jsonName.c_str(),
|
||||
sfSponsorSignature.getCode(),
|
||||
{
|
||||
{sfSigningPubKey, soeOPTIONAL},
|
||||
{sfTxnSignature, soeOPTIONAL},
|
||||
{sfSigners, soeOPTIONAL},
|
||||
|
||||
@@ -705,13 +705,6 @@ STObject::getFieldArray(SField const& field) const
|
||||
return getFieldByConstRef<STArray>(field, empty);
|
||||
}
|
||||
|
||||
STObject const&
|
||||
STObject::getFieldObject(SField const& field) const
|
||||
{
|
||||
static STObject const empty(field);
|
||||
return getFieldByConstRef<STObject>(field, empty);
|
||||
}
|
||||
|
||||
STCurrency const&
|
||||
STObject::getFieldCurrency(SField const& field) const
|
||||
{
|
||||
|
||||
@@ -49,7 +49,6 @@
|
||||
#include <xrpl/protocol/SeqProxy.h>
|
||||
#include <xrpl/protocol/Serializer.h>
|
||||
#include <xrpl/protocol/Sign.h>
|
||||
#include <xrpl/protocol/Sponsor.h>
|
||||
#include <xrpl/protocol/TxFlags.h>
|
||||
#include <xrpl/protocol/TxFormats.h>
|
||||
#include <xrpl/protocol/jss.h>
|
||||
@@ -185,26 +184,15 @@ STTx::getMentionedAccounts() const
|
||||
return list;
|
||||
}
|
||||
|
||||
Blob
|
||||
STTx::getSigningData(STObject const& that)
|
||||
static Blob
|
||||
getSigningData(STTx const& that)
|
||||
{
|
||||
Serializer s;
|
||||
s.add32(HashPrefix::txSign);
|
||||
that.addWithoutSigningFields(s);
|
||||
if (that.isFieldPresent(sfSponsor))
|
||||
{
|
||||
auto const sst = that.getFieldObject(sfSponsor);
|
||||
addSerializeSponsorData(s, sst.getAccountID(sfAccount), sst.getFlags());
|
||||
}
|
||||
return s.getData();
|
||||
}
|
||||
|
||||
Blob
|
||||
STTx::getSponsorSigningData(STTx const& that)
|
||||
{
|
||||
return startSponsorSigningData(that).getData();
|
||||
}
|
||||
|
||||
uint256
|
||||
STTx::getSigningHash() const
|
||||
{
|
||||
@@ -299,15 +287,14 @@ STTx::checkSign(
|
||||
if (auto const ret = checkSign(requireCanonicalSig, rules, nullptr); !ret)
|
||||
return ret;
|
||||
|
||||
/* Placeholder for field that will be added by Lending Protocol
|
||||
if (isFieldPresent(sfCounterpartySignature))
|
||||
if (isFieldPresent(sfSponsorSignature))
|
||||
{
|
||||
auto const counterSig = getFieldObject(sfCounterpartySignature);
|
||||
if (auto const ret = checkSign(requireCanonicalSig, rules, &counterSig);
|
||||
auto const sponsorSignatureObj = getFieldObject(sfSponsorSignature);
|
||||
if (auto const ret =
|
||||
checkSign(requireCanonicalSig, rules, &sponsorSignatureObj);
|
||||
!ret)
|
||||
return Unexpected("Counterparty: " + ret.error());
|
||||
return Unexpected("Sponsor: " + ret.error());
|
||||
}
|
||||
*/
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -347,42 +334,6 @@ STTx::checkBatchSign(
|
||||
return Unexpected("Internal batch signature check failure.");
|
||||
}
|
||||
|
||||
Expected<void, std::string>
|
||||
STTx::checkSponsorSign(
|
||||
RequireFullyCanonicalSig requireCanonicalSig,
|
||||
Rules const& rules) const
|
||||
{
|
||||
try
|
||||
{
|
||||
XRPL_ASSERT(
|
||||
isFieldPresent(sfSponsor),
|
||||
"STTx::checkSponsorSign: not a sponsored transaction");
|
||||
if (!isFieldPresent(sfSponsor))
|
||||
{
|
||||
JLOG(debugLog().fatal()) << "not a sponsored transaction";
|
||||
return Unexpected("Not a sponsored transaction.");
|
||||
}
|
||||
STObject const& sponsorObj{getFieldObject(sfSponsor)};
|
||||
|
||||
Blob const& signingPubKey = sponsorObj.getFieldVL(sfSigningPubKey);
|
||||
|
||||
auto const result = signingPubKey.empty()
|
||||
? checkSponsorMultiSign(sponsorObj, requireCanonicalSig, rules)
|
||||
: checkSponsorSingleSign(sponsorObj, requireCanonicalSig);
|
||||
|
||||
if (!result)
|
||||
return result;
|
||||
|
||||
return {};
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
{
|
||||
JLOG(debugLog().error())
|
||||
<< "Sponsor signature check failed: " << e.what();
|
||||
}
|
||||
return Unexpected("Sponsor signature check failure.");
|
||||
}
|
||||
|
||||
Json::Value
|
||||
STTx::getJson(JsonOptions options) const
|
||||
{
|
||||
@@ -523,17 +474,6 @@ STTx::checkBatchSingleSign(
|
||||
return singleSignHelper(batchSigner, msg.slice(), fullyCanonical);
|
||||
}
|
||||
|
||||
Expected<void, std::string>
|
||||
STTx::checkSponsorSingleSign(
|
||||
STObject const& signer,
|
||||
RequireFullyCanonicalSig requireCanonicalSig) const
|
||||
{
|
||||
auto const data = getSponsorSigningData(*this);
|
||||
bool const fullyCanonical = (getFlags() & tfFullyCanonicalSig) ||
|
||||
(requireCanonicalSig == STTx::RequireFullyCanonicalSig::yes);
|
||||
return singleSignHelper(signer, makeSlice(data), fullyCanonical);
|
||||
}
|
||||
|
||||
Expected<void, std::string>
|
||||
multiSignHelper(
|
||||
STObject const& sigObject,
|
||||
@@ -640,32 +580,6 @@ STTx::checkBatchMultiSign(
|
||||
rules);
|
||||
}
|
||||
|
||||
Expected<void, std::string>
|
||||
STTx::checkSponsorMultiSign(
|
||||
STObject const& sponsorObj,
|
||||
RequireFullyCanonicalSig requireCanonicalSig,
|
||||
Rules const& rules) const
|
||||
{
|
||||
bool const fullyCanonical = (getFlags() & tfFullyCanonicalSig) ||
|
||||
(requireCanonicalSig == RequireFullyCanonicalSig::yes);
|
||||
|
||||
// We can ease the computational load inside the loop a bit by
|
||||
// pre-constructing part of the data that we hash. Fill a Serializer
|
||||
// with the stuff that stays constant from signature to signature.
|
||||
auto const data = startSponsorSigningData(*this);
|
||||
Serializer dataStart = Serializer(data.data(), data.size());
|
||||
|
||||
return multiSignHelper(
|
||||
sponsorObj,
|
||||
fullyCanonical,
|
||||
[&dataStart](AccountID const& accountID) mutable -> Serializer {
|
||||
Serializer s = dataStart;
|
||||
finishSponsorSigningData(accountID, s);
|
||||
return s;
|
||||
},
|
||||
rules);
|
||||
}
|
||||
|
||||
Expected<void, std::string>
|
||||
STTx::checkMultiSign(
|
||||
RequireFullyCanonicalSig requireCanonicalSig,
|
||||
@@ -964,90 +878,4 @@ isPseudoTx(STObject const& tx)
|
||||
return tt == ttAMENDMENT || tt == ttFEE || tt == ttUNL_MODIFY;
|
||||
}
|
||||
|
||||
// Questions regarding buildMultiSigningData:
|
||||
//
|
||||
// Why do we include the Signer.Account in the blob to be signed?
|
||||
//
|
||||
// Unless you include the Account which is signing in the signing blob,
|
||||
// you could swap out any Signer.Account for any other, which may also
|
||||
// be on the SignerList and have a RegularKey matching the
|
||||
// Signer.SigningPubKey.
|
||||
//
|
||||
// That RegularKey may be set to allow some 3rd party to sign transactions
|
||||
// on the account's behalf, and that RegularKey could be common amongst all
|
||||
// users of the 3rd party. That's just one example of sharing the same
|
||||
// RegularKey amongst various accounts and just one vulnerability.
|
||||
//
|
||||
// "When you have something that's easy to do that makes entire classes of
|
||||
// attacks clearly and obviously impossible, you need a damn good reason
|
||||
// not to do it." -- David Schwartz
|
||||
//
|
||||
// Why would we include the signingFor account in the blob to be signed?
|
||||
//
|
||||
// In the current signing scheme, the account that a signer is `signing
|
||||
// for/on behalf of` is the tx_json.Account.
|
||||
//
|
||||
// Later we might support more levels of signing. Suppose Bob is a signer
|
||||
// for Alice, and Carol is a signer for Bob, so Carol can sign for Bob who
|
||||
// signs for Alice. But suppose Alice has two signers: Bob and Dave. If
|
||||
// Carol is a signer for both Bob and Dave, then the signature needs to
|
||||
// distinguish between Carol signing for Bob and Carol signing for Dave.
|
||||
//
|
||||
// So, if we support multiple levels of signing, then we'll need to
|
||||
// incorporate the "signing for" accounts into the signing data as well.
|
||||
Serializer
|
||||
buildMultiSigningData(STObject const& obj, AccountID const& signingID)
|
||||
{
|
||||
Serializer s{startMultiSigningData(obj)};
|
||||
finishMultiSigningData(signingID, s);
|
||||
return s;
|
||||
}
|
||||
|
||||
Serializer
|
||||
startMultiSigningData(STObject const& obj)
|
||||
{
|
||||
Serializer s;
|
||||
s.add32(HashPrefix::txMultiSign);
|
||||
obj.addWithoutSigningFields(s);
|
||||
// if (obj.isFieldPresent(sfSponsor))
|
||||
// {
|
||||
// auto const sst = obj.getFieldObject(sfSponsor);
|
||||
// addSerializeSponsorData(s, sst.getAccountID(sfAccount),
|
||||
// sst.getFlags());
|
||||
// }
|
||||
return s;
|
||||
}
|
||||
|
||||
Serializer
|
||||
buildSponsorMultiSigningData(
|
||||
STObject const& obj,
|
||||
AccountID const& signingID,
|
||||
uint32_t flags)
|
||||
{
|
||||
Serializer s{startSponsorSigningData(obj)};
|
||||
finishSponsorSigningData(signingID, s);
|
||||
return s;
|
||||
}
|
||||
|
||||
Serializer
|
||||
startSponsorSigningData(STObject const& obj)
|
||||
{
|
||||
Serializer s;
|
||||
s.add32(HashPrefix::sponsor);
|
||||
STObject tmp = obj;
|
||||
tmp.setFieldVL(sfSigningPubKey, Blob{});
|
||||
tmp.addWithoutSigningFields(s);
|
||||
|
||||
XRPL_ASSERT(
|
||||
tmp.isFieldPresent(sfSponsor),
|
||||
"STTx::getSponsorSigningData : sponsor is not set");
|
||||
|
||||
if (tmp.isFieldPresent(sfSponsor))
|
||||
{
|
||||
auto const sst = tmp.getFieldObject(sfSponsor);
|
||||
addSerializeSponsorData(s, sst.getAccountID(sfAccount), sst.getFlags());
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
@@ -61,4 +61,52 @@ verify(
|
||||
pk, Slice(ss.data(), ss.size()), Slice(sig->data(), sig->size()));
|
||||
}
|
||||
|
||||
// Questions regarding buildMultiSigningData:
|
||||
//
|
||||
// Why do we include the Signer.Account in the blob to be signed?
|
||||
//
|
||||
// Unless you include the Account which is signing in the signing blob,
|
||||
// you could swap out any Signer.Account for any other, which may also
|
||||
// be on the SignerList and have a RegularKey matching the
|
||||
// Signer.SigningPubKey.
|
||||
//
|
||||
// That RegularKey may be set to allow some 3rd party to sign transactions
|
||||
// on the account's behalf, and that RegularKey could be common amongst all
|
||||
// users of the 3rd party. That's just one example of sharing the same
|
||||
// RegularKey amongst various accounts and just one vulnerability.
|
||||
//
|
||||
// "When you have something that's easy to do that makes entire classes of
|
||||
// attacks clearly and obviously impossible, you need a damn good reason
|
||||
// not to do it." -- David Schwartz
|
||||
//
|
||||
// Why would we include the signingFor account in the blob to be signed?
|
||||
//
|
||||
// In the current signing scheme, the account that a signer is `signing
|
||||
// for/on behalf of` is the tx_json.Account.
|
||||
//
|
||||
// Later we might support more levels of signing. Suppose Bob is a signer
|
||||
// for Alice, and Carol is a signer for Bob, so Carol can sign for Bob who
|
||||
// signs for Alice. But suppose Alice has two signers: Bob and Dave. If
|
||||
// Carol is a signer for both Bob and Dave, then the signature needs to
|
||||
// distinguish between Carol signing for Bob and Carol signing for Dave.
|
||||
//
|
||||
// So, if we support multiple levels of signing, then we'll need to
|
||||
// incorporate the "signing for" accounts into the signing data as well.
|
||||
Serializer
|
||||
buildMultiSigningData(STObject const& obj, AccountID const& signingID)
|
||||
{
|
||||
Serializer s{startMultiSigningData(obj)};
|
||||
finishMultiSigningData(signingID, s);
|
||||
return s;
|
||||
}
|
||||
|
||||
Serializer
|
||||
startMultiSigningData(STObject const& obj)
|
||||
{
|
||||
Serializer s;
|
||||
s.add32(HashPrefix::txMultiSign);
|
||||
obj.addWithoutSigningFields(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
@@ -48,6 +48,7 @@ TxFormats::TxFormats()
|
||||
{sfNetworkID, soeOPTIONAL},
|
||||
{sfDelegate, soeOPTIONAL},
|
||||
{sfSponsor, soeOPTIONAL},
|
||||
{sfSponsorSignature, soeOPTIONAL},
|
||||
};
|
||||
|
||||
#pragma push_macro("UNWRAP")
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -20,7 +20,6 @@
|
||||
#ifndef RIPPLE_TEST_JTX_JTX_H_INCLUDED
|
||||
#define RIPPLE_TEST_JTX_JTX_H_INCLUDED
|
||||
|
||||
#include <test/jtx/Account.h>
|
||||
#include <test/jtx/basic_prop.h>
|
||||
#include <test/jtx/requires.h>
|
||||
|
||||
@@ -58,7 +57,7 @@ struct JTx
|
||||
// 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
|
||||
// sfCounterpartySignature and sfSponsorSignature
|
||||
std::vector<std::function<void(Env&, JTx&)>> postSigners;
|
||||
|
||||
JTx() = default;
|
||||
|
||||
@@ -592,9 +592,6 @@ Env::autofill_sig(JTx& jt)
|
||||
jtx::sign(jv, lookup(ar->getAccountID(sfRegularKey)));
|
||||
else
|
||||
jtx::sign(jv, account);
|
||||
|
||||
if (jt.sponsorSigner)
|
||||
jt.sponsorSigner(*this, jt);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -70,7 +70,8 @@ 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.
|
||||
// Where to put the signature. Supports sfCounterPartySignature and
|
||||
// sfSponsorSignature.
|
||||
auto& sigObject = subField ? jtx[*subField] : jtx.jv;
|
||||
|
||||
// The signing pub key is only required at the top level.
|
||||
|
||||
@@ -119,76 +119,6 @@ as::operator()(Env& env, JTx& jt) const
|
||||
jt.jv[sfSponsor.jsonName][sfFlags.jsonName] = flags;
|
||||
}
|
||||
|
||||
void
|
||||
sig::operator()(Env& env, JTx& jt) const
|
||||
{
|
||||
auto const signer = signer_;
|
||||
|
||||
jt.jv[sfSponsor.jsonName][sfAccount.jsonName] = signer.acct.human();
|
||||
jt.jv[sfSponsor.jsonName][sfSigningPubKey.jsonName] =
|
||||
strHex(signer.sig.pk().slice());
|
||||
|
||||
jt.sponsorSigner = [signer, &env](Env&, JTx& jtx) {
|
||||
std::optional<STObject> st;
|
||||
try
|
||||
{
|
||||
Json::Value jv = jtx.jv;
|
||||
st = parse(jv);
|
||||
}
|
||||
catch (parse_error const&)
|
||||
{
|
||||
env.test.log << pretty(jtx.jv) << std::endl;
|
||||
Rethrow();
|
||||
}
|
||||
|
||||
auto const sst = st->getFieldObject(sfSponsor);
|
||||
|
||||
auto const signingData =
|
||||
STTx::getSponsorSigningData(STTx{std::move(*st)});
|
||||
|
||||
auto const sig = ripple::sign(
|
||||
signer.acct.pk(), signer.acct.sk(), makeSlice(signingData));
|
||||
jtx.jv[sfSponsor.jsonName][jss::TxnSignature] =
|
||||
strHex(Slice{sig.data(), sig.size()});
|
||||
};
|
||||
}
|
||||
|
||||
void
|
||||
msig::operator()(Env& env, JTx& jt) const
|
||||
{
|
||||
auto const mySigners = signers;
|
||||
jt.sponsorSigner = [mySigners, &env](Env&, JTx& jtx) {
|
||||
std::optional<STObject> st;
|
||||
try
|
||||
{
|
||||
Json::Value jv = jtx.jv;
|
||||
jv[jss::SigningPubKey] = "";
|
||||
st = parse(jv);
|
||||
}
|
||||
catch (parse_error const&)
|
||||
{
|
||||
env.test.log << pretty(jtx.jv) << std::endl;
|
||||
Rethrow();
|
||||
}
|
||||
auto const sst = st->getFieldObject(sfSponsor);
|
||||
auto& js = jtx[sfSponsor.jsonName][sfSigners.jsonName];
|
||||
for (std::size_t i = 0; i < mySigners.size(); ++i)
|
||||
{
|
||||
auto const& e = mySigners[i];
|
||||
auto& jo = js[i][sfSigner.jsonName];
|
||||
jo[jss::Account] = e.acct.human();
|
||||
jo[jss::SigningPubKey] = strHex(e.sig.pk().slice());
|
||||
|
||||
Serializer ss{
|
||||
buildSponsorMultiSigningData(*st, e.acct.id(), sst.getFlags())};
|
||||
|
||||
auto const sig = ripple::sign(
|
||||
*publicKeyType(e.sig.pk().slice()), e.sig.sk(), ss.slice());
|
||||
jo[sfTxnSignature.jsonName] = strHex(Slice{sig.data(), sig.size()});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Json::Value
|
||||
ledgerEntry(
|
||||
jtx::Env& env,
|
||||
|
||||
@@ -101,35 +101,6 @@ public:
|
||||
operator()(jtx::Env&, jtx::JTx& jtx) const;
|
||||
};
|
||||
|
||||
struct sig
|
||||
{
|
||||
private:
|
||||
Reg signer_;
|
||||
|
||||
public:
|
||||
sig(Reg signer) : signer_(std::move(signer))
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
operator()(jtx::Env&, jtx::JTx& jtx) const;
|
||||
};
|
||||
|
||||
struct msig
|
||||
{
|
||||
private:
|
||||
std::vector<Reg> signers;
|
||||
|
||||
public:
|
||||
msig(std::vector<Reg> signers_) : signers(std::move(signers_))
|
||||
{
|
||||
sortSigners(signers);
|
||||
}
|
||||
|
||||
void
|
||||
operator()(jtx::Env&, jtx::JTx& jtx) const;
|
||||
};
|
||||
|
||||
Json::Value
|
||||
ledgerEntry(
|
||||
jtx::Env& env,
|
||||
|
||||
@@ -870,7 +870,7 @@ class AccountTx_test : public beast::unit_test::suite
|
||||
// fee sponsorship
|
||||
env(noop(alice),
|
||||
sponsor::as(sponsor, tfSponsorFee),
|
||||
sponsor::sig(sponsor));
|
||||
sig(sfSponsorSignature, sponsor));
|
||||
env.close();
|
||||
checkTx(alice, jss::AccountSet);
|
||||
checkTx(sponsor, jss::AccountSet);
|
||||
@@ -893,7 +893,7 @@ class AccountTx_test : public beast::unit_test::suite
|
||||
// transfer object sponsorship
|
||||
env(sponsor::transfer(alice, keylet::ticket(alice, seq + 1).key),
|
||||
sponsor::as(sponsor2, tfSponsorReserve),
|
||||
sponsor::sig(sponsor2));
|
||||
sig(sfSponsorSignature, sponsor2));
|
||||
env.close();
|
||||
checkTx(alice, jss::SponsorshipTransfer);
|
||||
checkTx(sponsor, jss::SponsorshipTransfer);
|
||||
@@ -903,7 +903,7 @@ class AccountTx_test : public beast::unit_test::suite
|
||||
env(noop(alice),
|
||||
ticket::use(seq + 1),
|
||||
sponsor::as(sponsor, tfSponsorFee),
|
||||
sponsor::sig(sponsor));
|
||||
sig(sfSponsorSignature, sponsor));
|
||||
env.close();
|
||||
checkTx(alice, jss::AccountSet);
|
||||
checkTx(sponsor, jss::AccountSet);
|
||||
@@ -912,7 +912,7 @@ class AccountTx_test : public beast::unit_test::suite
|
||||
// account sponsorship
|
||||
env(sponsor::transfer(alice),
|
||||
sponsor::as(sponsor, tfSponsorReserve),
|
||||
sponsor::sig(sponsor));
|
||||
sig(sfSponsorSignature, sponsor));
|
||||
env.close();
|
||||
checkTx(alice, jss::SponsorshipTransfer);
|
||||
checkTx(sponsor, jss::SponsorshipTransfer);
|
||||
|
||||
@@ -322,9 +322,7 @@ Transactor::checkSponsor(ReadView const& view, STTx const& tx)
|
||||
auto const sponsorAcc = txSponsor.getAccountID(sfAccount);
|
||||
auto const sponseeAcc = tx.getAccountID(sfAccount);
|
||||
|
||||
auto const hasSponsorSignature = txSponsor.isFieldPresent(sfTxnSignature) ||
|
||||
!txSponsor.getFieldVL(sfSigningPubKey).empty() ||
|
||||
txSponsor.isFieldPresent(sfSigners);
|
||||
auto const hasSponsorSignature = tx.isFieldPresent(sfSponsorSignature);
|
||||
|
||||
if (!hasSponsorSignature)
|
||||
{
|
||||
@@ -787,17 +785,20 @@ Transactor::checkSign(
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
if (sigObject.isFieldPresent(sfSponsor))
|
||||
if (sigObject.isFieldPresent(sfSponsorSignature))
|
||||
{
|
||||
if (!sigObject.isFieldPresent(sfSponsor))
|
||||
return temMALFORMED;
|
||||
|
||||
auto const sponsorObj = sigObject.getFieldObject(sfSponsor);
|
||||
auto const isCoSigned = sponsorObj.isFieldPresent(sfTxnSignature) ||
|
||||
!sponsorObj.getFieldVL(sfSigningPubKey).empty() ||
|
||||
sponsorObj.isFieldPresent(sfSigners);
|
||||
auto const isCoSigned = sigObject.isFieldPresent(sfSponsorSignature);
|
||||
if (isCoSigned)
|
||||
{
|
||||
auto const sponsorAcc = sponsorObj.getAccountID(sfAccount);
|
||||
auto const sponsorSignature =
|
||||
sigObject.getFieldObject(sfSponsorSignature);
|
||||
if (auto const ret =
|
||||
checkSign(view, flags, sponsorAcc, sponsorObj, j);
|
||||
checkSign(view, flags, sponsorAcc, sponsorSignature, j);
|
||||
!isTesSuccess(ret))
|
||||
return ret;
|
||||
}
|
||||
@@ -1266,9 +1267,7 @@ Transactor::getFeePayer(STTx const& tx)
|
||||
tx.getFieldObject(sfSponsor).isFlag(tfSponsorFee))
|
||||
{
|
||||
auto const sponsor = tx.getFieldObject(sfSponsor);
|
||||
auto const hasSignature = sponsor.isFieldPresent(sfTxnSignature) ||
|
||||
!sponsor.getFieldVL(sfSigningPubKey).empty() ||
|
||||
sponsor.isFieldPresent(sfSigners);
|
||||
auto const hasSignature = tx.isFieldPresent(sfSponsorSignature);
|
||||
|
||||
if (!hasSignature)
|
||||
{
|
||||
|
||||
@@ -86,13 +86,13 @@ checkValidity(
|
||||
if (tx.isFieldPresent(sfSponsor) && rules.enabled(featureSponsor))
|
||||
{
|
||||
auto const sponsorObj = tx.getFieldObject(sfSponsor);
|
||||
auto const isCoSigned = sponsorObj.isFieldPresent(sfTxnSignature) ||
|
||||
!sponsorObj.getFieldVL(sfSigningPubKey).empty() ||
|
||||
sponsorObj.isFieldPresent(sfSigners);
|
||||
auto const isCoSigned = tx.isFieldPresent(sfSponsorSignature);
|
||||
if (isCoSigned)
|
||||
{
|
||||
auto const sigVerify =
|
||||
tx.checkSponsorSign(requireCanonicalSig, rules);
|
||||
auto const sponsorSignatureObj =
|
||||
tx.getFieldObject(sfSponsorSignature);
|
||||
auto const sigVerify = tx.checkSign(
|
||||
requireCanonicalSig, rules, &sponsorSignatureObj);
|
||||
if (!sigVerify)
|
||||
{
|
||||
router.setFlags(id, SF_SIGBAD);
|
||||
|
||||
Reference in New Issue
Block a user