Reserve field codes for Hooks:

In order to preserve the Hooks ABI, it is important that field
values used for hooks be stable going forward.

This commit reserves the required codes so that they will not
be repurposed before Hooks can be proposed for inclusion in
the codebase.
This commit is contained in:
Richard Holland
2022-01-31 10:23:21 +00:00
committed by Nik Bougalis
parent b65e279db6
commit a07a729e3d
4 changed files with 275 additions and 0 deletions

View File

@@ -891,6 +891,7 @@ if (tests)
src/test/protocol/InnerObjectFormats_test.cpp
src/test/protocol/Issue_test.cpp
src/test/protocol/KnownFormatToGRPC_test.cpp
src/test/protocol/Hooks_test.cpp
src/test/protocol/PublicKey_test.cpp
src/test/protocol/Quality_test.cpp
src/test/protocol/STAccount_test.cpp

View File

@@ -341,6 +341,7 @@ extern SF_UINT8 const sfMethod;
extern SF_UINT8 const sfTransactionResult;
extern SF_UINT8 const sfTickSize;
extern SF_UINT8 const sfUNLModifyDisabling;
extern SF_UINT8 const sfHookResult;
// 16-bit integers
extern SF_UINT16 const sfLedgerEntryType;
@@ -349,6 +350,10 @@ extern SF_UINT16 const sfSignerWeight;
// 16-bit integers (uncommon)
extern SF_UINT16 const sfVersion;
extern SF_UINT16 const sfHookStateChangeCount;
extern SF_UINT16 const sfHookEmitCount;
extern SF_UINT16 const sfHookExecutionIndex;
extern SF_UINT16 const sfHookApiVersion;
// 32-bit integers (common)
extern SF_UINT32 const sfFlags;
@@ -392,6 +397,8 @@ extern SF_UINT32 const sfSignerListID;
extern SF_UINT32 const sfSettleDelay;
extern SF_UINT32 const sfTicketCount;
extern SF_UINT32 const sfTicketSequence;
extern SF_UINT32 const sfHookStateCount;
extern SF_UINT32 const sfEmitGeneration;
// 64-bit integers
extern SF_UINT64 const sfIndexNext;
@@ -405,6 +412,11 @@ extern SF_UINT64 const sfHighNode;
extern SF_UINT64 const sfDestinationNode;
extern SF_UINT64 const sfCookie;
extern SF_UINT64 const sfServerVersion;
extern SF_UINT64 const sfHookOn;
extern SF_UINT64 const sfHookInstructionCount;
extern SF_UINT64 const sfEmitBurden;
extern SF_UINT64 const sfHookReturnCode;
extern SF_UINT64 const sfReferenceCount;
// 128-bit
extern SF_HASH128 const sfEmailHash;
@@ -425,6 +437,9 @@ extern SF_HASH256 const sfLedgerIndex;
extern SF_HASH256 const sfWalletLocator;
extern SF_HASH256 const sfRootIndex;
extern SF_HASH256 const sfAccountTxnID;
extern SF_HASH256 const sfEmitParentTxnID;
extern SF_HASH256 const sfEmitNonce;
extern SF_HASH256 const sfEmitHookHash;
// 256-bit (uncommon)
extern SF_HASH256 const sfBookDirectory;
@@ -436,6 +451,10 @@ extern SF_HASH256 const sfChannel;
extern SF_HASH256 const sfConsensusHash;
extern SF_HASH256 const sfCheckID;
extern SF_HASH256 const sfValidatedHash;
extern SF_HASH256 const sfHookStateKey;
extern SF_HASH256 const sfHookHash;
extern SF_HASH256 const sfHookNamespace;
extern SF_HASH256 const sfHookSetTxnID;
// currency amount (common)
extern SF_AMOUNT const sfAmount;
@@ -476,6 +495,10 @@ extern SF_VL const sfMasterSignature;
extern SF_VL const sfUNLModifyValidator;
extern SF_VL const sfValidatorToDisable;
extern SF_VL const sfValidatorToReEnable;
extern SF_VL const sfHookStateData;
extern SF_VL const sfHookReturnString;
extern SF_VL const sfHookParameterName;
extern SF_VL const sfHookParameterValue;
// account
extern SF_ACCOUNT const sfAccount;
@@ -486,6 +509,10 @@ extern SF_ACCOUNT const sfAuthorize;
extern SF_ACCOUNT const sfUnauthorize;
extern SF_ACCOUNT const sfTarget;
extern SF_ACCOUNT const sfRegularKey;
extern SF_ACCOUNT const sfEmitCallback;
// account (uncommon)
extern SF_ACCOUNT const sfHookAccount;
// path set
extern SField const sfPaths;
@@ -510,6 +537,11 @@ extern SField const sfSignerEntry;
extern SField const sfSigner;
extern SField const sfMajority;
extern SField const sfDisabledValidator;
extern SField const sfEmittedTxn;
extern SField const sfHook;
extern SField const sfHookDefinition;
extern SField const sfHookParameter;
extern SField const sfHookGrant;
// array of objects
// ARRAY/1 is reserved for end of array
@@ -523,6 +555,13 @@ extern SField const sfAffectedNodes;
extern SField const sfMemos;
extern SField const sfMajorities;
extern SField const sfDisabledValidators;
extern SField const sfEmitDetails;
extern SField const sfHookExecutions;
extern SField const sfHookExecution;
extern SField const sfHookParameters;
extern SField const sfHooks;
extern SField const sfHookGrants;
//------------------------------------------------------------------------------
} // namespace ripple

View File

@@ -88,6 +88,7 @@ CONSTRUCT_TYPED_SFIELD(sfTransactionResult, "TransactionResult", UINT8,
// 8-bit integers (uncommon)
CONSTRUCT_TYPED_SFIELD(sfTickSize, "TickSize", UINT8, 16);
CONSTRUCT_TYPED_SFIELD(sfUNLModifyDisabling, "UNLModifyDisabling", UINT8, 17);
CONSTRUCT_TYPED_SFIELD(sfHookResult, "HookResult", UINT8, 18);
// 16-bit integers
CONSTRUCT_TYPED_SFIELD(sfLedgerEntryType, "LedgerEntryType", UINT16, 1, SField::sMD_Never);
@@ -96,6 +97,10 @@ CONSTRUCT_TYPED_SFIELD(sfSignerWeight, "SignerWeight", UINT16,
// 16-bit integers (uncommon)
CONSTRUCT_TYPED_SFIELD(sfVersion, "Version", UINT16, 16);
CONSTRUCT_TYPED_SFIELD(sfHookStateChangeCount, "HookStateChangeCount", UINT16, 17);
CONSTRUCT_TYPED_SFIELD(sfHookEmitCount, "HookEmitCount", UINT16, 18);
CONSTRUCT_TYPED_SFIELD(sfHookExecutionIndex, "HookExecutionIndex", UINT16, 19);
CONSTRUCT_TYPED_SFIELD(sfHookApiVersion, "HookApiVersion", UINT16, 20);
// 32-bit integers (common)
CONSTRUCT_TYPED_SFIELD(sfFlags, "Flags", UINT32, 2);
@@ -139,6 +144,8 @@ CONSTRUCT_TYPED_SFIELD(sfSignerListID, "SignerListID", UINT32,
CONSTRUCT_TYPED_SFIELD(sfSettleDelay, "SettleDelay", UINT32, 39);
CONSTRUCT_TYPED_SFIELD(sfTicketCount, "TicketCount", UINT32, 40);
CONSTRUCT_TYPED_SFIELD(sfTicketSequence, "TicketSequence", UINT32, 41);
CONSTRUCT_TYPED_SFIELD(sfHookStateCount, "HookStateCount", UINT32, 45);
CONSTRUCT_TYPED_SFIELD(sfEmitGeneration, "EmitGeneration", UINT32, 46);
// 64-bit integers
CONSTRUCT_TYPED_SFIELD(sfIndexNext, "IndexNext", UINT64, 1);
@@ -152,6 +159,11 @@ CONSTRUCT_TYPED_SFIELD(sfHighNode, "HighNode", UINT64,
CONSTRUCT_TYPED_SFIELD(sfDestinationNode, "DestinationNode", UINT64, 9);
CONSTRUCT_TYPED_SFIELD(sfCookie, "Cookie", UINT64, 10);
CONSTRUCT_TYPED_SFIELD(sfServerVersion, "ServerVersion", UINT64, 11);
CONSTRUCT_TYPED_SFIELD(sfEmitBurden, "EmitBurden", UINT64, 13);
CONSTRUCT_TYPED_SFIELD(sfHookOn, "HookOn", UINT64, 16);
CONSTRUCT_TYPED_SFIELD(sfHookInstructionCount, "HookInstructionCount", UINT64, 17);
CONSTRUCT_TYPED_SFIELD(sfHookReturnCode, "HookReturnCode", UINT64, 18);
CONSTRUCT_TYPED_SFIELD(sfReferenceCount, "ReferenceCount", UINT64, 19);
// 128-bit
CONSTRUCT_TYPED_SFIELD(sfEmailHash, "EmailHash", HASH128, 1);
@@ -172,6 +184,9 @@ CONSTRUCT_TYPED_SFIELD(sfLedgerIndex, "LedgerIndex", HASH256,
CONSTRUCT_TYPED_SFIELD(sfWalletLocator, "WalletLocator", HASH256, 7);
CONSTRUCT_TYPED_SFIELD(sfRootIndex, "RootIndex", HASH256, 8, SField::sMD_Always);
CONSTRUCT_TYPED_SFIELD(sfAccountTxnID, "AccountTxnID", HASH256, 9);
CONSTRUCT_TYPED_SFIELD(sfEmitParentTxnID, "EmitParentTxnID", HASH256, 11);
CONSTRUCT_TYPED_SFIELD(sfEmitNonce, "EmitNonce", HASH256, 12);
CONSTRUCT_TYPED_SFIELD(sfEmitHookHash, "EmitHookHash", HASH256, 13);
// 256-bit (uncommon)
CONSTRUCT_TYPED_SFIELD(sfBookDirectory, "BookDirectory", HASH256, 16);
@@ -184,6 +199,10 @@ CONSTRUCT_TYPED_SFIELD(sfChannel, "Channel", HASH256,
CONSTRUCT_TYPED_SFIELD(sfConsensusHash, "ConsensusHash", HASH256, 23);
CONSTRUCT_TYPED_SFIELD(sfCheckID, "CheckID", HASH256, 24);
CONSTRUCT_TYPED_SFIELD(sfValidatedHash, "ValidatedHash", HASH256, 25);
CONSTRUCT_TYPED_SFIELD(sfHookStateKey, "HookStateKey", HASH256, 30);
CONSTRUCT_TYPED_SFIELD(sfHookHash, "HookHash", HASH256, 31);
CONSTRUCT_TYPED_SFIELD(sfHookNamespace, "HookNamespace", HASH256, 32);
CONSTRUCT_TYPED_SFIELD(sfHookSetTxnID, "HookSetTxnID", HASH256, 33);
// currency amount (common)
CONSTRUCT_TYPED_SFIELD(sfAmount, "Amount", AMOUNT, 1);
@@ -225,6 +244,10 @@ CONSTRUCT_TYPED_SFIELD(sfMasterSignature, "MasterSignature", VL,
CONSTRUCT_TYPED_SFIELD(sfUNLModifyValidator, "UNLModifyValidator", VL, 19);
CONSTRUCT_TYPED_SFIELD(sfValidatorToDisable, "ValidatorToDisable", VL, 20);
CONSTRUCT_TYPED_SFIELD(sfValidatorToReEnable, "ValidatorToReEnable", VL, 21);
CONSTRUCT_TYPED_SFIELD(sfHookStateData, "HookStateData", VL, 22);
CONSTRUCT_TYPED_SFIELD(sfHookReturnString, "HookReturnString", VL, 23);
CONSTRUCT_TYPED_SFIELD(sfHookParameterName, "HookParameterName", VL, 24);
CONSTRUCT_TYPED_SFIELD(sfHookParameterValue, "HookParameterValue", VL, 25);
// account
CONSTRUCT_TYPED_SFIELD(sfAccount, "Account", ACCOUNT, 1);
@@ -235,6 +258,10 @@ CONSTRUCT_TYPED_SFIELD(sfAuthorize, "Authorize", ACCOUNT,
CONSTRUCT_TYPED_SFIELD(sfUnauthorize, "Unauthorize", ACCOUNT, 6);
// 7 is currently unused
CONSTRUCT_TYPED_SFIELD(sfRegularKey, "RegularKey", ACCOUNT, 8);
CONSTRUCT_TYPED_SFIELD(sfEmitCallback, "EmitCallback", ACCOUNT, 10);
// account (uncommon)
CONSTRUCT_TYPED_SFIELD(sfHookAccount, "HookAccount", ACCOUNT, 16);
// vector of 256-bit
CONSTRUCT_TYPED_SFIELD(sfIndexes, "Indexes", VECTOR256, 1, SField::sMD_Never);
@@ -256,12 +283,19 @@ CONSTRUCT_UNTYPED_SFIELD(sfNewFields, "NewFields", OBJECT,
CONSTRUCT_UNTYPED_SFIELD(sfTemplateEntry, "TemplateEntry", OBJECT, 9);
CONSTRUCT_UNTYPED_SFIELD(sfMemo, "Memo", OBJECT, 10);
CONSTRUCT_UNTYPED_SFIELD(sfSignerEntry, "SignerEntry", OBJECT, 11);
CONSTRUCT_UNTYPED_SFIELD(sfEmitDetails, "EmitDetails", OBJECT, 13);
CONSTRUCT_UNTYPED_SFIELD(sfHook, "Hook", OBJECT, 14);
// inner object (uncommon)
CONSTRUCT_UNTYPED_SFIELD(sfSigner, "Signer", OBJECT, 16);
// 17 has not been used yet
CONSTRUCT_UNTYPED_SFIELD(sfMajority, "Majority", OBJECT, 18);
CONSTRUCT_UNTYPED_SFIELD(sfDisabledValidator, "DisabledValidator", OBJECT, 19);
CONSTRUCT_UNTYPED_SFIELD(sfEmittedTxn, "EmittedTxn", OBJECT, 20);
CONSTRUCT_UNTYPED_SFIELD(sfHookExecution, "HookExecution", OBJECT, 21);
CONSTRUCT_UNTYPED_SFIELD(sfHookDefinition, "HookDefinition", OBJECT, 22);
CONSTRUCT_UNTYPED_SFIELD(sfHookParameter, "HookParameter", OBJECT, 23);
CONSTRUCT_UNTYPED_SFIELD(sfHookGrant, "HookGrant", OBJECT, 24);
// array of objects
// ARRAY/1 is reserved for end of array
@@ -273,10 +307,14 @@ CONSTRUCT_UNTYPED_SFIELD(sfNecessary, "Necessary", ARRAY,
CONSTRUCT_UNTYPED_SFIELD(sfSufficient, "Sufficient", ARRAY, 7);
CONSTRUCT_UNTYPED_SFIELD(sfAffectedNodes, "AffectedNodes", ARRAY, 8);
CONSTRUCT_UNTYPED_SFIELD(sfMemos, "Memos", ARRAY, 9);
CONSTRUCT_UNTYPED_SFIELD(sfHooks, "Hooks", ARRAY, 11);
// array of objects (uncommon)
CONSTRUCT_UNTYPED_SFIELD(sfMajorities, "Majorities", ARRAY, 16);
CONSTRUCT_UNTYPED_SFIELD(sfDisabledValidators, "DisabledValidators", ARRAY, 17);
CONSTRUCT_UNTYPED_SFIELD(sfHookExecutions, "HookExecutions", ARRAY, 18);
CONSTRUCT_UNTYPED_SFIELD(sfHookParameters, "HookParameters", ARRAY, 19);
CONSTRUCT_UNTYPED_SFIELD(sfHookGrants, "HookGrants", ARRAY, 20);
// clang-format on

View File

@@ -0,0 +1,197 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012-2017 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 <ripple/protocol/Feature.h>
#include <ripple/protocol/jss.h>
#include <functional>
#include <test/jtx.h>
#include <vector>
namespace ripple {
class Hooks_test : public beast::unit_test::suite
{
/**
* This unit test was requested here:
* https://github.com/ripple/rippled/pull/4089#issuecomment-1050274539
* These are tests that exercise facilities that are reserved for when Hooks
* is merged in the future.
**/
void
testHookFields()
{
testcase("Test Hooks fields");
using namespace test::jtx;
std::vector<std::reference_wrapper<SField const>> fields_to_test = {
sfHookResult,
sfHookStateChangeCount,
sfHookEmitCount,
sfHookExecutionIndex,
sfHookApiVersion,
sfHookStateCount,
sfEmitGeneration,
sfHookOn,
sfHookInstructionCount,
sfEmitBurden,
sfHookReturnCode,
sfReferenceCount,
sfEmitParentTxnID,
sfEmitNonce,
sfEmitHookHash,
sfHookStateKey,
sfHookHash,
sfHookNamespace,
sfHookSetTxnID,
sfHookStateData,
sfHookReturnString,
sfHookParameterName,
sfHookParameterValue,
sfEmitCallback,
sfHookAccount,
sfEmittedTxn,
sfHook,
sfHookDefinition,
sfHookParameter,
sfHookGrant,
sfEmitDetails,
sfHookExecutions,
sfHookExecution,
sfHookParameters,
sfHooks,
sfHookGrants};
for (auto const& rf : fields_to_test)
{
SField const& f = rf.get();
STObject dummy{sfGeneric};
BEAST_EXPECT(!dummy.isFieldPresent(f));
switch (f.fieldType)
{
case STI_UINT8: {
dummy.setFieldU8(f, 0);
BEAST_EXPECT(dummy.getFieldU8(f) == 0);
dummy.setFieldU8(f, 255);
BEAST_EXPECT(dummy.getFieldU8(f) == 255);
BEAST_EXPECT(dummy.isFieldPresent(f));
break;
}
case STI_UINT16: {
dummy.setFieldU16(f, 0);
BEAST_EXPECT(dummy.getFieldU16(f) == 0);
dummy.setFieldU16(f, 0xFFFFU);
BEAST_EXPECT(dummy.getFieldU16(f) == 0xFFFFU);
BEAST_EXPECT(dummy.isFieldPresent(f));
break;
}
case STI_UINT32: {
dummy.setFieldU32(f, 0);
BEAST_EXPECT(dummy.getFieldU32(f) == 0);
dummy.setFieldU32(f, 0xFFFFFFFFU);
BEAST_EXPECT(dummy.getFieldU32(f) == 0xFFFFFFFFU);
BEAST_EXPECT(dummy.isFieldPresent(f));
break;
}
case STI_UINT64: {
dummy.setFieldU64(f, 0);
BEAST_EXPECT(dummy.getFieldU64(f) == 0);
dummy.setFieldU64(f, 0xFFFFFFFFFFFFFFFFU);
BEAST_EXPECT(dummy.getFieldU64(f) == 0xFFFFFFFFFFFFFFFFU);
BEAST_EXPECT(dummy.isFieldPresent(f));
break;
}
case STI_HASH256: {
uint256 u = uint256::fromVoid(
"DEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBE"
"EFDEADBEEF");
dummy.setFieldH256(f, u);
BEAST_EXPECT(dummy.getFieldH256(f) == u);
BEAST_EXPECT(dummy.isFieldPresent(f));
break;
}
case STI_VL: {
std::vector<uint8_t> v{1, 2, 3};
dummy.setFieldVL(f, v);
BEAST_EXPECT(dummy.getFieldVL(f) == v);
BEAST_EXPECT(dummy.isFieldPresent(f));
break;
}
case STI_ACCOUNT: {
AccountID id = *parseBase58<AccountID>(
"rwfSjJNK2YQuN64bSWn7T2eY9FJAyAPYJT");
dummy.setAccountID(f, id);
BEAST_EXPECT(dummy.getAccountID(f) == id);
BEAST_EXPECT(dummy.isFieldPresent(f));
break;
}
case STI_OBJECT: {
dummy.emplace_back(STObject{f});
BEAST_EXPECT(dummy.getField(f).getFName() == f);
BEAST_EXPECT(dummy.isFieldPresent(f));
break;
}
case STI_ARRAY: {
STArray dummy2{f, 2};
dummy2.push_back(STObject{sfGeneric});
dummy2.push_back(STObject{sfGeneric});
dummy.setFieldArray(f, dummy2);
BEAST_EXPECT(dummy.getFieldArray(f) == dummy2);
BEAST_EXPECT(dummy.isFieldPresent(f));
break;
}
default:
BEAST_EXPECT(false);
}
}
}
public:
void
run() override
{
using namespace test::jtx;
testHookFields();
}
};
BEAST_DEFINE_TESTSUITE(Hooks, protocol, ripple);
} // namespace ripple