Compare commits

..

2 Commits

Author SHA1 Message Date
Richard Holland
51f8a9c9ac init 2026-06-21 13:35:55 +10:00
Richard Holland
bb244ef772 put release builds into a candidate folder to prevent auto-update scripts running before smoke tests (#761) 2026-06-21 12:12:43 +10:00
8 changed files with 65 additions and 54 deletions

View File

@@ -95,8 +95,16 @@ if [[ "$4" == "" ]]; then
echo "Non GH, local building, no Action runner magic" echo "Non GH, local building, no Action runner magic"
else else
# GH Action, runner # GH Action, runner
cp /io/release-build/xahaud /data/builds/$(date +%Y).$(date +%-m).$(date +%-d)-$(git rev-parse --abbrev-ref HEAD)+$4 if [[ "$(git rev-parse --abbrev-ref HEAD)" == "release" ]]; then
cp /io/release-build/release.info /data/builds/$(date +%Y).$(date +%-m).$(date +%-d)-$(git rev-parse --abbrev-ref HEAD)+$4.releaseinfo echo "building on the release branch... placing it in builds/candidate"
mkdir /data/builds/candidate
cp /io/release-build/xahaud /data/builds/candidate/$(date +%Y).$(date +%-m).$(date +%-d)-$(git rev-parse --abbrev-ref HEAD)+$4
cp /io/release-build/release.info /data/builds/candidate/$(date +%Y).$(date +%-m).$(date +%-d)-$(git rev-parse --abbrev-ref HEAD)+$4.releaseinfo
else
echo "building non-release branch, placing it in builds root"
cp /io/release-build/xahaud /data/builds/$(date +%Y).$(date +%-m).$(date +%-d)-$(git rev-parse --abbrev-ref HEAD)+$4
cp /io/release-build/release.info /data/builds/$(date +%Y).$(date +%-m).$(date +%-d)-$(git rev-parse --abbrev-ref HEAD)+$4.releaseinfo
fi
echo "Published build to: http://build.xahau.tech/" echo "Published build to: http://build.xahau.tech/"
echo $(date +%Y).$(date +%-m).$(date +%-d)-$(git rev-parse --abbrev-ref HEAD)+$4 echo $(date +%Y).$(date +%-m).$(date +%-d)-$(git rev-parse --abbrev-ref HEAD)+$4
fi fi

View File

@@ -34,6 +34,7 @@
// If you add an amendment here, then do not forget to increment `numFeatures` // If you add an amendment here, then do not forget to increment `numFeatures`
// in include/xrpl/protocol/Feature.h. // in include/xrpl/protocol/Feature.h.
XRPL_FEATURE(SecureUI, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (HookMap, Supported::yes, VoteBehavior::DefaultYes) XRPL_FIX (HookMap, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FIX (GuardDepth32, Supported::yes, VoteBehavior::DefaultNo) XRPL_FIX (GuardDepth32, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(NamedHooks, Supported::yes, VoteBehavior::DefaultNo) XRPL_FEATURE(NamedHooks, Supported::yes, VoteBehavior::DefaultNo)

View File

@@ -262,6 +262,7 @@ LEDGER_ENTRY(ltACCOUNT_ROOT, 0x0061, AccountRoot, account, ({
{sfHookStateScale, soeOPTIONAL}, {sfHookStateScale, soeOPTIONAL},
{sfCron, soeOPTIONAL}, {sfCron, soeOPTIONAL},
{sfAMMID, soeOPTIONAL}, {sfAMMID, soeOPTIONAL},
{sfSecureUI, soeOPTIONAL},
})) }))
/** A ledger object which contains a list of object identifiers. /** A ledger object which contains a list of object identifiers.

View File

@@ -293,6 +293,7 @@ TYPED_SFIELD(sfAssetClass, VL, 29)
TYPED_SFIELD(sfProvider, VL, 30) TYPED_SFIELD(sfProvider, VL, 30)
TYPED_SFIELD(sfMPTokenMetadata, VL, 31) TYPED_SFIELD(sfMPTokenMetadata, VL, 31)
TYPED_SFIELD(sfCredentialType, VL, 32) TYPED_SFIELD(sfCredentialType, VL, 32)
TYPED_SFIELD(sfSecureUI, VL, 96)
TYPED_SFIELD(sfHookName, VL, 97) TYPED_SFIELD(sfHookName, VL, 97)
TYPED_SFIELD(sfRemarkValue, VL, 98) TYPED_SFIELD(sfRemarkValue, VL, 98)
TYPED_SFIELD(sfRemarkName, VL, 99) TYPED_SFIELD(sfRemarkName, VL, 99)

View File

@@ -74,6 +74,7 @@ TRANSACTION(ttACCOUNT_SET, 3, AccountSet, ({
{sfTickSize, soeOPTIONAL}, {sfTickSize, soeOPTIONAL},
{sfNFTokenMinter, soeOPTIONAL}, {sfNFTokenMinter, soeOPTIONAL},
{sfHookStateScale, soeOPTIONAL}, {sfHookStateScale, soeOPTIONAL},
{sfSecureUI, soeOPTIONAL},
})) }))
/** This transaction type cancels an existing escrow. */ /** This transaction type cancels an existing escrow. */

View File

@@ -311,28 +311,12 @@ LedgerMaster::setValidLedger(std::shared_ptr<Ledger const> const& l)
if (auto const first = if (auto const first =
app_.getAmendmentTable().firstUnsupportedExpected()) app_.getAmendmentTable().firstUnsupportedExpected())
{ {
using namespace std::chrono_literals; JLOG(m_journal.error()) << "One or more unsupported amendments "
auto const now = app_.timeKeeper().closeTime(); "reached majority. Upgrade before "
if (*first > now && (*first - now) <= 1min) << to_string(*first)
{ << " to prevent your server from "
// Shut down just before the amendment activates to "becoming amendment blocked.";
// avoid processing ledgers with unknown fields. app_.getOPs().setAmendmentWarned();
JLOG(m_journal.error())
<< "Unsupported amendment activating imminently "
"at "
<< to_string(*first) << ". Shutting down.";
app_.getOPs().setAmendmentBlocked();
}
else
{
JLOG(m_journal.error())
<< "One or more unsupported amendments "
"reached majority. Upgrade before "
<< to_string(*first)
<< " to prevent your server from "
"becoming amendment blocked.";
app_.getOPs().setAmendmentWarned();
}
} }
else else
app_.getOPs().clearAmendmentWarned(); app_.getOPs().clearAmendmentWarned();

View File

@@ -1634,16 +1634,6 @@ NetworkOPsImp::setAmendmentBlocked()
{ {
amendmentBlocked_ = true; amendmentBlocked_ = true;
setMode(OperatingMode::CONNECTED); setMode(OperatingMode::CONNECTED);
if (!app_.config().standalone())
{
JLOG(m_journal.fatal())
<< "One or more unsupported amendments activated. "
"Shutting down. Upgrade the server to remain "
"compatible with the network.";
app_.signalStop(
"One or more unsupported amendments activated. "
"Server must be upgraded to remain compatible with the network.");
}
} }
inline bool inline bool
@@ -1799,23 +1789,8 @@ NetworkOPsImp::switchLastClosedLedger(
clearNeedNetworkLedger(); clearNeedNetworkLedger();
// Update fee computations. May throw if the ledger contains // Update fee computations.
// transactions with fields unknown to this binary (e.g. after an app_.getTxQ().processClosedLedger(app_, *newLCL, true);
// unsupported amendment activates). Catch to allow graceful shutdown.
//@@start process-closed-ledger-catch
try
{
app_.getTxQ().processClosedLedger(app_, *newLCL, true);
}
catch (std::runtime_error const& e)
{
if (!amendmentBlocked_)
throw;
JLOG(m_journal.error())
<< "Failed to process closed ledger: " << e.what();
return;
}
//@@end process-closed-ledger-catch
// Caller must own master lock // Caller must own master lock
{ {
@@ -2474,7 +2449,7 @@ NetworkOPsImp::getServerInfo(bool human, bool admin, bool counters)
"may be incorrectly configured or some [validator_list_sites] " "may be incorrectly configured or some [validator_list_sites] "
"may be unreachable."; "may be unreachable.";
} }
if (isAmendmentWarned()) if (admin && isAmendmentWarned())
{ {
Json::Value& w = warnings.append(Json::objectValue); Json::Value& w = warnings.append(Json::objectValue);
w[jss::id] = warnRPC_UNSUPPORTED_MAJORITY; w[jss::id] = warnRPC_UNSUPPORTED_MAJORITY;
@@ -2918,7 +2893,6 @@ NetworkOPsImp::pubLedger(std::shared_ptr<ReadView const> const& lpAccepted)
// Ledgers are published only when they acquire sufficient validations // Ledgers are published only when they acquire sufficient validations
// Holes are filled across connection loss or other catastrophe // Holes are filled across connection loss or other catastrophe
//@@start pubLedger-accepted-ledger-construction
std::shared_ptr<AcceptedLedger> alpAccepted = std::shared_ptr<AcceptedLedger> alpAccepted =
app_.getAcceptedLedgerCache().fetch(lpAccepted->info().hash); app_.getAcceptedLedgerCache().fetch(lpAccepted->info().hash);
if (!alpAccepted) if (!alpAccepted)
@@ -2927,7 +2901,6 @@ NetworkOPsImp::pubLedger(std::shared_ptr<ReadView const> const& lpAccepted)
app_.getAcceptedLedgerCache().canonicalize_replace_client( app_.getAcceptedLedgerCache().canonicalize_replace_client(
lpAccepted->info().hash, alpAccepted); lpAccepted->info().hash, alpAccepted);
} }
//@@end pubLedger-accepted-ledger-construction
XRPL_ASSERT( XRPL_ASSERT(
alpAccepted->getLedger().get() == lpAccepted.get(), alpAccepted->getLedger().get() == lpAccepted.get(),

View File

@@ -197,6 +197,31 @@ SetAccount::preflight(PreflightContext const& ctx)
return temMALFORMED; return temMALFORMED;
} }
if (tx.isFieldPresent(sfSecureUI))
{
if (!ctx.rules.enabled(featureSecureUI))
return temMALFORMED;
Blob ui = tx.getFieldVL(sfSecureUI);
if (ui.size() == 0)
{
// this is an unset operation, pass
}
else if (ui.size() > 4096)
{
JLOG(j.trace()) << "SecureUI: Too long > 4096 bytes";
return temMALFORMED;
}
else if (!URIToken::validateUTF8(ui))
{
JLOG(j.trace()) << "SecureUI: Not UTF-8";
return temMALFORMED;
}
// valid
}
return preflight2(ctx); return preflight2(ctx);
} }
@@ -699,6 +724,23 @@ SetAccount::doApply()
sle->setFieldU16(sfHookStateScale, newScale); sle->setFieldU16(sfHookStateScale, newScale);
} }
} }
if (tx.isFieldPresent(sfSecureUI))
{
Blob ui = tx.getFieldVL(sfSecureUI);
if (ui.size() == 0)
{
// unset operation
if (sle->isFieldPresent(sfSecureUI))
sle->makeFieldAbsent(sfSecureUI);
}
else
{
// set operation
sle->setFieldVL(sfSecureUI, std::move(ui));
}
}
ctx_.view().update(sle); ctx_.view().update(sle);
return tesSUCCESS; return tesSUCCESS;