mirror of
https://github.com/XRPLF/rippled.git
synced 2026-10-19 18:18:12 +00:00
Compare commits
1 Commits
mvadari/re
...
mvadari/ba
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0dfaf80a27 |
@@ -41,6 +41,7 @@ This section contains changes targeting a future version.
|
|||||||
|
|
||||||
### Bugfixes
|
### Bugfixes
|
||||||
|
|
||||||
|
- `sign_for`, `submit_multisigned`: A `BatchSigner` that signs from a signer list now covers a different signing prefix (`BCM`) than a `BatchSigner` that signs on its own (`BCH`), matching the existing split between `STX` and `SMT`. Clients that build batch signatures themselves must use the new prefix for the multi-signing form. `Batch` is not enabled on any network, so no existing signature is affected.
|
||||||
- `get_aggregate_price`: Duplicate entries in the `oracles` request array are now ignored. [#6586](https://github.com/XRPLF/rippled/pull/6586)
|
- `get_aggregate_price`: Duplicate entries in the `oracles` request array are now ignored. [#6586](https://github.com/XRPLF/rippled/pull/6586)
|
||||||
- Peer Crawler: The `port` field in `overlay.active[]` now consistently returns an integer instead of a string for outbound peers. [#6318](https://github.com/XRPLF/rippled/pull/6318)
|
- Peer Crawler: The `port` field in `overlay.active[]` now consistently returns an integer instead of a string for outbound peers. [#6318](https://github.com/XRPLF/rippled/pull/6318)
|
||||||
- `ping`: The `ip` field is no longer returned as an empty string for proxied connections without a forwarded-for header. It is now omitted, consistent with the behavior for identified connections. [#6730](https://github.com/XRPLF/rippled/pull/6730)
|
- `ping`: The `ip` field is no longer returned as an empty string for proxied connections without a forwarded-for header. It is now omitted, consistent with the behavior for identified connections. [#6730](https://github.com/XRPLF/rippled/pull/6730)
|
||||||
|
|||||||
@@ -10,15 +10,24 @@
|
|||||||
|
|
||||||
namespace xrpl {
|
namespace xrpl {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize the data that a batch signer signs.
|
||||||
|
*
|
||||||
|
* @param prefix HashPrefix::Batch when the batch signer signs on its own,
|
||||||
|
* HashPrefix::BatchMultiSign when the signature comes from a signer list. The
|
||||||
|
* two forms differ by the signer account that the caller appends, so the
|
||||||
|
* prefix keeps them in separate hash spaces, as with TxSign and TxMultiSign.
|
||||||
|
*/
|
||||||
inline void
|
inline void
|
||||||
serializeBatch(
|
serializeBatch(
|
||||||
Serializer& msg,
|
Serializer& msg,
|
||||||
|
HashPrefix prefix,
|
||||||
AccountID const& outerAccount,
|
AccountID const& outerAccount,
|
||||||
std::uint32_t outerSeqValue,
|
std::uint32_t outerSeqValue,
|
||||||
std::uint32_t const& flags,
|
std::uint32_t const& flags,
|
||||||
std::vector<uint256> const& txids)
|
std::vector<uint256> const& txids)
|
||||||
{
|
{
|
||||||
msg.add32(HashPrefix::Batch);
|
msg.add32(prefix);
|
||||||
msg.addBitString(outerAccount);
|
msg.addBitString(outerAccount);
|
||||||
msg.add32(outerSeqValue);
|
msg.add32(outerSeqValue);
|
||||||
msg.add32(flags);
|
msg.add32(flags);
|
||||||
|
|||||||
@@ -89,9 +89,14 @@ enum class HashPrefix : std::uint32_t {
|
|||||||
PaymentChannelClaim = detail::makeHashPrefix('C', 'L', 'M'),
|
PaymentChannelClaim = detail::makeHashPrefix('C', 'L', 'M'),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Batch
|
* Batch to sign
|
||||||
*/
|
*/
|
||||||
Batch = detail::makeHashPrefix('B', 'C', 'H'),
|
Batch = detail::makeHashPrefix('B', 'C', 'H'),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Batch to multi-sign
|
||||||
|
*/
|
||||||
|
BatchMultiSign = detail::makeHashPrefix('B', 'C', 'M'),
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class Hasher>
|
template <class Hasher>
|
||||||
|
|||||||
@@ -458,7 +458,8 @@ STTx::checkBatchSingleSign(STObject const& batchSigner, std::vector<uint256> con
|
|||||||
{
|
{
|
||||||
XRPL_ASSERT(getTxnType() == ttBATCH, "STTx::checkBatchSingleSign : batch transaction");
|
XRPL_ASSERT(getTxnType() == ttBATCH, "STTx::checkBatchSingleSign : batch transaction");
|
||||||
Serializer msg;
|
Serializer msg;
|
||||||
serializeBatch(msg, getAccountID(sfAccount), getSeqProxy().value(), getFlags(), txIds);
|
serializeBatch(
|
||||||
|
msg, HashPrefix::Batch, getAccountID(sfAccount), getSeqProxy().value(), getFlags(), txIds);
|
||||||
finishMultiSigningData(batchSigner.getAccountID(sfAccount), msg);
|
finishMultiSigningData(batchSigner.getAccountID(sfAccount), msg);
|
||||||
return singleSignHelper(batchSigner, msg.slice());
|
return singleSignHelper(batchSigner, msg.slice());
|
||||||
}
|
}
|
||||||
@@ -552,7 +553,13 @@ STTx::checkBatchMultiSign(
|
|||||||
// with the stuff that stays constant from signature to signature.
|
// with the stuff that stays constant from signature to signature.
|
||||||
auto const batchSignerAccount = batchSigner.getAccountID(sfAccount);
|
auto const batchSignerAccount = batchSigner.getAccountID(sfAccount);
|
||||||
Serializer dataStart;
|
Serializer dataStart;
|
||||||
serializeBatch(dataStart, getAccountID(sfAccount), getSeqProxy().value(), getFlags(), txIds);
|
serializeBatch(
|
||||||
|
dataStart,
|
||||||
|
HashPrefix::BatchMultiSign,
|
||||||
|
getAccountID(sfAccount),
|
||||||
|
getSeqProxy().value(),
|
||||||
|
getFlags(),
|
||||||
|
txIds);
|
||||||
dataStart.addBitString(batchSignerAccount);
|
dataStart.addBitString(batchSignerAccount);
|
||||||
return multiSignHelper(
|
return multiSignHelper(
|
||||||
batchSigner,
|
batchSigner,
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
#include <xrpld/app/misc/TxQ.h>
|
#include <xrpld/app/misc/TxQ.h>
|
||||||
|
|
||||||
#include <xrpl/basics/base_uint.h>
|
#include <xrpl/basics/base_uint.h>
|
||||||
|
#include <xrpl/basics/safe_cast.h>
|
||||||
#include <xrpl/basics/strHex.h>
|
#include <xrpl/basics/strHex.h>
|
||||||
#include <xrpl/beast/unit_test/suite.h>
|
#include <xrpl/beast/unit_test/suite.h>
|
||||||
#include <xrpl/beast/utility/Journal.h>
|
#include <xrpl/beast/utility/Journal.h>
|
||||||
@@ -648,6 +649,7 @@ class Batch_test : public beast::unit_test::Suite
|
|||||||
Serializer msg;
|
Serializer msg;
|
||||||
serializeBatch(
|
serializeBatch(
|
||||||
msg,
|
msg,
|
||||||
|
HashPrefix::Batch,
|
||||||
jt.stx->getAccountID(sfAccount),
|
jt.stx->getAccountID(sfAccount),
|
||||||
jt.stx->getSeqProxy().value(),
|
jt.stx->getSeqProxy().value(),
|
||||||
tfAllOrNothing,
|
tfAllOrNothing,
|
||||||
@@ -2910,6 +2912,79 @@ class Batch_test : public beast::unit_test::Suite
|
|||||||
env.close();
|
env.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
testSigningPrefixes(FeatureBitset features)
|
||||||
|
{
|
||||||
|
testcase("signing prefixes");
|
||||||
|
|
||||||
|
using namespace test::jtx;
|
||||||
|
using namespace std::literals;
|
||||||
|
|
||||||
|
// A batch signer signs one of two payloads: the batch data plus its
|
||||||
|
// own account, or, when it signs from a signer list, the batch data
|
||||||
|
// plus its own account plus the signer's account. Each payload has its
|
||||||
|
// own prefix, so a signature made for one cannot be read as the other.
|
||||||
|
static_assert(safeCast<std::uint32_t>(HashPrefix::Batch) == 0x42434800);
|
||||||
|
static_assert(safeCast<std::uint32_t>(HashPrefix::BatchMultiSign) == 0x42434D00);
|
||||||
|
|
||||||
|
Env env{*this, features};
|
||||||
|
|
||||||
|
auto const alice = Account("alice");
|
||||||
|
auto const bob = Account("bob");
|
||||||
|
auto const carol = Account("carol");
|
||||||
|
auto const dave = Account("dave");
|
||||||
|
env.fund(XRP(10000), alice, bob, carol, dave);
|
||||||
|
env.close();
|
||||||
|
|
||||||
|
env(signers(bob, 1, {{carol, 1}, {dave, 1}}));
|
||||||
|
env.close();
|
||||||
|
|
||||||
|
// A multi-signature over the single-signing payload is rejected.
|
||||||
|
{
|
||||||
|
auto const seq = env.seq(alice);
|
||||||
|
auto const batchFee = batch::calcBatchFee(env, 2, 2);
|
||||||
|
auto jt = env.jtnofill(
|
||||||
|
batch::outer(alice, seq, batchFee, tfAllOrNothing),
|
||||||
|
batch::Inner(pay(alice, bob, XRP(10)), seq + 1),
|
||||||
|
batch::Inner(pay(bob, alice, XRP(5)), env.seq(bob)));
|
||||||
|
|
||||||
|
Serializer msg;
|
||||||
|
serializeBatch(
|
||||||
|
msg,
|
||||||
|
HashPrefix::Batch,
|
||||||
|
jt.stx->getAccountID(sfAccount),
|
||||||
|
jt.stx->getSeqProxy().value(),
|
||||||
|
tfAllOrNothing,
|
||||||
|
jt.stx->getBatchTransactionIDs());
|
||||||
|
msg.addBitString(bob.id());
|
||||||
|
finishMultiSigningData(carol.id(), msg);
|
||||||
|
auto const sig = xrpl::sign(carol.pk(), carol.sk(), msg.slice());
|
||||||
|
|
||||||
|
auto& bso = jt.jv[sfBatchSigners.jsonName][0u][sfBatchSigner.jsonName];
|
||||||
|
bso[sfAccount.jsonName] = bob.human();
|
||||||
|
bso[sfSigningPubKey.jsonName] = "";
|
||||||
|
auto& iso = bso[sfSigners.jsonName][0u][sfSigner.jsonName];
|
||||||
|
iso[sfAccount.jsonName] = carol.human();
|
||||||
|
iso[sfSigningPubKey.jsonName] = strHex(carol.pk());
|
||||||
|
iso[sfTxnSignature.jsonName] = strHex(Slice{sig.data(), sig.size()});
|
||||||
|
|
||||||
|
env(jt.jv, Ter(telENV_RPC_FAILED));
|
||||||
|
env.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
// The same signature over the multi-signing payload is accepted.
|
||||||
|
{
|
||||||
|
auto const seq = env.seq(alice);
|
||||||
|
auto const batchFee = batch::calcBatchFee(env, 2, 2);
|
||||||
|
env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
|
||||||
|
batch::Inner(pay(alice, bob, XRP(10)), seq + 1),
|
||||||
|
batch::Inner(pay(bob, alice, XRP(5)), env.seq(bob)),
|
||||||
|
batch::Msig(bob, {carol}),
|
||||||
|
Ter(tesSUCCESS));
|
||||||
|
env.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
testAccountSet(FeatureBitset features)
|
testAccountSet(FeatureBitset features)
|
||||||
{
|
{
|
||||||
@@ -5913,6 +5988,7 @@ class Batch_test : public beast::unit_test::Suite
|
|||||||
testInnerSubmitRPC(features);
|
testInnerSubmitRPC(features);
|
||||||
testAccountActivation(features);
|
testAccountActivation(features);
|
||||||
testCheckAllSignatures(features);
|
testCheckAllSignatures(features);
|
||||||
|
testSigningPrefixes(features);
|
||||||
testAccountSet(features);
|
testAccountSet(features);
|
||||||
testAccountDelete(features);
|
testAccountDelete(features);
|
||||||
testLoan(features);
|
testLoan(features);
|
||||||
|
|||||||
@@ -101,6 +101,7 @@ Sig::operator()(Env& env, JTx& jt) const
|
|||||||
Serializer msg;
|
Serializer msg;
|
||||||
serializeBatch(
|
serializeBatch(
|
||||||
msg,
|
msg,
|
||||||
|
HashPrefix::Batch,
|
||||||
stx.getAccountID(sfAccount),
|
stx.getAccountID(sfAccount),
|
||||||
stx.getSeqProxy().value(),
|
stx.getSeqProxy().value(),
|
||||||
stx.getFlags(),
|
stx.getFlags(),
|
||||||
@@ -145,6 +146,7 @@ Msig::operator()(Env& env, JTx& jt) const
|
|||||||
Serializer msg;
|
Serializer msg;
|
||||||
serializeBatch(
|
serializeBatch(
|
||||||
msg,
|
msg,
|
||||||
|
HashPrefix::BatchMultiSign,
|
||||||
stx.getAccountID(sfAccount),
|
stx.getAccountID(sfAccount),
|
||||||
stx.getSeqProxy().value(),
|
stx.getSeqProxy().value(),
|
||||||
stx.getFlags(),
|
stx.getFlags(),
|
||||||
|
|||||||
Reference in New Issue
Block a user