Skip to content

Commit

Permalink
XChainBridge: Introduce sidechain support (XLS-38): (#4292)
Browse files Browse the repository at this point in the history
A bridge connects two blockchains: a locking chain and an issuing
chain (also called a mainchain and a sidechain). Both are independent
ledgers, with their own validators and potentially their own custom
transactions. Importantly, there is a way to move assets from the
locking chain to the issuing chain and a way to return those assets from
the issuing chain back to the locking chain: the bridge. This key
operation is called a cross-chain transfer. A cross-chain transfer is
not a single transaction. It happens on two chains, requires multiple
transactions, and involves an additional server type called a "witness".

A bridge does not exchange assets between two ledgers. Instead, it locks
assets on one ledger (the "locking chain") and represents those assets
with wrapped assets on another chain (the "issuing chain"). A good model
to keep in mind is a box with an infinite supply of wrapped assets.
Putting an asset from the locking chain into the box will release a
wrapped asset onto the issuing chain. Putting a wrapped asset from the
issuing chain back into the box will release one of the existing locking
chain assets back onto the locking chain. There is no other way to get
assets into or out of the box. Note that there is no way for the box to
"run out of" wrapped assets - it has an infinite supply.

Co-authored-by: Gregory Popovitch <[email protected]>
  • Loading branch information
seelabs and greg7mdp authored Sep 14, 2023
1 parent 7fae1c1 commit 649c11a
Show file tree
Hide file tree
Showing 59 changed files with 12,142 additions and 174 deletions.
6 changes: 4 additions & 2 deletions Builds/CMake/CMakeFuncs.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ macro(group_sources curdir)
endmacro()

macro (exclude_from_default target_)
set_target_properties (${target_} PROPERTIES EXCLUDE_FROM_ALL ON)
set_target_properties (${target_} PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD ON)
if(target_)
set_target_properties (${target_} PROPERTIES EXCLUDE_FROM_ALL ON)
set_target_properties (${target_} PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD ON)
endif()
endmacro ()

macro (exclude_if_included target_)
Expand Down
9 changes: 9 additions & 0 deletions Builds/CMake/RippledCore.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,9 @@ target_sources (xrpl_core PRIVATE
src/ripple/protocol/impl/STObject.cpp
src/ripple/protocol/impl/STParsedJSON.cpp
src/ripple/protocol/impl/STPathSet.cpp
src/ripple/protocol/impl/STXChainBridge.cpp
src/ripple/protocol/impl/STTx.cpp
src/ripple/protocol/impl/XChainAttestations.cpp
src/ripple/protocol/impl/STValidation.cpp
src/ripple/protocol/impl/STVar.cpp
src/ripple/protocol/impl/STVector256.cpp
Expand Down Expand Up @@ -243,6 +245,7 @@ install (
src/ripple/protocol/Indexes.h
src/ripple/protocol/InnerObjectFormats.h
src/ripple/protocol/Issue.h
src/ripple/protocol/json_get_or_throw.h
src/ripple/protocol/KeyType.h
src/ripple/protocol/Keylet.h
src/ripple/protocol/KnownFormats.h
Expand Down Expand Up @@ -273,6 +276,8 @@ install (
src/ripple/protocol/STParsedJSON.h
src/ripple/protocol/STPathSet.h
src/ripple/protocol/STTx.h
src/ripple/protocol/XChainAttestations.h
src/ripple/protocol/STXChainBridge.h
src/ripple/protocol/STValidation.h
src/ripple/protocol/STVector256.h
src/ripple/protocol/SecretKey.h
Expand Down Expand Up @@ -528,6 +533,7 @@ target_sources (rippled PRIVATE
src/ripple/app/tx/impl/SetRegularKey.cpp
src/ripple/app/tx/impl/SetSignerList.cpp
src/ripple/app/tx/impl/SetTrust.cpp
src/ripple/app/tx/impl/XChainBridge.cpp
src/ripple/app/tx/impl/SignerEntries.cpp
src/ripple/app/tx/impl/Taker.cpp
src/ripple/app/tx/impl/Transactor.cpp
Expand Down Expand Up @@ -809,6 +815,7 @@ if (tests)
src/test/app/ReducedOffer_test.cpp
src/test/app/Regression_test.cpp
src/test/app/SHAMapStore_test.cpp
src/test/app/XChain_test.cpp
src/test/app/SetAuth_test.cpp
src/test/app/SetRegularKey_test.cpp
src/test/app/SetTrust_test.cpp
Expand Down Expand Up @@ -927,6 +934,7 @@ if (tests)
src/test/jtx/impl/acctdelete.cpp
src/test/jtx/impl/account_txn_id.cpp
src/test/jtx/impl/amount.cpp
src/test/jtx/impl/attester.cpp
src/test/jtx/impl/balance.cpp
src/test/jtx/impl/check.cpp
src/test/jtx/impl/delivermin.cpp
Expand All @@ -948,6 +956,7 @@ if (tests)
src/test/jtx/impl/regkey.cpp
src/test/jtx/impl/sendmax.cpp
src/test/jtx/impl/seq.cpp
src/test/jtx/impl/xchain_bridge.cpp
src/test/jtx/impl/sig.cpp
src/test/jtx/impl/tag.cpp
src/test/jtx/impl/ticket.cpp
Expand Down
6 changes: 6 additions & 0 deletions Builds/CMake/RippledRelease.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
package/container targets - (optional)
#]===================================================================]

# Early return if the `containers` directory is missing,
# e.g. when we are building a Conan package.
if(NOT EXISTS containers)
return()
endif()

if (is_root_project)
if (NOT DOCKER)
find_program (DOCKER docker)
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
# make GIT_COMMIT_HASH define available to all sources
find_package(Git)
if(Git_FOUND)
execute_process(COMMAND ${GIT_EXECUTABLE} describe --always --abbrev=40
execute_process(COMMAND ${GIT_EXECUTABLE} --git-dir=${CMAKE_CURRENT_SOURCE_DIR}/.git describe --always --abbrev=40
OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE gch)
if(gch)
set(GIT_COMMIT_HASH "${gch}")
Expand Down
6 changes: 6 additions & 0 deletions src/ripple/app/main/Application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1279,6 +1279,12 @@ ApplicationImp::setup(boost::program_options::variables_map const& cmdline)
}
}

if (auto const& forcedRange = config().FORCED_LEDGER_RANGE_PRESENT)
{
m_ledgerMaster->setLedgerRangePresent(
forcedRange->first, forcedRange->second);
}

if (!config().reporting())
m_orderBookDB.setup(getLedgerMaster().getCurrentLedger());

Expand Down
54 changes: 52 additions & 2 deletions src/ripple/app/main/Main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -378,8 +378,13 @@ run(int argc, char** argv)
"Override the minimum validation quorum.")(
"reportingReadOnly", "Run in read-only reporting mode")(
"silent", "No output to the console after startup.")(
"standalone,a", "Run with no peers.")("verbose,v", "Verbose logging.")(
"version", "Display the build version.");
"standalone,a", "Run with no peers.")("verbose,v", "Verbose logging.")

("force_ledger_present_range",
po::value<std::string>(),
"Specify the range of present ledgers for testing purposes. Min and "
"max values are comma separated.")(
"version", "Display the build version.");

po::options_description data("Ledger/Data Options");
data.add_options()("import", importText.c_str())(
Expand Down Expand Up @@ -602,6 +607,51 @@ run(int argc, char** argv)
return 0;
}

if (vm.contains("force_ledger_present_range"))
{
try
{
auto const r = [&vm]() -> std::vector<std::uint32_t> {
std::vector<std::string> strVec;
boost::split(
strVec,
vm["force_ledger_present_range"].as<std::string>(),
boost::algorithm::is_any_of(","));
std::vector<std::uint32_t> result;
for (auto& s : strVec)
{
boost::trim(s);
if (!s.empty())
result.push_back(std::stoi(s));
}
return result;
}();

if (r.size() == 2)
{
if (r[0] > r[1])
{
throw std::runtime_error(
"Invalid force_ledger_present_range parameter");
}
config->FORCED_LEDGER_RANGE_PRESENT.emplace(r[0], r[1]);
}
else
{
throw std::runtime_error(
"Invalid force_ledger_present_range parameter");
}
}
catch (std::exception const& e)
{
std::cerr << "invalid 'force_ledger_present_range' parameter. The "
"parameter must be two numbers separated by a comma. "
"The first number must be <= the second."
<< std::endl;
return -1;
}
}

if (vm.count("start"))
{
config->START_UP = Config::FRESH;
Expand Down
30 changes: 23 additions & 7 deletions src/ripple/app/misc/NetworkOPs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -607,12 +607,14 @@ class NetworkOPsImp final : public NetworkOPs
void
pubValidatedTransaction(
std::shared_ptr<ReadView const> const& ledger,
AcceptedLedgerTx const& transaction);
AcceptedLedgerTx const& transaction,
bool last);

void
pubAccountTransaction(
std::shared_ptr<ReadView const> const& ledger,
AcceptedLedgerTx const& transaction);
AcceptedLedgerTx const& transaction,
bool last);

void
pubProposedAccountTransaction(
Expand Down Expand Up @@ -3031,7 +3033,8 @@ NetworkOPsImp::pubLedger(std::shared_ptr<ReadView const> const& lpAccepted)
for (auto const& accTx : *alpAccepted)
{
JLOG(m_journal.trace()) << "pubAccepted: " << accTx->getJson();
pubValidatedTransaction(lpAccepted, *accTx);
pubValidatedTransaction(
lpAccepted, *accTx, accTx == *(--alpAccepted->end()));
}
}

Expand Down Expand Up @@ -3138,7 +3141,8 @@ NetworkOPsImp::transJson(
void
NetworkOPsImp::pubValidatedTransaction(
std::shared_ptr<ReadView const> const& ledger,
const AcceptedLedgerTx& transaction)
const AcceptedLedgerTx& transaction,
bool last)
{
auto const& stTxn = transaction.getTxn();

Expand Down Expand Up @@ -3187,13 +3191,14 @@ NetworkOPsImp::pubValidatedTransaction(
if (transaction.getResult() == tesSUCCESS)
app_.getOrderBookDB().processTxn(ledger, transaction, jvObj);

pubAccountTransaction(ledger, transaction);
pubAccountTransaction(ledger, transaction, last);
}

void
NetworkOPsImp::pubAccountTransaction(
std::shared_ptr<ReadView const> const& ledger,
AcceptedLedgerTx const& transaction)
AcceptedLedgerTx const& transaction,
bool last)
{
hash_set<InfoSub::pointer> notify;
int iProposed = 0;
Expand Down Expand Up @@ -3301,6 +3306,9 @@ NetworkOPsImp::pubAccountTransaction(
for (InfoSub::ref isrListener : notify)
isrListener->send(jvObj, true);

if (last)
jvObj[jss::account_history_boundary] = true;

assert(!jvObj.isMember(jss::account_history_tx_stream));
for (auto& info : accountHistoryNotify)
{
Expand Down Expand Up @@ -3699,8 +3707,11 @@ NetworkOPsImp::addAccountHistoryJob(SubAccountHistoryInfoWeak subInfo)

auto const& txns = dbResult->first;
marker = dbResult->second;
for (auto const& [tx, meta] : txns)
size_t num_txns = txns.size();
for (size_t i = 0; i < num_txns; ++i)
{
auto const& [tx, meta] = txns[i];

if (!tx || !meta)
{
JLOG(m_journal.debug())
Expand Down Expand Up @@ -3735,6 +3746,11 @@ NetworkOPsImp::addAccountHistoryJob(SubAccountHistoryInfoWeak subInfo)
*stTxn, meta->getResultTER(), true, curTxLedger);
jvTx[jss::meta] = meta->getJson(JsonOptions::none);
jvTx[jss::account_history_tx_index] = txHistoryIndex--;

if (i + 1 == num_txns ||
txns[i + 1].first->getLedger() != tx->getLedger())
jvTx[jss::account_history_boundary] = true;

RPC::insertDeliveredAmount(
jvTx[jss::meta], *curTxLedger, stTxn, *meta);
if (isFirstTx(tx, meta))
Expand Down
8 changes: 7 additions & 1 deletion src/ripple/app/tx/impl/InvariantCheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <ripple/protocol/Feature.h>
#include <ripple/protocol/STArray.h>
#include <ripple/protocol/SystemParameters.h>
#include <ripple/protocol/TxFormats.h>
#include <ripple/protocol/nftPageMask.h>

namespace ripple {
Expand Down Expand Up @@ -387,6 +388,9 @@ LedgerEntryTypesMatch::visitEntry(
case ltNFTOKEN_PAGE:
case ltNFTOKEN_OFFER:
case ltAMM:
case ltBRIDGE:
case ltXCHAIN_OWNED_CLAIM_ID:
case ltXCHAIN_OWNED_CREATE_ACCOUNT_CLAIM_ID:
break;
default:
invalidTypeAdded_ = true;
Expand Down Expand Up @@ -487,7 +491,9 @@ ValidNewAccountRoot::finalize(
}

// From this point on we know exactly one account was created.
if ((tx.getTxnType() == ttPAYMENT || tx.getTxnType() == ttAMM_CREATE) &&
if ((tx.getTxnType() == ttPAYMENT || tx.getTxnType() == ttAMM_CREATE ||
tx.getTxnType() == ttXCHAIN_ADD_CLAIM_ATTESTATION ||
tx.getTxnType() == ttXCHAIN_ADD_ACCOUNT_CREATE_ATTESTATION) &&
result == tesSUCCESS)
{
std::uint32_t const startingSeq{
Expand Down
3 changes: 2 additions & 1 deletion src/ripple/app/tx/impl/InvariantCheck.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <ripple/protocol/STLedgerEntry.h>
#include <ripple/protocol/STTx.h>
#include <ripple/protocol/TER.h>

#include <cstdint>
#include <map>
#include <tuple>
Expand Down Expand Up @@ -300,7 +301,7 @@ class NoZeroEscrow
class ValidNewAccountRoot
{
std::uint32_t accountsCreated_ = 0;
std::uint32_t accountSeq_ = 0; // Only meaningful if accountsCreated_ > 0
std::uint32_t accountSeq_ = 0;

public:
void
Expand Down
Loading

0 comments on commit 649c11a

Please sign in to comment.