Fix STJson and multiple emitted transactions (#6724)

This commit is contained in:
Mayukha Vadari
2026-04-11 18:21:56 -04:00
committed by GitHub
parent 42cbecb9e4
commit 5351d4f089
29 changed files with 468 additions and 442 deletions

View File

@@ -10,6 +10,7 @@ libxrpl.ledger > xrpl.basics
libxrpl.ledger > xrpl.json
libxrpl.ledger > xrpl.ledger
libxrpl.ledger > xrpl.protocol
libxrpl.ledger > xrpl.server
libxrpl.net > xrpl.basics
libxrpl.net > xrpl.net
libxrpl.nodestore > xrpl.basics
@@ -188,6 +189,7 @@ xrpl.core > xrpl.json
xrpl.core > xrpl.protocol
xrpl.json > xrpl.basics
xrpl.ledger > xrpl.basics
xrpl.ledger > xrpl.core
xrpl.ledger > xrpl.protocol
xrpl.ledger > xrpl.server
xrpl.ledger > xrpl.shamap

View File

@@ -48,7 +48,7 @@ int64_t constexpr feeCalculationFailed = 0x7FFFFFFFFFFFFFFFLL;
std::size_t constexpr maxContractParams = 8;
/** The maximum number of contract functions that can be in a transaction. */
std::size_t constexpr maxContractFunctions = 8;
std::size_t constexpr maxContractFunctions = 32;
int64_t
contractCreateFee(uint64_t byteCount);

View File

@@ -193,7 +193,7 @@ STData::getFieldByValue() const
// if (!rf)
// throwFieldNotFound(getFName());
SerializedTypeID id = rf->getSType();
SerializedTypeID const id = rf->getSType();
if (id == STI_NOTPRESENT)
Throw<std::runtime_error>("Field not present");
@@ -220,7 +220,7 @@ STData::getFieldByConstRef(V const& empty) const
// if (!rf)
// throwFieldNotFound(field);
SerializedTypeID id = rf->getSType();
SerializedTypeID const id = rf->getSType();
if (id == STI_NOTPRESENT)
return empty; // optional field not present

View File

@@ -246,7 +246,7 @@ flow(
EitherAmount stepIn(*strand[0]->cachedIn());
for (auto i = 0; i < s; ++i)
{
bool valid;
bool valid = false;
std::tie(valid, stepIn) = strand[i]->validFwd(checkSB, checkAfView, stepIn);
if (!valid)
{

View File

@@ -1,6 +1,6 @@
#pragma once
#include <xrpl/ledger/Sandbox.h>
#include <xrpl/ledger/OpenView.h>
#include <xrpl/ledger/helpers/ContractUtils.h>
#include <xrpl/protocol/st.h>
#include <xrpl/tx/ApplyContext.h>
@@ -67,6 +67,25 @@ struct ContractContext
uint32_t generation = 0; // generation of the contract being executed
uint64_t burden = 0; // computational burden used
ContractResult result;
/// Persistent view used to track cumulative state from emitted
/// transactions so that successive emits within the same WASM
/// execution see the correct sequence numbers, balances, etc.
std::optional<OpenView> emitView;
/// Return the emit view, lazily creating it on first use.
/// The view is layered on top of the transactor's ApplyViewImpl
/// (applyCtx.view()) so that reads automatically fall through to
/// the transactor's pending state (e.g. the tfSendAmount balance
/// transfer, consumed sequence number, paid fee) without needing
/// to manually copy SLE changes.
OpenView&
getEmitView()
{
if (!emitView)
emitView.emplace(static_cast<ReadView const*>(&applyCtx.view()));
return *emitView;
}
};
} // namespace xrpl

View File

@@ -457,7 +457,7 @@ canTransferIOU(
SendTransferHandling transferHandling,
SendBalanceHandling balanceHandling)
{
AccountID issuer = amount.getIssuer();
AccountID const issuer = amount.getIssuer();
// If the issuer is the same as the sender
if (issuerHandling == SendIssuerHandling::ihSENDER_NOT_ALLOWED && issuer == sender)
return tecNO_PERMISSION;
@@ -574,7 +574,7 @@ canTransferMPT(
SendTransferHandling transferHandling,
SendBalanceHandling balanceHandling)
{
AccountID issuer = amount.getIssuer();
AccountID const issuer = amount.getIssuer();
// If the issuer is the same as the sender
if (issuerHandling == SendIssuerHandling::ihSENDER_NOT_ALLOWED && issuer == sender)
return tecNO_PERMISSION;

View File

@@ -1,22 +1,3 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2025 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#include <xrpl/ledger/View.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/ContractUtils.h>
@@ -46,7 +27,7 @@ contractCreateFee(uint64_t byteCount)
constexpr uint64_t mul = static_cast<uint64_t>(createByteMultiplier);
if (byteCount > std::numeric_limits<uint64_t>::max() / mul)
return feeCalculationFailed; // overflow
uint64_t uf = byteCount * mul;
uint64_t const uf = byteCount * mul;
if (uf > static_cast<uint64_t>(std::numeric_limits<int64_t>::max()))
return feeCalculationFailed;
return static_cast<int64_t>(uf);
@@ -299,7 +280,7 @@ preflightFlagParameters(STArray const& parameters, beast::Journal j)
if (!param.isFieldPresent(sfParameterValue))
return temMALFORMED;
auto const& value = param.getFieldData(sfParameterValue);
STAmount amount = value.getFieldAmount();
STAmount const amount = value.getFieldAmount();
// Preflight Transfer Amount
if (isXRP(amount))
{
@@ -355,7 +336,7 @@ preclaimFlagParameters(
return tecINTERNAL;
auto const& value = param.getFieldData(sfParameterValue);
STAmount amount = value.getFieldAmount();
STAmount const amount = value.getFieldAmount();
// Preclaim Transfer Amount
if (isXRP(amount))
{
@@ -435,7 +416,7 @@ doApplyFlagParameters(
return tecINTERNAL;
auto const& value = param.getFieldData(sfParameterValue);
STAmount amount = value.getFieldAmount();
STAmount const amount = value.getFieldAmount();
if (auto ter = accountSend(
view, sourceAccount, contractAccount, amount, j, WaiveTransferFee::No);
!isTesSuccess(ter))
@@ -529,7 +510,8 @@ setContractData(
if (!dataSle)
return tesSUCCESS;
uint32_t oldDataReserve = contractDataReserve(dataSle->getFieldJson(sfContractJson).size());
uint32_t const oldDataReserve =
contractDataReserve(dataSle->getFieldJson(sfContractJson).size());
std::uint64_t const page = (*dataSle)[sfOwnerNode];
// Remove the page from the account directory
@@ -544,13 +526,13 @@ setContractData(
return tesSUCCESS;
}
std::uint32_t ownerCount{(*sleAccount)[sfOwnerCount]};
bool createNew = !dataSle;
std::uint32_t const ownerCount{(*sleAccount)[sfOwnerCount]};
bool const createNew = !dataSle;
if (createNew)
{
// CREATE
uint32_t dataReserve = contractDataReserve(data.size());
uint32_t newReserve = ownerCount + dataReserve;
uint32_t const dataReserve = contractDataReserve(data.size());
uint32_t const newReserve = ownerCount + dataReserve;
XRPAmount const newReserveAmount{view.fees().accountReserve(newReserve)};
if (STAmount((*sleAccount)[sfBalance]).xrp() < newReserveAmount)
return tecINSUFFICIENT_RESERVE;
@@ -575,12 +557,13 @@ setContractData(
else
{
// UPDATE
uint32_t oldDataReserve = contractDataReserve(dataSle->getFieldJson(sfContractJson).size());
uint32_t newDataReserve = contractDataReserve(data.size());
uint32_t const oldDataReserve =
contractDataReserve(dataSle->getFieldJson(sfContractJson).size());
uint32_t const newDataReserve = contractDataReserve(data.size());
if (newDataReserve != oldDataReserve)
{
// if the reserve changes, we need to adjust the owner count
uint32_t newReserve = ownerCount - oldDataReserve + newDataReserve;
uint32_t const newReserve = ownerCount - oldDataReserve + newDataReserve;
XRPAmount const newReserveAmount{view.fees().accountReserve(newReserve)};
if (STAmount((*sleAccount)[sfBalance]).xrp() < newReserveAmount)
return tecINSUFFICIENT_RESERVE;
@@ -614,7 +597,7 @@ finalizeContractData(
{
auto const& acc = accEntry.first;
auto const& cacheEntry = accEntry.second;
bool is_modified = cacheEntry.first;
bool const is_modified = cacheEntry.first;
auto const& jsonData = cacheEntry.second;
if (is_modified)
{

View File

@@ -1119,7 +1119,7 @@ transferNFToken(
if (!tokenAndPage)
return tecINTERNAL; // LCOV_EXCL_LINE
if (auto const ret = nft::removeToken(view, seller, nftokenID, std::move(tokenAndPage->page));
if (auto const ret = nft::removeToken(view, seller, nftokenID, tokenAndPage->page);
!isTesSuccess(ret))
return ret;

View File

@@ -75,7 +75,7 @@ Emitable::getEmitableName(std::uint32_t const value) const
{
auto const emitableValue = static_cast<GranularEmitableType>(value);
if (auto const granular = getGranularName(emitableValue))
return *granular;
return granular;
// not a granular emitable, check if it maps to a transaction type
auto const txType = emitableToTxType(value);

View File

@@ -140,9 +140,9 @@ STData::STData(SField const& n, STNumber const& v)
STData::STData(SerialIter& sit, SField const& name) : STBase(name), data_(STBase{})
{
std::uint16_t stype = SerializedTypeID(sit.get16());
std::uint16_t const stype = SerializedTypeID(sit.get16());
inner_type_ = stype;
SerializedTypeID s = static_cast<SerializedTypeID>(stype);
SerializedTypeID const s = static_cast<SerializedTypeID>(stype);
switch (s)
{
case STI_UINT8: {
@@ -437,7 +437,7 @@ STData::getInnerTypeString() const
std::string
STData::getText() const
{
std::string inner_type_str = getInnerTypeString();
std::string const inner_type_str = getInnerTypeString();
return "STData{InnerType: " + inner_type_str + ", Data: " + data_.get().getText() + "}";
}
@@ -453,7 +453,7 @@ STData::getJson(JsonOptions options) const
STBase*
STData::makeFieldPresent()
{
STBase* f = &data_.get(); // getPIndex(index);
STBase const* f = &data_.get(); // getPIndex(index);
if (f->getSType() != STI_NOTPRESENT)
return f;
@@ -633,7 +633,7 @@ STData::getFieldH256() const
Blob
STData::getFieldVL() const
{
STBlob empty;
STBlob const empty;
STBlob const& b = getFieldByConstRef<STBlob>(empty);
return Blob(b.data(), b.data() + b.size());
}
@@ -738,7 +738,7 @@ dataFromJson(SField const& field, Json::Value const& v)
{
auto const str = value.asString();
std::uint64_t val;
std::uint64_t val = 0;
bool const useBase10 = field.shouldMeta(SField::sMD_BaseTen);
@@ -956,7 +956,7 @@ dataFromJson(SField const& field, Json::Value const& v)
Throw<std::runtime_error>("STData: expected string for NUMBER");
}
STNumber number = numberFromJson(field, value);
STNumber const number = numberFromJson(field, value);
STData data(field, number);
return data;
}

View File

@@ -26,7 +26,7 @@ STDataType::STDataType(SField const& n, SerializedTypeID v)
STDataType::STDataType(SerialIter& sit, SField const& name)
: STBase(name), inner_type_(STI_DATA), default_(false)
{
std::uint16_t stype = SerializedTypeID(sit.get16());
std::uint16_t const stype = SerializedTypeID(sit.get16());
inner_type_ = stype;
}
@@ -134,7 +134,7 @@ STDataType::getInnerTypeString() const
std::string
STDataType::getText() const
{
std::string inner_type_str = getInnerTypeString();
std::string const inner_type_str = getInnerTypeString();
return "STDataType{InnerType: " + inner_type_str + "}";
}
@@ -151,7 +151,7 @@ dataTypeFromJson(SField const& field, Json::Value const& v)
{
SerializedTypeID typeId = STI_NOTPRESENT;
Json::Value type;
Json::Value value;
Json::Value const value;
if (!v.isObject())
{

View File

@@ -1,3 +1,4 @@
#include <xrpl/basics/strHex.h>
#include <xrpl/json/json_value.h>
#include <xrpl/protocol/SField.h>
#include <xrpl/protocol/STAccount.h>
@@ -46,10 +47,10 @@ STJson::STJson(SerialIter& sit, SField const& name) : STBase{name}
// Read type byte
auto typeByte = sit.get8();
JsonType type = static_cast<JsonType>(typeByte);
JsonType const type = static_cast<JsonType>(typeByte);
length--; // Account for type byte
int initialBytesLeft = sit.getBytesLeft();
int const initialBytesLeft = sit.getBytesLeft();
if (type == JsonType::Array)
{
@@ -81,7 +82,7 @@ STJson::STJson(SerialIter& sit, SField const& name) : STBase{name}
data_ = std::move(map);
}
int consumedBytes = initialBytesLeft - sit.getBytesLeft();
int const consumedBytes = initialBytesLeft - sit.getBytesLeft();
if (consumedBytes != length)
Throw<std::runtime_error>("STJson length mismatch");
}
@@ -161,9 +162,14 @@ STJson::validateDepth(Value const& value, int currentDepth) const
if (!nested)
return;
int valueDepth = nested->getDepth();
if (currentDepth + valueDepth > 1)
// Adding an STJson value increases depth by 1
int const totalDepth = currentDepth + 1 + nested->getDepth();
if (totalDepth > 1)
Throw<std::runtime_error>("STJson nesting depth exceeds maximum of 1");
// Arrays cannot contain arrays
if (isArray() && nested->isArray())
Throw<std::runtime_error>("STJson arrays cannot contain arrays");
}
void
@@ -197,10 +203,10 @@ STJson::fromSerialIter(SerialIter& sit)
// Read type byte
auto typeByte = sit.get8();
JsonType type = static_cast<JsonType>(typeByte);
JsonType const type = static_cast<JsonType>(typeByte);
length--; // Account for type byte
int initialBytesLeft = sit.getBytesLeft();
int const initialBytesLeft = sit.getBytesLeft();
if (type == JsonType::Array)
{
@@ -220,7 +226,7 @@ STJson::fromSerialIter(SerialIter& sit)
}
}
int consumedBytes = initialBytesLeft - sit.getBytesLeft();
int const consumedBytes = initialBytesLeft - sit.getBytesLeft();
if (consumedBytes != length)
Throw<std::runtime_error>("STJson length mismatch");
@@ -235,7 +241,7 @@ STJson::fromSerialIter(SerialIter& sit)
map.emplace(std::move(key), std::move(value));
}
int consumedBytes = initialBytesLeft - sit.getBytesLeft();
int const consumedBytes = initialBytesLeft - sit.getBytesLeft();
if (consumedBytes != length)
Throw<std::runtime_error>("STJson length mismatch");
@@ -262,7 +268,7 @@ STJson::Array
STJson::parseArray(SerialIter& sit, int length)
{
Array array;
int initialBytesLeft = sit.getBytesLeft();
int const initialBytesLeft = sit.getBytesLeft();
while (sit.getBytesLeft() > 0 && (initialBytesLeft - sit.getBytesLeft()) < length)
{
@@ -290,7 +296,7 @@ STJson::makeValueFromVLWithType(SerialIter& sit)
// Read SType marker (1 byte)
auto typeCode = sit.get8();
SerializedTypeID stype = static_cast<SerializedTypeID>(typeCode);
SerializedTypeID const stype = static_cast<SerializedTypeID>(typeCode);
// Dispatch to correct SType
switch (stype)
@@ -699,10 +705,11 @@ STJson::getJson(JsonOptions options) const
auto const& map = std::get<Map>(data_);
for (auto const& [key, value] : map)
{
auto const hexKey = strHex(key);
if (value)
obj[key] = value->getJson(options);
obj[hexKey] = value->getJson(options);
else
obj[key] = Json::nullValue;
obj[hexKey] = Json::nullValue;
}
return obj;
}

View File

@@ -775,6 +775,9 @@ STObject::addFieldFromSlice(SField const& sfield, Slice const& data)
case STI_UINT160:
element = std::make_unique<STUInt160>(sit, sfield);
break;
case STI_UINT192:
element = std::make_unique<STUInt192>(sit, sfield);
break;
case STI_UINT256:
element = std::make_unique<STUInt256>(sit, sfield);
break;

View File

@@ -93,7 +93,7 @@ ContractCall::preclaim(PreclaimContext const& ctx)
auto it = std::find_if(
functions.begin(), functions.end(), [&functionNameHexStr](STObject const& func) {
auto const funcName = func.getFieldVL(sfFunctionName);
std::string functionNameDefHexStr(funcName.begin(), funcName.end());
std::string const functionNameDefHexStr(funcName.begin(), funcName.end());
return functionNameDefHexStr == functionNameHexStr;
});
@@ -178,9 +178,9 @@ ContractCall::doApply()
// WASM execution
auto const wasmStr = contractSourceSle->getFieldVL(sfContractCode);
std::vector<uint8_t> wasm(wasmStr.begin(), wasmStr.end());
std::vector<uint8_t> const wasm(wasmStr.begin(), wasmStr.end());
auto const functionName = ctx_.tx.getFieldVL(sfFunctionName);
std::string funcName(functionName.begin(), functionName.end());
std::string const funcName(functionName.begin(), functionName.end());
auto const contractFunctions = contractSle->isFieldPresent(sfFunctions)
? contractSle->getFieldArray(sfFunctions)
@@ -229,8 +229,8 @@ ContractCall::doApply()
return tecINVALID_PARAMETERS;
}
xrpl::ContractDataMap dataMap;
xrpl::ContractEventMap eventMap;
xrpl::ContractDataMap const dataMap;
xrpl::ContractEventMap const eventMap;
ContractContext contractCtx = {
.applyCtx = ctx_,
.instanceParameters = instanceParameters,
@@ -255,6 +255,7 @@ ContractCall::doApply()
.eventMap = eventMap,
.changedDataCount = 0,
},
.emitView = std::nullopt,
};
ContractHostFunctionsImpl ledgerDataProvider(contractCtx);
@@ -265,7 +266,7 @@ ContractCall::doApply()
return tefINTERNAL;
}
std::uint32_t allowance = ctx_.tx[sfComputationAllowance];
std::uint32_t const allowance = ctx_.tx[sfComputationAllowance];
auto re = runEscrowWasm(wasm, ledgerDataProvider, allowance, funcName, {});
// Wasm Result
@@ -291,7 +292,7 @@ ContractCall::doApply()
auto ret = re.value().result;
if (ret < 0)
{
JLOG(j_.trace()) << "WASM Execution Failed: " << contractCtx.result.exitReason;
JLOG(j_.trace()) << "WASM Execution Failed: " << ret;
ctx_.setWasmReturnCode(ret);
// ctx_.setWasmReturnStr(contractCtx.result.exitReason);
return tecWASM_REJECTED;

View File

@@ -55,7 +55,7 @@ ContractDelete::preclaim(PreclaimContext const& ctx)
return tecNO_PERMISSION;
}
std::uint32_t flags = contractSle->getFlags();
std::uint32_t const flags = contractSle->getFlags();
// Check if the contract is undeletable.
if (flags & tfUndeletable)

View File

@@ -103,7 +103,7 @@ ContractModify::preclaim(PreclaimContext const& ctx)
return tecNO_PERMISSION;
}
std::uint32_t flags = contractSle->getFlags();
std::uint32_t const flags = contractSle->getFlags();
// Check if the contract is immutable.
if (flags & tfImmutable)

View File

@@ -2262,10 +2262,6 @@ buildTxn_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results)
auto* hf = getHF(env);
auto const* rt = reinterpret_cast<InstanceWrapper const*>(hf->getRT());
int index = 0;
if (params->data[1].of.i32 > maxWasmDataLength)
{
return hfResult(results, HostFunctionError::DATA_FIELD_TOO_LARGE);
}
auto const txnType = getDataInt32(rt, params, index);
if (!txnType)
@@ -2314,10 +2310,6 @@ emitBuiltTxn_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* resul
auto* hf = getHF(env);
auto const* rt = reinterpret_cast<InstanceWrapper const*>(hf->getRT());
int index = 0;
if (params->data[1].of.i32 > maxWasmDataLength)
{
return hfResult(results, HostFunctionError::DATA_FIELD_TOO_LARGE);
}
auto const txnIndex = getDataInt32(rt, params, index);
if (!txnIndex)

View File

@@ -35,10 +35,10 @@ struct ContractHostFuncImpl_test : public beast::unit_test::suite
uint256 const& contractHash = uint256{1})
{
using namespace jtx;
xrpl::ContractDataMap dataMap;
xrpl::ContractEventMap eventMap;
std::vector<xrpl::ParameterValueVec> instanceParameters;
std::vector<xrpl::ParameterValueVec> functionParameters;
xrpl::ContractDataMap const dataMap;
xrpl::ContractEventMap const eventMap;
std::vector<xrpl::ParameterValueVec> const instanceParameters;
std::vector<xrpl::ParameterValueVec> const functionParameters;
uint256 const& txId = uint256{2};
@@ -69,6 +69,7 @@ struct ContractHostFuncImpl_test : public beast::unit_test::suite
.eventMap = eventMap,
.changedDataCount = 0,
},
.emitView = std::nullopt,
};
}
@@ -412,7 +413,7 @@ struct ContractHostFuncImpl_test : public beast::unit_test::suite
// Add test function parameters (same as instance parameters for
// testing) [Similar parameter setup as instanceParam test...]
ContractHostFunctionsImpl cfs(contractCtx);
ContractHostFunctionsImpl const cfs(contractCtx);
// [Similar tests as instanceParam but using functionParam method...]
}
@@ -513,14 +514,14 @@ struct ContractHostFuncImpl_test : public beast::unit_test::suite
// Test multiple keys for same account
{
auto value1 = createJsonValue(STI_VL, [](Serializer& s) {
Blob data = {'v', 'a', 'l', 'u', 'e', '1'};
Blob const data = {'v', 'a', 'l', 'u', 'e', '1'};
s.addVL(data);
});
auto setResult1 = cfs.setDataObjectField(alice.id(), "field1", value1);
BEAST_EXPECT(!setResult1.has_value());
auto value2 = createJsonValue(STI_VL, [](Serializer& s) {
Blob data = {'v', 'a', 'l', 'u', 'e', '2'};
Blob const data = {'v', 'a', 'l', 'u', 'e', '2'};
s.addVL(data);
});
auto setResult2 = cfs.setDataObjectField(alice.id(), "field2", value2);
@@ -566,28 +567,26 @@ struct ContractHostFuncImpl_test : public beast::unit_test::suite
// Test setDataNestedObjectField
{
auto value = createJsonValue(STI_VL, [](Serializer& s) {
Blob data = {'A', 'l', 'i', 'c', 'e'};
Blob const data = {'A', 'l', 'i', 'c', 'e'};
s.addVL(data);
});
auto setResult =
cfs.setDataNestedObjectField(alice.id(), "profile", "firstName", value);
BEAST_EXPECT(!setResult.has_value());
if (!setResult.has_value())
BEAST_EXPECT(setResult.error() == HostFunctionError::INTERNAL);
BEAST_EXPECT(setResult.has_value());
// Add more nested fields
auto value2 = createJsonValue(STI_VL, [](Serializer& s) {
Blob data = {'S', 'm', 'i', 't', 'h'};
Blob const data = {'S', 'm', 'i', 't', 'h'};
s.addVL(data);
});
auto setResult2 =
cfs.setDataNestedObjectField(alice.id(), "profile", "lastName", value2);
BEAST_EXPECT(!setResult2.has_value());
BEAST_EXPECT(setResult2.has_value());
auto value3 = createJsonValue(STI_UINT32, [](Serializer& s) { s.add32(25); });
auto setResult3 = cfs.setDataNestedObjectField(alice.id(), "profile", "age", value3);
BEAST_EXPECT(!setResult3.has_value());
BEAST_EXPECT(setResult3.has_value());
// Retrieve nested fields
auto getResult1 = cfs.getDataNestedObjectField(alice.id(), "profile", "firstName");
@@ -603,26 +602,26 @@ struct ContractHostFuncImpl_test : public beast::unit_test::suite
// Test nested objects with different parent keys
{
auto value1 = createJsonValue(STI_VL, [](Serializer& s) {
Blob data = {'d', 'a', 'r', 'k'};
Blob const data = {'d', 'a', 'r', 'k'};
s.addVL(data);
});
auto setResult1 = cfs.setDataNestedObjectField(alice.id(), "settings", "theme", value1);
BEAST_EXPECT(!setResult1.has_value());
BEAST_EXPECT(setResult1.has_value());
auto value2 = createJsonValue(STI_UINT8, [](Serializer& s) {
s.add8(1); // true
});
auto setResult2 =
cfs.setDataNestedObjectField(alice.id(), "settings", "notifications", value2);
BEAST_EXPECT(!setResult2.has_value());
BEAST_EXPECT(setResult2.has_value());
auto value3 = createJsonValue(STI_VL, [](Serializer& s) {
Blob data = {'e', 'n'};
Blob const data = {'e', 'n'};
s.addVL(data);
});
auto setResult3 =
cfs.setDataNestedObjectField(alice.id(), "preferences", "language", value3);
BEAST_EXPECT(!setResult3.has_value());
BEAST_EXPECT(setResult3.has_value());
// Verify nested data retrieval
auto getResult1 = cfs.getDataNestedObjectField(alice.id(), "settings", "theme");
@@ -652,11 +651,11 @@ struct ContractHostFuncImpl_test : public beast::unit_test::suite
{
auto value1 = createJsonValue(STI_UINT32, [](Serializer& s) { s.add32(100); });
auto setResult1 = cfs.setDataNestedObjectField(bob.id(), "stats", "score", value1);
BEAST_EXPECT(!setResult1.has_value());
BEAST_EXPECT(setResult1.has_value());
auto value2 = createJsonValue(STI_UINT32, [](Serializer& s) { s.add32(150); });
auto setResult2 = cfs.setDataNestedObjectField(bob.id(), "stats", "score", value2);
BEAST_EXPECT(!setResult2.has_value());
BEAST_EXPECT(setResult2.has_value());
auto getResult = cfs.getDataNestedObjectField(bob.id(), "stats", "score");
BEAST_EXPECT(getResult.has_value());
@@ -687,28 +686,26 @@ struct ContractHostFuncImpl_test : public beast::unit_test::suite
// Test setDataNestedObjectField
{
auto value = createJsonValue(STI_VL, [](Serializer& s) {
Blob data = {'A', 'l', 'i', 'c', 'e'};
Blob const data = {'A', 'l', 'i', 'c', 'e'};
s.addVL(data);
});
auto setResult =
cfs.setDataNestedObjectField(alice.id(), "profile", "firstName", value);
BEAST_EXPECT(!setResult.has_value());
if (!setResult.has_value())
BEAST_EXPECT(setResult.error() == HostFunctionError::INTERNAL);
BEAST_EXPECT(setResult.has_value());
// Add more nested fields
auto value2 = createJsonValue(STI_VL, [](Serializer& s) {
Blob data = {'S', 'm', 'i', 't', 'h'};
Blob const data = {'S', 'm', 'i', 't', 'h'};
s.addVL(data);
});
auto setResult2 =
cfs.setDataNestedObjectField(alice.id(), "profile", "lastName", value2);
BEAST_EXPECT(!setResult2.has_value());
BEAST_EXPECT(setResult2.has_value());
auto value3 = createJsonValue(STI_UINT32, [](Serializer& s) { s.add32(25); });
auto setResult3 = cfs.setDataNestedObjectField(alice.id(), "profile", "age", value3);
BEAST_EXPECT(!setResult3.has_value());
BEAST_EXPECT(setResult3.has_value());
// Retrieve nested fields
auto getResult1 = cfs.getDataNestedObjectField(alice.id(), "profile", "firstName");
@@ -724,26 +721,26 @@ struct ContractHostFuncImpl_test : public beast::unit_test::suite
// Test nested objects with different parent keys
{
auto value1 = createJsonValue(STI_VL, [](Serializer& s) {
Blob data = {'d', 'a', 'r', 'k'};
Blob const data = {'d', 'a', 'r', 'k'};
s.addVL(data);
});
auto setResult1 = cfs.setDataNestedObjectField(alice.id(), "settings", "theme", value1);
BEAST_EXPECT(!setResult1.has_value());
BEAST_EXPECT(setResult1.has_value());
auto value2 = createJsonValue(STI_UINT8, [](Serializer& s) {
s.add8(1); // true
});
auto setResult2 =
cfs.setDataNestedObjectField(alice.id(), "settings", "notifications", value2);
BEAST_EXPECT(!setResult2.has_value());
BEAST_EXPECT(setResult2.has_value());
auto value3 = createJsonValue(STI_VL, [](Serializer& s) {
Blob data = {'e', 'n'};
Blob const data = {'e', 'n'};
s.addVL(data);
});
auto setResult3 =
cfs.setDataNestedObjectField(alice.id(), "preferences", "language", value3);
BEAST_EXPECT(!setResult3.has_value());
BEAST_EXPECT(setResult3.has_value());
// Verify nested data retrieval
auto getResult1 = cfs.getDataNestedObjectField(alice.id(), "settings", "theme");
@@ -773,11 +770,11 @@ struct ContractHostFuncImpl_test : public beast::unit_test::suite
{
auto value1 = createJsonValue(STI_UINT32, [](Serializer& s) { s.add32(100); });
auto setResult1 = cfs.setDataNestedObjectField(bob.id(), "stats", "score", value1);
BEAST_EXPECT(!setResult1.has_value());
BEAST_EXPECT(setResult1.has_value());
auto value2 = createJsonValue(STI_UINT32, [](Serializer& s) { s.add32(150); });
auto setResult2 = cfs.setDataNestedObjectField(bob.id(), "stats", "score", value2);
BEAST_EXPECT(!setResult2.has_value());
BEAST_EXPECT(setResult2.has_value());
auto getResult = cfs.getDataNestedObjectField(bob.id(), "stats", "score");
BEAST_EXPECT(getResult.has_value());
@@ -911,7 +908,7 @@ struct ContractHostFuncImpl_test : public beast::unit_test::suite
if (!buildResult.has_value())
return;
uint32_t txIndex = buildResult.value();
uint32_t const txIndex = buildResult.value();
// Test adding Destination (AccountID) with 0x14 prefix
{
@@ -935,7 +932,7 @@ struct ContractHostFuncImpl_test : public beast::unit_test::suite
// Test adding Amount (STAmount - XRP)
{
STAmount amount{XRP(1000)};
STAmount const amount{XRP(1000)};
Serializer s;
amount.add(s);
auto result = cfs.addTxnField(txIndex, sfAmount, s.slice());
@@ -952,7 +949,7 @@ struct ContractHostFuncImpl_test : public beast::unit_test::suite
// Test adding SendMax (STAmount - IOU)
{
auto const USD = alice["USD"];
STAmount sendMax{USD.issue(), 500};
STAmount const sendMax{USD.issue(), 500};
Serializer s;
sendMax.add(s);
auto result = cfs.addTxnField(txIndex, sfSendMax, s.slice());
@@ -968,7 +965,7 @@ struct ContractHostFuncImpl_test : public beast::unit_test::suite
// Test adding DestinationTag (UInt32)
{
uint32_t tag = 12345;
uint32_t const tag = 12345;
Serializer s;
s.add32(tag);
auto result = cfs.addTxnField(txIndex, sfDestinationTag, s.slice());
@@ -987,12 +984,12 @@ struct ContractHostFuncImpl_test : public beast::unit_test::suite
BEAST_EXPECT(trustBuildResult.has_value());
if (trustBuildResult.has_value())
{
uint32_t trustIndex = trustBuildResult.value();
uint32_t const trustIndex = trustBuildResult.value();
// Test adding LimitAmount (STAmount for TrustSet)
{
auto const EUR = alice["EUR"];
STAmount limit{EUR.issue(), 10000};
STAmount const limit{EUR.issue(), 10000};
Serializer s;
limit.add(s);
auto result = cfs.addTxnField(trustIndex, sfLimitAmount, s.slice());
@@ -1008,7 +1005,7 @@ struct ContractHostFuncImpl_test : public beast::unit_test::suite
// Test adding QualityIn (UInt32)
{
uint32_t quality = 1000000;
uint32_t const quality = 1000000;
Serializer s;
s.add32(quality);
auto result = cfs.addTxnField(trustIndex, sfQualityIn, s.slice());
@@ -1028,11 +1025,11 @@ struct ContractHostFuncImpl_test : public beast::unit_test::suite
BEAST_EXPECT(accSetResult.has_value());
if (accSetResult.has_value())
{
uint32_t accSetIndex = accSetResult.value();
uint32_t const accSetIndex = accSetResult.value();
// Test adding Domain (Blob/VL)
{
Blob domain = {'e', 'x', 'a', 'm', 'p', 'l', 'e', '.', 'c', 'o', 'm'};
Blob const domain = {'e', 'x', 'a', 'm', 'p', 'l', 'e', '.', 'c', 'o', 'm'};
Serializer s;
s.addVL(domain);
auto result = cfs.addTxnField(accSetIndex, sfDomain, s.slice());
@@ -1048,7 +1045,7 @@ struct ContractHostFuncImpl_test : public beast::unit_test::suite
// Test adding TransferRate (UInt32)
{
uint32_t fee = 500;
uint32_t const fee = 500;
Serializer s;
s.add32(fee);
auto result = cfs.addTxnField(accSetIndex, sfTransferRate, s.slice());
@@ -1064,7 +1061,7 @@ struct ContractHostFuncImpl_test : public beast::unit_test::suite
// Test adding SetFlag (UInt32)
{
uint32_t flag = 8; // asfRequireAuth
uint32_t const flag = 8; // asfRequireAuth
Serializer s;
s.add32(flag);
auto result = cfs.addTxnField(accSetIndex, sfSetFlag, s.slice());
@@ -1143,7 +1140,7 @@ struct ContractHostFuncImpl_test : public beast::unit_test::suite
if (!buildResult.has_value())
return;
uint32_t txIndex = buildResult.value();
uint32_t const txIndex = buildResult.value();
// Add required fields for Payment
AccountID destAccount = bob.id();
@@ -1156,7 +1153,7 @@ struct ContractHostFuncImpl_test : public beast::unit_test::suite
BEAST_EXPECT(destResult.has_value());
// Add Amount field
STAmount amount{XRP(100)};
STAmount const amount{XRP(100)};
Serializer amtSerializer;
amount.add(amtSerializer);
auto amtResult = cfs.addTxnField(txIndex, sfAmount, amtSerializer.slice());
@@ -1171,81 +1168,79 @@ struct ContractHostFuncImpl_test : public beast::unit_test::suite
BEAST_EXPECT(contractCtx.result.emittedTxns.size() == 1);
// The result should be a TER code converted to int
int32_t terCode = emitResult.value();
int32_t const terCode = emitResult.value();
// We expect a success code
BEAST_EXPECT(terCode == 0);
}
}
// // Test emitting multiple transactions
// {
// // Build first transaction - Payment
// auto build1 = cfs.buildTxn(ttPAYMENT);
// BEAST_EXPECT(build1.has_value());
// if (build1.has_value())
// {
// uint32_t tx1 = build1.value();
// Test emitting multiple transactions
{
// Build first transaction - Payment
auto build1 = cfs.buildTxn(ttPAYMENT);
BEAST_EXPECT(build1.has_value());
if (build1.has_value())
{
uint32_t const tx1 = build1.value();
// // Add fields for first payment
// AccountID dest1 = alice.id();
// Blob dest1Buf;
// dest1Buf.reserve(1 + dest1.size());
// dest1Buf.push_back(0x14);
// dest1Buf.insert(dest1Buf.end(), dest1.begin(), dest1.end());
// auto const result = cfs.addTxnField(
// tx1,
// sfDestination,
// Slice{dest1Buf.data(), dest1Buf.size()});
// BEAST_EXPECT(result.has_value());
// Add fields for first payment
AccountID dest1 = alice.id();
Blob dest1Buf;
dest1Buf.reserve(1 + dest1.size());
dest1Buf.push_back(0x14);
dest1Buf.insert(dest1Buf.end(), dest1.begin(), dest1.end());
auto const result =
cfs.addTxnField(tx1, sfDestination, Slice{dest1Buf.data(), dest1Buf.size()});
BEAST_EXPECT(result.has_value());
// STAmount amt1{XRP(50)};
// Serializer amt1Ser;
// amt1.add(amt1Ser);
// cfs.addTxnField(tx1, sfAmount, amt1Ser.slice());
// }
STAmount const amt1{XRP(50)};
Serializer amt1Ser;
amt1.add(amt1Ser);
[[maybe_unused]] auto const amt1Result =
cfs.addTxnField(tx1, sfAmount, amt1Ser.slice());
}
// // Build second transaction - Another Payment
// auto build2 = cfs.buildTxn(ttPAYMENT);
// BEAST_EXPECT(build2.has_value());
// if (build2.has_value())
// {
// uint32_t tx2 = build2.value();
// Build second transaction - Another Payment
auto build2 = cfs.buildTxn(ttPAYMENT);
BEAST_EXPECT(build2.has_value());
if (build2.has_value())
{
uint32_t const tx2 = build2.value();
// // Add fields for second payment
// AccountID dest2 = carol.id();
// Blob dest2Buf;
// dest2Buf.reserve(1 + dest2.size());
// dest2Buf.push_back(0x14);
// dest2Buf.insert(dest2Buf.end(), dest2.begin(), dest2.end());
// auto const result = cfs.addTxnField(
// tx2,
// sfDestination,
// Slice{dest2Buf.data(), dest2Buf.size()});
// BEAST_EXPECT(result.has_value());
// Add fields for second payment
AccountID dest2 = carol.id();
Blob dest2Buf;
dest2Buf.reserve(1 + dest2.size());
dest2Buf.push_back(0x14);
dest2Buf.insert(dest2Buf.end(), dest2.begin(), dest2.end());
auto const result =
cfs.addTxnField(tx2, sfDestination, Slice{dest2Buf.data(), dest2Buf.size()});
BEAST_EXPECT(result.has_value());
// STAmount amt2{XRP(75)};
// Serializer amt2Ser;
// amt2.add(amt2Ser);
// cfs.addTxnField(tx2, sfAmount, amt2Ser.slice());
// }
STAmount const amt2{XRP(75)};
Serializer amt2Ser;
amt2.add(amt2Ser);
[[maybe_unused]] auto const amt2Result =
cfs.addTxnField(tx2, sfAmount, amt2Ser.slice());
}
// // Emit both transactions
// if (build1.has_value())
// {
// auto emit1 = cfs.emitBuiltTxn(build1.value());
// BEAST_EXPECT(emit1.has_value());
// }
// Emit both transactions
if (build1.has_value())
{
auto emit1 = cfs.emitBuiltTxn(build1.value());
BEAST_EXPECT(emit1.has_value());
}
// if (build2.has_value())
// {
// auto emit2 = cfs.emitBuiltTxn(build2.value());
// BEAST_EXPECT(emit2.has_value());
// }
if (build2.has_value())
{
auto emit2 = cfs.emitBuiltTxn(build2.value());
BEAST_EXPECT(emit2.has_value());
}
// // Check that both were added to emitted transactions
// // (Note: actual count depends on previous test state)
// BEAST_EXPECT(contractCtx.result.emittedTxns.size() >= 2);
// }
// Check that both were added to emitted transactions
// (Note: actual count depends on previous test state)
BEAST_EXPECT(contractCtx.result.emittedTxns.size() >= 2);
}
// // Test emitting transaction with invalid index
// {

View File

@@ -310,11 +310,15 @@ class Contract_test : public beast::unit_test::suite
auto const wasmBytes = strUnHex(jt.jv[sfContractCode.jsonName].asString());
// std::cout << "WASM Size: " << wasmBytes->size() << std::endl;
if (!wasmBytes || wasmBytes->empty())
return std::make_tuple(jtx::Account{"invalid"}, uint256{}, jt.jv);
uint256 const contractHash =
xrpl::sha512Half_s(xrpl::Slice(wasmBytes->data(), wasmBytes->size()));
auto const accountID = parseBase58<AccountID>(jt.jv[sfAccount].asString());
auto const [contractKey, sle] = contractKeyAndSle(
*env.current(), contractHash, *accountID, jt.jv[sfSequence.jsonName].asUInt());
if (!sle)
return std::make_tuple(jtx::Account{"invalid"}, contractHash, jt.jv);
jtx::Account const contractAccount{
"Contract pseudo-account", sle->getAccountID(sfContractAccount)};
return std::make_tuple(contractAccount, contractHash, jt.jv);
@@ -1434,8 +1438,8 @@ class Contract_test : public beast::unit_test::suite
loadContractWasmStr(std::string const& contract_name = "")
{
std::string const& dir = "e2e-tests";
std::string name = "/Users/darkmatter/projects/ledger-works/xrpl-wasm-std/" + dir + "/" +
contract_name + "/target/wasm32v1-none/release/" + contract_name + ".wasm";
std::string const name = "/Users/darkmatter/projects/ledger-works/xrpl-wasm-std/" + dir +
"/" + contract_name + "/target/wasm32v1-none/release/" + contract_name + ".wasm";
if (!boost::filesystem::exists(name))
{
std::cout << "File does not exist: " << name << "\n";
@@ -1451,7 +1455,7 @@ class Contract_test : public beast::unit_test::suite
}
// Read the file into a vector
std::vector<char> buffer(
std::vector<char> const buffer(
(std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
// Check if the buffer is empty
@@ -1478,7 +1482,7 @@ class Contract_test : public beast::unit_test::suite
env.fund(XRP(10'000), alice, bob);
env.close();
std::string contractDataWasmHex = loadContractWasmStr("contract_data");
std::string const contractDataWasmHex = loadContractWasmStr("contract_data");
auto const [contractAccount, contractHash, _] = setContract(
env,
tesSUCCESS,
@@ -1513,7 +1517,7 @@ class Contract_test : public beast::unit_test::suite
env.fund(XRP(10'000), alice, bob);
env.close();
std::string contractDataWasmHex = loadContractWasmStr("contract_data");
std::string const contractDataWasmHex = loadContractWasmStr("contract_data");
auto const [contractAccount, contractHash, _] = setContract(
env,
tesSUCCESS,
@@ -1548,7 +1552,7 @@ class Contract_test : public beast::unit_test::suite
env.fund(XRP(10'000), alice, bob);
env.close();
std::string contractDataWasmHex = loadContractWasmStr("contract_data");
std::string const contractDataWasmHex = loadContractWasmStr("contract_data");
auto const [contractAccount, contractHash, _] = setContract(
env,
tesSUCCESS,
@@ -1583,7 +1587,7 @@ class Contract_test : public beast::unit_test::suite
env.fund(XRP(10'000), alice, bob);
env.close();
std::string contractDataWasmHex = loadContractWasmStr("contract_data");
std::string const contractDataWasmHex = loadContractWasmStr("contract_data");
auto const [contractAccount, contractHash, _] = setContract(
env,
tesSUCCESS,
@@ -1623,7 +1627,7 @@ class Contract_test : public beast::unit_test::suite
// Test Instance Parameter (1 of 2)
// uint8, uint16, uint32, uint64, uint128, uint160, uint192, uint256
{
std::string wasmHex = loadContractWasmStr("instance_params_uint");
std::string const wasmHex = loadContractWasmStr("instance_params_uint");
auto const [contractAccount, contractHash, _] = setContract(
env,
tesSUCCESS,
@@ -1667,7 +1671,7 @@ class Contract_test : public beast::unit_test::suite
{
// Test Instance Parameter (2 of 2)
// vl, account, amount (XRP), amount (IOU), number, currency, issue
std::string wasmHex = loadContractWasmStr("instance_params_other");
std::string const wasmHex = loadContractWasmStr("instance_params_other");
auto const [contractAccount, contractHash, _] = setContract(
env,
tesSUCCESS,
@@ -1714,7 +1718,7 @@ class Contract_test : public beast::unit_test::suite
env.fund(XRP(10'000), alice, bob);
env.close();
std::string wasmHex = loadContractWasmStr("function_params");
std::string const wasmHex = loadContractWasmStr("function_params");
auto const [contractAccount, contractHash, _] = setContract(
env,
tesSUCCESS,
@@ -1804,7 +1808,7 @@ class Contract_test : public beast::unit_test::suite
env.fund(XRP(10'000), alice, bob);
env.close();
std::string emitTxWasmHex = loadContractWasmStr("emit_txn");
std::string const emitTxWasmHex = loadContractWasmStr("emit_txn");
auto const [contractAccount, contractHash, _] = setContract(
env,
tesSUCCESS,
@@ -1862,7 +1866,7 @@ class Contract_test : public beast::unit_test::suite
BEAST_EXPECT(jv[jss::result][jss::status] == "success");
}
std::string eventsWasmHex = loadContractWasmStr("events");
std::string const eventsWasmHex = loadContractWasmStr("events");
auto const [contractAccount, contractHash, _] = setContract(
env,
tesSUCCESS,
@@ -1943,7 +1947,7 @@ class Contract_test : public beast::unit_test::suite
env.fund(XRP(10'000), alice, bob);
env.close();
std::string wasmHex = loadContractWasmStr("easymode");
std::string const wasmHex = loadContractWasmStr("easymode");
auto const [contractAccount, contractHash, _] = setContract(
env,
tesSUCCESS,

View File

@@ -1816,10 +1816,10 @@ class Delegate_test : public beast::unit_test::suite
#pragma push_macro("TRANSACTION")
#undef TRANSACTION
#define TRANSACTION(tag, value, name, delegable, ...) \
if (delegable == xrpl::delegable) \
{ \
delegableCount++; \
#define TRANSACTION(tag, value, name, delegationStatus, ...) \
if (delegationStatus == Delegation::delegable) \
{ \
delegableCount++; \
}
#include <xrpl/protocol/detail/transactions.macro>
@@ -1845,7 +1845,7 @@ class Delegate_test : public beast::unit_test::suite
// DO NOT modify expectedDelegableCount unless all scenarios, including
// edge cases, have been fully tested and verified.
// ====================================================================
std::size_t const expectedDelegableCount = 75;
std::size_t const expectedDelegableCount = 57;
BEAST_EXPECTS(
delegableCount == expectedDelegableCount,

View File

@@ -16,7 +16,7 @@ struct STDataType_test : public beast::unit_test::suite
// Test default constructor
{
STDataType dt1(sf);
STDataType const dt1(sf);
BEAST_EXPECT(dt1.getInnerSType() == STI_NOTPRESENT);
BEAST_EXPECT(dt1.getSType() == STI_DATATYPE);
BEAST_EXPECT(dt1.getFName() == sf);
@@ -24,7 +24,7 @@ struct STDataType_test : public beast::unit_test::suite
// Test constructor with SerializedTypeID
{
STDataType dt2(sf, STI_UINT32);
STDataType const dt2(sf, STI_UINT32);
BEAST_EXPECT(dt2.getInnerSType() == STI_UINT32);
BEAST_EXPECT(!dt2.isDefault());
}
@@ -34,7 +34,7 @@ struct STDataType_test : public beast::unit_test::suite
Serializer s;
s.add16(STI_UINT64);
SerialIter sit(s.slice());
STDataType dt3(sit, sf);
STDataType const dt3(sit, sf);
BEAST_EXPECT(dt3.getInnerSType() == STI_UINT64);
}
}
@@ -48,7 +48,7 @@ struct STDataType_test : public beast::unit_test::suite
// Test copy
{
STDataType original(sf, STI_UINT32);
STDataType const original(sf, STI_UINT32);
// Use aligned storage for placement new
alignas(STDataType) char buffer[sizeof(STDataType)];
@@ -96,7 +96,7 @@ struct STDataType_test : public beast::unit_test::suite
std::string expectedHex;
};
TypeTest tests[] = {
TypeTest const tests[] = {
{STI_UINT16, "0001"},
{STI_UINT32, "0002"},
{STI_UINT64, "0003"},
@@ -137,22 +137,22 @@ struct STDataType_test : public beast::unit_test::suite
// Test equivalent objects
{
STDataType dt1(sf1, STI_UINT32);
STDataType dt2(sf1, STI_UINT32);
STDataType const dt1(sf1, STI_UINT32);
STDataType const dt2(sf1, STI_UINT32);
BEAST_EXPECT(dt1.isEquivalent(dt2));
}
// Test non-equivalent objects (different inner types)
{
STDataType dt1(sf1, STI_UINT32);
STDataType dt2(sf1, STI_UINT64);
STDataType const dt1(sf1, STI_UINT32);
STDataType const dt2(sf1, STI_UINT64);
BEAST_EXPECT(!dt1.isEquivalent(dt2));
}
// Test non-equivalent objects (different default states)
{
STDataType dt1(sf1);
STDataType dt2(sf1, STI_NOTPRESENT);
STDataType const dt1(sf1);
STDataType const dt2(sf1, STI_NOTPRESENT);
// dt1 has default_ = true (implicit from first constructor)
// dt2 has default_ = false (set in second constructor)
BEAST_EXPECT(!dt1.isEquivalent(dt2));
@@ -160,7 +160,7 @@ struct STDataType_test : public beast::unit_test::suite
// Test with non-STDataType object
{
STDataType dt1(sf1, STI_UINT32);
STDataType const dt1(sf1, STI_UINT32);
// Create a dummy STBase-derived object for comparison
// Since we can't easily create other STBase types here,
// we'll test that isEquivalent returns false for nullptr cast
@@ -199,7 +199,7 @@ struct STDataType_test : public beast::unit_test::suite
return nullptr;
}
};
DummySTBase dummy;
DummySTBase const dummy;
BEAST_EXPECT(!dt1.isEquivalent(dummy));
}
}
@@ -213,14 +213,14 @@ struct STDataType_test : public beast::unit_test::suite
// Test default state
{
STDataType dt1(sf);
STDataType const dt1(sf);
// First constructor doesn't set default_ explicitly,
// so it should be true (member initialization)
BEAST_EXPECT(dt1.isDefault());
}
{
STDataType dt2(sf, STI_UINT32);
STDataType const dt2(sf, STI_UINT32);
BEAST_EXPECT(!dt2.isDefault());
}
}
@@ -234,78 +234,78 @@ struct STDataType_test : public beast::unit_test::suite
// Test known types
{
STDataType dt(sf, STI_UINT8);
STDataType const dt(sf, STI_UINT8);
BEAST_EXPECT(dt.getText() == "STDataType{InnerType: UINT8}");
}
{
STDataType dt(sf, STI_UINT16);
STDataType const dt(sf, STI_UINT16);
BEAST_EXPECT(dt.getText() == "STDataType{InnerType: UINT16}");
}
{
STDataType dt(sf, STI_UINT32);
STDataType const dt(sf, STI_UINT32);
BEAST_EXPECT(dt.getText() == "STDataType{InnerType: UINT32}");
}
{
STDataType dt(sf, STI_UINT64);
STDataType const dt(sf, STI_UINT64);
BEAST_EXPECT(dt.getText() == "STDataType{InnerType: UINT64}");
}
{
STDataType dt(sf, STI_UINT128);
STDataType const dt(sf, STI_UINT128);
BEAST_EXPECT(dt.getText() == "STDataType{InnerType: UINT128}");
}
{
STDataType dt(sf, STI_UINT160);
STDataType const dt(sf, STI_UINT160);
BEAST_EXPECT(dt.getText() == "STDataType{InnerType: UINT160}");
}
{
STDataType dt(sf, STI_UINT192);
STDataType const dt(sf, STI_UINT192);
BEAST_EXPECT(dt.getText() == "STDataType{InnerType: UINT192}");
}
{
STDataType dt(sf, STI_UINT256);
STDataType const dt(sf, STI_UINT256);
BEAST_EXPECT(dt.getText() == "STDataType{InnerType: UINT256}");
}
{
STDataType dt(sf, STI_VL);
STDataType const dt(sf, STI_VL);
BEAST_EXPECT(dt.getText() == "STDataType{InnerType: VL}");
}
{
STDataType dt(sf, STI_ACCOUNT);
STDataType const dt(sf, STI_ACCOUNT);
BEAST_EXPECT(dt.getText() == "STDataType{InnerType: ACCOUNT}");
}
{
STDataType dt(sf, STI_AMOUNT);
STDataType const dt(sf, STI_AMOUNT);
BEAST_EXPECT(dt.getText() == "STDataType{InnerType: AMOUNT}");
}
{
STDataType dt(sf, STI_ISSUE);
STDataType const dt(sf, STI_ISSUE);
BEAST_EXPECT(dt.getText() == "STDataType{InnerType: ISSUE}");
}
{
STDataType dt(sf, STI_CURRENCY);
STDataType const dt(sf, STI_CURRENCY);
BEAST_EXPECT(dt.getText() == "STDataType{InnerType: CURRENCY}");
}
{
STDataType dt(sf, STI_NUMBER);
STDataType const dt(sf, STI_NUMBER);
BEAST_EXPECT(dt.getText() == "STDataType{InnerType: NUMBER}");
}
// Test unknown type (should return numeric string)
{
STDataType dt(sf, static_cast<SerializedTypeID>(999));
STDataType const dt(sf, static_cast<SerializedTypeID>(999));
BEAST_EXPECT(dt.getText() == "STDataType{InnerType: 999}");
}
}
@@ -319,21 +319,21 @@ struct STDataType_test : public beast::unit_test::suite
// Test JSON output for various types
{
STDataType dt(sf, STI_UINT32);
STDataType const dt(sf, STI_UINT32);
Json::Value json = dt.getJson(JsonOptions::none);
BEAST_EXPECT(json.isObject());
BEAST_EXPECT(json[jss::type].asString() == "UINT32");
}
{
STDataType dt(sf, STI_AMOUNT);
STDataType const dt(sf, STI_AMOUNT);
Json::Value json = dt.getJson(JsonOptions::none);
BEAST_EXPECT(json.isObject());
BEAST_EXPECT(json[jss::type].asString() == "AMOUNT");
}
{
STDataType dt(sf, STI_ACCOUNT);
STDataType const dt(sf, STI_ACCOUNT);
Json::Value json = dt.getJson(JsonOptions::none);
BEAST_EXPECT(json.isObject());
BEAST_EXPECT(json[jss::type].asString() == "ACCOUNT");
@@ -341,7 +341,7 @@ struct STDataType_test : public beast::unit_test::suite
// Test unknown type
{
STDataType dt(sf, static_cast<SerializedTypeID>(999));
STDataType const dt(sf, static_cast<SerializedTypeID>(999));
Json::Value json = dt.getJson(JsonOptions::none);
BEAST_EXPECT(json.isObject());
BEAST_EXPECT(json[jss::type].asString() == "999");
@@ -359,98 +359,98 @@ struct STDataType_test : public beast::unit_test::suite
{
Json::Value v;
v[jss::type] = "UINT8";
STDataType dt = dataTypeFromJson(sf, v);
STDataType const dt = dataTypeFromJson(sf, v);
BEAST_EXPECT(dt.getInnerSType() == STI_UINT8);
}
{
Json::Value v;
v[jss::type] = "UINT16";
STDataType dt = dataTypeFromJson(sf, v);
STDataType const dt = dataTypeFromJson(sf, v);
BEAST_EXPECT(dt.getInnerSType() == STI_UINT16);
}
{
Json::Value v;
v[jss::type] = "UINT32";
STDataType dt = dataTypeFromJson(sf, v);
STDataType const dt = dataTypeFromJson(sf, v);
BEAST_EXPECT(dt.getInnerSType() == STI_UINT32);
}
{
Json::Value v;
v[jss::type] = "UINT64";
STDataType dt = dataTypeFromJson(sf, v);
STDataType const dt = dataTypeFromJson(sf, v);
BEAST_EXPECT(dt.getInnerSType() == STI_UINT64);
}
{
Json::Value v;
v[jss::type] = "UINT128";
STDataType dt = dataTypeFromJson(sf, v);
STDataType const dt = dataTypeFromJson(sf, v);
BEAST_EXPECT(dt.getInnerSType() == STI_UINT128);
}
{
Json::Value v;
v[jss::type] = "UINT160";
STDataType dt = dataTypeFromJson(sf, v);
STDataType const dt = dataTypeFromJson(sf, v);
BEAST_EXPECT(dt.getInnerSType() == STI_UINT160);
}
{
Json::Value v;
v[jss::type] = "UINT192";
STDataType dt = dataTypeFromJson(sf, v);
STDataType const dt = dataTypeFromJson(sf, v);
BEAST_EXPECT(dt.getInnerSType() == STI_UINT192);
}
{
Json::Value v;
v[jss::type] = "UINT256";
STDataType dt = dataTypeFromJson(sf, v);
STDataType const dt = dataTypeFromJson(sf, v);
BEAST_EXPECT(dt.getInnerSType() == STI_UINT256);
}
{
Json::Value v;
v[jss::type] = "VL";
STDataType dt = dataTypeFromJson(sf, v);
STDataType const dt = dataTypeFromJson(sf, v);
BEAST_EXPECT(dt.getInnerSType() == STI_VL);
}
{
Json::Value v;
v[jss::type] = "ACCOUNT";
STDataType dt = dataTypeFromJson(sf, v);
STDataType const dt = dataTypeFromJson(sf, v);
BEAST_EXPECT(dt.getInnerSType() == STI_ACCOUNT);
}
{
Json::Value v;
v[jss::type] = "AMOUNT";
STDataType dt = dataTypeFromJson(sf, v);
STDataType const dt = dataTypeFromJson(sf, v);
BEAST_EXPECT(dt.getInnerSType() == STI_AMOUNT);
}
{
Json::Value v;
v[jss::type] = "ISSUE";
STDataType dt = dataTypeFromJson(sf, v);
STDataType const dt = dataTypeFromJson(sf, v);
BEAST_EXPECT(dt.getInnerSType() == STI_ISSUE);
}
{
Json::Value v;
v[jss::type] = "CURRENCY";
STDataType dt = dataTypeFromJson(sf, v);
STDataType const dt = dataTypeFromJson(sf, v);
BEAST_EXPECT(dt.getInnerSType() == STI_CURRENCY);
}
{
Json::Value v;
v[jss::type] = "NUMBER";
STDataType dt = dataTypeFromJson(sf, v);
STDataType const dt = dataTypeFromJson(sf, v);
BEAST_EXPECT(dt.getInnerSType() == STI_NUMBER);
}
@@ -458,10 +458,10 @@ struct STDataType_test : public beast::unit_test::suite
// Non-object JSON should throw
{
Json::Value v = "not an object";
Json::Value const v = "not an object";
try
{
STDataType dt = dataTypeFromJson(sf, v);
STDataType const dt = dataTypeFromJson(sf, v);
BEAST_EXPECT(false); // Should not reach here
}
catch (std::runtime_error const& e)
@@ -476,7 +476,7 @@ struct STDataType_test : public beast::unit_test::suite
v[jss::type] = "UNKNOWN_TYPE";
try
{
STDataType dt = dataTypeFromJson(sf, v);
STDataType const dt = dataTypeFromJson(sf, v);
BEAST_EXPECT(false); // Should not reach here
}
catch (std::runtime_error const& e)
@@ -492,7 +492,7 @@ struct STDataType_test : public beast::unit_test::suite
v[jss::type] = "";
try
{
STDataType dt = dataTypeFromJson(sf, v);
STDataType const dt = dataTypeFromJson(sf, v);
BEAST_EXPECT(false); // Should not reach here
}
catch (std::runtime_error const& e)
@@ -527,7 +527,7 @@ struct STDataType_test : public beast::unit_test::suite
STI_NUMBER})
{
// Create original
STDataType original(sf, typeId);
STDataType const original(sf, typeId);
// Serialize
Serializer s;
@@ -535,7 +535,7 @@ struct STDataType_test : public beast::unit_test::suite
// Deserialize
SerialIter sit(s.slice());
STDataType deserialized(sit, sf);
STDataType const deserialized(sit, sf);
// Compare
BEAST_EXPECT(deserialized.getInnerSType() == typeId);
@@ -550,7 +550,7 @@ struct STDataType_test : public beast::unit_test::suite
auto const& sf = sfParameterType;
std::vector<std::string> typeStrings = {
std::vector<std::string> const typeStrings = {
"UINT8",
"UINT16",
"UINT32",
@@ -571,7 +571,7 @@ struct STDataType_test : public beast::unit_test::suite
// Create from JSON
Json::Value input;
input[jss::type] = typeStr;
STDataType dt = dataTypeFromJson(sf, input);
STDataType const dt = dataTypeFromJson(sf, input);
// Convert back to JSON
Json::Value output = dt.getJson(JsonOptions::none);
@@ -594,7 +594,7 @@ struct STDataType_test : public beast::unit_test::suite
std::string expected;
};
TypeStringTest tests[] = {
TypeStringTest const tests[] = {
{STI_UINT8, "UINT8"},
{STI_UINT16, "UINT16"},
{STI_UINT32, "UINT32"},
@@ -614,7 +614,7 @@ struct STDataType_test : public beast::unit_test::suite
for (auto const& test : tests)
{
STDataType dt(sf, test.type);
STDataType const dt(sf, test.type);
BEAST_EXPECT(dt.getInnerTypeString() == test.expected);
}
}

View File

@@ -17,7 +17,7 @@ struct STData_test : public beast::unit_test::suite
// Default constructor
{
STData data(sf);
STData const data(sf);
BEAST_EXPECT(data.getSType() == STI_DATA);
BEAST_EXPECT(data.isDefault());
}
@@ -25,82 +25,82 @@ struct STData_test : public beast::unit_test::suite
// Type-specific constructors
{
// UINT8
STData data_u8(sf, static_cast<std::uint8_t>(8));
STData const data_u8(sf, static_cast<std::uint8_t>(8));
BEAST_EXPECT(data_u8.getFieldU8() == 8);
BEAST_EXPECT(data_u8.getInnerTypeString() == "UINT8");
BEAST_EXPECT(data_u8.isDefault());
// UINT16
STData data_u16(sf, static_cast<std::uint16_t>(16));
STData const data_u16(sf, static_cast<std::uint16_t>(16));
BEAST_EXPECT(data_u16.getFieldU16() == 16);
BEAST_EXPECT(data_u16.getInnerTypeString() == "UINT16");
// UINT32
STData data_u32(sf, static_cast<std::uint32_t>(32));
STData const data_u32(sf, static_cast<std::uint32_t>(32));
BEAST_EXPECT(data_u32.getFieldU32() == 32);
BEAST_EXPECT(data_u32.getInnerTypeString() == "UINT32");
// UINT64
STData data_u64(sf, static_cast<std::uint64_t>(64));
STData const data_u64(sf, static_cast<std::uint64_t>(64));
BEAST_EXPECT(data_u64.getFieldU64() == 64);
BEAST_EXPECT(data_u64.getInnerTypeString() == "UINT64");
// UINT128
uint128 val128 = uint128(1);
STData data_u128(sf, val128);
uint128 const val128 = uint128(1);
STData const data_u128(sf, val128);
BEAST_EXPECT(data_u128.getFieldH128() == val128);
BEAST_EXPECT(data_u128.getInnerTypeString() == "UINT128");
// UINT160
uint160 val160 = uint160(1);
STData data_u160(sf, val160);
uint160 const val160 = uint160(1);
STData const data_u160(sf, val160);
BEAST_EXPECT(data_u160.getFieldH160() == val160);
BEAST_EXPECT(data_u160.getInnerTypeString() == "UINT160");
// UINT192
uint192 val192 = uint192(1);
STData data_u192(sf, val192);
uint192 const val192 = uint192(1);
STData const data_u192(sf, val192);
BEAST_EXPECT(data_u192.getFieldH192() == val192);
BEAST_EXPECT(data_u192.getInnerTypeString() == "UINT192");
// UINT256
uint256 val256 = uint256(1);
STData data_u256(sf, val256);
uint256 const val256 = uint256(1);
STData const data_u256(sf, val256);
BEAST_EXPECT(data_u256.getFieldH256() == val256);
BEAST_EXPECT(data_u256.getInnerTypeString() == "UINT256");
// Blob
Blob blob = strUnHex("DEADBEEFCAFEBABE").value();
STData data_blob(sf, blob);
Blob const blob = strUnHex("DEADBEEFCAFEBABE").value();
STData const data_blob(sf, blob);
BEAST_EXPECT(data_blob.getFieldVL() == blob);
BEAST_EXPECT(data_blob.getInnerTypeString() == "VL");
// Slice
std::string test_str = "Hello World";
Slice slice(test_str.data(), test_str.size());
STData data_slice(sf, slice);
Blob expected_blob(test_str.begin(), test_str.end());
Slice const slice(test_str.data(), test_str.size());
STData const data_slice(sf, slice);
Blob const expected_blob(test_str.begin(), test_str.end());
BEAST_EXPECT(data_slice.getFieldVL() == expected_blob);
// AccountID
AccountID account(0x123456789ABCDEF0);
STData data_account(sf, account);
AccountID const account(0x123456789ABCDEF0);
STData const data_account(sf, account);
BEAST_EXPECT(data_account.getAccountID() == account);
BEAST_EXPECT(data_account.getInnerTypeString() == "ACCOUNT");
// STAmount (Native)
STAmount amount_native(1000);
STData data_amount_native(sf, amount_native);
STAmount const amount_native(1000);
STData const data_amount_native(sf, amount_native);
BEAST_EXPECT(data_amount_native.getFieldAmount() == amount_native);
BEAST_EXPECT(data_amount_native.getInnerTypeString() == "AMOUNT");
// STAmount (IOU)
IOUAmount iou_amount(5000);
IOUAmount const iou_amount(5000);
Issue const usd(
Currency(0x5553440000000000),
parseBase58<AccountID>("rG1QQv2nh2gr7RCZ1P8YYcBUKCCN633jCn").value());
STAmount amount_iou(iou_amount, usd);
STData data_amount_iou(sf, amount_iou);
STAmount const amount_iou(iou_amount, usd);
STData const data_amount_iou(sf, amount_iou);
BEAST_EXPECT(data_amount_iou.getFieldAmount() == amount_iou);
}
}
@@ -115,14 +115,14 @@ struct STData_test : public beast::unit_test::suite
// Test each type's serialization and deserialization round-trip
{
// UINT8
std::uint8_t original_u8 = 8;
STData data_u8(sf, original_u8);
std::uint8_t const original_u8 = 8;
STData const data_u8(sf, original_u8);
Serializer s;
data_u8.add(s);
SerialIter sit(s.slice());
STData deserialized_u8(sit, sf);
STData const deserialized_u8(sit, sf);
BEAST_EXPECT(deserialized_u8.getFieldU8() == original_u8);
BEAST_EXPECT(deserialized_u8.getInnerTypeString() == "UINT8");
@@ -130,14 +130,14 @@ struct STData_test : public beast::unit_test::suite
{
// UINT16
std::uint16_t original_u16 = 16;
STData data_u16(sf, original_u16);
std::uint16_t const original_u16 = 16;
STData const data_u16(sf, original_u16);
Serializer s;
data_u16.add(s);
SerialIter sit(s.slice());
STData deserialized_u16(sit, sf);
STData const deserialized_u16(sit, sf);
BEAST_EXPECT(deserialized_u16.getFieldU16() == original_u16);
BEAST_EXPECT(deserialized_u16.getInnerTypeString() == "UINT16");
@@ -145,14 +145,14 @@ struct STData_test : public beast::unit_test::suite
{
// UINT32
std::uint32_t original_u32 = 32;
STData data_u32(sf, original_u32);
std::uint32_t const original_u32 = 32;
STData const data_u32(sf, original_u32);
Serializer s;
data_u32.add(s);
SerialIter sit(s.slice());
STData deserialized_u32(sit, sf);
STData const deserialized_u32(sit, sf);
BEAST_EXPECT(deserialized_u32.getFieldU32() == original_u32);
BEAST_EXPECT(deserialized_u32.getInnerTypeString() == "UINT32");
@@ -160,14 +160,14 @@ struct STData_test : public beast::unit_test::suite
{
// UINT64
std::uint64_t original_u64 = 64;
STData data_u64(sf, original_u64);
std::uint64_t const original_u64 = 64;
STData const data_u64(sf, original_u64);
Serializer s;
data_u64.add(s);
SerialIter sit(s.slice());
STData deserialized_u64(sit, sf);
STData const deserialized_u64(sit, sf);
BEAST_EXPECT(deserialized_u64.getFieldU64() == original_u64);
BEAST_EXPECT(deserialized_u64.getInnerTypeString() == "UINT64");
@@ -175,14 +175,14 @@ struct STData_test : public beast::unit_test::suite
{
// UINT128
uint128 original_u128 = uint128(1);
STData data_u128(sf, original_u128);
uint128 const original_u128 = uint128(1);
STData const data_u128(sf, original_u128);
Serializer s;
data_u128.add(s);
SerialIter sit(s.slice());
STData deserialized_u128(sit, sf);
STData const deserialized_u128(sit, sf);
BEAST_EXPECT(deserialized_u128.getFieldH128() == original_u128);
BEAST_EXPECT(deserialized_u128.getInnerTypeString() == "UINT128");
@@ -190,14 +190,14 @@ struct STData_test : public beast::unit_test::suite
{
// UINT160
uint160 original_u160 = uint160(1);
STData data_u160(sf, original_u160);
uint160 const original_u160 = uint160(1);
STData const data_u160(sf, original_u160);
Serializer s;
data_u160.add(s);
SerialIter sit(s.slice());
STData deserialized_u160(sit, sf);
STData const deserialized_u160(sit, sf);
BEAST_EXPECT(deserialized_u160.getFieldH160() == original_u160);
BEAST_EXPECT(deserialized_u160.getInnerTypeString() == "UINT160");
@@ -205,14 +205,14 @@ struct STData_test : public beast::unit_test::suite
{
// UINT192
uint192 original_u192 = uint192(1);
STData data_u192(sf, original_u192);
uint192 const original_u192 = uint192(1);
STData const data_u192(sf, original_u192);
Serializer s;
data_u192.add(s);
SerialIter sit(s.slice());
STData deserialized_u192(sit, sf);
STData const deserialized_u192(sit, sf);
BEAST_EXPECT(deserialized_u192.getFieldH192() == original_u192);
BEAST_EXPECT(deserialized_u192.getInnerTypeString() == "UINT192");
@@ -220,14 +220,14 @@ struct STData_test : public beast::unit_test::suite
{
// UINT256
uint256 original_u256 = uint256(1);
STData data_u256(sf, original_u256);
uint256 const original_u256 = uint256(1);
STData const data_u256(sf, original_u256);
Serializer s;
data_u256.add(s);
SerialIter sit(s.slice());
STData deserialized_u256(sit, sf);
STData const deserialized_u256(sit, sf);
BEAST_EXPECT(deserialized_u256.getFieldH256() == original_u256);
BEAST_EXPECT(deserialized_u256.getInnerTypeString() == "UINT256");
@@ -235,14 +235,14 @@ struct STData_test : public beast::unit_test::suite
{
// VL (Variable Length)
Blob original_blob = strUnHex("DEADBEEFCAFEBABE1234567890ABCDEF").value();
STData data_vl(sf, original_blob);
Blob const original_blob = strUnHex("DEADBEEFCAFEBABE1234567890ABCDEF").value();
STData const data_vl(sf, original_blob);
Serializer s;
data_vl.add(s);
SerialIter sit(s.slice());
STData deserialized_vl(sit, sf);
STData const deserialized_vl(sit, sf);
BEAST_EXPECT(deserialized_vl.getFieldVL() == original_blob);
BEAST_EXPECT(deserialized_vl.getInnerTypeString() == "VL");
@@ -250,14 +250,14 @@ struct STData_test : public beast::unit_test::suite
{
// ACCOUNT
AccountID original_account(0xFEDCBA9876543210);
STData data_account(sf, original_account);
AccountID const original_account(0xFEDCBA9876543210);
STData const data_account(sf, original_account);
Serializer s;
data_account.add(s);
SerialIter sit(s.slice());
STData deserialized_account(sit, sf);
STData const deserialized_account(sit, sf);
BEAST_EXPECT(deserialized_account.getAccountID() == original_account);
BEAST_EXPECT(deserialized_account.getInnerTypeString() == "ACCOUNT");
@@ -265,14 +265,14 @@ struct STData_test : public beast::unit_test::suite
{
// AMOUNT (Native)
STAmount original_amount(99999);
STData data_amount(sf, original_amount);
STAmount const original_amount(99999);
STData const data_amount(sf, original_amount);
Serializer s;
data_amount.add(s);
SerialIter sit(s.slice());
STData deserialized_amount(sit, sf);
STData const deserialized_amount(sit, sf);
BEAST_EXPECT(deserialized_amount.getFieldAmount() == original_amount);
BEAST_EXPECT(deserialized_amount.getInnerTypeString() == "AMOUNT");
@@ -302,7 +302,7 @@ struct STData_test : public beast::unit_test::suite
// Test all setter/getter combinations
{
// UINT8
unsigned char val_u8 = 8;
unsigned char const val_u8 = 8;
data.setFieldU8(val_u8);
BEAST_EXPECT(data.getFieldU8() == val_u8);
BEAST_EXPECT(data.getInnerTypeString() == "UINT8");
@@ -310,7 +310,7 @@ struct STData_test : public beast::unit_test::suite
{
// UINT16
std::uint16_t val_u16 = 16;
std::uint16_t const val_u16 = 16;
data.setFieldU16(val_u16);
BEAST_EXPECT(data.getFieldU16() == val_u16);
BEAST_EXPECT(data.getInnerTypeString() == "UINT16");
@@ -318,7 +318,7 @@ struct STData_test : public beast::unit_test::suite
{
// UINT32
std::uint32_t val_u32 = 32;
std::uint32_t const val_u32 = 32;
data.setFieldU32(val_u32);
BEAST_EXPECT(data.getFieldU32() == val_u32);
BEAST_EXPECT(data.getInnerTypeString() == "UINT32");
@@ -326,7 +326,7 @@ struct STData_test : public beast::unit_test::suite
{
// UINT64
std::uint64_t val_u64 = 64;
std::uint64_t const val_u64 = 64;
data.setFieldU64(val_u64);
BEAST_EXPECT(data.getFieldU64() == val_u64);
BEAST_EXPECT(data.getInnerTypeString() == "UINT64");
@@ -334,7 +334,7 @@ struct STData_test : public beast::unit_test::suite
{
// UINT128
uint128 val_u128 = uint128(1);
uint128 const val_u128 = uint128(1);
data.setFieldH128(val_u128);
BEAST_EXPECT(data.getFieldH128() == val_u128);
BEAST_EXPECT(data.getInnerTypeString() == "UINT128");
@@ -342,7 +342,7 @@ struct STData_test : public beast::unit_test::suite
{
// UINT160
uint160 val_u160 = uint160(1);
uint160 const val_u160 = uint160(1);
data.setFieldH160(val_u160);
BEAST_EXPECT(data.getFieldH160() == val_u160);
BEAST_EXPECT(data.getInnerTypeString() == "UINT160");
@@ -350,7 +350,7 @@ struct STData_test : public beast::unit_test::suite
{
// UINT192
uint192 val_u192 = uint192(1);
uint192 const val_u192 = uint192(1);
data.setFieldH192(val_u192);
BEAST_EXPECT(data.getFieldH192() == val_u192);
BEAST_EXPECT(data.getInnerTypeString() == "UINT192");
@@ -358,7 +358,7 @@ struct STData_test : public beast::unit_test::suite
{
// UINT256
uint256 val_u256 = uint256(1);
uint256 const val_u256 = uint256(1);
data.setFieldH256(val_u256);
BEAST_EXPECT(data.getFieldH256() == val_u256);
BEAST_EXPECT(data.getInnerTypeString() == "UINT256");
@@ -366,7 +366,7 @@ struct STData_test : public beast::unit_test::suite
{
// VL (Variable Length) - Blob
Blob val_blob = strUnHex("0102030405060708090A0B0C0D0E0F10").value();
Blob const val_blob = strUnHex("0102030405060708090A0B0C0D0E0F10").value();
data.setFieldVL(val_blob);
BEAST_EXPECT(data.getFieldVL() == val_blob);
BEAST_EXPECT(data.getInnerTypeString() == "VL");
@@ -375,16 +375,16 @@ struct STData_test : public beast::unit_test::suite
{
// VL (Variable Length) - Slice
std::string test_str = "Test String for Slice";
Slice val_slice(test_str.data(), test_str.size());
Slice const val_slice(test_str.data(), test_str.size());
data.setFieldVL(val_slice);
Blob expected_blob(test_str.begin(), test_str.end());
Blob const expected_blob(test_str.begin(), test_str.end());
BEAST_EXPECT(data.getFieldVL() == expected_blob);
BEAST_EXPECT(data.getInnerTypeString() == "VL");
}
{
// ACCOUNT
AccountID val_account(0x123456789ABCDEF0);
AccountID const val_account(0x123456789ABCDEF0);
data.setAccountID(val_account);
BEAST_EXPECT(data.getAccountID() == val_account);
BEAST_EXPECT(data.getInnerTypeString() == "ACCOUNT");
@@ -392,7 +392,7 @@ struct STData_test : public beast::unit_test::suite
{
// AMOUNT
STAmount val_amount(777777);
STAmount const val_amount(777777);
data.setFieldAmount(val_amount);
BEAST_EXPECT(data.getFieldAmount() == val_amount);
BEAST_EXPECT(data.getInnerTypeString() == "AMOUNT");
@@ -421,7 +421,7 @@ struct STData_test : public beast::unit_test::suite
// Test JSON serialization for each type
{
// UINT8
STData data_u8(sf, static_cast<unsigned char>(8));
STData const data_u8(sf, static_cast<unsigned char>(8));
Json::Value json_u8 = data_u8.getJson(JsonOptions::none);
BEAST_EXPECT(json_u8[jss::type].asString() == "UINT8");
BEAST_EXPECT(json_u8[jss::value].asUInt() == 8);
@@ -429,7 +429,7 @@ struct STData_test : public beast::unit_test::suite
{
// UINT16
STData data_u16(sf, static_cast<std::uint16_t>(16));
STData const data_u16(sf, static_cast<std::uint16_t>(16));
Json::Value json_u16 = data_u16.getJson(JsonOptions::none);
BEAST_EXPECT(json_u16[jss::type].asString() == "UINT16");
BEAST_EXPECT(json_u16[jss::value].asUInt() == 16);
@@ -437,7 +437,7 @@ struct STData_test : public beast::unit_test::suite
{
// UINT32
STData data_u32(sf, static_cast<std::uint32_t>(32));
STData const data_u32(sf, static_cast<std::uint32_t>(32));
Json::Value json_u32 = data_u32.getJson(JsonOptions::none);
BEAST_EXPECT(json_u32[jss::type].asString() == "UINT32");
BEAST_EXPECT(json_u32[jss::value].asUInt() == 32);
@@ -445,7 +445,7 @@ struct STData_test : public beast::unit_test::suite
{
// UINT64
STData data_u64(sf, static_cast<std::uint64_t>(64));
STData const data_u64(sf, static_cast<std::uint64_t>(64));
Json::Value json_u64 = data_u64.getJson(JsonOptions::none);
BEAST_EXPECT(json_u64[jss::type].asString() == "UINT64");
BEAST_EXPECT(json_u64[jss::value].asString() == "40");
@@ -453,8 +453,8 @@ struct STData_test : public beast::unit_test::suite
{
// UINT128
uint128 val_u128 = uint128(1);
STData data_u128(sf, val_u128);
uint128 const val_u128 = uint128(1);
STData const data_u128(sf, val_u128);
Json::Value json_u128 = data_u128.getJson(JsonOptions::none);
BEAST_EXPECT(json_u128[jss::type].asString() == "UINT128");
BEAST_EXPECT(json_u128[jss::value].asString() == "00000000000000000000000000000001");
@@ -462,8 +462,8 @@ struct STData_test : public beast::unit_test::suite
{
// UINT160
uint160 val_u160 = uint160(1);
STData data_u160(sf, val_u160);
uint160 const val_u160 = uint160(1);
STData const data_u160(sf, val_u160);
Json::Value json_u160 = data_u160.getJson(JsonOptions::none);
BEAST_EXPECT(json_u160[jss::type].asString() == "UINT160");
BEAST_EXPECT(
@@ -472,8 +472,8 @@ struct STData_test : public beast::unit_test::suite
{
// UINT192
uint192 val_u192 = uint192(1);
STData data_u192(sf, val_u192);
uint192 const val_u192 = uint192(1);
STData const data_u192(sf, val_u192);
Json::Value json_u192 = data_u192.getJson(JsonOptions::none);
BEAST_EXPECT(json_u192[jss::type].asString() == "UINT192");
BEAST_EXPECT(
@@ -483,8 +483,8 @@ struct STData_test : public beast::unit_test::suite
{
// UINT256
uint256 val_u256 = uint256(1);
STData data_u256(sf, val_u256);
uint256 const val_u256 = uint256(1);
STData const data_u256(sf, val_u256);
Json::Value json_u256 = data_u256.getJson(JsonOptions::none);
BEAST_EXPECT(json_u256[jss::type].asString() == "UINT256");
BEAST_EXPECT(
@@ -495,8 +495,8 @@ struct STData_test : public beast::unit_test::suite
{
// VL
Blob blob = strUnHex("DEADBEEF").value();
STData data_vl(sf, blob);
Blob const blob = strUnHex("DEADBEEF").value();
STData const data_vl(sf, blob);
Json::Value json_vl = data_vl.getJson(JsonOptions::none);
BEAST_EXPECT(json_vl[jss::type].asString() == "VL");
BEAST_EXPECT(json_vl[jss::value].asString() == "DEADBEEF");
@@ -504,8 +504,8 @@ struct STData_test : public beast::unit_test::suite
{
// ACCOUNT
AccountID account(0x123456789ABCDEF0);
STData data_account(sf, account);
AccountID const account(0x123456789ABCDEF0);
STData const data_account(sf, account);
Json::Value json_account = data_account.getJson(JsonOptions::none);
BEAST_EXPECT(json_account[jss::type].asString() == "ACCOUNT");
BEAST_EXPECT(json_account[jss::value].asString() == "rrrrrrrrrrrrrLveWzSkxhcH3hGw6");
@@ -513,8 +513,8 @@ struct STData_test : public beast::unit_test::suite
{
// AMOUNT
STAmount amount(1000);
STData data_amount(sf, amount);
STAmount const amount(1000);
STData const data_amount(sf, amount);
Json::Value json_amount = data_amount.getJson(JsonOptions::none);
BEAST_EXPECT(json_amount[jss::type].asString() == "AMOUNT");
BEAST_EXPECT(json_amount[jss::value].asString() == "1000");
@@ -547,7 +547,7 @@ struct STData_test : public beast::unit_test::suite
json_u8[jss::type] = "UINT8";
json_u8[jss::value] = 8;
STData data_u8 = dataFromJson(sf, json_u8);
STData const data_u8 = dataFromJson(sf, json_u8);
BEAST_EXPECT(data_u8.getFieldU8() == 8);
BEAST_EXPECT(data_u8.getInnerTypeString() == "UINT8");
}
@@ -558,7 +558,7 @@ struct STData_test : public beast::unit_test::suite
json_u16[jss::type] = "UINT16";
json_u16[jss::value] = 16;
STData data_u16 = dataFromJson(sf, json_u16);
STData const data_u16 = dataFromJson(sf, json_u16);
BEAST_EXPECT(data_u16.getFieldU16() == 16);
BEAST_EXPECT(data_u16.getInnerTypeString() == "UINT16");
}
@@ -569,7 +569,7 @@ struct STData_test : public beast::unit_test::suite
json_u32[jss::type] = "UINT32";
json_u32[jss::value] = 32;
STData data_u32 = dataFromJson(sf, json_u32);
STData const data_u32 = dataFromJson(sf, json_u32);
BEAST_EXPECT(data_u32.getFieldU32() == 32);
BEAST_EXPECT(data_u32.getInnerTypeString() == "UINT32");
}
@@ -579,7 +579,7 @@ struct STData_test : public beast::unit_test::suite
Json::Value json_u64(Json::objectValue);
json_u64[jss::type] = "UINT64";
json_u64[jss::value] = 64;
STData data_u64 = dataFromJson(sf, json_u64);
STData const data_u64 = dataFromJson(sf, json_u64);
BEAST_EXPECT(data_u64.getFieldU64() == 64);
BEAST_EXPECT(data_u64.getInnerTypeString() == "UINT64");
}
@@ -589,9 +589,9 @@ struct STData_test : public beast::unit_test::suite
Json::Value json_u128(Json::objectValue);
json_u128[jss::type] = "UINT128";
json_u128[jss::value] = "00000000000000000000000000000001";
STData data_u128 = dataFromJson(sf, json_u128);
STData const data_u128 = dataFromJson(sf, json_u128);
uint128 expected;
bool ok = expected.parseHex("00000000000000000000000000000001");
bool const ok = expected.parseHex("00000000000000000000000000000001");
BEAST_EXPECT(ok);
BEAST_EXPECT(data_u128.getFieldH128() == expected);
BEAST_EXPECT(data_u128.getInnerTypeString() == "UINT128");
@@ -602,9 +602,9 @@ struct STData_test : public beast::unit_test::suite
Json::Value json_u160(Json::objectValue);
json_u160[jss::type] = "UINT160";
json_u160[jss::value] = "0000000000000000000000000000000000000001";
STData data_u160 = dataFromJson(sf, json_u160);
STData const data_u160 = dataFromJson(sf, json_u160);
uint160 expected;
bool ok = expected.parseHex("0000000000000000000000000000000000000001");
bool const ok = expected.parseHex("0000000000000000000000000000000000000001");
BEAST_EXPECT(ok);
BEAST_EXPECT(data_u160.getFieldH160() == expected);
BEAST_EXPECT(data_u160.getInnerTypeString() == "UINT160");
@@ -615,9 +615,9 @@ struct STData_test : public beast::unit_test::suite
Json::Value json_u192(Json::objectValue);
json_u192[jss::type] = "UINT192";
json_u192[jss::value] = "000000000000000000000000000000000000000000000001";
STData data_u192 = dataFromJson(sf, json_u192);
STData const data_u192 = dataFromJson(sf, json_u192);
uint192 expected;
bool ok = expected.parseHex("000000000000000000000000000000000000000000000001");
bool const ok = expected.parseHex("000000000000000000000000000000000000000000000001");
BEAST_EXPECT(ok);
BEAST_EXPECT(data_u192.getFieldH192() == expected);
BEAST_EXPECT(data_u192.getInnerTypeString() == "UINT192");
@@ -630,9 +630,9 @@ struct STData_test : public beast::unit_test::suite
json_u256[jss::value] =
"00000000000000000000000000000000000000000000000000000000000000"
"01";
STData data_u256 = dataFromJson(sf, json_u256);
STData const data_u256 = dataFromJson(sf, json_u256);
uint256 expected;
bool ok = expected.parseHex(
bool const ok = expected.parseHex(
"00000000000000000000000000000000000000000000000000000000000000"
"01");
BEAST_EXPECT(ok);
@@ -646,8 +646,8 @@ struct STData_test : public beast::unit_test::suite
json_vl[jss::type] = "VL";
json_vl[jss::value] = "DEADBEEFCAFEBABE";
STData data_vl = dataFromJson(sf, json_vl);
Blob expected_blob = strUnHex("DEADBEEFCAFEBABE").value();
STData const data_vl = dataFromJson(sf, json_vl);
Blob const expected_blob = strUnHex("DEADBEEFCAFEBABE").value();
BEAST_EXPECT(data_vl.getFieldVL() == expected_blob);
BEAST_EXPECT(data_vl.getInnerTypeString() == "VL");
}
@@ -658,8 +658,8 @@ struct STData_test : public beast::unit_test::suite
json_account[jss::type] = "ACCOUNT";
json_account[jss::value] = "rG1QQv2nh2gr7RCZ1P8YYcBUKCCN633jCn";
STData data_account = dataFromJson(sf, json_account);
AccountID expected_account =
STData const data_account = dataFromJson(sf, json_account);
AccountID const expected_account =
parseBase58<AccountID>("rG1QQv2nh2gr7RCZ1P8YYcBUKCCN633jCn").value();
BEAST_EXPECT(data_account.getAccountID() == expected_account);
BEAST_EXPECT(data_account.getInnerTypeString() == "ACCOUNT");
@@ -671,8 +671,8 @@ struct STData_test : public beast::unit_test::suite
json_amount[jss::type] = "AMOUNT";
json_amount[jss::value] = "1000";
STData data_amount = dataFromJson(sf, json_amount);
STAmount expected_amount(1000);
STData const data_amount = dataFromJson(sf, json_amount);
STAmount const expected_amount(1000);
BEAST_EXPECT(data_amount.getFieldAmount() == expected_amount);
BEAST_EXPECT(data_amount.getInnerTypeString() == "AMOUNT");
}

View File

@@ -1,6 +1,7 @@
#include <xrpl/basics/Buffer.h>
#include <xrpl/basics/StringUtilities.h>
#include <xrpl/basics/base_uint.h>
#include <xrpl/basics/strHex.h>
#include <xrpl/beast/unit_test.h>
#include <xrpl/json/json_value.h>
#include <xrpl/protocol/Indexes.h>
@@ -32,7 +33,7 @@ struct STJson_test : public beast::unit_test::suite
testDefaultConstructor()
{
testcase("Default constructor");
STJson json;
STJson const json;
BEAST_EXPECT(json.isObject());
BEAST_EXPECT(!json.isArray());
BEAST_EXPECT(json.getMap().empty());
@@ -62,7 +63,7 @@ struct STJson_test : public beast::unit_test::suite
testcase("Move constructor (Object)");
STJson::Map map;
map["bar"] = std::make_shared<STUInt16>(sfTransactionType, 42);
STJson json(std::move(map));
STJson const json(std::move(map));
BEAST_EXPECT(json.isObject());
BEAST_EXPECT(json.getMap().size() == 1);
BEAST_EXPECT(std::dynamic_pointer_cast<STUInt16>(json.getMap().at("bar"))->value() == 42);
@@ -76,7 +77,7 @@ struct STJson_test : public beast::unit_test::suite
arr.push_back(std::make_shared<STUInt32>(sfNetworkID, 100));
arr.push_back(std::make_shared<STUInt32>(sfNetworkID, 200));
STJson json(std::move(arr));
STJson const json(std::move(arr));
BEAST_EXPECT(json.isArray());
BEAST_EXPECT(!json.isObject());
BEAST_EXPECT(json.arraySize() == 2);
@@ -90,12 +91,12 @@ struct STJson_test : public beast::unit_test::suite
testTypeChecking()
{
testcase("Type checking methods");
STJson objJson;
STJson const objJson;
BEAST_EXPECT(objJson.isObject());
BEAST_EXPECT(!objJson.isArray());
BEAST_EXPECT(objJson.getType() == STJson::JsonType::Object);
STJson arrJson(STJson::Array{});
STJson const arrJson(STJson::Array{});
BEAST_EXPECT(arrJson.isArray());
BEAST_EXPECT(!arrJson.isObject());
BEAST_EXPECT(arrJson.getType() == STJson::JsonType::Array);
@@ -469,11 +470,13 @@ struct STJson_test : public beast::unit_test::suite
STJson json;
json.setObjectField("foo", std::make_shared<STUInt16>(sfTransactionType, 65535));
json.setObjectField("bar", nullptr); // test null value
json.setNestedObjectField("meta", "version", std::make_shared<STUInt32>(sfNetworkID, 2));
Json::Value jv = json.getJson(JsonOptions::none);
BEAST_EXPECT(jv.isObject());
BEAST_EXPECT(jv["foo"].asUInt() == 65535);
BEAST_EXPECT(jv["bar"].isNull());
BEAST_EXPECT(jv[strHex(std::string{"foo"})].asUInt() == 65535);
BEAST_EXPECT(jv[strHex(std::string{"bar"})].isNull());
BEAST_EXPECT(jv[strHex(std::string{"meta"})][strHex(std::string{"version"})].asUInt() == 2);
}
void
@@ -631,7 +634,7 @@ struct STJson_test : public beast::unit_test::suite
{
STJson json;
// XRP amount
STAmount xrp(sfAmount, static_cast<std::int64_t>(123456789u));
STAmount const xrp(sfAmount, static_cast<std::int64_t>(123456789u));
json.setObjectField("amount", std::make_shared<STAmount>(xrp));
Serializer s;
json.add(s);
@@ -661,7 +664,7 @@ struct STJson_test : public beast::unit_test::suite
{
STJson json;
// Use a known AccountID (20 bytes)
AccountID acct = AccountID{};
AccountID const acct = AccountID{};
json.setObjectField("acct", std::make_shared<STAccount>(sfAccount, acct));
Serializer s;
json.add(s);
@@ -690,7 +693,7 @@ struct STJson_test : public beast::unit_test::suite
{
STJson innerJson;
// XRP amount
STAmount xrp(sfAmount, static_cast<std::int64_t>(123456789u));
STAmount const xrp(sfAmount, static_cast<std::int64_t>(123456789u));
innerJson.setObjectField("amount", std::make_shared<STAmount>(xrp));
STJson json;
@@ -713,7 +716,7 @@ struct STJson_test : public beast::unit_test::suite
// Empty object
{
STJson json;
STJson const json;
Serializer s;
json.add(s);
auto parsed = STJson::fromBlob(s.peekData().data(), s.peekData().size());
@@ -723,7 +726,7 @@ struct STJson_test : public beast::unit_test::suite
// Empty array
{
STJson json(STJson::Array{});
STJson const json(STJson::Array{});
Serializer s;
json.add(s);
auto parsed = STJson::fromBlob(s.peekData().data(), s.peekData().size());
@@ -749,14 +752,13 @@ struct STJson_test : public beast::unit_test::suite
BEAST_EXPECT(*elem1 != nullptr);
}
// Object with null value
// Object with null value - getObjectField treats null as absent
{
STJson json;
json.setObjectField("null_field", nullptr);
auto val = json.getObjectField("null_field");
BEAST_EXPECT(val.has_value());
BEAST_EXPECT(*val == nullptr);
BEAST_EXPECT(!val.has_value());
}
}

View File

@@ -484,6 +484,9 @@ public:
if (jv.isMember(jss::extension_size) != isFlagLedger)
return false;
if (jv.isMember(jss::gas_price) != isFlagLedger)
return false;
}
else
{
@@ -492,6 +495,9 @@ public:
if (jv.isMember(jss::extension_size))
return false;
if (jv.isMember(jss::gas_price))
return false;
}
return true;
};

View File

@@ -2278,7 +2278,7 @@ NetworkOPsImp::pubConsensus(ConsensusPhase phase)
void
NetworkOPsImp::pubContractEvent(std::string const& name, STJson const& event)
{
std::lock_guard sl(mSubLock);
std::lock_guard const sl(mSubLock);
auto& streamMap = mStreamMaps[sContractEvents];
if (!streamMap.empty())
@@ -4269,7 +4269,7 @@ NetworkOPsImp::unsubConsensus(std::uint64_t uSeq)
bool
NetworkOPsImp::subContractEvent(InfoSub::ref isrListener)
{
std::lock_guard sl(mSubLock);
std::lock_guard const sl(mSubLock);
return mStreamMaps[sContractEvents].emplace(isrListener->getSeq(), isrListener).second;
}
@@ -4277,7 +4277,7 @@ NetworkOPsImp::subContractEvent(InfoSub::ref isrListener)
bool
NetworkOPsImp::unsubContractEvent(std::uint64_t uSeq)
{
std::lock_guard sl(mSubLock);
std::lock_guard const sl(mSubLock);
return mStreamMaps[sContractEvents].erase(uSeq);
}

View File

@@ -19,13 +19,13 @@ getFieldBytesFromSTData(xrpl::STData const& funcParam, std::uint32_t stTypeId)
case STI_UINT8: {
if (funcParam.getInnerSType() != STI_UINT8)
return Unexpected(HostFunctionError::INVALID_PARAMS);
uint8_t data = funcParam.getFieldU8();
uint8_t const data = funcParam.getFieldU8();
return Bytes{data};
}
case STI_UINT16: {
if (funcParam.getInnerSType() != STI_UINT16)
return Unexpected(HostFunctionError::INVALID_PARAMS);
uint16_t data = funcParam.getFieldU16();
uint16_t const data = funcParam.getFieldU16();
return Bytes{
static_cast<unsigned char>(data & 0xFF),
static_cast<unsigned char>((data >> 8) & 0xFF)};
@@ -33,7 +33,7 @@ getFieldBytesFromSTData(xrpl::STData const& funcParam, std::uint32_t stTypeId)
case STI_UINT32: {
if (funcParam.getInnerSType() != STI_UINT32)
return Unexpected(HostFunctionError::INVALID_PARAMS);
uint32_t data = funcParam.getFieldU32();
uint32_t const data = funcParam.getFieldU32();
return Bytes{
static_cast<unsigned char>(data & 0xFF),
static_cast<unsigned char>((data >> 8) & 0xFF),
@@ -43,7 +43,7 @@ getFieldBytesFromSTData(xrpl::STData const& funcParam, std::uint32_t stTypeId)
case STI_UINT64: {
if (funcParam.getInnerSType() != STI_UINT64)
return Unexpected(HostFunctionError::INVALID_PARAMS);
uint64_t data = funcParam.getFieldU64();
uint64_t const data = funcParam.getFieldU64();
return Bytes{
static_cast<unsigned char>(data & 0xFF),
static_cast<unsigned char>((data >> 8) & 0xFF),
@@ -95,7 +95,7 @@ getFieldBytesFromSTData(xrpl::STData const& funcParam, std::uint32_t stTypeId)
case STI_AMOUNT: {
if (funcParam.getInnerSType() != STI_AMOUNT)
return Unexpected(HostFunctionError::INVALID_PARAMS);
STAmount data = funcParam.getFieldAmount();
STAmount const data = funcParam.getFieldAmount();
Serializer s;
data.add(s);
auto const& serialized = s.getData();
@@ -104,7 +104,7 @@ getFieldBytesFromSTData(xrpl::STData const& funcParam, std::uint32_t stTypeId)
case STI_NUMBER: {
if (funcParam.getInnerSType() != STI_NUMBER)
return Unexpected(HostFunctionError::INVALID_PARAMS);
STNumber data = funcParam.getFieldNumber();
STNumber const data = funcParam.getFieldNumber();
Serializer s;
data.add(s);
auto const& serialized = s.getData();
@@ -113,7 +113,7 @@ getFieldBytesFromSTData(xrpl::STData const& funcParam, std::uint32_t stTypeId)
case STI_ISSUE: {
if (funcParam.getInnerSType() != STI_ISSUE)
return Unexpected(HostFunctionError::INVALID_PARAMS);
STIssue data = funcParam.getFieldIssue();
STIssue const data = funcParam.getFieldIssue();
Serializer s;
data.add(s);
auto const& serialized = s.getData();
@@ -122,7 +122,7 @@ getFieldBytesFromSTData(xrpl::STData const& funcParam, std::uint32_t stTypeId)
case STI_CURRENCY: {
if (funcParam.getInnerSType() != STI_CURRENCY)
return Unexpected(HostFunctionError::INVALID_PARAMS);
STCurrency data = funcParam.getFieldCurrency();
STCurrency const data = funcParam.getFieldCurrency();
Serializer s;
data.add(s);
auto const& serialized = s.getData();
@@ -198,12 +198,12 @@ getDataOrCache(ContractContext& contractCtx, AccountID const& account)
if (dataSle)
{
// Return the STJson from the SLE
STJson data = dataSle->getFieldJson(sfContractJson);
STJson const data = dataSle->getFieldJson(sfContractJson);
return {data.isObject(), data};
}
// Return New STJson if not found
STJson data;
STJson const data;
return {true, data};
}
@@ -231,7 +231,7 @@ setDataCache(
return HostFunctionError::INVALID_ACCOUNT;
}
uint32_t maxDataModifications = 1000u;
uint32_t const maxDataModifications = 1000u;
if (modified && dataMap.modifiedCount >= maxDataModifications)
{
@@ -243,7 +243,7 @@ setDataCache(
if (dataMap.find(account) == dataMap.end())
{
auto const& fees = contractCtx.applyCtx.view().fees();
STAmount bal = sleAccount->getFieldAmount(sfBalance);
STAmount const bal = sleAccount->getFieldAmount(sfBalance);
int64_t availableForReserves =
bal.xrp().drops() - fees.accountReserve(sleAccount->getFieldU32(sfOwnerCount)).drops();
@@ -465,7 +465,7 @@ ContractHostFunctionsImpl::setDataObjectField(
}
data.setObjectField(std::string(key), value);
if (HostFunctionError ret = setDataCache(contractCtx, account, data, j, true);
if (HostFunctionError const ret = setDataCache(contractCtx, account, data, j, true);
ret != HostFunctionError::SUCCESS)
{
JLOG(j.trace()) << "WasmTrace[" << contractId << "]: "
@@ -502,7 +502,7 @@ ContractHostFunctionsImpl::setDataNestedObjectField(
}
data.setNestedObjectField(std::string(key), std::string(nestedKey), value);
if (HostFunctionError ret = setDataCache(contractCtx, account, data, j, true);
if (HostFunctionError const ret = setDataCache(contractCtx, account, data, j, true);
ret != HostFunctionError::SUCCESS)
{
JLOG(j.trace()) << "WasmTrace[" << contractId << "]: "
@@ -761,7 +761,7 @@ ContractHostFunctionsImpl::setDataArrayElementField(
}
data.setArrayElementField(index, std::string(key), value);
if (HostFunctionError ret = setDataCache(contractCtx, account, data, j, true);
if (HostFunctionError const ret = setDataCache(contractCtx, account, data, j, true);
ret != HostFunctionError::SUCCESS)
{
JLOG(j.trace()) << "WasmTrace[" << contractId << "]: "
@@ -801,7 +801,7 @@ ContractHostFunctionsImpl::setDataNestedArrayElementField(
}
data.setNestedArrayElementField(std::string(key), index, std::string(nestedKey), value);
if (HostFunctionError ret = setDataCache(contractCtx, account, data, j, true);
if (HostFunctionError const ret = setDataCache(contractCtx, account, data, j, true);
ret != HostFunctionError::SUCCESS)
{
JLOG(j.trace()) << "WasmTrace[" << contractId << "]: "
@@ -956,22 +956,28 @@ ContractHostFunctionsImpl::emitBuiltTxn(std::uint32_t const& index)
return Unexpected(HostFunctionError::SUBMIT_TXN_FAILURE);
}
OpenView wholeBatchView(batch_view, contractCtx.applyCtx.openView());
auto applyOneTransaction =
[&app, &j, &parentBatchId, &wholeBatchView](std::shared_ptr<STTx const> const& tx) {
auto const pfResult =
preflight(app, wholeBatchView.rules(), parentBatchId, *tx, tapBATCH, j);
auto const ret = preclaim(pfResult, app, wholeBatchView);
JLOG(j.trace()) << "WasmTrace[" << parentBatchId << "]: " << tx->getTransactionID()
<< " " << transToken(ret.ter);
return ret;
};
// Use a persistent emit view that is seeded with the
// transactor's pending state changes (balances, consumed
// sequence, etc.) so that each emitted transaction validates
// against the full current state. A full apply() is used
// (matching the Batch inner-transaction pattern) so that
// sequence numbers, balances, owner counts, and all other
// ledger state are properly updated between successive emits.
auto& emitView = contractCtx.getEmitView();
auto const stx = tpTrans->getSTransaction();
auto const result = applyOneTransaction(stx);
if (isTesSuccess(result.ter))
OpenView perTxView(batch_view, emitView);
auto const ret = apply(app, perTxView, parentBatchId, *stx, tapBATCH, j);
JLOG(j.trace()) << "WasmTrace[" << parentBatchId << "]: " << stx->getTransactionID() << " "
<< transToken(ret.ter);
if (ret.applied && (isTesSuccess(ret.ter) || isTecClaim(ret.ter)))
{
perTxView.apply(emitView);
contractCtx.result.emittedTxns.push(stx);
return TERtoInt(result.ter);
}
return TERtoInt(ret.ter);
}
catch (std::exception const& e)
{
@@ -1005,23 +1011,25 @@ ContractHostFunctionsImpl::emitTxn(std::shared_ptr<STTx const> const& stxPtr)
if (tpTrans->getStatus() != NEW)
return Unexpected(HostFunctionError::SUBMIT_TXN_FAILURE);
OpenView wholeBatchView(batch_view, contractCtx.applyCtx.openView());
// Use a persistent emit view seeded with the transactor's
// pending state, and do a full apply() for each emission
// (see emitBuiltTxn for detailed rationale).
auto& emitView = contractCtx.getEmitView();
auto const parentBatchId = parentTx.getTransactionID();
auto applyOneTransaction =
[&app, &j, &parentBatchId, &wholeBatchView](std::shared_ptr<STTx const> const& tx) {
auto const pfResult =
preflight(app, wholeBatchView.rules(), parentBatchId, *tx, tapBATCH, j);
auto const ret = preclaim(pfResult, app, wholeBatchView);
JLOG(j.trace()) << "WasmTrace[" << parentBatchId << "]: " << tx->getTransactionID()
<< " " << transToken(ret.ter);
return ret;
};
auto const stx = tpTrans->getSTransaction();
auto const result = applyOneTransaction(stx);
if (isTesSuccess(result.ter))
OpenView perTxView(batch_view, emitView);
auto const ret = apply(app, perTxView, parentBatchId, *stx, tapBATCH, j);
JLOG(j.trace()) << "WasmTrace[" << parentBatchId << "]: " << stx->getTransactionID() << " "
<< transToken(ret.ter);
if (ret.applied && (isTesSuccess(ret.ter) || isTecClaim(ret.ter)))
{
perTxView.apply(emitView);
contractCtx.result.emittedTxns.push(stx);
return TERtoInt(result.ter);
}
return TERtoInt(ret.ter);
}
catch (std::exception const& e)
{

View File

@@ -68,7 +68,11 @@ struct FeeSetup
/* (Remember to update the example cfg files when changing any of these
* values.) */
/** Convert to a Fees object for use with Ledger construction. */
/** Convert to a Fees object for use with Ledger construction.
Extension fees (extensionComputeLimit, extensionSizeLimit, gasPrice)
are intentionally NOT set here. They start at 0 and are activated
through fee voting on the first flag ledger, or via the genesis
ledger SLE when featureSmartEscrow is in the initial amendments. */
Fees
toFees() const
{
@@ -76,9 +80,9 @@ struct FeeSetup
f.base = reference_fee;
f.reserve = account_reserve;
f.increment = owner_reserve;
f.extensionComputeLimit = extension_compute_limit;
f.extensionSizeLimit = extension_size_limit;
f.gasPrice = gas_price;
f.extensionComputeLimit = 0;
f.extensionSizeLimit = 0;
f.gasPrice = 0;
return f;
}
};

View File

@@ -66,7 +66,7 @@ doContractInfo(RPC::JsonContext& context)
RPC::inject_error(rpcACT_MALFORMED, result);
return result;
}
auto const caID{std::move(caid.value())};
auto const caID{caid.value()};
auto const caSle = ledger->read(keylet::account(caID));
if (!caSle)
{

View File

@@ -883,7 +883,7 @@ struct LedgerEntry
Json::Value
doLedgerEntry(RPC::JsonContext& context)
{
static LedgerEntry ledgerEntryParsers[] = {
static LedgerEntry const ledgerEntryParsers[] = {
#pragma push_macro("LEDGER_ENTRY")
#undef LEDGER_ENTRY