diff --git a/Builds/CMake/RippledCore.cmake b/Builds/CMake/RippledCore.cmake index ec9e23663fd..350917276d6 100644 --- a/Builds/CMake/RippledCore.cmake +++ b/Builds/CMake/RippledCore.cmake @@ -641,7 +641,6 @@ target_sources (rippled PRIVATE src/ripple/rpc/handlers/WalletPropose.cpp src/ripple/rpc/impl/DeliveredAmount.cpp src/ripple/rpc/impl/Handler.cpp - src/ripple/rpc/impl/GRPCHelpers.cpp src/ripple/rpc/impl/LegacyPathFind.cpp src/ripple/rpc/impl/RPCHandler.cpp src/ripple/rpc/impl/RPCHelpers.cpp @@ -911,7 +910,6 @@ if (tests) src/test/protocol/BuildInfo_test.cpp 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 @@ -946,7 +944,6 @@ if (tests) src/test/rpc/DepositAuthorized_test.cpp src/test/rpc/DeliveredAmount_test.cpp src/test/rpc/Feature_test.cpp - src/test/rpc/Fee_test.cpp src/test/rpc/GatewayBalances_test.cpp src/test/rpc/GetCounts_test.cpp src/test/rpc/JSONRPC_test.cpp @@ -969,12 +966,10 @@ if (tests) src/test/rpc/ServerInfo_test.cpp src/test/rpc/ShardArchiveHandler_test.cpp src/test/rpc/Status_test.cpp - src/test/rpc/Submit_test.cpp src/test/rpc/Subscribe_test.cpp src/test/rpc/Transaction_test.cpp src/test/rpc/TransactionEntry_test.cpp src/test/rpc/TransactionHistory_test.cpp - src/test/rpc/Tx_test.cpp src/test/rpc/ValidatorInfo_test.cpp src/test/rpc/ValidatorRPC_test.cpp src/test/rpc/Version_test.cpp diff --git a/Builds/levelization/results/ordering.txt b/Builds/levelization/results/ordering.txt index ed6b4e57c3e..401040fc2d7 100644 --- a/Builds/levelization/results/ordering.txt +++ b/Builds/levelization/results/ordering.txt @@ -113,7 +113,6 @@ test.consensus > ripple.basics test.consensus > ripple.beast test.consensus > ripple.consensus test.consensus > ripple.ledger -test.consensus > ripple.rpc test.consensus > test.csf test.consensus > test.toplevel test.consensus > test.unit_test diff --git a/cfg/rippled-example.cfg b/cfg/rippled-example.cfg index 83a9353aa4d..fda1671e416 100644 --- a/cfg/rippled-example.cfg +++ b/cfg/rippled-example.cfg @@ -1629,10 +1629,10 @@ ip = 127.0.0.1 admin = 127.0.0.1 protocol = ws -#[port_grpc] -#port = 50051 -#ip = 0.0.0.0 -#secure_gateway = 127.0.0.1 +[port_grpc] +port = 50051 +ip = 127.0.0.1 +secure_gateway = 127.0.0.1 #[port_ws_public] #port = 6005 diff --git a/src/ripple/app/main/GRPCServer.cpp b/src/ripple/app/main/GRPCServer.cpp index aef2612c0ef..fdef8c1cec8 100644 --- a/src/ripple/app/main/GRPCServer.cpp +++ b/src/ripple/app/main/GRPCServer.cpp @@ -590,94 +590,6 @@ GRPCServerImpl::setupListeners() requests.push_back(std::move(callData)); }; - { - using cd = CallData< - org::xrpl::rpc::v1::GetFeeRequest, - org::xrpl::rpc::v1::GetFeeResponse>; - - addToRequests(std::make_shared( - service_, - *cq_, - app_, - &org::xrpl::rpc::v1::XRPLedgerAPIService::AsyncService:: - RequestGetFee, - doFeeGrpc, - &org::xrpl::rpc::v1::XRPLedgerAPIService::Stub::GetFee, - RPC::NEEDS_CURRENT_LEDGER, - Resource::feeReferenceRPC, - secureGatewayIPs_)); - } - { - using cd = CallData< - org::xrpl::rpc::v1::GetAccountInfoRequest, - org::xrpl::rpc::v1::GetAccountInfoResponse>; - - addToRequests(std::make_shared( - service_, - *cq_, - app_, - &org::xrpl::rpc::v1::XRPLedgerAPIService::AsyncService:: - RequestGetAccountInfo, - doAccountInfoGrpc, - &org::xrpl::rpc::v1::XRPLedgerAPIService::Stub::GetAccountInfo, - RPC::NO_CONDITION, - Resource::feeReferenceRPC, - secureGatewayIPs_)); - } - { - using cd = CallData< - org::xrpl::rpc::v1::GetTransactionRequest, - org::xrpl::rpc::v1::GetTransactionResponse>; - - addToRequests(std::make_shared( - service_, - *cq_, - app_, - &org::xrpl::rpc::v1::XRPLedgerAPIService::AsyncService:: - RequestGetTransaction, - doTxGrpc, - &org::xrpl::rpc::v1::XRPLedgerAPIService::Stub::GetTransaction, - RPC::NEEDS_NETWORK_CONNECTION, - Resource::feeReferenceRPC, - secureGatewayIPs_)); - } - { - using cd = CallData< - org::xrpl::rpc::v1::SubmitTransactionRequest, - org::xrpl::rpc::v1::SubmitTransactionResponse>; - - addToRequests(std::make_shared( - service_, - *cq_, - app_, - &org::xrpl::rpc::v1::XRPLedgerAPIService::AsyncService:: - RequestSubmitTransaction, - doSubmitGrpc, - &org::xrpl::rpc::v1::XRPLedgerAPIService::Stub::SubmitTransaction, - RPC::NEEDS_CURRENT_LEDGER, - Resource::feeMediumBurdenRPC, - secureGatewayIPs_)); - } - - { - using cd = CallData< - org::xrpl::rpc::v1::GetAccountTransactionHistoryRequest, - org::xrpl::rpc::v1::GetAccountTransactionHistoryResponse>; - - addToRequests(std::make_shared( - service_, - *cq_, - app_, - &org::xrpl::rpc::v1::XRPLedgerAPIService::AsyncService:: - RequestGetAccountTransactionHistory, - doAccountTxGrpc, - &org::xrpl::rpc::v1::XRPLedgerAPIService::Stub:: - GetAccountTransactionHistory, - RPC::NO_CONDITION, - Resource::feeMediumBurdenRPC, - secureGatewayIPs_)); - } - { using cd = CallData< org::xrpl::rpc::v1::GetLedgerRequest, diff --git a/src/ripple/app/reporting/P2pProxy.h b/src/ripple/app/reporting/P2pProxy.h index a3984018ee2..92cc508a1a0 100644 --- a/src/ripple/app/reporting/P2pProxy.h +++ b/src/ripple/app/reporting/P2pProxy.h @@ -48,8 +48,6 @@ needCurrentOrClosed(Request& request) { // These are the only gRPC requests that specify a ledger if constexpr ( - std::is_same:: - value || std::is_same::value || std::is_same:: value || diff --git a/src/ripple/proto/org/xrpl/rpc/v1/account.proto b/src/ripple/proto/org/xrpl/rpc/v1/account.proto deleted file mode 100644 index 40e9a7a4f43..00000000000 --- a/src/ripple/proto/org/xrpl/rpc/v1/account.proto +++ /dev/null @@ -1,14 +0,0 @@ -syntax = "proto3"; - -package org.xrpl.rpc.v1; -option java_package = "org.xrpl.rpc.v1"; -option java_multiple_files = true; - -// A representation of an account address -// Next field: 2 -message AccountAddress -{ - // base58 encoding of an account - string address = 1; -} - diff --git a/src/ripple/proto/org/xrpl/rpc/v1/amount.proto b/src/ripple/proto/org/xrpl/rpc/v1/amount.proto deleted file mode 100644 index 64ea2f6416f..00000000000 --- a/src/ripple/proto/org/xrpl/rpc/v1/amount.proto +++ /dev/null @@ -1,48 +0,0 @@ -syntax = "proto3"; - -package org.xrpl.rpc.v1; -option java_package = "org.xrpl.rpc.v1"; -option java_multiple_files = true; - -import "org/xrpl/rpc/v1/account.proto"; - -// Next field: 3 -message CurrencyAmount -{ - oneof amount - { - XRPDropsAmount xrp_amount = 1; - IssuedCurrencyAmount issued_currency_amount = 2; - } -} - -// A representation of an amount of XRP. -// Next field: 2 -message XRPDropsAmount -{ - uint64 drops = 1 [jstype=JS_STRING]; -} - -// A representation of an amount of issued currency. -// Next field: 4 -message IssuedCurrencyAmount -{ - // The currency used to value the amount. - Currency currency = 1; - - // The value of the amount. 8 bytes - string value = 2; - - // Unique account address of the entity issuing the currency. - AccountAddress issuer = 3; -} - -// Next field: 3 -message Currency -{ - // 3 character ASCII code - string name = 1; - - // 160 bit currency code. 20 bytes - bytes code = 2; -} diff --git a/src/ripple/proto/org/xrpl/rpc/v1/common.proto b/src/ripple/proto/org/xrpl/rpc/v1/common.proto deleted file mode 100644 index fd514cbacee..00000000000 --- a/src/ripple/proto/org/xrpl/rpc/v1/common.proto +++ /dev/null @@ -1,606 +0,0 @@ -syntax = "proto3"; - -package org.xrpl.rpc.v1; -option java_package = "org.xrpl.rpc.v1"; -option java_multiple_files = true; - -import "org/xrpl/rpc/v1/amount.proto"; -import "org/xrpl/rpc/v1/account.proto"; - -// These fields are used in many different message types. They can be present -// in one or more transactions, as well as metadata of one or more transactions. -// Each is defined as its own message type with a single field "value", to -// ensure the field is the correct type everywhere it's used - - -// *** Messages wrapping uint32 *** - -message BurnedNFTokens -{ - uint32 value = 1; -} - -message CancelAfter -{ - // time in seconds since Ripple epoch - uint32 value = 1; -} - -message ClearFlag -{ - uint32 value = 1; -} - -message CloseTime -{ - // time in seconds since Ripple epoch - uint32 value = 1; -} - -message Date -{ - // time in seconds since Ripple epoch - uint32 value = 1; -} - -message DestinationTag -{ - uint32 value = 1; -} - -message Expiration -{ - // time in seconds since Ripple epoch - uint32 value = 1; -} - -message FinishAfter -{ - // time in seconds since Ripple epoch - uint32 value = 1; -} - -message Flags -{ - uint32 value = 1; -} - -message HighQualityIn -{ - uint32 value = 1; -} - -message HighQualityOut -{ - uint32 value = 1; -} - -message FirstLedgerSequence -{ - uint32 value = 1; -} - -message LastLedgerSequence -{ - uint32 value = 1; -} - -message LowQualityIn -{ - uint32 value = 1; -} - -message LowQualityOut -{ - uint32 value = 1; -} - -message MintedNFTokens -{ - uint32 value = 1; -} - -message OfferSequence -{ - uint32 value = 1; -} - -message OwnerCount -{ - uint32 value = 1; -} - -message PreviousTransactionLedgerSequence -{ - uint32 value = 1; -} - -message QualityIn -{ - uint32 value = 1; -} - -message QualityOut -{ - uint32 value = 1; -} - -message ReferenceFeeUnits -{ - uint32 value = 1; -} - -message ReserveBase -{ - // in drops - uint32 value = 1; -} - -message ReserveIncrement -{ - // in drops - uint32 value = 1; -} - -message Sequence -{ - uint32 value = 1; -} - -message SetFlag -{ - uint32 value = 1; -} - -message SettleDelay -{ - uint32 value = 1; -} - -message SignerListID -{ - uint32 value = 1; -} - -message SignerQuorum -{ - uint32 value = 1; -} - -message SignerWeight -{ - // is actually uint16 - uint32 value = 1; -} - -message SourceTag -{ - uint32 value = 1; -} - -message TickSize -{ - // is actually uint8 - uint32 value = 1; -} - -message Ticket -{ - uint32 value = 1; -} - -message TicketCount -{ - uint32 value = 1; -} - -message TicketSequence -{ - uint32 value = 1; -} - -message NFTokenTaxon -{ - uint32 value = 1; -} - -message TransferFee -{ - // is actually uint16 - uint32 value = 1; -} - -message TransferRate -{ - uint32 value = 1; -} - - -// *** Messages wrapping uint64 *** - -message BaseFee -{ - // in drops - uint64 value = 1 [jstype=JS_STRING]; -} - -message BookNode -{ - uint64 value = 1 [jstype=JS_STRING]; -} - -message DestinationNode -{ - uint64 value = 1 [jstype=JS_STRING]; -} - -message HighNode -{ - uint64 value = 1 [jstype=JS_STRING]; -} - -message IndexNext -{ - uint64 value = 1 [jstype=JS_STRING]; -} - -message IndexPrevious -{ - uint64 value = 1 [jstype=JS_STRING]; -} - -message LowNode -{ - uint64 value = 1 [jstype=JS_STRING]; -} - -message NFTokenOfferNode -{ - uint64 value = 1 [jstype=JS_STRING]; -} - -message OwnerNode -{ - uint64 value = 1 [jstype=JS_STRING]; -} - - -// *** Messages wrapping 16 bytes *** - -message EmailHash -{ - bytes value = 1; -} - -message NFTokenID -{ - bytes value = 1; -} - - -// *** Messages wrapping 20 bytes *** - -message TakerGetsIssuer -{ - // 20 bytes - bytes value = 1; -} - -message TakerPaysIssuer -{ - // 20 bytes - bytes value = 1; -} - - -// *** Messages wrapping 32 bytes *** - -message AccountTransactionID -{ - // 32 bytes - bytes value = 1; -} - -message BookDirectory -{ - // 32 btes - bytes value = 1; -} - -message Channel -{ - // 32 bytes - bytes value = 1; -} - -message CheckID -{ - // 32 bytes - bytes value = 1; -} - -message Hash -{ - // 32 bytes - bytes value = 1; -} - -message Index -{ - // 32 bytes - bytes value = 1; -} - -message InvoiceID -{ - // 32 bytes - bytes value = 1; -} - -message NextPageMin -{ - // 32 bytes - bytes value = 1; -} - -message NFTokenBuyOffer -{ - // 32 bytes - bytes value = 1; -} - -message NFTokenSellOffer -{ - // 32 bytes - bytes value = 1; -} - -message PreviousPageMin -{ - // 32 bytes - bytes value = 1; -} - -message PreviousTransactionID -{ - // 32 bytes - bytes value = 1; -} - -message RootIndex -{ - // 32 bytes - bytes value = 1; -} - -message WalletLocator -{ - // 32 bytes - bytes value = 1; -} - - -// *** Messages wrapping variable length byte arrays *** - -message Condition -{ - bytes value = 1; -} - -message Fulfillment -{ - bytes value = 1; -} - -message MemoData -{ - bytes value = 1; -} - -message MemoFormat -{ - bytes value = 1; -} - -message MemoType -{ - bytes value = 1; -} - -message MessageKey -{ - bytes value = 1; -} - -message PublicKey -{ - bytes value = 1; -} - -message PaymentChannelSignature -{ - bytes value = 1; -} - -message SigningPublicKey -{ - bytes value = 1; -} - -message TransactionSignature -{ - bytes value = 1; -} - -message ValidatorToDisable -{ - bytes value = 1; -} - -message ValidatorToReEnable -{ - bytes value = 1; -} - -// *** Messages wrapping a Currency value *** -// -// TODO: if there's a V2 of the API, fix this misspelling. -message TakerGetsCurreny -{ - Currency value = 1; -} - -message TakerPaysCurrency -{ - Currency value = 1; -} - - -// *** Messages wrapping a CurrencyAmount *** - -message Amount -{ - // Note, CurrencyAmount is a oneof, that can represent an XRP drops amount - // or an Issued Currency amount. However, in some transaction types/ledger - // objects, this value can only be in drops. For instance, the Amount field - // of a Payment transaction can be specified in XRP drops or an Issued - // Currency amount, but the Amount field of a PaymentChannelClaim - // transaction can only be an XRP drops amount. - CurrencyAmount value = 1; -} - -message Balance -{ - CurrencyAmount value = 1; -} - -message NFTokenBrokerFee -{ - CurrencyAmount value = 1; -} - -message DeliverMin -{ - CurrencyAmount value = 1; -} - -message DeliveredAmount -{ - CurrencyAmount value = 1; -} - -message HighLimit -{ - CurrencyAmount value = 1; -} - -message LimitAmount -{ - CurrencyAmount value = 1; -} - -message LowLimit -{ - CurrencyAmount value = 1; -} - -message SendMax -{ - CurrencyAmount value = 1; -} - -message TakerGets -{ - CurrencyAmount value = 1; -} - -message TakerPays -{ - CurrencyAmount value = 1; -} - - -// *** Messages wrapping an AccountAddress *** - -message Account -{ - AccountAddress value = 1; -} - -message Authorize -{ - AccountAddress value = 1; -} - -message Destination -{ - AccountAddress value = 1; -} - -message Issuer -{ - AccountAddress value = 1; -} - -message NFTokenMinter -{ - AccountAddress value = 1; -} - -message Owner -{ - AccountAddress value = 1; -} - -message RegularKey -{ - AccountAddress value = 1; -} - -message Unauthorize -{ - AccountAddress value = 1; -} - - -// *** Messages wrapping a string *** - -message Domain -{ - string value = 1; -} - -message URI -{ - string value = 1; -} - - -// *** Aggregate type messages - -// Next field: 3 -message NFToken -{ - NFTokenID nftoken_id = 1; - - URI uri = 2; -} - -// Next field: 3 -message SignerEntry -{ - Account account = 1; - - SignerWeight signer_weight = 2; - - WalletLocator wallet_locator = 3; -} - -// Next field: 3 -message DisabledValidator -{ - PublicKey public_key = 1; - - FirstLedgerSequence ledger_sequence = 2; -} - diff --git a/src/ripple/proto/org/xrpl/rpc/v1/get_account_info.proto b/src/ripple/proto/org/xrpl/rpc/v1/get_account_info.proto deleted file mode 100644 index bc23a8c66d4..00000000000 --- a/src/ripple/proto/org/xrpl/rpc/v1/get_account_info.proto +++ /dev/null @@ -1,93 +0,0 @@ -syntax = "proto3"; - -package org.xrpl.rpc.v1; -option java_package = "org.xrpl.rpc.v1"; -option java_multiple_files = true; - -import "org/xrpl/rpc/v1/ledger_objects.proto"; -import "org/xrpl/rpc/v1/amount.proto"; -import "org/xrpl/rpc/v1/account.proto"; -import "org/xrpl/rpc/v1/ledger.proto"; -import "org/xrpl/rpc/v1/common.proto"; - -// A request to get info about an account. -// Next field: 6 -message GetAccountInfoRequest -{ - // The address to get info about. - AccountAddress account = 1; - - bool strict = 2; - - // Which ledger to use to retrieve data. - // If this field is not set, the server will use the open ledger. - // The open ledger includes data that is not validated or final. - // To retrieve the most up to date and validated data, use - // SHORTCUT_VALIDATED - LedgerSpecifier ledger = 3; - - bool queue = 4; - - bool signer_lists = 5; - - string client_ip = 6; -} - -// Response to GetAccountInfo RPC -// Next field: 6 -message GetAccountInfoResponse -{ - AccountRoot account_data = 1; - - SignerList signer_list = 2; - - uint32 ledger_index = 3; - - QueueData queue_data = 4; - - bool validated = 5; -} - -// Aggregate data about queued transactions -// Next field: 11 -message QueueData -{ - uint32 txn_count = 1; - - bool auth_change_queued = 2; - - uint32 lowest_sequence = 3; - - uint32 highest_sequence = 4; - - XRPDropsAmount max_spend_drops_total = 5; - - repeated QueuedTransaction transactions = 6; - - uint32 lowest_ticket = 7; - - uint32 highest_ticket = 8; - - uint32 sequence_count = 9; - - uint32 ticket_count = 10; -} - -// Data about a single queued transaction -// Next field: 8 -message QueuedTransaction -{ - bool auth_change = 1; - - XRPDropsAmount fee = 2; - - uint64 fee_level = 3 [jstype=JS_STRING]; - - XRPDropsAmount max_spend_drops = 4; - - Sequence sequence = 5; - - LastLedgerSequence last_ledger_sequence = 6; - - Ticket ticket = 7; -} diff --git a/src/ripple/proto/org/xrpl/rpc/v1/get_account_transaction_history.proto b/src/ripple/proto/org/xrpl/rpc/v1/get_account_transaction_history.proto deleted file mode 100644 index c4889a6bdbe..00000000000 --- a/src/ripple/proto/org/xrpl/rpc/v1/get_account_transaction_history.proto +++ /dev/null @@ -1,75 +0,0 @@ -syntax = "proto3"; - -import "org/xrpl/rpc/v1/get_transaction.proto"; -import "org/xrpl/rpc/v1/account.proto"; -import "org/xrpl/rpc/v1/ledger.proto"; - -package org.xrpl.rpc.v1; -option java_package = "org.xrpl.rpc.v1"; -option java_multiple_files = true; - -// Next field: 8 -message GetAccountTransactionHistoryRequest -{ - AccountAddress account = 1; - - // What ledger to include results from. Specifying a not yet validated - // ledger results in an error. Not specifying a ledger uses the entire - // range of validated ledgers available to the server. - // Note, this parameter acts as a filter, and can only reduce the number of - // results. Specifying a single ledger will return only transactions from - // that ledger. This includes specifying a ledger with a Shortcut. For - // example, specifying SHORTCUT_VALIDATED will result in only transactions - // that were part of the most recently validated ledger being returned. - // Specifying a range of ledgers results in only transactions that were - // included in a ledger within the specified range being returned. - oneof ledger - { - LedgerSpecifier ledger_specifier = 2; - LedgerRange ledger_range = 3; - }; - - // Return results as binary blobs. Defaults to false. - bool binary = 4; - - // If set to true, returns values indexed by older ledger first. - // Default to false. - bool forward = 5; - - // Limit the number of results. Server may choose a lower limit. - // If this value is 0, the limit is ignored and the number of results - // returned is determined by the server - uint32 limit = 6; - - // Marker to resume where previous request left off - // Used for pagination - Marker marker = 7; -} - - -// Next field: 8 -message GetAccountTransactionHistoryResponse -{ - AccountAddress account = 1; - - uint32 ledger_index_min = 2; - - uint32 ledger_index_max = 3; - - uint32 limit = 4; - - Marker marker = 5; - - repeated GetTransactionResponse transactions = 6; - - bool validated = 7; -} - -// Next field: 3 -message Marker -{ - uint32 ledger_index = 1; - - uint32 account_sequence = 2; -} - diff --git a/src/ripple/proto/org/xrpl/rpc/v1/get_fee.proto b/src/ripple/proto/org/xrpl/rpc/v1/get_fee.proto deleted file mode 100644 index aec3f24133c..00000000000 --- a/src/ripple/proto/org/xrpl/rpc/v1/get_fee.proto +++ /dev/null @@ -1,58 +0,0 @@ -syntax = "proto3"; - -package org.xrpl.rpc.v1; -option java_package = "org.xrpl.rpc.v1"; -option java_multiple_files = true; - -import "org/xrpl/rpc/v1/amount.proto"; - -// A request for the current transaction fee on the ledger. -// Next field: 1 -message GetFeeRequest -{ - string client_ip = 1; -} - -// Response to a GetFee RPC -// Next field: 8 -message GetFeeResponse -{ - uint64 current_ledger_size = 1 [jstype=JS_STRING]; - - uint64 current_queue_size = 2 [jstype=JS_STRING]; - - Fee fee = 3; - - uint64 expected_ledger_size = 4 [jstype=JS_STRING]; - - uint32 ledger_current_index = 5; - - FeeLevels levels = 6; - - uint64 max_queue_size = 7 [jstype=JS_STRING]; - -} - -// Next field: 5 -message Fee -{ - XRPDropsAmount base_fee = 1; - - XRPDropsAmount median_fee = 2; - - XRPDropsAmount minimum_fee = 3; - - XRPDropsAmount open_ledger_fee = 4; -} - -// Next field: 5 -message FeeLevels -{ - uint64 median_level = 1 [jstype=JS_STRING]; - - uint64 minimum_level = 2 [jstype=JS_STRING]; - - uint64 open_ledger_level = 3 [jstype=JS_STRING]; - - uint64 reference_level = 4 [jstype=JS_STRING]; -} diff --git a/src/ripple/proto/org/xrpl/rpc/v1/get_transaction.proto b/src/ripple/proto/org/xrpl/rpc/v1/get_transaction.proto deleted file mode 100644 index 93ba48a11ec..00000000000 --- a/src/ripple/proto/org/xrpl/rpc/v1/get_transaction.proto +++ /dev/null @@ -1,62 +0,0 @@ -syntax = "proto3"; - -package org.xrpl.rpc.v1; -option java_package = "org.xrpl.rpc.v1"; -option java_multiple_files = true; - -import "org/xrpl/rpc/v1/meta.proto"; -import "org/xrpl/rpc/v1/ledger.proto"; -import "org/xrpl/rpc/v1/transaction.proto"; -import "org/xrpl/rpc/v1/common.proto"; - -// Next field: 4 -message GetTransactionRequest { - - // hash of the transaction. 32 bytes - // ATTN: this is in binary, not hex. The JSON API accepts a hex string for - // a transaction hash, but here we need that hex string converted into its - // binary form. Each pair of hex characters should be converted into its - // corresponding byte. For example, the 4 character hex string "00FF" - // should be converted to a 2 byte array: [0, 255] - bytes hash = 1; - - // if true, return data in binary format. defaults to false - bool binary = 2; - - // If the transaction was not found, server will report whether the entire - // specified range was searched. The value is contained in the error message. - // The error message is of the form: - // "txn not found. searched_all = [true,false]" - // If the transaction was found, this parameter is ignored. - LedgerRange ledger_range = 3; - - string client_ip = 4; -} - -// Next field: 9 -message GetTransactionResponse { - - oneof serialized_transaction { - - Transaction transaction = 1; - // Variable length - bytes transaction_binary = 2; - }; - // Sequence number of ledger that contains this transaction - uint32 ledger_index = 3; - - // 32 bytes - bytes hash = 4; - - // whether the ledger has been validated - bool validated = 5; - - // metadata about the transaction - oneof serialized_meta { - Meta meta = 6; - // Variable length - bytes meta_binary = 7; - } - - Date date = 8; -} diff --git a/src/ripple/proto/org/xrpl/rpc/v1/ledger.proto b/src/ripple/proto/org/xrpl/rpc/v1/ledger.proto index 78e4211f5f0..3bb199de22f 100644 --- a/src/ripple/proto/org/xrpl/rpc/v1/ledger.proto +++ b/src/ripple/proto/org/xrpl/rpc/v1/ledger.proto @@ -25,16 +25,6 @@ message LedgerSpecifier } } -// Next field: 3 -message LedgerRange -{ - uint32 ledger_index_min = 1; - - // Note, if ledger_index_min is non-zero and ledger_index_max is 0, the - // software will use the max validated ledger in place of ledger_index_max - uint32 ledger_index_max = 2; -}; - // Next field: 3 message RawLedgerObject diff --git a/src/ripple/proto/org/xrpl/rpc/v1/ledger_objects.proto b/src/ripple/proto/org/xrpl/rpc/v1/ledger_objects.proto deleted file mode 100644 index d6db469a213..00000000000 --- a/src/ripple/proto/org/xrpl/rpc/v1/ledger_objects.proto +++ /dev/null @@ -1,418 +0,0 @@ -syntax = "proto3"; - -package org.xrpl.rpc.v1; -option java_package = "org.xrpl.rpc.v1"; -option java_multiple_files = true; - -import "org/xrpl/rpc/v1/common.proto"; - -// Next field: 17 -message LedgerObject -{ - oneof object - { - AccountRoot account_root = 1; - Amendments amendments = 2; - Check check = 3; - DepositPreauthObject deposit_preauth = 4; - DirectoryNode directory_node = 5; - Escrow escrow = 6; - FeeSettings fee_settings = 7; - LedgerHashes ledger_hashes = 8; - NFTokenOffer nftoken_offer = 15; - NFTokenPage nftoken_page = 16; - Offer offer = 9; - PayChannel pay_channel = 10; - RippleState ripple_state = 11; - SignerList signer_list = 12; - NegativeUNL negative_unl = 13; - TicketObject ticket = 14; - } -} - -// Next field: 15 -enum LedgerEntryType -{ - LEDGER_ENTRY_TYPE_UNSPECIFIED = 0; - LEDGER_ENTRY_TYPE_ACCOUNT_ROOT = 1; - LEDGER_ENTRY_TYPE_AMENDMENTS = 2; - LEDGER_ENTRY_TYPE_CHECK = 3; - LEDGER_ENTRY_TYPE_DEPOSIT_PREAUTH = 4; - LEDGER_ENTRY_TYPE_DIRECTORY_NODE = 5; - LEDGER_ENTRY_TYPE_ESCROW = 6; - LEDGER_ENTRY_TYPE_FEE_SETTINGS = 7; - LEDGER_ENTRY_TYPE_LEDGER_HASHES = 8; - LEDGER_ENTRY_TYPE_OFFER = 9; - LEDGER_ENTRY_TYPE_PAY_CHANNEL = 10; - LEDGER_ENTRY_TYPE_RIPPLE_STATE = 11; - LEDGER_ENTRY_TYPE_SIGNER_LIST = 12; - LEDGER_ENTRY_TYPE_NEGATIVE_UNL = 13; - LEDGER_ENTRY_TYPE_TICKET = 14; - LEDGER_ENTRY_TYPE_NFTOKEN_OFFER = 15; - LEDGER_ENTRY_TYPE_NFTOKEN_PAGE = 16; -} - -// Next field: 19 -message AccountRoot -{ - Account account = 1; - - Balance balance = 2; - - BurnedNFTokens burned_nftokens = 16; - - Sequence sequence = 3; - - Flags flags = 4; - - OwnerCount owner_count = 5; - - PreviousTransactionID previous_transaction_id = 6; - - PreviousTransactionLedgerSequence previous_transaction_ledger_sequence = 7; - - AccountTransactionID account_transaction_id = 8; - - Domain domain = 9; - - EmailHash email_hash = 10; - - MessageKey message_key = 11; - - MintedNFTokens minted_nftokens = 17; - - NFTokenMinter nftoken_minter = 18; - - RegularKey regular_key = 12; - - TickSize tick_size = 13; - - TicketCount ticket_count = 15; - - TransferRate transfer_rate = 14; -} - -// Next field: 4 -message Amendments -{ - // Next field: 2 - message Amendment - { - // 32 bytes - bytes value = 1; - } - - // Next field: 3 - message Majority - { - Amendment amendment = 1; - - CloseTime close_time = 2; - } - - repeated Amendment amendments = 1; - - repeated Majority majorities = 2; - - Flags flags = 3; -} - -// Next field: 14 -message Check -{ - Account account = 1; - - Destination destination = 2; - - Flags flags = 3; - - OwnerNode owner_node = 4; - - PreviousTransactionID previous_transaction_id = 5; - - PreviousTransactionLedgerSequence previous_transaction_ledger_sequence = 6; - - SendMax send_max = 7; - - Sequence sequence = 8; - - DestinationNode destination_node = 9; - - DestinationTag destination_tag = 10; - - Expiration expiration = 11; - - InvoiceID invoice_id = 12; - - SourceTag source_tag = 13; -} - -// Next field: 7 -message DepositPreauthObject -{ - Account account = 1; - - Authorize authorize = 2; - - Flags flags = 3; - - OwnerNode owner_node = 4; - - PreviousTransactionID previous_transaction_id = 5; - - PreviousTransactionLedgerSequence previous_transaction_ledger_sequence = 6; -} - -// Next field: 12 -message DirectoryNode -{ - Flags flags = 1; - - RootIndex root_index = 2; - - repeated Index indexes = 3; - - IndexNext index_next = 4; - - IndexPrevious index_previous = 5; - - Owner owner = 6; - - TakerPaysCurrency taker_pays_currency = 7; - - TakerPaysIssuer taker_pays_issuer = 8; - - TakerGetsCurreny taker_gets_currency = 9; - - TakerGetsIssuer taker_gets_issuer = 10; - - NFTokenID nftoken_id = 11; -} - -// Next field: 14 -message Escrow -{ - Account account = 1; - - Destination destination = 2; - - Amount amount = 3; - - Condition condition = 4; - - CancelAfter cancel_after = 5; - - FinishAfter finish_after = 6; - - Flags flags = 7; - - SourceTag source_tag = 8; - - DestinationTag destination_tag = 9; - - OwnerNode owner_node = 10; - - DestinationNode destination_node = 11; - - PreviousTransactionID previous_transaction_id = 12; - - PreviousTransactionLedgerSequence previous_transaction_ledger_sequence = 13; -} - -// Next field: 6 -message FeeSettings -{ - BaseFee base_fee = 1; - - ReferenceFeeUnits reference_fee_units = 2; - - ReserveBase reserve_base = 3; - - ReserveIncrement reserve_increment = 4; - - Flags flags = 5; -} - -// Next field: 4 -message LedgerHashes -{ - LastLedgerSequence last_ledger_sequence = 1; - - repeated Hash hashes = 2; - - Flags flags = 3; -} - -// Next field: 12 -message Offer -{ - Account account = 1; - - Sequence sequence = 2; - - Flags flags = 3; - - TakerPays taker_pays = 4; - - TakerGets taker_gets = 5; - - BookDirectory book_directory = 6; - - BookNode book_node = 7; - - OwnerNode owner_node = 8; - - Expiration expiration = 9; - - PreviousTransactionID previous_transaction_id = 10; - - PreviousTransactionLedgerSequence previous_transaction_ledger_sequence = 11; -} - -// Next field: 11 -message NFTokenOffer -{ - Flags flags = 1; - - Owner owner = 2; - - NFTokenID nftoken_id = 3; - - Amount amount = 4; - - OwnerNode owner_node = 5; - - NFTokenOfferNode nftoken_offer_node = 6; - - Destination destination = 7; - - Expiration expiration = 8; - - PreviousTransactionID previous_transaction_id = 9; - - PreviousTransactionLedgerSequence previous_transaction_ledger_sequence = 10; -} - -// Next field: 7 -message NFTokenPage -{ - Flags flags = 1; - - PreviousPageMin previous_page_min = 2; - - NextPageMin next_page_min = 3; - - repeated NFToken nftokens = 4; - - PreviousTransactionID previous_transaction_id = 5; - - PreviousTransactionLedgerSequence previous_transaction_ledger_sequence = 6; -} - -// Next field: 13 -message PayChannel -{ - Account account = 1; - - Destination destination = 2; - - Amount amount = 3; - - Balance balance = 4; - - PublicKey public_key = 5; - - SettleDelay settle_delay = 6; - - OwnerNode owner_node = 7; - - PreviousTransactionID previous_transaction_id = 8; - - PreviousTransactionLedgerSequence previous_transaction_ledger_sequence = 9; - - Flags flags = 10; - - Expiration expiration = 11; - - CancelAfter cancel_after = 12; - - SourceTag source_tag = 13; - - DestinationTag destination_tag = 14; - - DestinationNode destination_node = 15; -} - -// Next field: 13 -message RippleState -{ - Balance balance = 1; - - Flags flags = 2; - - LowLimit low_limit = 3; - - HighLimit high_limit = 4; - - LowNode low_node = 5; - - HighNode high_node = 6; - - LowQualityIn low_quality_in = 7; - - LowQualityOut low_quality_out = 8; - - HighQualityIn high_quality_in = 9; - - HighQualityOut high_quality_out = 10; - - PreviousTransactionID previous_transaction_id = 11; - - PreviousTransactionLedgerSequence previous_transaction_ledger_sequence = 12; -} - -// Next field: 8 -message SignerList -{ - Flags flags = 1; - - PreviousTransactionID previous_transaction_id = 2; - - PreviousTransactionLedgerSequence previous_transaction_ledger_sequence = 3; - - OwnerNode owner_node = 4; - - repeated SignerEntry signer_entries = 5; - - SignerListID signer_list_id = 6; - - SignerQuorum signer_quorum = 7; -} - -// Next field: 7 -message TicketObject -{ - Flags flags = 1; - - Account account = 2; - - OwnerNode owner_node = 3; - - PreviousTransactionID previous_transaction_id = 4; - - PreviousTransactionLedgerSequence previous_transaction_ledger_sequence = 5; - - TicketSequence ticket_sequence = 6; -} - -// Next field: 5 -message NegativeUNL -{ - repeated DisabledValidator disabled_validators = 1; - - ValidatorToDisable validator_to_disable = 2; - - ValidatorToReEnable validator_to_re_enable = 3; - - Flags flags = 4; -} diff --git a/src/ripple/proto/org/xrpl/rpc/v1/meta.proto b/src/ripple/proto/org/xrpl/rpc/v1/meta.proto deleted file mode 100644 index 35660b3ddc0..00000000000 --- a/src/ripple/proto/org/xrpl/rpc/v1/meta.proto +++ /dev/null @@ -1,116 +0,0 @@ -syntax = "proto3"; - -package org.xrpl.rpc.v1; -option java_package = "org.xrpl.rpc.v1"; -option java_multiple_files = true; - -import "org/xrpl/rpc/v1/ledger_objects.proto"; -import "org/xrpl/rpc/v1/common.proto"; - -message SubmitMetadataRequest -{ - - repeated AffectedNode affected_nodes = 1; - uint32 ledger_sequence = 2; -} - -message SubmitMetadataResponse -{ - bool success = 1; - - string msg = 2; -} - -message PrepareLedgerRequest -{ - uint32 ledger_index = 1; -} - -message PrepareLedgerResponse -{ - bool success = 1; - - string msg = 2; -} - -// Next field: 5 -message Meta -{ - // index in ledger - uint64 transaction_index = 1 [jstype=JS_STRING]; - - // result code indicating whether the transaction succeeded or failed - TransactionResult transaction_result = 2; - - repeated AffectedNode affected_nodes = 3; - - DeliveredAmount delivered_amount = 4; -} - -// Next field: 3 -message TransactionResult -{ - // Next field: 7 - enum ResultType - { - RESULT_TYPE_UNSPECIFIED = 0; - // Claimed cost only - RESULT_TYPE_TEC = 1; - // Failure - RESULT_TYPE_TEF = 2; - // Local error - RESULT_TYPE_TEL = 3; - // Malformed transaction - RESULT_TYPE_TEM = 4; - // Retry - RESULT_TYPE_TER = 5; - // Success - RESULT_TYPE_TES = 6; - } - - // category of the transaction result - ResultType result_type = 1; - - // full result string, i.e. tesSUCCESS - string result = 2; -} - -// Next field: 6 -message AffectedNode -{ - LedgerEntryType ledger_entry_type = 1; - - // 32 bytes - bytes ledger_index = 2; - - oneof node - { - CreatedNode created_node = 3; - DeletedNode deleted_node = 4; - ModifiedNode modified_node = 5; - } -} - -// Next field: 2 -message CreatedNode -{ - LedgerObject new_fields = 1; -} - -// Next field: 2 -message DeletedNode -{ - LedgerObject final_fields = 1; -} - -// Next field: 5 -message ModifiedNode { - - LedgerObject final_fields = 1; - - LedgerObject previous_fields = 2; - - PreviousTransactionID previous_transaction_id = 3; - - PreviousTransactionLedgerSequence previous_transaction_ledger_sequence = 4; -} diff --git a/src/ripple/proto/org/xrpl/rpc/v1/submit.proto b/src/ripple/proto/org/xrpl/rpc/v1/submit.proto deleted file mode 100644 index f8b0a82708f..00000000000 --- a/src/ripple/proto/org/xrpl/rpc/v1/submit.proto +++ /dev/null @@ -1,37 +0,0 @@ -syntax = "proto3"; - -package org.xrpl.rpc.v1; -option java_package = "org.xrpl.rpc.v1"; -option java_multiple_files = true; - -import "org/xrpl/rpc/v1/meta.proto"; - -// A request to submit the signed transaction to the ledger. -// Next field: 3 -message SubmitTransactionRequest -{ - // The signed transaction to submit. - bytes signed_transaction = 1; - - bool fail_hard = 2; - - string client_ip = 3; -} - -// A response when a signed transaction is submitted to the ledger. -// Next field: 5 -message SubmitTransactionResponse -{ - // Code indicating the preliminary result of the transaction. - TransactionResult engine_result = 1; - - // Numeric code indicating the preliminary result of the transaction, - // directly correlated to engine_result. - int64 engine_result_code = 2; - - // Human-readable explanation of the transaction's preliminary result. - string engine_result_message = 3; - - // 32 bytes - bytes hash = 4; -} diff --git a/src/ripple/proto/org/xrpl/rpc/v1/transaction.proto b/src/ripple/proto/org/xrpl/rpc/v1/transaction.proto deleted file mode 100644 index 05300422b1a..00000000000 --- a/src/ripple/proto/org/xrpl/rpc/v1/transaction.proto +++ /dev/null @@ -1,390 +0,0 @@ -syntax = "proto3"; - -package org.xrpl.rpc.v1; -option java_package = "org.xrpl.rpc.v1"; -option java_multiple_files = true; - -import "org/xrpl/rpc/v1/common.proto"; -import "org/xrpl/rpc/v1/amount.proto"; -import "org/xrpl/rpc/v1/account.proto"; - -// A message encompassing all transaction types -// Next field: 37 -message Transaction -{ - Account account = 1; - - XRPDropsAmount fee = 2; - - Sequence sequence = 3; - - // Data specific to the type of transaction - oneof transaction_data - { - Payment payment = 4; - - AccountSet account_set = 13; - - AccountDelete account_delete = 14; - - CheckCancel check_cancel = 15; - - CheckCash check_cash = 16; - - CheckCreate check_create = 17; - - DepositPreauth deposit_preauth = 18; - - EscrowCancel escrow_cancel = 19; - - EscrowCreate escrow_create = 20; - - EscrowFinish escrow_finish = 21; - - NFTokenAcceptOffer nftoken_accept_offer = 32; - - NFTokenBurn nftoken_burn = 33; - - NFTokenCancelOffer nftoken_cancel_offer = 34; - - NFTokenCreateOffer nftoken_create_offer = 35; - - NFTokenMint nftoken_mint = 36; - - OfferCancel offer_cancel = 22; - - OfferCreate offer_create = 23; - - PaymentChannelClaim payment_channel_claim = 24; - - PaymentChannelCreate payment_channel_create= 25; - - PaymentChannelFund payment_channel_fund = 26; - - SetRegularKey set_regular_key = 27; - - SignerListSet signer_list_set = 28; - - TicketCreate ticket_create = 30; - - TrustSet trust_set = 29; - } - - SigningPublicKey signing_public_key = 5; - - TransactionSignature transaction_signature = 6; - - Flags flags = 7; - - LastLedgerSequence last_ledger_sequence = 8; - - SourceTag source_tag = 9; - - repeated Memo memos = 10; - - repeated Signer signers = 11; - - AccountTransactionID account_transaction_id = 12; - - TicketSequence ticket_sequence = 31; -} - -// Next field: 4 -message Memo -{ - MemoData memo_data = 1; - - MemoFormat memo_format = 2; - - MemoType memo_type = 3; -} - -// Next field: 4 -message Signer -{ - Account account = 1; - - TransactionSignature transaction_signature = 2; - - SigningPublicKey signing_public_key = 3; -} - -// Next field: 9 -message AccountSet -{ - ClearFlag clear_flag = 1; - - Domain domain = 2; - - EmailHash email_hash = 3; - - MessageKey message_key = 4; - - SetFlag set_flag = 5; - - TransferRate transfer_rate = 6; - - TickSize tick_size = 7; - - NFTokenMinter nftoken_minter = 8; -} - -// Next field: 3 -message AccountDelete -{ - Destination destination = 1; - - DestinationTag destination_tag = 2; -} - -// Next field: 2 -message CheckCancel -{ - CheckID check_id = 1; -} - -// Next field: 4 -message CheckCash -{ - CheckID check_id = 1; - - oneof amount_oneof - { - Amount amount = 2; - - DeliverMin deliver_min = 3; - } -} - -// Next field: 6 -message CheckCreate -{ - Destination destination = 1; - - SendMax send_max = 2; - - DestinationTag destination_tag = 3; - - Expiration expiration = 4; - - InvoiceID invoice_id = 5; -} - -// Next field: 3 -message DepositPreauth -{ - oneof authorization_oneof - { - Authorize authorize = 1; - - Unauthorize unauthorize = 2; - } -} - -// Next field: 3 -message EscrowCancel -{ - Owner owner = 1; - - OfferSequence offer_sequence = 2; -} - -// Next field: 7 -message EscrowCreate -{ - Amount amount = 1; - - Destination destination = 2; - - CancelAfter cancel_after = 3; - - FinishAfter finish_after = 4; - - Condition condition = 5; - - DestinationTag destination_tag = 6; -} - -// Next field: 5 -message EscrowFinish -{ - Owner owner = 1; - - OfferSequence offer_sequence = 2; - - Condition condition = 3; - - Fulfillment fulfillment = 4; -} - -// Next field: 4 -message NFTokenAcceptOffer -{ - NFTokenBrokerFee nftoken_broker_fee = 1; - - NFTokenBuyOffer nftoken_buy_offer = 2; - - NFTokenSellOffer nftoken_sell_offer = 3; -} - -// Next field: 3 -message NFTokenBurn -{ - Owner owner = 1; - - NFTokenID nftoken_id = 2; -} - -// Next field: 2 -message NFTokenCancelOffer -{ - repeated Index nftoken_offers = 1; -} - -// Next field: 6 -message NFTokenCreateOffer -{ - Amount amount = 1; - - Destination destination = 2; - - Expiration expiration = 3; - - Owner owner = 4; - - NFTokenID nftoken_id = 5; -} - -// Next field: 5 -message NFTokenMint -{ - Issuer issuer = 1; - - NFTokenTaxon nftoken_taxon = 2; - - TransferFee transfer_fee = 3; - - URI uri = 4; -} - -// Next field: 2 -message OfferCancel -{ - OfferSequence offer_sequence = 1; -} - -// Next field: 5 -message OfferCreate -{ - Expiration expiration = 1; - - OfferSequence offer_sequence = 2; - - TakerGets taker_gets = 3; - - TakerPays taker_pays = 4; -} - -// Next field: 8 -message Payment -{ - // Next field: 4 - message PathElement - { - AccountAddress account = 1; - - Currency currency = 2; - - AccountAddress issuer = 3; - } - - // Next field: 2 - message Path - { - repeated PathElement elements = 1; - } - - Amount amount = 1; - - Destination destination = 2; - - DestinationTag destination_tag = 3; - - InvoiceID invoice_id = 4; - - repeated Path paths = 5; - - SendMax send_max = 6; - - DeliverMin deliver_min = 7; -} - -// Next field: 6 -message PaymentChannelClaim -{ - Channel channel = 1; - - Balance balance = 2; - - Amount amount = 3; - - PaymentChannelSignature payment_channel_signature = 4; - - PublicKey public_key = 5; -} - -// Next field: 7 -message PaymentChannelCreate -{ - Amount amount = 1; - - Destination destination = 2; - - SettleDelay settle_delay = 3; - - PublicKey public_key = 4; - - CancelAfter cancel_after = 5; - - DestinationTag destination_tag = 6; -} - -// Next field: 4 -message PaymentChannelFund -{ - Channel channel = 1; - - Amount amount = 2; - - Expiration expiration = 3; -} - -// Next field: 2 -message SetRegularKey -{ - RegularKey regular_key = 1; -} - -// Next field: 3 -message SignerListSet -{ - SignerQuorum signer_quorum = 1; - - repeated SignerEntry signer_entries = 2; -} - -// Next field: 2 -message TicketCreate -{ - TicketCount count = 1; -} - -// Next field: 4 -message TrustSet -{ - LimitAmount limit_amount = 1; - - QualityIn quality_in = 2; - - QualityOut quality_out = 3; -} diff --git a/src/ripple/proto/org/xrpl/rpc/v1/xrp_ledger.proto b/src/ripple/proto/org/xrpl/rpc/v1/xrp_ledger.proto index 6f48d486087..995edba48a1 100644 --- a/src/ripple/proto/org/xrpl/rpc/v1/xrp_ledger.proto +++ b/src/ripple/proto/org/xrpl/rpc/v1/xrp_ledger.proto @@ -4,39 +4,18 @@ package org.xrpl.rpc.v1; option java_package = "org.xrpl.rpc.v1"; option java_multiple_files = true; -import "org/xrpl/rpc/v1/get_account_info.proto"; -import "org/xrpl/rpc/v1/get_fee.proto"; -import "org/xrpl/rpc/v1/submit.proto"; -import "org/xrpl/rpc/v1/get_transaction.proto"; -import "org/xrpl/rpc/v1/get_account_transaction_history.proto"; import "org/xrpl/rpc/v1/get_ledger.proto"; import "org/xrpl/rpc/v1/get_ledger_entry.proto"; import "org/xrpl/rpc/v1/get_ledger_data.proto"; import "org/xrpl/rpc/v1/get_ledger_diff.proto"; -// RPCs available to interact with the XRP Ledger. -// The gRPC API mimics the JSON API. Refer to xrpl.org for documentation +// These methods are binary only methods for retrieiving arbitrary ledger state +// via gRPC. These methods are used by clio and reporting mode, but can also be +// used by any client that wants to extract ledger state in an efficient manner. +// They do not directly mimic the JSON equivalent methods. service XRPLedgerAPIService { - // Get account info for an account on the XRP Ledger. - rpc GetAccountInfo (GetAccountInfoRequest) returns (GetAccountInfoResponse); - - // Get the fee for a transaction on the XRP Ledger. - rpc GetFee (GetFeeRequest) returns (GetFeeResponse); - - // Submit a signed transaction to the XRP Ledger. - rpc SubmitTransaction (SubmitTransactionRequest) returns (SubmitTransactionResponse); - - // Get the status of a transaction - rpc GetTransaction(GetTransactionRequest) returns (GetTransactionResponse); - - // Get all validated transactions associated with a given account - rpc GetAccountTransactionHistory(GetAccountTransactionHistoryRequest) returns (GetAccountTransactionHistoryResponse); - - ///////////////////////////////////////////////////////////////////////////// - // The below methods do not mimic the JSON API exactly, and are mostly binary - // Get a specific ledger, optionally including transactions and any modified, // added or deleted ledger objects rpc GetLedger(GetLedgerRequest) returns (GetLedgerResponse); diff --git a/src/ripple/rpc/GRPCHandlers.h b/src/ripple/rpc/GRPCHandlers.h index d7b1cc3a927..493de7a5c47 100644 --- a/src/ripple/rpc/GRPCHandlers.h +++ b/src/ripple/rpc/GRPCHandlers.h @@ -34,28 +34,6 @@ namespace ripple { * the status will be sent to the client, and the response will be ommitted */ -std::pair -doAccountInfoGrpc( - RPC::GRPCContext& context); - -std::pair -doFeeGrpc(RPC::GRPCContext& context); - -std::pair -doSubmitGrpc( - RPC::GRPCContext& context); - -// NOTE, this only supports Payment transactions at this time -std::pair -doTxGrpc(RPC::GRPCContext& context); - -std::pair< - org::xrpl::rpc::v1::GetAccountTransactionHistoryResponse, - grpc::Status> -doAccountTxGrpc( - RPC::GRPCContext& - context); - std::pair doLedgerGrpc(RPC::GRPCContext& context); diff --git a/src/ripple/rpc/handlers/AccountInfo.cpp b/src/ripple/rpc/handlers/AccountInfo.cpp index 417a3ffcd38..5b37ec2c795 100644 --- a/src/ripple/rpc/handlers/AccountInfo.cpp +++ b/src/ripple/rpc/handlers/AccountInfo.cpp @@ -27,7 +27,6 @@ #include #include #include -#include #include #include @@ -222,95 +221,4 @@ doAccountInfo(RPC::JsonContext& context) return result; } -std::pair -doAccountInfoGrpc( - RPC::GRPCContext& context) -{ - // Return values - org::xrpl::rpc::v1::GetAccountInfoResponse result; - grpc::Status status = grpc::Status::OK; - - // input - org::xrpl::rpc::v1::GetAccountInfoRequest& params = context.params; - - // get ledger - std::shared_ptr ledger; - auto lgrStatus = RPC::ledgerFromRequest(ledger, context); - if (lgrStatus || !ledger) - { - grpc::Status errorStatus; - if (lgrStatus.toErrorCode() == rpcINVALID_PARAMS) - { - errorStatus = grpc::Status( - grpc::StatusCode::INVALID_ARGUMENT, lgrStatus.message()); - } - else - { - errorStatus = - grpc::Status(grpc::StatusCode::NOT_FOUND, lgrStatus.message()); - } - return {result, errorStatus}; - } - - result.set_ledger_index(ledger->info().seq); - result.set_validated( - RPC::isValidated(context.ledgerMaster, *ledger, context.app)); - - // decode account - AccountID accountID; - std::string strIdent = params.account().address(); - error_code_i code = - RPC::accountFromStringWithCode(accountID, strIdent, params.strict()); - if (code != rpcSUCCESS) - { - grpc::Status errorStatus{ - grpc::StatusCode::INVALID_ARGUMENT, "invalid account"}; - return {result, errorStatus}; - } - - // get account data - auto const sleAccepted = ledger->read(keylet::account(accountID)); - if (sleAccepted) - { - RPC::convert(*result.mutable_account_data(), *sleAccepted); - - // signer lists - if (params.signer_lists()) - { - auto const sleSigners = ledger->read(keylet::signers(accountID)); - if (sleSigners) - { - org::xrpl::rpc::v1::SignerList& signerListProto = - *result.mutable_signer_list(); - RPC::convert(signerListProto, *sleSigners); - } - } - - // queued transactions - if (params.queue()) - { - if (!ledger->open()) - { - grpc::Status errorStatus{ - grpc::StatusCode::INVALID_ARGUMENT, - "requested queue but ledger is not open"}; - return {result, errorStatus}; - } - std::vector const txs = - context.app.getTxQ().getAccountTxs(accountID); - org::xrpl::rpc::v1::QueueData& queueData = - *result.mutable_queue_data(); - RPC::convert(queueData, txs); - } - } - else - { - grpc::Status errorStatus{ - grpc::StatusCode::NOT_FOUND, "account not found"}; - return {result, errorStatus}; - } - - return {result, status}; -} - } // namespace ripple diff --git a/src/ripple/rpc/handlers/AccountTx.cpp b/src/ripple/rpc/handlers/AccountTx.cpp index e5e7d54382a..67c80ad9bdc 100644 --- a/src/ripple/rpc/handlers/AccountTx.cpp +++ b/src/ripple/rpc/handlers/AccountTx.cpp @@ -35,7 +35,6 @@ #include #include #include -#include #include #include @@ -51,69 +50,6 @@ using AccountTxResult = RelationalDatabase::AccountTxResult; using LedgerShortcut = RelationalDatabase::LedgerShortcut; using LedgerSpecifier = RelationalDatabase::LedgerSpecifier; -// parses args into a ledger specifier, or returns a grpc status object on error -std::variant, grpc::Status> -parseLedgerArgs( - org::xrpl::rpc::v1::GetAccountTransactionHistoryRequest const& params) -{ - grpc::Status status; - if (params.has_ledger_range()) - { - uint32_t min = params.ledger_range().ledger_index_min(); - uint32_t max = params.ledger_range().ledger_index_max(); - - // if min is set but not max, need to set max - if (min != 0 && max == 0) - { - max = UINT32_MAX; - } - - return LedgerRange{min, max}; - } - else if (params.has_ledger_specifier()) - { - LedgerSpecifier ledger; - - auto& specifier = params.ledger_specifier(); - using LedgerCase = org::xrpl::rpc::v1::LedgerSpecifier::LedgerCase; - LedgerCase ledgerCase = specifier.ledger_case(); - - if (ledgerCase == LedgerCase::kShortcut) - { - using LedgerSpecifier = org::xrpl::rpc::v1::LedgerSpecifier; - - if (specifier.shortcut() == LedgerSpecifier::SHORTCUT_VALIDATED) - ledger = LedgerShortcut::VALIDATED; - else if (specifier.shortcut() == LedgerSpecifier::SHORTCUT_CLOSED) - ledger = LedgerShortcut::CLOSED; - else if (specifier.shortcut() == LedgerSpecifier::SHORTCUT_CURRENT) - ledger = LedgerShortcut::CURRENT; - else - return {}; - } - else if (ledgerCase == LedgerCase::kSequence) - { - ledger = specifier.sequence(); - } - else if (ledgerCase == LedgerCase::kHash) - { - if (auto hash = uint256::fromVoidChecked(specifier.hash())) - { - ledger = *hash; - } - else - { - grpc::Status errorStatus{ - grpc::StatusCode::INVALID_ARGUMENT, - "ledger hash malformed"}; - return errorStatus; - } - } - return ledger; - } - return std::optional{}; -} - // parses args into a ledger specifier, or returns a Json object on error std::variant, Json::Value> parseLedgerArgs(Json::Value const& params) @@ -331,131 +267,6 @@ doAccountTxHelp(RPC::Context& context, AccountTxArgs const& args) return {result, rpcSUCCESS}; } -std::pair< - org::xrpl::rpc::v1::GetAccountTransactionHistoryResponse, - grpc::Status> -populateProtoResponse( - std::pair const& res, - AccountTxArgs const& args, - RPC::GRPCContext< - org::xrpl::rpc::v1::GetAccountTransactionHistoryRequest> const& context) -{ - org::xrpl::rpc::v1::GetAccountTransactionHistoryResponse response; - grpc::Status status = grpc::Status::OK; - - RPC::Status const& error = res.second; - if (error.toErrorCode() != rpcSUCCESS) - { - if (error.toErrorCode() == rpcLGR_NOT_FOUND) - { - status = {grpc::StatusCode::NOT_FOUND, error.message()}; - } - else if (error.toErrorCode() == rpcNOT_SYNCED) - { - status = {grpc::StatusCode::FAILED_PRECONDITION, error.message()}; - } - else - { - status = {grpc::StatusCode::INVALID_ARGUMENT, error.message()}; - } - } - else - { - AccountTxResult const& result = res.first; - - // account_tx always returns validated data - response.set_validated(true); - response.set_limit(result.limit); - response.mutable_account()->set_address( - context.params.account().address()); - response.set_ledger_index_min(result.ledgerRange.min); - response.set_ledger_index_max(result.ledgerRange.max); - - if (auto txnsData = std::get_if(&result.transactions)) - { - assert(!args.binary); - for (auto const& [txn, txnMeta] : *txnsData) - { - if (txn) - { - auto txnProto = response.add_transactions(); - - RPC::convert( - *txnProto->mutable_transaction(), - txn->getSTransaction()); - - // account_tx always returns validated data - txnProto->set_validated(true); - txnProto->set_ledger_index(txn->getLedger()); - auto& hash = txn->getID(); - txnProto->set_hash(hash.data(), hash.size()); - auto closeTime = - context.app.getLedgerMaster().getCloseTimeBySeq( - txn->getLedger()); - if (closeTime) - txnProto->mutable_date()->set_value( - closeTime->time_since_epoch().count()); - if (txnMeta) - { - RPC::convert(*txnProto->mutable_meta(), txnMeta); - if (!txnProto->meta().has_delivered_amount()) - { - if (auto amt = getDeliveredAmount( - context, - txn->getSTransaction(), - *txnMeta, - txn->getLedger())) - { - RPC::convert( - *txnProto->mutable_meta() - ->mutable_delivered_amount(), - *amt); - } - } - } - } - } - } - else - { - assert(args.binary); - - for (auto const& binaryData : - std::get(result.transactions)) - { - auto txnProto = response.add_transactions(); - Blob const& txnBlob = std::get<0>(binaryData); - txnProto->set_transaction_binary( - txnBlob.data(), txnBlob.size()); - - Blob const& metaBlob = std::get<1>(binaryData); - txnProto->set_meta_binary(metaBlob.data(), metaBlob.size()); - - txnProto->set_ledger_index(std::get<2>(binaryData)); - - // account_tx always returns validated data - txnProto->set_validated(true); - - auto closeTime = - context.app.getLedgerMaster().getCloseTimeBySeq( - std::get<2>(binaryData)); - if (closeTime) - txnProto->mutable_date()->set_value( - closeTime->time_since_epoch().count()); - } - } - - if (result.marker) - { - response.mutable_marker()->set_ledger_index( - result.marker->ledgerSeq); - response.mutable_marker()->set_account_sequence( - result.marker->txnSeq); - } - } - return {response, status}; -} - Json::Value populateJsonResponse( std::pair const& res, @@ -597,59 +408,4 @@ doAccountTxJson(RPC::JsonContext& context) return populateJsonResponse(res, args, context); } -std::pair< - org::xrpl::rpc::v1::GetAccountTransactionHistoryResponse, - grpc::Status> -doAccountTxGrpc( - RPC::GRPCContext& - context) -{ - if (!context.app.config().useTxTables()) - { - return { - {}, - {grpc::StatusCode::UNIMPLEMENTED, "Not enabled in configuration."}}; - } - - // return values - org::xrpl::rpc::v1::GetAccountTransactionHistoryResponse response; - grpc::Status status = grpc::Status::OK; - AccountTxArgs args; - - auto& request = context.params; - - auto const account = parseBase58(request.account().address()); - if (!account) - { - return { - {}, - {grpc::StatusCode::INVALID_ARGUMENT, "Could not decode account"}}; - } - - args.account = *account; - args.limit = request.limit(); - args.binary = request.binary(); - args.forward = request.forward(); - - if (request.has_marker()) - { - args.marker = { - request.marker().ledger_index(), - request.marker().account_sequence()}; - } - - auto parseRes = parseLedgerArgs(request); - if (auto stat = std::get_if(&parseRes)) - { - return {response, *stat}; - } - else - { - args.ledger = std::get>(parseRes); - } - - auto res = doAccountTxHelp(context, args); - return populateProtoResponse(res, args, context); -} - } // namespace ripple diff --git a/src/ripple/rpc/handlers/Fee1.cpp b/src/ripple/rpc/handlers/Fee1.cpp index f28f9b4475a..554480f10af 100644 --- a/src/ripple/rpc/handlers/Fee1.cpp +++ b/src/ripple/rpc/handlers/Fee1.cpp @@ -38,49 +38,4 @@ doFee(RPC::JsonContext& context) return context.params; } -std::pair -doFeeGrpc(RPC::GRPCContext& context) -{ - org::xrpl::rpc::v1::GetFeeResponse reply; - grpc::Status status = grpc::Status::OK; - - Application& app = context.app; - auto const view = app.openLedger().current(); - if (!view) - { - BOOST_ASSERT(false); - return {reply, status}; - } - - auto const metrics = app.getTxQ().getMetrics(*view); - - // current ledger data - reply.set_current_ledger_size(metrics.txInLedger); - reply.set_current_queue_size(metrics.txCount); - reply.set_expected_ledger_size(metrics.txPerLedger); - reply.set_ledger_current_index(view->info().seq); - reply.set_max_queue_size(*metrics.txQMaxSize); - - // fee levels data - org::xrpl::rpc::v1::FeeLevels& levels = *reply.mutable_levels(); - levels.set_median_level(metrics.medFeeLevel.fee()); - levels.set_minimum_level(metrics.minProcessingFeeLevel.fee()); - levels.set_open_ledger_level(metrics.openLedgerFeeLevel.fee()); - levels.set_reference_level(metrics.referenceFeeLevel.fee()); - - // fee data - org::xrpl::rpc::v1::Fee& fee = *reply.mutable_fee(); - auto const baseFee = view->fees().base; - fee.mutable_base_fee()->set_drops( - toDrops(metrics.referenceFeeLevel, baseFee).drops()); - fee.mutable_minimum_fee()->set_drops( - toDrops(metrics.minProcessingFeeLevel, baseFee).drops()); - fee.mutable_median_fee()->set_drops( - toDrops(metrics.medFeeLevel, baseFee).drops()); - - fee.mutable_open_ledger_fee()->set_drops( - (toDrops(metrics.openLedgerFeeLevel - FeeLevel64{1}, baseFee) + 1) - .drops()); - return {reply, status}; -} } // namespace ripple diff --git a/src/ripple/rpc/handlers/LedgerData.cpp b/src/ripple/rpc/handlers/LedgerData.cpp index fbc17b75b7b..7392b505126 100644 --- a/src/ripple/rpc/handlers/LedgerData.cpp +++ b/src/ripple/rpc/handlers/LedgerData.cpp @@ -25,7 +25,6 @@ #include #include #include -#include #include #include diff --git a/src/ripple/rpc/handlers/LedgerEntry.cpp b/src/ripple/rpc/handlers/LedgerEntry.cpp index 4b2526698b4..fff2ceac01c 100644 --- a/src/ripple/rpc/handlers/LedgerEntry.cpp +++ b/src/ripple/rpc/handlers/LedgerEntry.cpp @@ -27,7 +27,6 @@ #include #include #include -#include #include namespace ripple { diff --git a/src/ripple/rpc/handlers/LedgerHandler.cpp b/src/ripple/rpc/handlers/LedgerHandler.cpp index e28b181fcba..b3a441f48a0 100644 --- a/src/ripple/rpc/handlers/LedgerHandler.cpp +++ b/src/ripple/rpc/handlers/LedgerHandler.cpp @@ -27,7 +27,6 @@ #include #include #include -#include #include namespace ripple { diff --git a/src/ripple/rpc/handlers/Submit.cpp b/src/ripple/rpc/handlers/Submit.cpp index 220760172cc..2b5c8bba925 100644 --- a/src/ripple/rpc/handlers/Submit.cpp +++ b/src/ripple/rpc/handlers/Submit.cpp @@ -26,7 +26,6 @@ #include #include #include -#include #include #include @@ -194,102 +193,4 @@ doSubmit(RPC::JsonContext& context) } } -std::pair -doSubmitGrpc( - RPC::GRPCContext& context) -{ - // return values - org::xrpl::rpc::v1::SubmitTransactionResponse result; - grpc::Status status = grpc::Status::OK; - - // input - auto request = context.params; - - std::string const& tx = request.signed_transaction(); - - // convert to blob - Blob blob{tx.begin(), tx.end()}; - - // serialize - SerialIter sitTrans(makeSlice(blob)); - std::shared_ptr stpTrans; - try - { - stpTrans = std::make_shared(std::ref(sitTrans)); - } - catch (std::exception& e) - { - grpc::Status errorStatus{ - grpc::StatusCode::INVALID_ARGUMENT, - "invalid transaction: " + std::string(e.what())}; - return {result, errorStatus}; - } - - // check validity - { - if (!context.app.checkSigs()) - forceValidity( - context.app.getHashRouter(), - stpTrans->getTransactionID(), - Validity::SigGoodOnly); - auto [validity, reason] = checkValidity( - context.app.getHashRouter(), - *stpTrans, - context.ledgerMaster.getCurrentLedger()->rules(), - context.app.config()); - if (validity != Validity::Valid) - { - grpc::Status errorStatus{ - grpc::StatusCode::INVALID_ARGUMENT, - "invalid transaction: " + reason}; - return {result, errorStatus}; - } - } - - std::string reason; - auto tpTrans = std::make_shared(stpTrans, reason, context.app); - if (tpTrans->getStatus() != NEW) - { - grpc::Status errorStatus{ - grpc::StatusCode::INVALID_ARGUMENT, - "invalid transaction: " + reason}; - return {result, errorStatus}; - } - - try - { - auto const failType = NetworkOPs::doFailHard(request.fail_hard()); - - // submit to network - context.netOps.processTransaction( - tpTrans, isUnlimited(context.role), true, failType); - } - catch (std::exception& e) - { - grpc::Status errorStatus{ - grpc::StatusCode::INVALID_ARGUMENT, - "invalid transaction : " + std::string(e.what())}; - return {result, errorStatus}; - } - - // return preliminary result - if (temUNCERTAIN != tpTrans->getResult()) - { - RPC::convert(*result.mutable_engine_result(), tpTrans->getResult()); - - std::string sToken; - std::string sHuman; - - transResultInfo(tpTrans->getResult(), sToken, sHuman); - - result.mutable_engine_result()->set_result(sToken); - result.set_engine_result_code(TERtoInt(tpTrans->getResult())); - result.set_engine_result_message(sHuman); - - uint256 hash = tpTrans->getID(); - result.set_hash(hash.data(), hash.size()); - } - return {result, status}; -} - } // namespace ripple diff --git a/src/ripple/rpc/handlers/Tx.cpp b/src/ripple/rpc/handlers/Tx.cpp index aa941d795c3..4a70f1fe061 100644 --- a/src/ripple/rpc/handlers/Tx.cpp +++ b/src/ripple/rpc/handlers/Tx.cpp @@ -28,7 +28,6 @@ #include #include #include -#include #include namespace ripple { @@ -251,101 +250,6 @@ doTxHelp(RPC::Context& context, TxArgs const& args) return {result, rpcSUCCESS}; } -std::pair -populateProtoResponse( - std::pair const& res, - TxArgs const& args, - RPC::GRPCContext const& context) -{ - org::xrpl::rpc::v1::GetTransactionResponse response; - grpc::Status status = grpc::Status::OK; - RPC::Status const& error = res.second; - TxResult const& result = res.first; - // handle errors - if (error.toErrorCode() != rpcSUCCESS) - { - if (error.toErrorCode() == rpcTXN_NOT_FOUND && - result.searchedAll != TxSearched::unknown) - { - status = { - grpc::StatusCode::NOT_FOUND, - "txn not found. searched_all = " + - to_string( - (result.searchedAll == TxSearched::all ? "true" - : "false"))}; - } - else - { - if (error.toErrorCode() == rpcTXN_NOT_FOUND) - status = {grpc::StatusCode::NOT_FOUND, "txn not found"}; - else - status = {grpc::StatusCode::INTERNAL, error.message()}; - } - } - // no errors - else if (result.txn) - { - auto& txn = result.txn; - - std::shared_ptr stTxn = txn->getSTransaction(); - if (args.binary) - { - Serializer s = stTxn->getSerializer(); - response.set_transaction_binary(s.data(), s.size()); - } - else - { - RPC::convert(*response.mutable_transaction(), stTxn); - } - - response.set_hash(context.params.hash()); - - auto ledgerIndex = txn->getLedger(); - response.set_ledger_index(ledgerIndex); - if (ledgerIndex) - { - auto ct = - context.app.getLedgerMaster().getCloseTimeBySeq(ledgerIndex); - if (ct) - response.mutable_date()->set_value( - ct->time_since_epoch().count()); - } - - RPC::convert( - *response.mutable_meta()->mutable_transaction_result(), - txn->getResult()); - response.mutable_meta()->mutable_transaction_result()->set_result( - transToken(txn->getResult())); - - // populate binary metadata - if (auto blob = std::get_if(&result.meta)) - { - assert(args.binary); - Slice slice = makeSlice(*blob); - response.set_meta_binary(slice.data(), slice.size()); - } - // populate meta data - else if (auto m = std::get_if>(&result.meta)) - { - auto& meta = *m; - if (meta) - { - RPC::convert(*response.mutable_meta(), meta); - auto amt = - getDeliveredAmount(context, stTxn, *meta, txn->getLedger()); - if (amt) - { - RPC::convert( - *response.mutable_meta()->mutable_delivered_amount(), - *amt); - } - } - } - response.set_validated(result.validated); - } - return {response, status}; -} - Json::Value populateJsonResponse( std::pair const& res, @@ -437,48 +341,4 @@ doTxJson(RPC::JsonContext& context) return populateJsonResponse(res, args, context); } -std::pair -doTxGrpc(RPC::GRPCContext& context) -{ - if (!context.app.config().useTxTables()) - { - return { - {}, - {grpc::StatusCode::UNIMPLEMENTED, "Not enabled in configuration."}}; - } - - // return values - org::xrpl::rpc::v1::GetTransactionResponse response; - grpc::Status status = grpc::Status::OK; - - // input - org::xrpl::rpc::v1::GetTransactionRequest& request = context.params; - - TxArgs args; - - if (auto hash = uint256::fromVoidChecked(request.hash())) - { - args.hash = *hash; - } - else - { - grpc::Status errorStatus{ - grpc::StatusCode::INVALID_ARGUMENT, "tx hash malformed"}; - return {response, errorStatus}; - } - - args.binary = request.binary(); - - if (request.ledger_range().ledger_index_min() != 0 && - request.ledger_range().ledger_index_max() != 0) - { - args.ledgerRange = std::make_pair( - request.ledger_range().ledger_index_min(), - request.ledger_range().ledger_index_max()); - } - - std::pair res = doTxHelp(context, args); - return populateProtoResponse(res, args, context); -} - } // namespace ripple diff --git a/src/ripple/rpc/impl/GRPCHelpers.cpp b/src/ripple/rpc/impl/GRPCHelpers.cpp deleted file mode 100644 index e06512ce2c8..00000000000 --- a/src/ripple/rpc/impl/GRPCHelpers.cpp +++ /dev/null @@ -1,2192 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of rippled: https://github.com/ripple/rippled - Copyright (c) 2020 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 - -namespace ripple { -namespace RPC { - -// In the below populateProto* functions, getProto is a function that returns -// a reference to the mutable protobuf message to be populated. The reason this -// is a function, as opposed to just a pointer or reference to the object, -// is that there is no way to get a non-const reference, and getting a pointer -// to the proto object causes default initialization of the object. However, -// if the corresponding field is not present in the STObject, we don't want to -// initialize the proto object. To get around this, getProto is a function that -// is called only if the field is present in the STObject -template -void -populateProtoPrimitive( - L const& getProto, - STObject const& from, - TypedField const& field) -{ - if (!from.isFieldPresent(field)) - return; - - if constexpr (std::is_integral_v) - { - getProto()->set_value(from[field]); - } - else - { - auto v = from[field]; - getProto()->set_value(v.data(), v.size()); - } -} - -template -void -populateProtoVLasString( - T const& getProto, - STObject const& from, - SF_VL const& field) -{ - if (from.isFieldPresent(field)) - { - auto data = from.getFieldVL(field); - getProto()->set_value( - reinterpret_cast(data.data()), data.size()); - } -} - -template -void -populateProtoVec256( - T const& getProto, - STObject const& from, - SF_VECTOR256 const& field) -{ - if (from.isFieldPresent(field)) - { - const STVector256& vec = from.getFieldV256(field); - for (size_t i = 0; i < vec.size(); ++i) - { - uint256 const& elt = vec[i]; - getProto()->set_value(elt.data(), elt.size()); - } - } -} - -template -void -populateProtoAccount( - T const& getProto, - STObject const& from, - SF_ACCOUNT const& field) -{ - if (from.isFieldPresent(field)) - { - getProto()->mutable_value()->set_address( - toBase58(from.getAccountID(field))); - } -} - -template -void -populateProtoAmount( - T const& getProto, - STObject const& from, - SF_AMOUNT const& field) -{ - if (from.isFieldPresent(field)) - { - auto amount = from.getFieldAmount(field); - convert(*getProto(), amount); - } -} - -template -void -populateProtoCurrency( - T const& getProto, - STObject const& from, - SF_UINT160 const& field) -{ - if (from.isFieldPresent(field)) - { - auto cur = from.getFieldH160(field); - auto proto = getProto()->mutable_value(); - proto->set_code(cur.data(), cur.size()); - proto->set_name(to_string(cur)); - } -} - -template -void -populateProtoArray( - T const& getProto, - R const& populateProto, - STObject const& from, - SField const& outerField, - SField const& innerField) -{ - if (from.isFieldPresent(outerField) && - from.peekAtField(outerField).getSType() == SerializedTypeID::STI_ARRAY) - { - auto arr = from.getFieldArray(outerField); - for (auto it = arr.begin(); it != arr.end(); ++it) - { - populateProto(*it, *getProto()); - } - } -} - -template -void -populateClearFlag(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_clear_flag(); }, from, sfClearFlag); -} - -template -void -populateDomain(T& to, STObject const& from) -{ - populateProtoVLasString( - [&to]() { return to.mutable_domain(); }, from, sfDomain); -} - -template -void -populateEmailHash(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_email_hash(); }, from, sfEmailHash); -} - -template -void -populateMessageKey(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_message_key(); }, from, sfMessageKey); -} - -template -void -populateSetFlag(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_set_flag(); }, from, sfSetFlag); -} - -template -void -populateTransferRate(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_transfer_rate(); }, from, sfTransferRate); -} - -template -void -populateTickSize(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_tick_size(); }, from, sfTickSize); -} - -template -void -populateExpiration(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_expiration(); }, from, sfExpiration); -} - -template -void -populateOfferSequence(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_offer_sequence(); }, from, sfOfferSequence); -} - -template -void -populateTakerGets(T& to, STObject const& from) -{ - populateProtoAmount( - [&to]() { return to.mutable_taker_gets(); }, from, sfTakerGets); -} - -template -void -populateTakerPays(T& to, STObject const& from) -{ - populateProtoAmount( - [&to]() { return to.mutable_taker_pays(); }, from, sfTakerPays); -} - -template -void -populateDestination(T& to, STObject const& from) -{ - populateProtoAccount( - [&to]() { return to.mutable_destination(); }, from, sfDestination); -} - -template -void -populateCheckID(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_check_id(); }, from, sfCheckID); -} - -template -void -populateAmount(T& to, STObject const& from) -{ - populateProtoAmount( - [&to]() { return to.mutable_amount(); }, from, sfAmount); -} - -template -void -populateDeliverMin(T& to, STObject const& from) -{ - populateProtoAmount( - [&to]() { return to.mutable_deliver_min(); }, from, sfDeliverMin); -} - -template -void -populateSendMax(T& to, STObject const& from) -{ - populateProtoAmount( - [&to]() { return to.mutable_send_max(); }, from, sfSendMax); -} - -template -void -populateDeliveredAmount(T& to, STObject const& from) -{ - populateProtoAmount( - [&to]() { return to.mutable_delivered_amount(); }, - from, - sfDeliveredAmount); -} - -template -void -populateDestinationTag(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_destination_tag(); }, - from, - sfDestinationTag); -} - -template -void -populateInvoiceID(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_invoice_id(); }, from, sfInvoiceID); -} - -template -void -populateAuthorize(T& to, STObject const& from) -{ - populateProtoAccount( - [&to]() { return to.mutable_authorize(); }, from, sfAuthorize); -} - -template -void -populateUnauthorize(T& to, STObject const& from) -{ - populateProtoAccount( - [&to]() { return to.mutable_unauthorize(); }, from, sfUnauthorize); -} - -template -void -populateOwner(T& to, STObject const& from) -{ - populateProtoAccount([&to]() { return to.mutable_owner(); }, from, sfOwner); -} - -template -void -populateCancelAfter(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_cancel_after(); }, from, sfCancelAfter); -} - -template -void -populateFinishAfter(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_finish_after(); }, from, sfFinishAfter); -} - -template -void -populateCondition(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_condition(); }, from, sfCondition); -} - -template -void -populateFulfillment(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_fulfillment(); }, from, sfFulfillment); -} - -template -void -populateChannel(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_channel(); }, from, sfChannel); -} - -template -void -populateBalance(T& to, STObject const& from) -{ - populateProtoAmount( - [&to]() { return to.mutable_balance(); }, from, sfBalance); -} - -template -void -populatePaymentChannelSignature(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_payment_channel_signature(); }, - from, - sfSignature); -} - -template -void -populatePublicKey(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_public_key(); }, from, sfPublicKey); -} - -template -void -populateSettleDelay(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_settle_delay(); }, from, sfSettleDelay); -} - -template -void -populateRegularKey(T& to, STObject const& from) -{ - populateProtoAccount( - [&to]() { return to.mutable_regular_key(); }, from, sfRegularKey); -} - -template -void -populateSignerQuorum(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_signer_quorum(); }, from, sfSignerQuorum); -} - -template -void -populateTicketCount(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_count(); }, from, sfTicketCount); -} - -template -void -populateLimitAmount(T& to, STObject const& from) -{ - populateProtoAmount( - [&to]() { return to.mutable_limit_amount(); }, from, sfLimitAmount); -} -template -void -populateQualityIn(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_quality_in(); }, from, sfQualityIn); -} - -template -void -populateQualityOut(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_quality_out(); }, from, sfQualityOut); -} - -template -void -populateAccount(T& to, STObject const& from) -{ - populateProtoAccount( - [&to]() { return to.mutable_account(); }, from, sfAccount); -} - -template -void -populateFee(T& to, STObject const& from) -{ - if (from.isFieldPresent(sfFee)) - { - to.mutable_fee()->set_drops(from.getFieldAmount(sfFee).xrp().drops()); - } -} - -template -void -populateSigningPublicKey(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_signing_public_key(); }, - from, - sfSigningPubKey); -} - -template -void -populateTransactionSignature(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_transaction_signature(); }, - from, - sfTxnSignature); -} - -template -void -populateFlags(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_flags(); }, from, sfFlags); -} - -template -void -populateFirstLedgerSequence(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_ledger_sequence(); }, - from, - sfFirstLedgerSequence); -} - -template -void -populateValidatorToDisable(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_validator_to_disable(); }, - from, - sfValidatorToDisable); -} - -template -void -populateValidatorToReEnable(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_validator_to_re_enable(); }, - from, - sfValidatorToReEnable); -} - -template -void -populateLastLedgerSequence(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_last_ledger_sequence(); }, - from, - sfLastLedgerSequence); -} - -template -void -populateSourceTag(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_source_tag(); }, from, sfSourceTag); -} - -template -void -populateAccountTransactionID(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_account_transaction_id(); }, - from, - sfAccountTxnID); -} - -template -void -populateMemoData(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_memo_data(); }, from, sfMemoData); -} - -template -void -populateMemoFormat(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_memo_format(); }, from, sfMemoFormat); -} - -template -void -populateMemoType(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_memo_type(); }, from, sfMemoType); -} - -template -void -populateSequence(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_sequence(); }, from, sfSequence); -} - -template -void -populateAmendment(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_amendment(); }, from, sfAmendment); -} - -template -void -populateCloseTime(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_close_time(); }, from, sfCloseTime); -} - -template -void -populateSignerWeight(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_signer_weight(); }, from, sfSignerWeight); -} - -template -void -populateAmendments(T& to, STObject const& from) -{ - populateProtoVec256( - [&to]() { return to.add_amendments(); }, from, sfAmendments); -} - -template -void -populateOwnerCount(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_owner_count(); }, from, sfOwnerCount); -} - -template -void -populatePreviousTransactionID(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_previous_transaction_id(); }, - from, - sfPreviousTxnID); -} - -template -void -populatePreviousTransactionLedgerSequence(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_previous_transaction_ledger_sequence(); }, - from, - sfPreviousTxnLgrSeq); -} - -template -void -populateLowLimit(T& to, STObject const& from) -{ - populateProtoAmount( - [&to]() { return to.mutable_low_limit(); }, from, sfLowLimit); -} - -template -void -populateHighLimit(T& to, STObject const& from) -{ - populateProtoAmount( - [&to]() { return to.mutable_high_limit(); }, from, sfHighLimit); -} - -template -void -populateLowNode(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_low_node(); }, from, sfLowNode); -} - -template -void -populateHighNode(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_high_node(); }, from, sfHighNode); -} - -template -void -populateLowQualityIn(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_low_quality_in(); }, from, sfLowQualityIn); -} - -template -void -populateLowQualityOut(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_low_quality_out(); }, - from, - sfLowQualityOut); -} - -template -void -populateHighQualityIn(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_high_quality_in(); }, - from, - sfHighQualityIn); -} - -template -void -populateHighQualityOut(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_high_quality_out(); }, - from, - sfHighQualityOut); -} - -template -void -populateBookDirectory(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_book_directory(); }, from, sfBookDirectory); -} - -template -void -populateBookNode(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_book_node(); }, from, sfBookNode); -} - -template -void -populateOwnerNode(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_owner_node(); }, from, sfOwnerNode); -} - -template -void -populateSignerListID(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_signer_list_id(); }, from, sfSignerListID); -} - -template -void -populateWalletLocator(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_wallet_locator(); }, from, sfWalletLocator); -} - -template -void -populateTicketSequence(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_ticket_sequence(); }, - from, - sfTicketSequence); -} - -template -void -populateHashes(T& to, STObject const& from) -{ - populateProtoVec256([&to]() { return to.add_hashes(); }, from, sfHashes); -} - -template -void -populateIndexes(T& to, STObject const& from) -{ - populateProtoVec256([&to]() { return to.add_indexes(); }, from, sfIndexes); -} - -template -void -populateNFTokenOffers(T& to, STObject const& from) -{ - populateProtoVec256( - [&to]() { return to.add_nftoken_offers(); }, from, sfNFTokenOffers); -} - -template -void -populateRootIndex(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_root_index(); }, from, sfRootIndex); -} - -template -void -populateIndexNext(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_index_next(); }, from, sfIndexNext); -} - -template -void -populateIndexPrevious(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_index_previous(); }, from, sfIndexPrevious); -} - -template -void -populateTakerPaysCurrency(T& to, STObject const& from) -{ - populateProtoCurrency( - [&to]() { return to.mutable_taker_pays_currency(); }, - from, - sfTakerPaysCurrency); -} - -template -void -populateTakerPaysIssuer(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_taker_pays_issuer(); }, - from, - sfTakerPaysIssuer); -} - -template -void -populateTakerGetsCurrency(T& to, STObject const& from) -{ - populateProtoCurrency( - [&to]() { return to.mutable_taker_gets_currency(); }, - from, - sfTakerGetsCurrency); -} - -template -void -populateTakerGetsIssuer(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_taker_gets_issuer(); }, - from, - sfTakerGetsIssuer); -} - -template -void -populateDestinationNode(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_destination_node(); }, - from, - sfDestinationNode); -} - -template -void -populateBaseFee(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_base_fee(); }, from, sfBaseFee); -} - -template -void -populateReferenceFeeUnits(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_reference_fee_units(); }, - from, - sfReferenceFeeUnits); -} - -template -void -populatePreviousPageMin(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_previous_page_min(); }, - from, - sfPreviousPageMin); -} - -template -void -populateNextPageMin(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_next_page_min(); }, from, sfNextPageMin); -} - -template -void -populateNFTokenID(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_nftoken_id(); }, from, sfNFTokenID); -} - -template -void -populateURI(T& to, STObject const& from) -{ - populateProtoVLasString([&to]() { return to.mutable_uri(); }, from, sfURI); -} - -template -void -populateBurnedNFTokens(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_burned_nftokens(); }, - from, - sfBurnedNFTokens); -} - -template -void -populateMintedNFTokens(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_minted_nftokens(); }, - from, - sfMintedNFTokens); -} - -template -void -populateNFTokenMinter(T& to, STObject const& from) -{ - populateProtoAccount( - [&to]() { return to.mutable_nftoken_minter(); }, from, sfNFTokenMinter); -} - -template -void -populateNFTokenBrokerFee(T& to, STObject const& from) -{ - populateProtoAmount( - [&to]() { return to.mutable_nftoken_broker_fee(); }, - from, - sfNFTokenBrokerFee); -} - -template -void -populateNFTokenBuyOffer(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_nftoken_buy_offer(); }, - from, - sfNFTokenBuyOffer); -} - -template -void -populateNFTokenSellOffer(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_nftoken_sell_offer(); }, - from, - sfNFTokenSellOffer); -} - -template -void -populateIssuer(T& to, STObject const& from) -{ - populateProtoAccount( - [&to]() { return to.mutable_issuer(); }, from, sfIssuer); -} - -template -void -populateNFTokenTaxon(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_nftoken_taxon(); }, from, sfNFTokenTaxon); -} - -template -void -populateTransferFee(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_transfer_fee(); }, from, sfTransferFee); -} - -template -void -populateReserveBase(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_reserve_base(); }, from, sfReserveBase); -} - -template -void -populateReserveIncrement(T& to, STObject const& from) -{ - populateProtoPrimitive( - [&to]() { return to.mutable_reserve_increment(); }, - from, - sfReserveIncrement); -} - -template -void -populateSignerEntries(T& to, STObject const& from) -{ - populateProtoArray( - [&to]() { return to.add_signer_entries(); }, - [](auto& innerObj, auto& innerProto) { - populateAccount(innerProto, innerObj); - populateSignerWeight(innerProto, innerObj); - populateWalletLocator(innerProto, innerObj); - }, - from, - sfSignerEntries, - sfSignerEntry); -} - -template -void -populateDisabledValidators(T& to, STObject const& from) -{ - populateProtoArray( - [&to]() { return to.add_disabled_validators(); }, - [](auto& innerObj, auto& innerProto) { - populatePublicKey(innerProto, innerObj); - populateFirstLedgerSequence(innerProto, innerObj); - }, - from, - sfDisabledValidators, - sfDisabledValidator); -} - -template -void -populateMemos(T& to, STObject const& from) -{ - populateProtoArray( - [&to]() { return to.add_memos(); }, - [](auto& innerObj, auto& innerProto) { - populateMemoData(innerProto, innerObj); - populateMemoType(innerProto, innerObj); - populateMemoFormat(innerProto, innerObj); - }, - from, - sfMemos, - sfMemo); -} - -template -void -populateSigners(T& to, STObject const& from) -{ - populateProtoArray( - [&to]() { return to.add_signers(); }, - [](auto& innerObj, auto& innerProto) { - populateAccount(innerProto, innerObj); - populateTransactionSignature(innerProto, innerObj); - populateSigningPublicKey(innerProto, innerObj); - }, - from, - sfSigners, - sfSigner); -} - -template -void -populateMajorities(T& to, STObject const& from) -{ - populateProtoArray( - [&to]() { return to.add_majorities(); }, - [](auto innerObj, auto innerProto) { - populateAmendment(innerProto, innerObj); - populateCloseTime(innerProto, innerObj); - }, - from, - sfMajorities, - sfMajority); -} - -template -void -populateNFTokens(T& to, STObject const& from) -{ - populateProtoArray( - [&to]() { return to.add_nftokens(); }, - [](auto innerObj, auto innerProto) { - populateNFTokenID(innerProto, innerObj); - populateURI(innerProto, innerObj); - }, - from, - sfNFTokens, - sfNFToken); -} - -void -convert(org::xrpl::rpc::v1::TransactionResult& to, TER from) -{ - if (isTecClaim(from)) - { - to.set_result_type( - org::xrpl::rpc::v1::TransactionResult::RESULT_TYPE_TEC); - } - if (isTefFailure(from)) - { - to.set_result_type( - org::xrpl::rpc::v1::TransactionResult::RESULT_TYPE_TEF); - } - if (isTelLocal(from)) - { - to.set_result_type( - org::xrpl::rpc::v1::TransactionResult::RESULT_TYPE_TEL); - } - if (isTemMalformed(from)) - { - to.set_result_type( - org::xrpl::rpc::v1::TransactionResult::RESULT_TYPE_TEM); - } - if (isTerRetry(from)) - { - to.set_result_type( - org::xrpl::rpc::v1::TransactionResult::RESULT_TYPE_TER); - } - if (isTesSuccess(from)) - { - to.set_result_type( - org::xrpl::rpc::v1::TransactionResult::RESULT_TYPE_TES); - } -} - -void -convert(org::xrpl::rpc::v1::AccountSet& to, STObject const& from) -{ - populateClearFlag(to, from); - - populateDomain(to, from); - - populateEmailHash(to, from); - - populateMessageKey(to, from); - - populateNFTokenMinter(to, from); - - populateSetFlag(to, from); - - populateTransferRate(to, from); - - populateTickSize(to, from); -} - -void -convert(org::xrpl::rpc::v1::OfferCreate& to, STObject const& from) -{ - populateExpiration(to, from); - - populateOfferSequence(to, from); - - populateTakerGets(to, from); - - populateTakerPays(to, from); -} - -void -convert(org::xrpl::rpc::v1::OfferCancel& to, STObject const& from) -{ - populateOfferSequence(to, from); -} - -void -convert(org::xrpl::rpc::v1::AccountDelete& to, STObject const& from) -{ - populateDestination(to, from); -} - -void -convert(org::xrpl::rpc::v1::CheckCancel& to, STObject const& from) -{ - populateCheckID(to, from); -} - -void -convert(org::xrpl::rpc::v1::CheckCash& to, STObject const& from) -{ - populateCheckID(to, from); - - populateAmount(to, from); - - populateDeliverMin(to, from); -} - -void -convert(org::xrpl::rpc::v1::CheckCreate& to, STObject const& from) -{ - populateDestination(to, from); - - populateSendMax(to, from); - - populateDestinationTag(to, from); - - populateExpiration(to, from); - - populateInvoiceID(to, from); -} - -void -convert(org::xrpl::rpc::v1::DepositPreauth& to, STObject const& from) -{ - populateAuthorize(to, from); - - populateUnauthorize(to, from); -} - -void -convert(org::xrpl::rpc::v1::EscrowCancel& to, STObject const& from) -{ - populateOwner(to, from); - - populateOfferSequence(to, from); -} - -void -convert(org::xrpl::rpc::v1::EscrowCreate& to, STObject const& from) -{ - populateAmount(to, from); - - populateDestination(to, from); - - populateCancelAfter(to, from); - - populateFinishAfter(to, from); - - populateCondition(to, from); - - populateDestinationTag(to, from); -} - -void -convert(org::xrpl::rpc::v1::EscrowFinish& to, STObject const& from) -{ - populateOwner(to, from); - - populateOfferSequence(to, from); - - populateCondition(to, from); - - populateFulfillment(to, from); -} - -void -convert(org::xrpl::rpc::v1::NFTokenAcceptOffer& to, STObject const& from) -{ - populateNFTokenBrokerFee(to, from); - - populateNFTokenBuyOffer(to, from); - - populateNFTokenSellOffer(to, from); -} - -void -convert(org::xrpl::rpc::v1::NFTokenBurn& to, STObject const& from) -{ - populateOwner(to, from); - - populateNFTokenID(to, from); -} - -void -convert(org::xrpl::rpc::v1::NFTokenCancelOffer& to, STObject const& from) -{ - populateNFTokenOffers(to, from); -} - -void -convert(org::xrpl::rpc::v1::NFTokenCreateOffer& to, STObject const& from) -{ - populateAmount(to, from); - - populateDestination(to, from); - - populateExpiration(to, from); - - populateOwner(to, from); - - populateNFTokenID(to, from); -} - -void -convert(org::xrpl::rpc::v1::NFTokenMint& to, STObject const& from) -{ - populateIssuer(to, from); - - populateNFTokenTaxon(to, from); - - populateTransferFee(to, from); - - populateURI(to, from); -} - -void -convert(org::xrpl::rpc::v1::PaymentChannelClaim& to, STObject const& from) -{ - populateChannel(to, from); - - populateBalance(to, from); - - populateAmount(to, from); - - populatePaymentChannelSignature(to, from); - - populatePublicKey(to, from); -} - -void -convert(org::xrpl::rpc::v1::PaymentChannelCreate& to, STObject const& from) -{ - populateAmount(to, from); - - populateDestination(to, from); - - populateSettleDelay(to, from); - - populatePublicKey(to, from); - - populateCancelAfter(to, from); - - populateDestinationTag(to, from); -} - -void -convert(org::xrpl::rpc::v1::PaymentChannelFund& to, STObject const& from) -{ - populateChannel(to, from); - - populateAmount(to, from); - - populateExpiration(to, from); -} - -void -convert(org::xrpl::rpc::v1::SetRegularKey& to, STObject const& from) -{ - populateRegularKey(to, from); -} - -void -convert(org::xrpl::rpc::v1::SignerListSet& to, STObject const& from) -{ - populateSignerQuorum(to, from); - - populateSignerEntries(to, from); -} - -void -convert(org::xrpl::rpc::v1::TicketCreate& to, STObject const& from) -{ - populateTicketCount(to, from); -} - -void -convert(org::xrpl::rpc::v1::TrustSet& to, STObject const& from) -{ - populateLimitAmount(to, from); - - populateQualityIn(to, from); - - populateQualityOut(to, from); -} - -void -convert(org::xrpl::rpc::v1::Payment& to, STObject const& from) -{ - populateAmount(to, from); - - populateDestination(to, from); - - populateDestinationTag(to, from); - - populateInvoiceID(to, from); - - populateSendMax(to, from); - - populateDeliverMin(to, from); - - if (from.isFieldPresent(sfPaths)) - { - // populate path data - STPathSet const& pathset = from.getFieldPathSet(sfPaths); - for (auto it = pathset.begin(); it < pathset.end(); ++it) - { - STPath const& path = *it; - - org::xrpl::rpc::v1::Payment_Path* protoPath = to.add_paths(); - - for (auto it2 = path.begin(); it2 != path.end(); ++it2) - { - org::xrpl::rpc::v1::Payment_PathElement* protoElement = - protoPath->add_elements(); - STPathElement const& elt = *it2; - - if (elt.isOffer()) - { - if (elt.hasCurrency()) - { - Currency const& currency = elt.getCurrency(); - protoElement->mutable_currency()->set_name( - to_string(currency)); - } - if (elt.hasIssuer()) - { - AccountID const& issuer = elt.getIssuerID(); - protoElement->mutable_issuer()->set_address( - toBase58(issuer)); - } - } - else if (elt.isAccount()) - { - AccountID const& pathAccount = elt.getAccountID(); - protoElement->mutable_account()->set_address( - toBase58(pathAccount)); - } - } - } - } -} - -void -convert(org::xrpl::rpc::v1::AccountRoot& to, STObject const& from) -{ - populateAccount(to, from); - - populateBalance(to, from); - - populateSequence(to, from); - - populateFlags(to, from); - - populateOwnerCount(to, from); - - populatePreviousTransactionID(to, from); - - populatePreviousTransactionLedgerSequence(to, from); - - populateAccountTransactionID(to, from); - - populateDomain(to, from); - - populateEmailHash(to, from); - - populateMessageKey(to, from); - - populateRegularKey(to, from); - - populateTickSize(to, from); - - populateTransferRate(to, from); - - populateBurnedNFTokens(to, from); - - populateMintedNFTokens(to, from); - - populateNFTokenMinter(to, from); -} - -void -convert(org::xrpl::rpc::v1::Amendments& to, STObject const& from) -{ - populateAmendments(to, from); - - populateMajorities(to, from); -} - -void -convert(org::xrpl::rpc::v1::Check& to, STObject const& from) -{ - populateAccount(to, from); - - populateDestination(to, from); - - populateFlags(to, from); - - populateOwnerNode(to, from); - - populatePreviousTransactionID(to, from); - - populatePreviousTransactionLedgerSequence(to, from); - - populateSendMax(to, from); - - populateSequence(to, from); - - populateDestinationNode(to, from); - - populateDestinationTag(to, from); - - populateExpiration(to, from); - - populateInvoiceID(to, from); - - populateSourceTag(to, from); -} - -void -convert(org::xrpl::rpc::v1::DepositPreauthObject& to, STObject const& from) -{ - populateAccount(to, from); - - populateAuthorize(to, from); - - populateFlags(to, from); - - populateOwnerNode(to, from); - - populatePreviousTransactionID(to, from); - - populatePreviousTransactionLedgerSequence(to, from); -} - -void -convert(org::xrpl::rpc::v1::FeeSettings& to, STObject const& from) -{ - populateBaseFee(to, from); - - populateReferenceFeeUnits(to, from); - - populateReserveBase(to, from); - - populateReserveIncrement(to, from); - - populateFlags(to, from); -} - -void -convert(org::xrpl::rpc::v1::Escrow& to, STObject const& from) -{ - populateAccount(to, from); - - populateDestination(to, from); - - populateAmount(to, from); - - populateCondition(to, from); - - populateCancelAfter(to, from); - - populateFinishAfter(to, from); - - populateFlags(to, from); - - populateSourceTag(to, from); - - populateDestinationTag(to, from); - - populateOwnerNode(to, from); - - populateDestinationNode(to, from); - - populatePreviousTransactionID(to, from); - - populatePreviousTransactionLedgerSequence(to, from); -} - -void -convert(org::xrpl::rpc::v1::LedgerHashes& to, STObject const& from) -{ - populateLastLedgerSequence(to, from); - - populateHashes(to, from); - - populateFlags(to, from); -} - -void -convert(org::xrpl::rpc::v1::PayChannel& to, STObject const& from) -{ - populateAccount(to, from); - - populateAmount(to, from); - - populateBalance(to, from); - - populatePublicKey(to, from); - - populateSettleDelay(to, from); - - populateOwnerNode(to, from); - - populatePreviousTransactionID(to, from); - - populatePreviousTransactionLedgerSequence(to, from); - - populateFlags(to, from); - - populateExpiration(to, from); - - populateCancelAfter(to, from); - - populateSourceTag(to, from); - - populateDestinationTag(to, from); - - populateDestinationNode(to, from); -} - -void -convert(org::xrpl::rpc::v1::DirectoryNode& to, STObject const& from) -{ - populateFlags(to, from); - - populateRootIndex(to, from); - - populateIndexes(to, from); - - populateIndexNext(to, from); - - populateIndexPrevious(to, from); - - populateTakerPaysIssuer(to, from); - - populateTakerPaysCurrency(to, from); - - populateTakerGetsCurrency(to, from); - - populateTakerGetsIssuer(to, from); - - populateNFTokenID(to, from); -} - -void -convert(org::xrpl::rpc::v1::Offer& to, STObject const& from) -{ - populateAccount(to, from); - - populateSequence(to, from); - - populateFlags(to, from); - - populateTakerPays(to, from); - - populateTakerGets(to, from); - - populateBookDirectory(to, from); - - populateBookNode(to, from); -} - -void -convert(org::xrpl::rpc::v1::RippleState& to, STObject const& from) -{ - populateBalance(to, from); - - populateFlags(to, from); - - populateLowNode(to, from); - - populateHighNode(to, from); - - populateLowQualityIn(to, from); - - populateLowQualityOut(to, from); - - populateHighQualityIn(to, from); - - populateHighQualityOut(to, from); - - populatePreviousTransactionID(to, from); - - populatePreviousTransactionLedgerSequence(to, from); -} - -void -convert(org::xrpl::rpc::v1::SignerList& to, STObject const& from) -{ - populateFlags(to, from); - - populatePreviousTransactionID(to, from); - - populatePreviousTransactionLedgerSequence(to, from); - - populateOwnerNode(to, from); - - populateSignerEntries(to, from); - - populateSignerQuorum(to, from); - - populateSignerListID(to, from); -} - -void -convert(org::xrpl::rpc::v1::NegativeUNL& to, STObject const& from) -{ - populateDisabledValidators(to, from); - - populateValidatorToDisable(to, from); - - populateValidatorToReEnable(to, from); - - populateFlags(to, from); -} - -void -convert(org::xrpl::rpc::v1::TicketObject& to, STObject const& from) -{ - populateAccount(to, from); - - populateFlags(to, from); - - populateOwnerNode(to, from); - - populatePreviousTransactionID(to, from); - - populatePreviousTransactionLedgerSequence(to, from); - - populateTicketSequence(to, from); -} - -void -convert(org::xrpl::rpc::v1::NFTokenOffer& to, STObject const& from) -{ - populateFlags(to, from); - - populateOwner(to, from); - - populateNFTokenID(to, from); - - populateAmount(to, from); - - populateOwnerNode(to, from); - - populateDestination(to, from); - - populateExpiration(to, from); - - populatePreviousTransactionID(to, from); - - populatePreviousTransactionLedgerSequence(to, from); -} - -void -convert(org::xrpl::rpc::v1::NFTokenPage& to, STObject const& from) -{ - populateFlags(to, from); - - populatePreviousPageMin(to, from); - - populateNextPageMin(to, from); - - populateNFTokens(to, from); - - populatePreviousTransactionID(to, from); - - populatePreviousTransactionLedgerSequence(to, from); -} - -void -setLedgerEntryType( - org::xrpl::rpc::v1::AffectedNode& proto, - std::uint16_t lgrType) -{ - switch (lgrType) - { - case ltACCOUNT_ROOT: - proto.set_ledger_entry_type( - org::xrpl::rpc::v1::LEDGER_ENTRY_TYPE_ACCOUNT_ROOT); - break; - case ltDIR_NODE: - proto.set_ledger_entry_type( - org::xrpl::rpc::v1::LEDGER_ENTRY_TYPE_DIRECTORY_NODE); - break; - case ltRIPPLE_STATE: - proto.set_ledger_entry_type( - org::xrpl::rpc::v1::LEDGER_ENTRY_TYPE_RIPPLE_STATE); - break; - case ltSIGNER_LIST: - proto.set_ledger_entry_type( - org::xrpl::rpc::v1::LEDGER_ENTRY_TYPE_SIGNER_LIST); - break; - case ltOFFER: - proto.set_ledger_entry_type( - org::xrpl::rpc::v1::LEDGER_ENTRY_TYPE_OFFER); - break; - case ltLEDGER_HASHES: - proto.set_ledger_entry_type( - org::xrpl::rpc::v1::LEDGER_ENTRY_TYPE_LEDGER_HASHES); - break; - case ltAMENDMENTS: - proto.set_ledger_entry_type( - org::xrpl::rpc::v1::LEDGER_ENTRY_TYPE_AMENDMENTS); - break; - case ltFEE_SETTINGS: - proto.set_ledger_entry_type( - org::xrpl::rpc::v1::LEDGER_ENTRY_TYPE_FEE_SETTINGS); - break; - case ltESCROW: - proto.set_ledger_entry_type( - org::xrpl::rpc::v1::LEDGER_ENTRY_TYPE_ESCROW); - break; - case ltPAYCHAN: - proto.set_ledger_entry_type( - org::xrpl::rpc::v1::LEDGER_ENTRY_TYPE_PAY_CHANNEL); - break; - case ltCHECK: - proto.set_ledger_entry_type( - org::xrpl::rpc::v1::LEDGER_ENTRY_TYPE_CHECK); - break; - case ltDEPOSIT_PREAUTH: - proto.set_ledger_entry_type( - org::xrpl::rpc::v1::LEDGER_ENTRY_TYPE_DEPOSIT_PREAUTH); - break; - case ltNEGATIVE_UNL: - proto.set_ledger_entry_type( - org::xrpl::rpc::v1::LEDGER_ENTRY_TYPE_NEGATIVE_UNL); - break; - case ltTICKET: - proto.set_ledger_entry_type( - org::xrpl::rpc::v1::LEDGER_ENTRY_TYPE_TICKET); - break; - case ltNFTOKEN_OFFER: - proto.set_ledger_entry_type( - org::xrpl::rpc::v1::LEDGER_ENTRY_TYPE_NFTOKEN_OFFER); - break; - case ltNFTOKEN_PAGE: - proto.set_ledger_entry_type( - org::xrpl::rpc::v1::LEDGER_ENTRY_TYPE_NFTOKEN_PAGE); - break; - } -} - -template -void -convert(T& to, STObject& from, std::uint16_t type) -{ - switch (type) - { - case ltACCOUNT_ROOT: - RPC::convert(*to.mutable_account_root(), from); - break; - case ltAMENDMENTS: - RPC::convert(*to.mutable_amendments(), from); - break; - case ltDIR_NODE: - RPC::convert(*to.mutable_directory_node(), from); - break; - case ltRIPPLE_STATE: - RPC::convert(*to.mutable_ripple_state(), from); - break; - case ltSIGNER_LIST: - RPC::convert(*to.mutable_signer_list(), from); - break; - case ltOFFER: - RPC::convert(*to.mutable_offer(), from); - break; - case ltLEDGER_HASHES: - RPC::convert(*to.mutable_ledger_hashes(), from); - break; - case ltFEE_SETTINGS: - RPC::convert(*to.mutable_fee_settings(), from); - break; - case ltESCROW: - RPC::convert(*to.mutable_escrow(), from); - break; - case ltPAYCHAN: - RPC::convert(*to.mutable_pay_channel(), from); - break; - case ltCHECK: - RPC::convert(*to.mutable_check(), from); - break; - case ltDEPOSIT_PREAUTH: - RPC::convert(*to.mutable_deposit_preauth(), from); - break; - case ltNEGATIVE_UNL: - RPC::convert(*to.mutable_negative_unl(), from); - break; - case ltTICKET: - RPC::convert(*to.mutable_ticket(), from); - break; - case ltNFTOKEN_OFFER: - RPC::convert(*to.mutable_nftoken_offer(), from); - break; - case ltNFTOKEN_PAGE: - RPC::convert(*to.mutable_nftoken_page(), from); - break; - } -} - -template -void -populateFields( - T const& getProto, - STObject& obj, - SField const& field, - uint16_t lgrType) -{ - // final fields - if (obj.isFieldPresent(field)) - { - STObject& data = obj.getField(field).downcast(); - - convert(*getProto(), data, lgrType); - } -} - -template -void -populateFinalFields(T const& getProto, STObject& obj, uint16_t lgrType) -{ - populateFields(getProto, obj, sfFinalFields, lgrType); -} - -template -void -populatePreviousFields(T const& getProto, STObject& obj, uint16_t lgrType) -{ - populateFields(getProto, obj, sfPreviousFields, lgrType); -} - -template -void -populateNewFields(T const& getProto, STObject& obj, uint16_t lgrType) -{ - populateFields(getProto, obj, sfNewFields, lgrType); -} - -void -convert(org::xrpl::rpc::v1::Meta& to, std::shared_ptr const& from) -{ - to.set_transaction_index(from->getIndex()); - - convert(*to.mutable_transaction_result(), from->getResultTER()); - to.mutable_transaction_result()->set_result( - transToken(from->getResultTER())); - - if (from->hasDeliveredAmount()) - convert(*to.mutable_delivered_amount(), from->getDeliveredAmount()); - - STArray& nodes = from->getNodes(); - for (auto it = nodes.begin(); it != nodes.end(); ++it) - { - STObject& obj = *it; - org::xrpl::rpc::v1::AffectedNode* node = to.add_affected_nodes(); - - // ledger index - uint256 ledgerIndex = obj.getFieldH256(sfLedgerIndex); - node->set_ledger_index(ledgerIndex.data(), ledgerIndex.size()); - - // ledger entry type - std::uint16_t lgrType = obj.getFieldU16(sfLedgerEntryType); - setLedgerEntryType(*node, lgrType); - - // modified node - if (obj.getFName() == sfModifiedNode) - { - populateFinalFields( - [&node]() { - return node->mutable_modified_node() - ->mutable_final_fields(); - }, - obj, - lgrType); - - populatePreviousFields( - [&node]() { - return node->mutable_modified_node() - ->mutable_previous_fields(); - }, - obj, - lgrType); - - populatePreviousTransactionID(*node->mutable_modified_node(), obj); - - populatePreviousTransactionLedgerSequence( - *node->mutable_modified_node(), obj); - } - // created node - else if (obj.getFName() == sfCreatedNode) - { - populateNewFields( - [&node]() { - return node->mutable_created_node()->mutable_new_fields(); - }, - obj, - lgrType); - } - // deleted node - else if (obj.getFName() == sfDeletedNode) - { - populateFinalFields( - [&node]() { - return node->mutable_deleted_node()->mutable_final_fields(); - }, - obj, - lgrType); - } - } -} - -void -convert( - org::xrpl::rpc::v1::QueueData& to, - std::vector const& from) -{ - if (!from.empty()) - { - to.set_txn_count(from.size()); - - std::uint32_t seqCount = 0; - std::uint32_t ticketCount = 0; - std::optional lowestSeq; - std::optional highestSeq; - std::optional lowestTicket; - std::optional highestTicket; - bool anyAuthChanged = false; - XRPAmount totalSpend(0); - - for (auto const& tx : from) - { - org::xrpl::rpc::v1::QueuedTransaction& qt = *to.add_transactions(); - - if (tx.seqProxy.isSeq()) - { - qt.mutable_sequence()->set_value(tx.seqProxy.value()); - ++seqCount; - if (!lowestSeq) - lowestSeq = tx.seqProxy.value(); - highestSeq = tx.seqProxy.value(); - } - else - { - qt.mutable_ticket()->set_value(tx.seqProxy.value()); - ++ticketCount; - if (!lowestTicket) - lowestTicket = tx.seqProxy.value(); - highestTicket = tx.seqProxy.value(); - } - - qt.set_fee_level(tx.feeLevel.fee()); - if (tx.lastValid) - qt.mutable_last_ledger_sequence()->set_value(*tx.lastValid); - - qt.mutable_fee()->set_drops(tx.consequences.fee().drops()); - auto const spend = - tx.consequences.potentialSpend() + tx.consequences.fee(); - qt.mutable_max_spend_drops()->set_drops(spend.drops()); - totalSpend += spend; - bool const authChanged = tx.consequences.isBlocker(); - if (authChanged) - anyAuthChanged = true; - qt.set_auth_change(authChanged); - } - - if (seqCount) - to.set_sequence_count(seqCount); - if (ticketCount) - to.set_ticket_count(ticketCount); - if (lowestSeq) - to.set_lowest_sequence(*lowestSeq); - if (highestSeq) - to.set_highest_sequence(*highestSeq); - if (lowestTicket) - to.set_lowest_ticket(*lowestTicket); - if (highestTicket) - to.set_highest_ticket(*highestTicket); - - to.set_auth_change_queued(anyAuthChanged); - to.mutable_max_spend_drops_total()->set_drops(totalSpend.drops()); - } -} - -void -convert( - org::xrpl::rpc::v1::Transaction& to, - std::shared_ptr const& from) -{ - STObject const& fromObj = *from; - - populateAccount(to, fromObj); - - populateFee(to, fromObj); - - populateSequence(to, fromObj); - - populateSigningPublicKey(to, fromObj); - - populateTransactionSignature(to, fromObj); - - populateFlags(to, fromObj); - - populateLastLedgerSequence(to, fromObj); - - populateSourceTag(to, fromObj); - - populateAccountTransactionID(to, fromObj); - - populateMemos(to, fromObj); - - populateSigners(to, fromObj); - - populateTicketSequence(to, fromObj); - - auto type = safe_cast(fromObj.getFieldU16(sfTransactionType)); - - switch (type) - { - case TxType::ttPAYMENT: - convert(*to.mutable_payment(), fromObj); - break; - case TxType::ttESCROW_CREATE: - convert(*to.mutable_escrow_create(), fromObj); - break; - case TxType::ttESCROW_FINISH: - convert(*to.mutable_escrow_finish(), fromObj); - break; - case TxType::ttACCOUNT_SET: - convert(*to.mutable_account_set(), fromObj); - break; - case TxType::ttESCROW_CANCEL: - convert(*to.mutable_escrow_cancel(), fromObj); - break; - case TxType::ttREGULAR_KEY_SET: - convert(*to.mutable_set_regular_key(), fromObj); - break; - case TxType::ttOFFER_CREATE: - convert(*to.mutable_offer_create(), fromObj); - break; - case TxType::ttOFFER_CANCEL: - convert(*to.mutable_offer_cancel(), fromObj); - break; - case TxType::ttSIGNER_LIST_SET: - convert(*to.mutable_signer_list_set(), fromObj); - break; - case TxType::ttPAYCHAN_CREATE: - convert(*to.mutable_payment_channel_create(), fromObj); - break; - case TxType::ttPAYCHAN_FUND: - convert(*to.mutable_payment_channel_fund(), fromObj); - break; - case TxType::ttPAYCHAN_CLAIM: - convert(*to.mutable_payment_channel_claim(), fromObj); - break; - case TxType::ttCHECK_CREATE: - convert(*to.mutable_check_create(), fromObj); - break; - case TxType::ttCHECK_CASH: - convert(*to.mutable_check_cash(), fromObj); - break; - case TxType::ttCHECK_CANCEL: - convert(*to.mutable_check_cancel(), fromObj); - break; - case TxType::ttDEPOSIT_PREAUTH: - convert(*to.mutable_deposit_preauth(), fromObj); - break; - case TxType::ttTRUST_SET: - convert(*to.mutable_trust_set(), fromObj); - break; - case TxType::ttACCOUNT_DELETE: - convert(*to.mutable_account_delete(), fromObj); - break; - case TxType::ttTICKET_CREATE: - convert(*to.mutable_ticket_create(), fromObj); - break; - case TxType::ttNFTOKEN_MINT: - convert(*to.mutable_nftoken_mint(), fromObj); - break; - case TxType::ttNFTOKEN_BURN: - convert(*to.mutable_nftoken_burn(), fromObj); - break; - case TxType::ttNFTOKEN_CREATE_OFFER: - convert(*to.mutable_nftoken_create_offer(), fromObj); - break; - case TxType::ttNFTOKEN_CANCEL_OFFER: - convert(*to.mutable_nftoken_cancel_offer(), fromObj); - break; - case TxType::ttNFTOKEN_ACCEPT_OFFER: - convert(*to.mutable_nftoken_accept_offer(), fromObj); - break; - default: - break; - } -} - -} // namespace RPC -} // namespace ripple diff --git a/src/ripple/rpc/impl/GRPCHelpers.h b/src/ripple/rpc/impl/GRPCHelpers.h deleted file mode 100644 index 80c34f96c29..00000000000 --- a/src/ripple/rpc/impl/GRPCHelpers.h +++ /dev/null @@ -1,90 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of rippled: https://github.com/ripple/rippled - Copyright (c) 2020 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. -*/ -//============================================================================== - -#ifndef RIPPLE_RPC_GRPCHELPERS_H_INCLUDED -#define RIPPLE_RPC_GRPCHELPERS_H_INCLUDED - -#include "org/xrpl/rpc/v1/get_account_info.pb.h" -#include "org/xrpl/rpc/v1/ledger_objects.pb.h" -#include "org/xrpl/rpc/v1/meta.pb.h" -#include "org/xrpl/rpc/v1/transaction.pb.h" - -#include -#include -#include -#include -#include - -#include - -namespace ripple { -namespace RPC { - -void -convert(org::xrpl::rpc::v1::Meta& to, std::shared_ptr const& from); - -void -convert( - org::xrpl::rpc::v1::QueueData& to, - std::vector const& from); - -void -convert( - org::xrpl::rpc::v1::Transaction& to, - std::shared_ptr const& from); - -void -convert(org::xrpl::rpc::v1::TransactionResult& to, TER from); - -void -convert(org::xrpl::rpc::v1::AccountRoot& to, STObject const& from); - -void -convert(org::xrpl::rpc::v1::SignerList& to, STObject const& from); - -void -convert(org::xrpl::rpc::v1::NegativeUNL& to, STObject const& from); - -template -void -convert(T& to, STAmount const& from) -{ - if (from.native()) - { - to.mutable_value()->mutable_xrp_amount()->set_drops(from.xrp().drops()); - } - else - { - Issue const& issue = from.issue(); - - org::xrpl::rpc::v1::IssuedCurrencyAmount* issued = - to.mutable_value()->mutable_issued_currency_amount(); - - issued->mutable_currency()->set_name(to_string(issue.currency)); - issued->mutable_currency()->set_code( - issue.currency.data(), Currency::size()); - issued->mutable_issuer()->set_address(toBase58(issue.account)); - issued->set_value(to_string(from.iou())); - } -} - -} // namespace RPC -} // namespace ripple - -#endif diff --git a/src/ripple/rpc/impl/RPCHelpers.cpp b/src/ripple/rpc/impl/RPCHelpers.cpp index 77255a5e6f6..3d1bfe6375b 100644 --- a/src/ripple/rpc/impl/RPCHelpers.cpp +++ b/src/ripple/rpc/impl/RPCHelpers.cpp @@ -33,7 +33,6 @@ #include #include -#include namespace ripple { namespace RPC { @@ -300,12 +299,6 @@ ledgerFromRequest(T& ledger, GRPCContext& context) return ledgerFromSpecifier(ledger, request.ledger(), context); } -// explicit instantiation of above function -template Status -ledgerFromRequest<>( - std::shared_ptr&, - GRPCContext&); - // explicit instantiation of above function template Status ledgerFromRequest<>( diff --git a/src/test/app/AccountTxPaging_test.cpp b/src/test/app/AccountTxPaging_test.cpp index 332ef213186..d3969e279b7 100644 --- a/src/test/app/AccountTxPaging_test.cpp +++ b/src/test/app/AccountTxPaging_test.cpp @@ -263,1906 +263,11 @@ class AccountTxPaging_test : public beast::unit_test::suite } } - class GrpcAccountTxClient : public test::GRPCTestClientBase - { - public: - org::xrpl::rpc::v1::GetAccountTransactionHistoryRequest request; - org::xrpl::rpc::v1::GetAccountTransactionHistoryResponse reply; - - explicit GrpcAccountTxClient(std::string const& port) - : GRPCTestClientBase(port) - { - } - - void - AccountTx() - { - status = - stub_->GetAccountTransactionHistory(&context, request, &reply); - } - }; - - bool - checkTransaction( - org::xrpl::rpc::v1::GetTransactionResponse const& tx, - int sequence, - int ledger) - { - return ( - tx.transaction().sequence().value() == sequence && - tx.ledger_index() == ledger); - } - - std::pair< - org::xrpl::rpc::v1::GetAccountTransactionHistoryResponse, - grpc::Status> - nextBinary( - std::string grpcPort, - test::jtx::Env& env, - std::string const& account = "", - int ledger_min = -1, - int ledger_max = -1, - int limit = -1, - bool forward = false, - org::xrpl::rpc::v1::Marker* marker = nullptr) - { - GrpcAccountTxClient client{grpcPort}; - auto& request = client.request; - if (account != "") - request.mutable_account()->set_address(account); - if (ledger_min != -1) - request.mutable_ledger_range()->set_ledger_index_min(ledger_min); - if (ledger_max != -1) - request.mutable_ledger_range()->set_ledger_index_max(ledger_max); - request.set_forward(forward); - request.set_binary(true); - if (limit != -1) - request.set_limit(limit); - if (marker) - { - *request.mutable_marker() = *marker; - } - - client.AccountTx(); - return {client.reply, client.status}; - } - - std::pair< - org::xrpl::rpc::v1::GetAccountTransactionHistoryResponse, - grpc::Status> - next( - std::string grpcPort, - test::jtx::Env& env, - std::string const& account = "", - int ledger_min = -1, - int ledger_max = -1, - int limit = -1, - bool forward = false, - org::xrpl::rpc::v1::Marker* marker = nullptr) - { - GrpcAccountTxClient client{grpcPort}; - auto& request = client.request; - if (account != "") - request.mutable_account()->set_address(account); - if (ledger_min != -1) - request.mutable_ledger_range()->set_ledger_index_min(ledger_min); - if (ledger_max != -1) - request.mutable_ledger_range()->set_ledger_index_max(ledger_max); - request.set_forward(forward); - if (limit != -1) - request.set_limit(limit); - if (marker) - { - *request.mutable_marker() = *marker; - } - - client.AccountTx(); - return {client.reply, client.status}; - } - - std::pair< - org::xrpl::rpc::v1::GetAccountTransactionHistoryResponse, - grpc::Status> - nextWithSeq( - std::string grpcPort, - test::jtx::Env& env, - std::string const& account = "", - int ledger_seq = -1, - int limit = -1, - bool forward = false, - org::xrpl::rpc::v1::Marker* marker = nullptr) - { - GrpcAccountTxClient client{grpcPort}; - auto& request = client.request; - if (account != "") - request.mutable_account()->set_address(account); - if (ledger_seq != -1) - request.mutable_ledger_specifier()->set_sequence(ledger_seq); - request.set_forward(forward); - if (limit != -1) - request.set_limit(limit); - if (marker) - { - *request.mutable_marker() = *marker; - } - - client.AccountTx(); - return {client.reply, client.status}; - } - - std::pair< - org::xrpl::rpc::v1::GetAccountTransactionHistoryResponse, - grpc::Status> - nextWithHash( - std::string grpcPort, - test::jtx::Env& env, - std::string const& account = "", - uint256 const& hash = beast::zero, - int limit = -1, - bool forward = false, - org::xrpl::rpc::v1::Marker* marker = nullptr) - { - GrpcAccountTxClient client{grpcPort}; - auto& request = client.request; - if (account != "") - request.mutable_account()->set_address(account); - if (hash != beast::zero) - request.mutable_ledger_specifier()->set_hash( - hash.data(), hash.size()); - request.set_forward(forward); - if (limit != -1) - request.set_limit(limit); - if (marker) - { - *request.mutable_marker() = *marker; - } - - client.AccountTx(); - return {client.reply, client.status}; - } - - void - testAccountTxParametersGrpc() - { - testcase("Test Account_tx Grpc"); - - using namespace test::jtx; - std::unique_ptr config = envconfig(addGrpcConfig); - std::string grpcPort = *(*config)["port_grpc"].get("port"); - Env env(*this, std::move(config)); - - Account A1{"A1"}; - env.fund(XRP(10000), A1); - env.close(); - - // Ledger 3 has the two txs associated with funding the account - // All other ledgers have no txs - - auto hasTxs = [](auto res) { - return res.second.error_code() == 0 && - (res.first.transactions().size() == 2) && - //(res.transactions()[0u].transaction().has_account_set()) && - (res.first.transactions()[1u].transaction().has_payment()); - }; - auto noTxs = [](auto res) { - return res.second.error_code() == 0 && - (res.first.transactions().size() == 0); - }; - - auto isErr = [](auto res, auto expect) { - return res.second.error_code() == expect; - }; - - BEAST_EXPECT( - isErr(next(grpcPort, env, ""), grpc::StatusCode::INVALID_ARGUMENT)); - - BEAST_EXPECT(isErr( - next(grpcPort, env, "0xDEADBEEF"), - grpc::StatusCode::INVALID_ARGUMENT)); - - BEAST_EXPECT(hasTxs(next(grpcPort, env, A1.human()))); - - // Ledger min/max index - { - BEAST_EXPECT(hasTxs(next(grpcPort, env, A1.human()))); - - BEAST_EXPECT(hasTxs(next(grpcPort, env, A1.human(), 0, 100))); - - BEAST_EXPECT(noTxs(next(grpcPort, env, A1.human(), 1, 2))); - - BEAST_EXPECT(isErr( - next(grpcPort, env, A1.human(), 2, 1), - grpc::StatusCode::INVALID_ARGUMENT)); - } - - // Ledger index min only - { - BEAST_EXPECT(hasTxs(next(grpcPort, env, A1.human(), -1))); - - BEAST_EXPECT(hasTxs(next(grpcPort, env, A1.human(), 1))); - - BEAST_EXPECT(isErr( - next(grpcPort, env, A1.human(), env.current()->info().seq), - grpc::StatusCode::INVALID_ARGUMENT)); - } - - // Ledger index max only - { - BEAST_EXPECT(hasTxs(next(grpcPort, env, A1.human(), -1, -1))); - - BEAST_EXPECT(hasTxs(next( - grpcPort, env, A1.human(), -1, env.current()->info().seq))); - - BEAST_EXPECT(hasTxs( - next(grpcPort, env, A1.human(), -1, env.closed()->info().seq))); - - BEAST_EXPECT(noTxs(next( - grpcPort, env, A1.human(), -1, env.closed()->info().seq - 1))); - } - // Ledger Sequence - { - BEAST_EXPECT(hasTxs(nextWithSeq( - grpcPort, env, A1.human(), env.closed()->info().seq))); - - BEAST_EXPECT(noTxs(nextWithSeq( - grpcPort, env, A1.human(), env.closed()->info().seq - 1))); - - BEAST_EXPECT(isErr( - nextWithSeq( - grpcPort, env, A1.human(), env.current()->info().seq), - grpc::StatusCode::INVALID_ARGUMENT)); - - BEAST_EXPECT(isErr( - nextWithSeq( - grpcPort, env, A1.human(), env.current()->info().seq + 1), - grpc::StatusCode::NOT_FOUND)); - } - - // Ledger Hash - { - BEAST_EXPECT(hasTxs(nextWithHash( - grpcPort, env, A1.human(), env.closed()->info().hash))); - - BEAST_EXPECT(noTxs(nextWithHash( - grpcPort, env, A1.human(), env.closed()->info().parentHash))); - } - } - - struct TxCheck - { - uint32_t sequence; - uint32_t ledgerIndex; - std::string hash; - std::function - checkTxn; - }; - - void - testAccountTxContentsGrpc() - { - testcase("Test AccountTx context grpc"); - // Get results for all transaction types that can be associated - // with an account. Start by generating all transaction types. - using namespace test::jtx; - using namespace std::chrono_literals; - - std::unique_ptr config = envconfig(addGrpcConfig); - std::string grpcPort = *(*config)["port_grpc"].get("port"); - Env env(*this, std::move(config)); - // Set time to this value (or greater) to get delivered_amount in meta - env.timeKeeper().set(NetClock::time_point{446000001s}); - Account const alice{"alice"}; - Account const alie{"alie"}; - Account const gw{"gw"}; - auto const USD{gw["USD"]}; - - std::vector> txns; - - env.fund(XRP(1000000), alice, gw); - env.close(); - - // AccountSet - env(noop(alice)); - - txns.emplace_back(env.tx()); - // Payment - env(pay(alice, gw, XRP(100)), stag(42), dtag(24), last_ledger_seq(20)); - - txns.emplace_back(env.tx()); - // Regular key set - env(regkey(alice, alie)); - env.close(); - - txns.emplace_back(env.tx()); - // Trust and Offers - env(trust(alice, USD(200)), sig(alie)); - - txns.emplace_back(env.tx()); - std::uint32_t const offerSeq{env.seq(alice)}; - env(offer(alice, USD(50), XRP(150)), sig(alie)); - - txns.emplace_back(env.tx()); - env.close(); - - env(offer_cancel(alice, offerSeq), sig(alie)); - env.close(); - - txns.emplace_back(env.tx()); - - // SignerListSet - env(signers(alice, 1, {{"bogie", 1}, {"demon", 1}, {gw, 1}}), - sig(alie)); - - txns.emplace_back(env.tx()); - // Escrow - { - // Create an escrow. Requires either a CancelAfter or FinishAfter. - auto escrow = [](Account const& account, - Account const& to, - STAmount const& amount) { - Json::Value escro; - escro[jss::TransactionType] = jss::EscrowCreate; - escro[jss::Flags] = tfUniversal; - escro[jss::Account] = account.human(); - escro[jss::Destination] = to.human(); - escro[jss::Amount] = amount.getJson(JsonOptions::none); - return escro; - }; - - NetClock::time_point const nextTime{env.now() + 2s}; - - Json::Value escrowWithFinish{escrow(alice, alice, XRP(500))}; - escrowWithFinish[sfFinishAfter.jsonName] = - nextTime.time_since_epoch().count(); - - std::uint32_t const escrowFinishSeq{env.seq(alice)}; - env(escrowWithFinish, sig(alie)); - - txns.emplace_back(env.tx()); - Json::Value escrowWithCancel{escrow(alice, alice, XRP(500))}; - escrowWithCancel[sfFinishAfter.jsonName] = - nextTime.time_since_epoch().count(); - escrowWithCancel[sfCancelAfter.jsonName] = - nextTime.time_since_epoch().count() + 1; - - std::uint32_t const escrowCancelSeq{env.seq(alice)}; - env(escrowWithCancel, sig(alie)); - env.close(); - - txns.emplace_back(env.tx()); - { - Json::Value escrowFinish; - escrowFinish[jss::TransactionType] = jss::EscrowFinish; - escrowFinish[jss::Flags] = tfUniversal; - escrowFinish[jss::Account] = alice.human(); - escrowFinish[sfOwner.jsonName] = alice.human(); - escrowFinish[sfOfferSequence.jsonName] = escrowFinishSeq; - env(escrowFinish, sig(alie)); - - txns.emplace_back(env.tx()); - } - { - Json::Value escrowCancel; - escrowCancel[jss::TransactionType] = jss::EscrowCancel; - escrowCancel[jss::Flags] = tfUniversal; - escrowCancel[jss::Account] = alice.human(); - escrowCancel[sfOwner.jsonName] = alice.human(); - escrowCancel[sfOfferSequence.jsonName] = escrowCancelSeq; - env(escrowCancel, sig(alie)); - - txns.emplace_back(env.tx()); - } - env.close(); - } - - // PayChan - { - std::uint32_t payChanSeq{env.seq(alice)}; - Json::Value payChanCreate; - payChanCreate[jss::TransactionType] = jss::PaymentChannelCreate; - payChanCreate[jss::Flags] = tfUniversal; - payChanCreate[jss::Account] = alice.human(); - payChanCreate[jss::Destination] = gw.human(); - payChanCreate[jss::Amount] = - XRP(500).value().getJson(JsonOptions::none); - payChanCreate[sfSettleDelay.jsonName] = - NetClock::duration{100s}.count(); - payChanCreate[sfPublicKey.jsonName] = strHex(alice.pk().slice()); - env(payChanCreate, sig(alie)); - env.close(); - - txns.emplace_back(env.tx()); - std::string const payChanIndex{ - strHex(keylet::payChan(alice, gw, payChanSeq).key)}; - - { - Json::Value payChanFund; - payChanFund[jss::TransactionType] = jss::PaymentChannelFund; - payChanFund[jss::Flags] = tfUniversal; - payChanFund[jss::Account] = alice.human(); - payChanFund[sfChannel.jsonName] = payChanIndex; - payChanFund[jss::Amount] = - XRP(200).value().getJson(JsonOptions::none); - env(payChanFund, sig(alie)); - env.close(); - - txns.emplace_back(env.tx()); - } - { - Json::Value payChanClaim; - payChanClaim[jss::TransactionType] = jss::PaymentChannelClaim; - payChanClaim[jss::Flags] = tfClose; - payChanClaim[jss::Account] = gw.human(); - payChanClaim[sfChannel.jsonName] = payChanIndex; - payChanClaim[sfPublicKey.jsonName] = strHex(alice.pk().slice()); - env(payChanClaim); - env.close(); - - txns.emplace_back(env.tx()); - } - } - - // Check - { - auto const aliceCheckId = keylet::check(alice, env.seq(alice)).key; - env(check::create(alice, gw, XRP(300)), sig(alie)); - - auto txn = env.tx(); - auto const gwCheckId = keylet::check(gw, env.seq(gw)).key; - env(check::create(gw, alice, XRP(200))); - env.close(); - - // need to switch the order of the previous 2 txns, since they are - // in the same ledger and account_tx returns them in a different - // order - txns.emplace_back(env.tx()); - txns.emplace_back(txn); - env(check::cash(alice, gwCheckId, XRP(200)), sig(alie)); - - txns.emplace_back(env.tx()); - env(check::cancel(alice, aliceCheckId), sig(alie)); - - txns.emplace_back(env.tx()); - env.close(); - } - - // Deposit preauthorization. - env(deposit::auth(alice, gw), sig(alie)); - env.close(); - - txns.emplace_back(env.tx()); - // Multi Sig with memo - auto const baseFee = env.current()->fees().base; - env(noop(alice), - msig(gw), - fee(2 * baseFee), - memo("data", "format", "type")); - env.close(); - - txns.emplace_back(env.tx()); - if (!BEAST_EXPECT(txns.size() == 20)) - return; - // Setup is done. Look at the transactions returned by account_tx. - - static const TxCheck txCheck[]{ - {21, - 15, - strHex(txns[txns.size() - 1]->getTransactionID()), - [this, &txns](auto res) { - auto txnJson = - txns[txns.size() - 1]->getJson(JsonOptions::none); - return BEAST_EXPECT(res.has_account_set()) && - BEAST_EXPECT(res.has_fee()) && - BEAST_EXPECT(res.fee().drops() == 20) && - BEAST_EXPECT(res.memos_size() == 1) && - BEAST_EXPECT(res.memos(0).has_memo_data()) && - BEAST_EXPECT(res.memos(0).memo_data().value() == "data") && - BEAST_EXPECT(res.memos(0).has_memo_format()) && - BEAST_EXPECT( - res.memos(0).memo_format().value() == "format") && - BEAST_EXPECT(res.memos(0).has_memo_type()) && - BEAST_EXPECT(res.memos(0).memo_type().value() == "type") && - BEAST_EXPECT(res.has_signing_public_key()) && - BEAST_EXPECT(res.signing_public_key().value() == "") && - BEAST_EXPECT(res.signers_size() == 1) && - BEAST_EXPECT(res.signers(0).has_account()) && - BEAST_EXPECT( - res.signers(0).account().value().address() == - txnJson["Signers"][0u]["Signer"]["Account"]) && - BEAST_EXPECT(res.signers(0).has_transaction_signature()) && - BEAST_EXPECT( - strHex(res.signers(0) - .transaction_signature() - .value()) == - txnJson["Signers"][0u]["Signer"]["TxnSignature"]) && - BEAST_EXPECT(res.signers(0).has_signing_public_key()) && - BEAST_EXPECT( - strHex( - res.signers(0).signing_public_key().value()) == - txnJson["Signers"][0u]["Signer"]["SigningPubKey"]); - }}, - {20, - 14, - strHex(txns[txns.size() - 2]->getTransactionID()), - [&txns, this](auto res) { - return BEAST_EXPECT(res.has_deposit_preauth()) && - BEAST_EXPECT( - res.deposit_preauth() - .authorize() - .value() - .address() == - // TODO do them all like this - txns[txns.size() - 2]->getJson( - JsonOptions::none)["Authorize"]); - }}, - {19, - 13, - strHex(txns[txns.size() - 3]->getTransactionID()), - [&txns, this](auto res) { - return BEAST_EXPECT(res.has_check_cancel()) && - BEAST_EXPECT( - strHex(res.check_cancel().check_id().value()) == - - txns[txns.size() - 3]->getJson( - JsonOptions::none)["CheckID"]); - }}, - {18, - 13, - strHex(txns[txns.size() - 4]->getTransactionID()), - [&txns, this](auto res) { - auto txnJson = - txns[txns.size() - 4]->getJson(JsonOptions::none); - return BEAST_EXPECT(res.has_check_cash()) && - BEAST_EXPECT( - strHex(res.check_cash().check_id().value()) == - txnJson["CheckID"]) && - BEAST_EXPECT(res.check_cash() - .amount() - .value() - .has_xrp_amount()) && - BEAST_EXPECT( - res.check_cash() - .amount() - .value() - .xrp_amount() - .drops() == txnJson["Amount"].asUInt()); - }}, - {17, - 12, - strHex(txns[txns.size() - 5]->getTransactionID()), - [&txns, this](auto res) { - auto txnJson = - txns[txns.size() - 5]->getJson(JsonOptions::none); - return BEAST_EXPECT(res.has_check_create()) && - BEAST_EXPECT( - res.check_create() - .destination() - .value() - .address() == txnJson["Destination"]) && - BEAST_EXPECT(res.check_create() - .send_max() - .value() - .has_xrp_amount()) && - BEAST_EXPECT( - res.check_create() - .send_max() - .value() - .xrp_amount() - .drops() == txnJson["SendMax"].asUInt()); - }}, - {5, - 12, - strHex(txns[txns.size() - 6]->getTransactionID()), - [&txns, this](auto res) { - auto txnJson = - txns[txns.size() - 6]->getJson(JsonOptions::none); - return BEAST_EXPECT(res.has_check_create()) && - BEAST_EXPECT( - res.check_create() - .destination() - .value() - .address() == txnJson["Destination"]) && - BEAST_EXPECT(res.check_create() - .send_max() - .value() - .has_xrp_amount()) && - BEAST_EXPECT( - res.check_create() - .send_max() - .value() - .xrp_amount() - .drops() == - - txnJson["SendMax"].asUInt()); - }}, - {4, - 11, - strHex(txns[txns.size() - 7]->getTransactionID()), - [&txns, this](auto res) { - auto txnJson = - txns[txns.size() - 7]->getJson(JsonOptions::none); - return BEAST_EXPECT(res.has_payment_channel_claim()) && - BEAST_EXPECT( - strHex(res.payment_channel_claim() - .channel() - .value()) == txnJson["Channel"]) && - BEAST_EXPECT( - strHex(res.payment_channel_claim() - .public_key() - .value()) == txnJson["PublicKey"]); - }}, - {16, - 10, - strHex(txns[txns.size() - 8]->getTransactionID()), - [&txns, this](auto res) { - auto txnJson = - txns[txns.size() - 8]->getJson(JsonOptions::none); - return BEAST_EXPECT(res.has_payment_channel_fund()) && - BEAST_EXPECT( - strHex( - res.payment_channel_fund().channel().value()) == - txnJson["Channel"]) && - BEAST_EXPECT(res.payment_channel_fund() - .amount() - .value() - .has_xrp_amount()) && - BEAST_EXPECT( - res.payment_channel_fund() - .amount() - .value() - .xrp_amount() - .drops() == txnJson["Amount"].asUInt()); - }}, - {15, - 9, - strHex(txns[txns.size() - 9]->getTransactionID()), - [&txns, this](auto res) { - auto txnJson = - txns[txns.size() - 9]->getJson(JsonOptions::none); - return BEAST_EXPECT(res.has_payment_channel_create()) && - BEAST_EXPECT(res.payment_channel_create() - .amount() - .value() - .has_xrp_amount()) && - BEAST_EXPECT( - res.payment_channel_create() - .amount() - .value() - .xrp_amount() - .drops() == txnJson["Amount"].asUInt()) && - BEAST_EXPECT( - res.payment_channel_create() - .destination() - .value() - .address() == txnJson["Destination"]) && - BEAST_EXPECT( - res.payment_channel_create() - .settle_delay() - .value() == txnJson["SettleDelay"].asUInt()) && - BEAST_EXPECT( - strHex(res.payment_channel_create() - .public_key() - .value()) == txnJson["PublicKey"]); - }}, - {14, - 8, - strHex(txns[txns.size() - 10]->getTransactionID()), - [&txns, this](auto res) { - auto txnJson = - txns[txns.size() - 10]->getJson(JsonOptions::none); - return BEAST_EXPECT(res.has_escrow_cancel()) && - BEAST_EXPECT( - res.escrow_cancel().owner().value().address() == - txnJson["Owner"]) && - BEAST_EXPECT( - res.escrow_cancel().offer_sequence().value() == - txnJson["OfferSequence"].asUInt() - - ); - }}, - {13, - 8, - strHex(txns[txns.size() - 11]->getTransactionID()), - [&txns, this](auto res) { - auto txnJson = - txns[txns.size() - 11]->getJson(JsonOptions::none); - return BEAST_EXPECT(res.has_escrow_finish()) && - BEAST_EXPECT( - res.escrow_finish().owner().value().address() == - txnJson["Owner"]) && - BEAST_EXPECT( - res.escrow_finish().offer_sequence().value() == - txnJson["OfferSequence"].asUInt() - - ); - }}, - {12, - 7, - strHex(txns[txns.size() - 12]->getTransactionID()), - [&txns, this](auto res) { - auto txnJson = - txns[txns.size() - 12]->getJson(JsonOptions::none); - return BEAST_EXPECT(res.has_escrow_create()) && - BEAST_EXPECT(res.escrow_create() - .amount() - .value() - .has_xrp_amount()) && - BEAST_EXPECT( - res.escrow_create() - .amount() - .value() - .xrp_amount() - .drops() == txnJson["Amount"].asUInt()) && - BEAST_EXPECT( - res.escrow_create() - .destination() - .value() - .address() == txnJson["Destination"]) && - BEAST_EXPECT( - res.escrow_create().cancel_after().value() == - txnJson["CancelAfter"].asUInt()) && - BEAST_EXPECT( - res.escrow_create().finish_after().value() == - txnJson["FinishAfter"].asUInt()); - }}, - {11, - 7, - strHex(txns[txns.size() - 13]->getTransactionID()), - [&txns, this](auto res) { - auto txnJson = - txns[txns.size() - 13]->getJson(JsonOptions::none); - return BEAST_EXPECT(res.has_escrow_create()) && - BEAST_EXPECT(res.escrow_create() - .amount() - .value() - .has_xrp_amount()) && - BEAST_EXPECT( - res.escrow_create() - .amount() - .value() - .xrp_amount() - .drops() == txnJson["Amount"].asUInt()) && - BEAST_EXPECT( - res.escrow_create() - .destination() - .value() - .address() == txnJson["Destination"]) && - BEAST_EXPECT( - res.escrow_create().finish_after().value() == - txnJson["FinishAfter"].asUInt()); - }}, - {10, - 7, - strHex(txns[txns.size() - 14]->getTransactionID()), - [&txns, this](auto res) { - auto txnJson = - txns[txns.size() - 14]->getJson(JsonOptions::none); - return BEAST_EXPECT(res.has_signer_list_set()) && - BEAST_EXPECT( - res.signer_list_set().signer_quorum().value() == - txnJson["SignerQuorum"].asUInt()) && - BEAST_EXPECT( - res.signer_list_set().signer_entries().size() == - 3) && - BEAST_EXPECT( - res.signer_list_set() - .signer_entries()[0] - .account() - .value() - .address() == - txnJson["SignerEntries"][0u]["SignerEntry"] - ["Account"]) && - BEAST_EXPECT( - res.signer_list_set() - .signer_entries()[0] - .signer_weight() - .value() == - txnJson["SignerEntries"][0u]["SignerEntry"] - ["SignerWeight"] - .asUInt()) && - BEAST_EXPECT( - res.signer_list_set() - .signer_entries()[1] - .account() - .value() - .address() == - txnJson["SignerEntries"][1u]["SignerEntry"] - ["Account"]) && - BEAST_EXPECT( - res.signer_list_set() - .signer_entries()[1] - .signer_weight() - .value() == - txnJson["SignerEntries"][1u]["SignerEntry"] - ["SignerWeight"] - .asUInt()) && - BEAST_EXPECT( - res.signer_list_set() - .signer_entries()[2] - .account() - .value() - .address() == - txnJson["SignerEntries"][2u]["SignerEntry"] - ["Account"]) && - BEAST_EXPECT( - res.signer_list_set() - .signer_entries()[2] - .signer_weight() - .value() == - txnJson["SignerEntries"][2u]["SignerEntry"] - ["SignerWeight"] - .asUInt()); - }}, - {9, - 6, - strHex(txns[txns.size() - 15]->getTransactionID()), - [&txns, this](auto res) { - auto txnJson = - txns[txns.size() - 15]->getJson(JsonOptions::none); - return BEAST_EXPECT(res.has_offer_cancel()) && - BEAST_EXPECT( - res.offer_cancel().offer_sequence().value() == - txnJson["OfferSequence"].asUInt()); - }}, - {8, - 5, - strHex(txns[txns.size() - 16]->getTransactionID()), - [&txns, this](auto res) { - auto txnJson = - txns[txns.size() - 16]->getJson(JsonOptions::none); - return BEAST_EXPECT(res.has_offer_create()) && - BEAST_EXPECT(res.offer_create() - .taker_gets() - .value() - .has_xrp_amount()) && - BEAST_EXPECT( - res.offer_create() - .taker_gets() - .value() - .xrp_amount() - .drops() == txnJson["TakerGets"].asUInt()) && - BEAST_EXPECT(res.offer_create() - .taker_pays() - .value() - .has_issued_currency_amount()) && - BEAST_EXPECT( - res.offer_create() - .taker_pays() - .value() - .issued_currency_amount() - .currency() - .name() == txnJson["TakerPays"]["currency"]) && - BEAST_EXPECT( - res.offer_create() - .taker_pays() - .value() - .issued_currency_amount() - .value() == txnJson["TakerPays"]["value"]) && - BEAST_EXPECT( - res.offer_create() - .taker_pays() - .value() - .issued_currency_amount() - .issuer() - .address() == txnJson["TakerPays"]["issuer"]); - }}, - {7, - 5, - strHex(txns[txns.size() - 17]->getTransactionID()), - [&txns, this](auto res) { - auto txnJson = - txns[txns.size() - 17]->getJson(JsonOptions::none); - return BEAST_EXPECT(res.has_trust_set()) && - BEAST_EXPECT(res.trust_set() - .limit_amount() - .value() - .has_issued_currency_amount()) && - BEAST_EXPECT( - res.trust_set() - .limit_amount() - .value() - .issued_currency_amount() - .currency() - .name() == - txnJson["LimitAmount"]["currency"]) && - BEAST_EXPECT( - res.trust_set() - .limit_amount() - .value() - .issued_currency_amount() - .value() == txnJson["LimitAmount"]["value"]) && - BEAST_EXPECT( - res.trust_set() - .limit_amount() - .value() - .issued_currency_amount() - .issuer() - .address() == txnJson["LimitAmount"]["issuer"]); - }}, - {6, - 4, - strHex(txns[txns.size() - 18]->getTransactionID()), - [&txns, this](auto res) { - auto txnJson = - txns[txns.size() - 18]->getJson(JsonOptions::none); - return BEAST_EXPECT(res.has_set_regular_key()) && - BEAST_EXPECT( - res.set_regular_key() - .regular_key() - .value() - .address() == txnJson["RegularKey"]); - }}, - {5, - 4, - strHex(txns[txns.size() - 19]->getTransactionID()), - [&txns, this](auto res) { - auto txnJson = - txns[txns.size() - 19]->getJson(JsonOptions::none); - return BEAST_EXPECT(res.has_payment()) && - BEAST_EXPECT( - res.payment().amount().value().has_xrp_amount()) && - BEAST_EXPECT( - res.payment() - .amount() - .value() - .xrp_amount() - .drops() == txnJson["Amount"].asUInt()) && - BEAST_EXPECT( - res.payment().destination().value().address() == - txnJson["Destination"]) && - BEAST_EXPECT(res.has_source_tag()) && - BEAST_EXPECT( - res.source_tag().value() == - txnJson["SourceTag"].asUInt()) && - BEAST_EXPECT(res.payment().has_destination_tag()) && - BEAST_EXPECT( - res.payment().destination_tag().value() == - txnJson["DestinationTag"].asUInt()) && - BEAST_EXPECT(res.has_last_ledger_sequence()) && - BEAST_EXPECT( - res.last_ledger_sequence().value() == - txnJson["LastLedgerSequence"].asUInt()) && - BEAST_EXPECT(res.has_transaction_signature()) && - BEAST_EXPECT(res.has_account()) && - BEAST_EXPECT( - res.account().value().address() == - txnJson["Account"]) && - BEAST_EXPECT(res.has_flags()) && - BEAST_EXPECT( - res.flags().value() == txnJson["Flags"].asUInt()); - }}, - {4, - 4, - strHex(txns[txns.size() - 20]->getTransactionID()), - [this](auto res) { return BEAST_EXPECT(res.has_account_set()); }}, - {3, - 3, - "9CE54C3B934E473A995B477E92EC229F99CED5B62BF4D2ACE4DC42719103AE2F", - [this](auto res) { - return BEAST_EXPECT(res.has_account_set()) && - BEAST_EXPECT(res.account_set().set_flag().value() == 8); - }}, - {1, - 3, - "2B5054734FA43C6C7B54F61944FAD6178ACD5D0272B39BA7FCD32A5D3932FBFF", - [&alice, this](auto res) { - return BEAST_EXPECT(res.has_payment()) && - BEAST_EXPECT( - res.payment().amount().value().has_xrp_amount()) && - BEAST_EXPECT( - res.payment() - .amount() - .value() - .xrp_amount() - .drops() == 1000000000010) && - BEAST_EXPECT( - res.payment().destination().value().address() == - alice.human()); - }}}; - - using MetaCheck = - std::function; - static const MetaCheck txMetaCheck[]{ - {[this](auto meta) { - return BEAST_EXPECT(meta.transaction_index() == 0) && - BEAST_EXPECT(meta.affected_nodes_size() == 1) && - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](org::xrpl::rpc::v1::AffectedNode const& - entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_ACCOUNT_ROOT; - }) == 1); - }}, - {[this](auto meta) { - return BEAST_EXPECT(meta.transaction_index() == 0) && - BEAST_EXPECT(meta.affected_nodes_size() == 3) && - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_DEPOSIT_PREAUTH; - }) == 1) && - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_ACCOUNT_ROOT; - }) == 1) && - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_DIRECTORY_NODE; - }) == 1); - }}, - {[this](auto meta) { - return BEAST_EXPECT(meta.transaction_index() == 1) && - BEAST_EXPECT(meta.affected_nodes_size() == 5) && - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_CHECK; - }) == 1) && - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_DIRECTORY_NODE; - }) == 2) && - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_ACCOUNT_ROOT; - }) == 2); - }}, - {[this](auto meta) { - return BEAST_EXPECT(meta.transaction_index() == 0) && - BEAST_EXPECT(meta.affected_nodes_size() == 5) && - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_CHECK; - }) == 1) && - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_DIRECTORY_NODE; - }) == 2) && - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_ACCOUNT_ROOT; - }) == 2); - }}, - {[this](auto meta) { - return BEAST_EXPECT(meta.transaction_index() == 1) && - BEAST_EXPECT(meta.affected_nodes_size() == 5) && - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_CHECK; - }) == 1) && - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_DIRECTORY_NODE; - }) == 2) && - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_ACCOUNT_ROOT; - }) == 2); - }}, - {[this](auto meta) { - return BEAST_EXPECT(meta.transaction_index() == 0) && - BEAST_EXPECT(meta.affected_nodes_size() == 5) && - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_CHECK; - }) == 1) && - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_DIRECTORY_NODE; - }) == 2) && - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_ACCOUNT_ROOT; - }) == 2); - }}, - {[this](auto meta) { - return BEAST_EXPECT(meta.transaction_index() == 0) && - BEAST_EXPECT(meta.affected_nodes_size() == 5) && - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_PAY_CHANNEL; - }) == 1) && - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_DIRECTORY_NODE; - }) == 2) && - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_ACCOUNT_ROOT; - }) == 2); - }}, - {[this](auto meta) { - return BEAST_EXPECT(meta.transaction_index() == 0) && - BEAST_EXPECT(meta.affected_nodes_size() == 2) && - - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_PAY_CHANNEL; - }) == 1) && - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_ACCOUNT_ROOT; - }) == 1); - }}, - {[this](auto meta) { - return BEAST_EXPECT(meta.transaction_index() == 0) && - BEAST_EXPECT(meta.affected_nodes_size() == 5) && - - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_PAY_CHANNEL; - }) == 1) && - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_DIRECTORY_NODE; - }) == 2) && - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_ACCOUNT_ROOT; - }) == 2); - }}, - {[this](auto meta) { - return BEAST_EXPECT(meta.transaction_index() == 1) && - BEAST_EXPECT(meta.affected_nodes_size() == 3) && - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_ESCROW; - }) == 1) && - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_ACCOUNT_ROOT; - }) == 1) && - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_DIRECTORY_NODE; - }) == 1); - }}, - {[this](auto meta) { - return BEAST_EXPECT(meta.transaction_index() == 0) && - BEAST_EXPECT(meta.affected_nodes_size() == 3) && - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_ESCROW; - }) == 1) && - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_ACCOUNT_ROOT; - }) == 1) && - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_DIRECTORY_NODE; - }) == 1); - }}, - {[this](auto meta) { - return BEAST_EXPECT(meta.transaction_index() == 2) && - BEAST_EXPECT(meta.affected_nodes_size() == 3) && - - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_ESCROW; - }) == 1) && - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_ACCOUNT_ROOT; - }) == 1) && - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_DIRECTORY_NODE; - }) == 1); - }}, - {[this](auto meta) { - return BEAST_EXPECT(meta.transaction_index() == 1) && - BEAST_EXPECT(meta.affected_nodes_size() == 3) && - - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_ESCROW; - }) == 1) && - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_ACCOUNT_ROOT; - }) == 1) && - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_DIRECTORY_NODE; - }) == 1); - }}, - {[this](auto meta) { - return BEAST_EXPECT(meta.transaction_index() == 0) && - BEAST_EXPECT(meta.affected_nodes_size() == 3) && - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_SIGNER_LIST; - }) == 1) && - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_ACCOUNT_ROOT; - }) == 1) && - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_DIRECTORY_NODE; - }) == 1); - }}, - {[this](auto meta) { - return BEAST_EXPECT(meta.transaction_index() == 0) && - BEAST_EXPECT(meta.affected_nodes_size() == 4) && - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_DIRECTORY_NODE; - }) == 2) && - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_ACCOUNT_ROOT; - }) == 1) && - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_OFFER; - }) == 1); - }}, - {[this](auto meta) { - return BEAST_EXPECT(meta.transaction_index() == 1) && - BEAST_EXPECT(meta.affected_nodes_size() == 4) && - - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_DIRECTORY_NODE; - }) == 2) && - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_ACCOUNT_ROOT; - }) == 1) && - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_OFFER; - }) == 1); - }}, - {[this](auto meta) { - return BEAST_EXPECT(meta.transaction_index() == 0) && - BEAST_EXPECT(meta.affected_nodes_size() == 5) && - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_DIRECTORY_NODE; - }) == 2) && - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_ACCOUNT_ROOT; - }) == 2) && - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_RIPPLE_STATE; - }) == 1); - }}, - {[this](auto meta) { - return BEAST_EXPECT(meta.transaction_index() == 2) && - BEAST_EXPECT(meta.affected_nodes_size() == 1) && - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_ACCOUNT_ROOT; - }) == 1); - }}, - {[this](auto meta) { - return BEAST_EXPECT(meta.transaction_index() == 1) && - BEAST_EXPECT(meta.affected_nodes_size() == 2) && - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_ACCOUNT_ROOT; - }) == 2); - }}, - {[this](auto meta) { - return BEAST_EXPECT(meta.transaction_index() == 0) && - BEAST_EXPECT(meta.affected_nodes_size() == 1) && - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_ACCOUNT_ROOT; - }) == 1); - }}, - {[this](auto meta) { - return BEAST_EXPECT(meta.transaction_index() == 2) && - BEAST_EXPECT(meta.affected_nodes_size() == 1) && - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_ACCOUNT_ROOT; - }) == 1); - }}, - {[this](auto meta) { - return BEAST_EXPECT(meta.transaction_index() == 0) && - BEAST_EXPECT(meta.affected_nodes_size() == 2) && - BEAST_EXPECT( - std::count_if( - meta.affected_nodes().begin(), - meta.affected_nodes().end(), - [](auto entry) { - return entry.ledger_entry_type() == - org::xrpl::rpc::v1::LedgerEntryType:: - LEDGER_ENTRY_TYPE_ACCOUNT_ROOT; - }) == 2); - }}}; - - auto doCheck = [this](auto txn, auto txCheck) { - return BEAST_EXPECT(txn.has_transaction()) && - BEAST_EXPECT(txn.validated()) && - BEAST_EXPECT(strHex(txn.hash()) == txCheck.hash) && - BEAST_EXPECT(txn.ledger_index() == txCheck.ledgerIndex) && - BEAST_EXPECT( - txn.transaction().sequence().value() == - txCheck.sequence) && - txCheck.checkTxn(txn.transaction()); - }; - - auto doMetaCheck = [this](auto txn, auto txMetaCheck) { - return BEAST_EXPECT(txn.has_meta()) && - BEAST_EXPECT(txn.meta().has_transaction_result()) && - BEAST_EXPECT( - txn.meta().transaction_result().result_type() == - org::xrpl::rpc::v1::TransactionResult:: - RESULT_TYPE_TES) && - BEAST_EXPECT( - txn.meta().transaction_result().result() == - "tesSUCCESS") && - txMetaCheck(txn.meta()); - }; - - auto [res, status] = next(grpcPort, env, alice.human()); - - if (!BEAST_EXPECT(status.error_code() == 0)) - return; - - if (!BEAST_EXPECT(res.transactions().size() == std::size(txCheck))) - return; - for (int i = 0; i < res.transactions().size(); ++i) - { - BEAST_EXPECT(doCheck(res.transactions()[i], txCheck[i])); - BEAST_EXPECT(doMetaCheck(res.transactions()[i], txMetaCheck[i])); - } - - // test binary representation - std::tie(res, status) = nextBinary(grpcPort, env, alice.human()); - - // txns vector does not contain the first two transactions returned by - // account_tx - if (!BEAST_EXPECT(res.transactions().size() == txns.size() + 2)) - return; - - std::reverse(txns.begin(), txns.end()); - for (int i = 0; i < txns.size(); ++i) - { - auto toByteString = [](auto data) { - const char* bytes = reinterpret_cast(data.data()); - return std::string(bytes, data.size()); - }; - - auto tx = txns[i]; - Serializer s = tx->getSerializer(); - std::string bin = toByteString(s); - - BEAST_EXPECT(res.transactions(i).transaction_binary() == bin); - } - } - - void - testAccountTxPagingGrpc() - { - testcase("Test Account_tx Grpc"); - - using namespace test::jtx; - std::unique_ptr config = envconfig(addGrpcConfig); - std::string grpcPort = *(*config)["port_grpc"].get("port"); - Env env(*this, std::move(config)); - - Account A1{"A1"}; - Account A2{"A2"}; - Account A3{"A3"}; - - env.fund(XRP(10000), A1, A2, A3); - env.close(); - - env.trust(A3["USD"](1000), A1); - env.trust(A2["USD"](1000), A1); - env.trust(A3["USD"](1000), A2); - env.close(); - - for (auto i = 0; i < 5; ++i) - { - env(pay(A2, A1, A2["USD"](2))); - env(pay(A3, A1, A3["USD"](2))); - env(offer(A1, XRP(11), A1["USD"](1))); - env(offer(A2, XRP(10), A2["USD"](1))); - env(offer(A3, XRP(9), A3["USD"](1))); - env.close(); - } - - /* The sequence/ledger for A3 are as follows: - * seq ledger_index - * 3 ----> 3 - * 1 ----> 3 - * 2 ----> 4 - * 2 ----> 4 - * 2 ----> 5 - * 3 ----> 5 - * 4 ----> 6 - * 5 ----> 6 - * 6 ----> 7 - * 7 ----> 7 - * 8 ----> 8 - * 9 ----> 8 - * 10 ----> 9 - * 11 ----> 9 - */ - - // page through the results in several ways. - { - // limit = 2, 3 batches giving the first 6 txs - auto [res, status] = next(grpcPort, env, A3.human(), 2, 5, 2, true); - - auto txs = res.transactions(); - if (!BEAST_EXPECT(txs.size() == 2)) - return; - - BEAST_EXPECT(checkTransaction(txs[0u], 3, 3)); - BEAST_EXPECT(checkTransaction(txs[1u], 3, 3)); - if (!BEAST_EXPECT(res.has_marker())) - return; - - std::tie(res, status) = next( - grpcPort, env, A3.human(), 2, 5, 2, true, res.mutable_marker()); - txs = res.transactions(); - if (!BEAST_EXPECT(txs.size() == 2)) - return; - BEAST_EXPECT(checkTransaction(txs[0u], 4, 4)); - BEAST_EXPECT(checkTransaction(txs[1u], 4, 4)); - if (!BEAST_EXPECT(res.has_marker())) - return; - - std::tie(res, status) = next( - grpcPort, env, A3.human(), 2, 5, 2, true, res.mutable_marker()); - txs = res.transactions(); - if (!BEAST_EXPECT(txs.size() == 2)) - return; - BEAST_EXPECT(checkTransaction(txs[0u], 4, 5)); - BEAST_EXPECT(checkTransaction(txs[1u], 5, 5)); - BEAST_EXPECT(!res.has_marker()); - return; - } - - { - // limit 1, 3 requests giving the first 3 txs - auto [res, status] = next(grpcPort, env, A3.human(), 3, 9, 1, true); - auto txs = res.transactions(); - if (!BEAST_EXPECT(txs.size() == 1)) - return; - BEAST_EXPECT(checkTransaction(txs[0u], 3, 3)); - if (!BEAST_EXPECT(res.has_marker())) - return; - - std::tie(res, status) = next( - grpcPort, env, A3.human(), 3, 9, 1, true, res.mutable_marker()); - txs = res.transactions(); - if (!BEAST_EXPECT(txs.size() == 1)) - return; - BEAST_EXPECT(checkTransaction(txs[0u], 3, 3)); - if (!BEAST_EXPECT(res.has_marker())) - return; - - std::tie(res, status) = next( - grpcPort, env, A3.human(), 3, 9, 1, true, res.mutable_marker()); - txs = res.transactions(); - if (!BEAST_EXPECT(txs.size() == 1)) - return; - BEAST_EXPECT(checkTransaction(txs[0u], 4, 4)); - if (!BEAST_EXPECT(res.has_marker())) - return; - - // continue with limit 3, to end of all txs - std::tie(res, status) = next( - grpcPort, env, A3.human(), 3, 9, 3, true, res.mutable_marker()); - txs = res.transactions(); - if (!BEAST_EXPECT(txs.size() == 3)) - return; - BEAST_EXPECT(checkTransaction(txs[0u], 4, 4)); - BEAST_EXPECT(checkTransaction(txs[1u], 4, 5)); - BEAST_EXPECT(checkTransaction(txs[2u], 5, 5)); - if (!BEAST_EXPECT(res.has_marker())) - return; - - std::tie(res, status) = next( - grpcPort, env, A3.human(), 3, 9, 3, true, res.mutable_marker()); - txs = res.transactions(); - if (!BEAST_EXPECT(txs.size() == 3)) - return; - BEAST_EXPECT(checkTransaction(txs[0u], 6, 6)); - BEAST_EXPECT(checkTransaction(txs[1u], 7, 6)); - BEAST_EXPECT(checkTransaction(txs[2u], 8, 7)); - if (!BEAST_EXPECT(res.has_marker())) - return; - - std::tie(res, status) = next( - grpcPort, env, A3.human(), 3, 9, 3, true, res.mutable_marker()); - txs = res.transactions(); - if (!BEAST_EXPECT(txs.size() == 3)) - return; - BEAST_EXPECT(checkTransaction(txs[0u], 9, 7)); - BEAST_EXPECT(checkTransaction(txs[1u], 10, 8)); - BEAST_EXPECT(checkTransaction(txs[2u], 11, 8)); - if (!BEAST_EXPECT(res.has_marker())) - return; - - std::tie(res, status) = next( - grpcPort, env, A3.human(), 3, 9, 3, true, res.mutable_marker()); - txs = res.transactions(); - if (!BEAST_EXPECT(txs.size() == 2)) - return; - BEAST_EXPECT(checkTransaction(txs[0u], 12, 9)); - BEAST_EXPECT(checkTransaction(txs[1u], 13, 9)); - BEAST_EXPECT(!res.has_marker()); - } - - { - // limit 2, descending, 2 batches giving last 4 txs - auto [res, status] = - next(grpcPort, env, A3.human(), 3, 9, 2, false); - auto txs = res.transactions(); - if (!BEAST_EXPECT(txs.size() == 2)) - return; - BEAST_EXPECT(checkTransaction(txs[0u], 13, 9)); - BEAST_EXPECT(checkTransaction(txs[1u], 12, 9)); - if (!BEAST_EXPECT(res.has_marker())) - return; - - std::tie(res, status) = next( - grpcPort, - env, - A3.human(), - 3, - 9, - 2, - false, - res.mutable_marker()); - txs = res.transactions(); - if (!BEAST_EXPECT(txs.size() == 2)) - return; - BEAST_EXPECT(checkTransaction(txs[0u], 11, 8)); - BEAST_EXPECT(checkTransaction(txs[1u], 10, 8)); - if (!BEAST_EXPECT(res.has_marker())) - return; - - // continue with limit 3 until all txs have been seen - std::tie(res, status) = next( - grpcPort, - env, - A3.human(), - 3, - 9, - 3, - false, - res.mutable_marker()); - txs = res.transactions(); - if (!BEAST_EXPECT(txs.size() == 3)) - return; - BEAST_EXPECT(checkTransaction(txs[0u], 9, 7)); - BEAST_EXPECT(checkTransaction(txs[1u], 8, 7)); - BEAST_EXPECT(checkTransaction(txs[2u], 7, 6)); - if (!BEAST_EXPECT(res.has_marker())) - return; - - std::tie(res, status) = next( - grpcPort, - env, - A3.human(), - 3, - 9, - 3, - false, - res.mutable_marker()); - txs = res.transactions(); - if (!BEAST_EXPECT(txs.size() == 3)) - return; - BEAST_EXPECT(checkTransaction(txs[0u], 6, 6)); - BEAST_EXPECT(checkTransaction(txs[1u], 5, 5)); - BEAST_EXPECT(checkTransaction(txs[2u], 4, 5)); - if (!BEAST_EXPECT(res.has_marker())) - return; - - std::tie(res, status) = next( - grpcPort, - env, - A3.human(), - 3, - 9, - 3, - false, - res.mutable_marker()); - txs = res.transactions(); - if (!BEAST_EXPECT(txs.size() == 3)) - return; - BEAST_EXPECT(checkTransaction(txs[0u], 4, 4)); - BEAST_EXPECT(checkTransaction(txs[1u], 4, 4)); - BEAST_EXPECT(checkTransaction(txs[2u], 3, 3)); - if (!BEAST_EXPECT(res.has_marker())) - return; - - std::tie(res, status) = next( - grpcPort, - env, - A3.human(), - 3, - 9, - 3, - false, - res.mutable_marker()); - txs = res.transactions(); - if (!BEAST_EXPECT(txs.size() == 1)) - return; - BEAST_EXPECT(checkTransaction(txs[0u], 3, 3)); - BEAST_EXPECT(!res.has_marker()); - } - } - public: void run() override { testAccountTxPaging(); - testAccountTxPagingGrpc(); - testAccountTxParametersGrpc(); - testAccountTxContentsGrpc(); } }; diff --git a/src/test/consensus/NegativeUNL_test.cpp b/src/test/consensus/NegativeUNL_test.cpp index 39028afff81..fee790281a0 100644 --- a/src/test/consensus/NegativeUNL_test.cpp +++ b/src/test/consensus/NegativeUNL_test.cpp @@ -25,7 +25,6 @@ #include #include #include -#include #include namespace ripple { @@ -1883,114 +1882,6 @@ class NegativeUNLVoteFilterValidations_test : public beast::unit_test::suite } }; -class NegativeUNLgRPC_test : public beast::unit_test::suite -{ - template - std::string - toByteString(T const& data) - { - const char* bytes = reinterpret_cast(data.data()); - return {bytes, data.size()}; - } - - void - testGRPC() - { - testcase("gRPC test"); - - auto gRpcTest = [this]( - std::uint32_t negUnlSize, - bool hasToDisable, - bool hasToReEnable) -> bool { - NetworkHistory history = { - *this, {20, negUnlSize, hasToDisable, hasToReEnable, {}}}; - if (!history.goodHistory) - return false; - - auto const& negUnlObject = - history.lastLedger()->read(keylet::negativeUNL()); - if (!negUnlSize && !hasToDisable && !hasToReEnable && !negUnlObject) - return true; - if (!negUnlObject) - return false; - - org::xrpl::rpc::v1::NegativeUNL to; - ripple::RPC::convert(to, *negUnlObject); - if (!to.has_flags() || - to.flags().value() != negUnlObject->getFlags()) - return false; - - bool goodSize = to.disabled_validators_size() == negUnlSize && - to.has_validator_to_disable() == hasToDisable && - to.has_validator_to_re_enable() == hasToReEnable; - if (!goodSize) - return false; - - if (negUnlSize) - { - if (!negUnlObject->isFieldPresent(sfDisabledValidators)) - return false; - auto const& nUnlData = - negUnlObject->getFieldArray(sfDisabledValidators); - if (nUnlData.size() != negUnlSize) - return false; - int idx = 0; - for (auto const& n : nUnlData) - { - if (!n.isFieldPresent(sfPublicKey) || - !n.isFieldPresent(sfFirstLedgerSequence)) - return false; - - if (!to.disabled_validators(idx).has_ledger_sequence() || - !to.disabled_validators(idx).has_public_key()) - return false; - - if (to.disabled_validators(idx).public_key().value() != - toByteString(n.getFieldVL(sfPublicKey))) - return false; - - if (to.disabled_validators(idx).ledger_sequence().value() != - n.getFieldU32(sfFirstLedgerSequence)) - return false; - - ++idx; - } - } - - if (hasToDisable) - { - if (!negUnlObject->isFieldPresent(sfValidatorToDisable)) - return false; - if (to.validator_to_disable().value() != - toByteString( - negUnlObject->getFieldVL(sfValidatorToDisable))) - return false; - } - - if (hasToReEnable) - { - if (!negUnlObject->isFieldPresent(sfValidatorToReEnable)) - return false; - if (to.validator_to_re_enable().value() != - toByteString( - negUnlObject->getFieldVL(sfValidatorToReEnable))) - return false; - } - - return true; - }; - - BEAST_EXPECT(gRpcTest(0, false, false)); - BEAST_EXPECT(gRpcTest(2, true, true)); - } - - void - run() override - { - testGRPC(); - } -}; - BEAST_DEFINE_TESTSUITE(NegativeUNL, ledger, ripple); BEAST_DEFINE_TESTSUITE(NegativeUNLNoAmendment, ledger, ripple); @@ -2006,7 +1897,6 @@ BEAST_DEFINE_TESTSUITE_PRIO( 1); BEAST_DEFINE_TESTSUITE(NegativeUNLVoteNewValidator, consensus, ripple); BEAST_DEFINE_TESTSUITE(NegativeUNLVoteFilterValidations, consensus, ripple); -BEAST_DEFINE_TESTSUITE(NegativeUNLgRPC, ledger, ripple); /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// diff --git a/src/test/protocol/KnownFormatToGRPC_test.cpp b/src/test/protocol/KnownFormatToGRPC_test.cpp deleted file mode 100644 index bf49f2e3134..00000000000 --- a/src/test/protocol/KnownFormatToGRPC_test.cpp +++ /dev/null @@ -1,975 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of rippled: https://github.com/ripple/rippled - Copyright (c) 2020 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 -#include -#include -#include -#include - -#include "org/xrpl/rpc/v1/ledger_objects.pb.h" -#include "org/xrpl/rpc/v1/transaction.pb.h" - -#include -#include -#include -#include - -namespace ripple { - -// This test suite uses the google::protobuf::Descriptor class to do runtime -// reflection on our gRPC stuff. At the time of this writing documentation -// for Descriptor could be found here: -// -// https://developers.google.com/protocol-buffers/docs/reference/cpp/google.protobuf.descriptor#Descriptor - -class KnownFormatToGRPC_test : public beast::unit_test::suite -{ -private: - static constexpr auto fieldTYPE_UINT32 = - google::protobuf::FieldDescriptor::Type::TYPE_UINT32; - - static constexpr auto fieldTYPE_UINT64 = - google::protobuf::FieldDescriptor::Type::TYPE_UINT64; - - static constexpr auto fieldTYPE_BYTES = - google::protobuf::FieldDescriptor::Type::TYPE_BYTES; - - static constexpr auto fieldTYPE_STRING = - google::protobuf::FieldDescriptor::Type::TYPE_STRING; - - static constexpr auto fieldTYPE_MESSAGE = - google::protobuf::FieldDescriptor::Type::TYPE_MESSAGE; - - // Format names are CamelCase and FieldDescriptor names are snake_case. - // Convert from CamelCase to snake_case. Do not be fooled by consecutive - // capital letters like in NegativeUNL. - static std::string - formatNameToEntryTypeName(std::string const& fmtName) - { - std::string entryName; - entryName.reserve(fmtName.size()); - bool prevUpper = false; - for (std::size_t i = 0; i < fmtName.size(); i++) - { - char const ch = fmtName[i]; - bool const upper = std::isupper(ch); - if (i > 0 && !prevUpper && upper) - entryName.push_back('_'); - - prevUpper = upper; - entryName.push_back(std::tolower(ch)); - } - return entryName; - }; - - // Create a map of (most) all the SFields in an SOTemplate. This map - // can be used to correlate a gRPC Descriptor to its corresponding SField. - template - static std::map - soTemplateToSFields( - SOTemplate const& soTemplate, - [[maybe_unused]] KeyType fmtId) - { - std::map sFields; - for (SOElement const& element : soTemplate) - { - SField const& sField = element.sField(); - - // Fields that gRPC never includes. - // - // o sfLedgerIndex and - // o sfLedgerEntryType are common to all ledger objects, so - // gRPC includes them at a higher level than the ledger - // object itself. - // - // o sfOperationLimit is an optional field in all transactions, - // but no one knows what it was intended for. - using FieldCode_t = - std::remove_const::type; - static const std::set excludedSFields{ - sfLedgerIndex.fieldCode, - sfLedgerEntryType.fieldCode, - sfOperationLimit.fieldCode}; - - if (excludedSFields.count(sField.fieldCode)) - continue; - - // There are certain fields that gRPC never represents in - // transactions. Exclude those. - // - // o sfPreviousTxnID is obsolete and was replaced by - // sfAccountTxnID some time before November of 2014. - // - // o sfWalletLocator and - // o sfWalletSize have been deprecated for six years or more. - // - // o sfTransactionType is not needed by gRPC, since the typing - // is handled using protobuf message types. - if constexpr (std::is_same_v) - { - static const std::set excludedTxFields{ - sfPreviousTxnID.fieldCode, - sfTransactionType.fieldCode, - sfWalletLocator.fieldCode, - sfWalletSize.fieldCode}; - - if (excludedTxFields.count(sField.fieldCode)) - continue; - } - - // If fmtId is a LedgerEntryType, exclude certain fields. - if constexpr (std::is_same_v) - { - // Fields that gRPC does not include in certain LedgerFormats. - // - // o sfWalletLocator, - // o sfWalletSize, - // o sfExchangeRate, and - // o sfFirstLedgerSequence are all deprecated fields in - // their respective ledger objects. - static const std:: - map> - gRPCOmitFields{ - {ltACCOUNT_ROOT, {&sfWalletLocator, &sfWalletSize}}, - {ltDIR_NODE, {&sfExchangeRate}}, - {ltLEDGER_HASHES, {&sfFirstLedgerSequence}}, - }; - - if (auto const iter = gRPCOmitFields.find(fmtId); - iter != gRPCOmitFields.end()) - { - std::vector const& omits = iter->second; - - // Check for fields that gRPC omits from this type. - if (std::find_if( - omits.begin(), - omits.end(), - [&sField](SField const* const omit) { - return *omit == sField; - }) != omits.end()) - { - // This is one of the fields that gRPC omits. - continue; - } - } - } - - // The SFields and gRPC disagree on the names of some fields. - // Provide a mapping from SField names to gRPC names for the - // known exceptions. - // - // clang-format off - // - // The implementers of the gRPC interface made the decision not - // to abbreviate anything. This accounts for the following - // field name differences: - // - // "AccountTxnID", "AccountTransactionID" - // "PreviousTxnID", "PreviousTransactionID" - // "PreviousTxnLgrSeq", "PreviousTransactionLedgerSequence" - // "SigningPubKey", "SigningPublicKey" - // "TxnSignature", "TransactionSignature" - // - // gRPC adds typing information for Fee, which accounts for - // "Fee", "XRPDropsAmount" - // - // There's one misspelling which accounts for - // "TakerGetsCurrency", "TakerGetsCurreny" - // - // The implementers of the gRPC interface observed that a - // PaymentChannelClaim transaction has a TxnSignature field at the - // upper level and a Signature field at the lever level. They - // felt that was confusing, which is the reason for - // "Signature", "PaymentChannelSignature" - // - static const std::map sFieldToGRPC{ - {"AccountTxnID", "AccountTransactionID"}, - {"Fee", "XRPDropsAmount"}, - {"PreviousTxnID", "PreviousTransactionID"}, - {"PreviousTxnLgrSeq", "PreviousTransactionLedgerSequence"}, - {"Signature", "PaymentChannelSignature"}, - {"SigningPubKey", "SigningPublicKey"}, - {"TakerGetsCurrency", "TakerGetsCurreny"}, - {"TxnSignature", "TransactionSignature"}, - }; - // clang-format on - - auto const iter = sFieldToGRPC.find(sField.getName()); - std::string gRPCName = - iter != sFieldToGRPC.end() ? iter->second : sField.getName(); - - sFields.insert({std::move(gRPCName), &sField}); - } - return sFields; - } - - // Given a Descriptor for a KnownFormat and a map of the SFields of that - // KnownFormat, make sure the fields are aligned. - void - validateDescriptorAgainstSFields( - google::protobuf::Descriptor const* const pbufDescriptor, - google::protobuf::Descriptor const* const commonFields, - std::string const& knownFormatName, - std::map&& sFields) - { - // Create namespace aliases for shorter names. - namespace pbuf = google::protobuf; - - // We'll be running through two sets of pbuf::Descriptors: the ones in - // the OneOf and the common fields. Here is a lambda that factors out - // the common checking code for these two cases. - auto checkFieldDesc = [this, &sFields, &knownFormatName]( - pbuf::FieldDescriptor const* const - fieldDesc) { - // gRPC has different handling for repeated vs non-repeated - // types. So we need to do that too. - std::string name; - if (fieldDesc->is_repeated()) - { - // Repeated-type handling. - - // Munge the fieldDescriptor name so it looks like the - // name in sFields. - name = fieldDesc->camelcase_name(); - name[0] = toupper(name[0]); - - // The ledger gives UNL all caps. Adapt to that. - if (size_t const i = name.find("Unl"); i != std::string::npos) - { - name[i + 1] = 'N'; - name[i + 2] = 'L'; - } - - // The ledger gives the NFT part of NFToken all caps. - // Adapt to that. - if (size_t const i = name.find("Nft"); i != std::string::npos) - { - name[i + 1] = 'F'; - name[i + 2] = 'T'; - } - - if (!sFields.count(name)) - { - fail( - std::string("Repeated Protobuf Descriptor '") + name + - "' expected in KnownFormat '" + knownFormatName + - "' and not found", - __FILE__, - __LINE__); - return; - } - pass(); - - validateRepeatedField(fieldDesc, sFields.at(name)); - } - else - { - // Non-repeated handling. - pbuf::Descriptor const* const entryDesc = - fieldDesc->message_type(); - if (entryDesc == nullptr) - return; - - name = entryDesc->name(); - if (!sFields.count(name)) - { - fail( - std::string("Protobuf Descriptor '") + - entryDesc->name() + "' expected in KnownFormat '" + - knownFormatName + "' and not found", - __FILE__, - __LINE__); - return; - } - pass(); - - validateDescriptor(entryDesc, sFields.at(entryDesc->name())); - } - // Remove the validated field from the map so we can tell if - // there are left over fields at the end of all comparisons. - sFields.erase(name); - }; - - // Compare the SFields to the FieldDescriptor->Descriptors. - for (int i = 0; i < pbufDescriptor->field_count(); ++i) - { - pbuf::FieldDescriptor const* const fieldDesc = - pbufDescriptor->field(i); - if (fieldDesc == nullptr || fieldDesc->type() != fieldTYPE_MESSAGE) - continue; - - checkFieldDesc(fieldDesc); - } - - // Now all of the OneOf-specific fields have been removed from - // sFields. But there may be common fields left in there. Process - // the commonFields next. - if (commonFields) - { - for (int i = 0; i < commonFields->field_count(); ++i) - { - // If the field we picked up is a OneOf, skip it. Common - // fields are never OneOfs. - pbuf::FieldDescriptor const* const fieldDesc = - commonFields->field(i); - - if (fieldDesc == nullptr || - fieldDesc->containing_oneof() != nullptr || - fieldDesc->type() != fieldTYPE_MESSAGE) - continue; - - checkFieldDesc(fieldDesc); - } - } - - // All SFields in the KnownFormat have corresponding gRPC fields - // if the sFields map is now empty. - if (!sFields.empty()) - { - fail( - std::string("Protobuf Descriptor '") + pbufDescriptor->name() + - "' did not account for all fields in KnownFormat '" + - knownFormatName + "'. Left over field: `" + - sFields.begin()->first + "'", - __FILE__, - __LINE__); - return; - } - pass(); - } - - // Compare a protobuf descriptor with multiple oneOfFields to choose from - // to an SField. - void - validateOneOfDescriptor( - google::protobuf::Descriptor const* const entryDesc, - SField const* const sField) - { - // Create namespace aliases for shorter names. - namespace pbuf = google::protobuf; - - // Note that it's not okay to compare names because SFields and - // gRPC do not always agree on the names. - if (entryDesc->field_count() == 0 || entryDesc->oneof_decl_count() != 1) - { - fail( - std::string("Protobuf Descriptor '") + entryDesc->name() + - "' expected to have multiple OneOf fields and nothing else", - __FILE__, - __LINE__); - return; - } - - pbuf::FieldDescriptor const* const fieldDesc = entryDesc->field(0); - if (fieldDesc == nullptr) - { - fail( - std::string("Internal test failure. Unhandled nullptr " - "in FieldDescriptor for '") + - entryDesc->name() + "'", - __FILE__, - __LINE__); - return; - } - - // Special handling for CurrencyAmount - if (sField->fieldType == STI_AMOUNT && - entryDesc->name() == "CurrencyAmount") - { - // SFields of type STI_AMOUNT are represented in gRPC by a - // multi-field CurrencyAmount. We don't really learn anything - // by diving into the interior of CurrencyAmount, so we stop here - // and call it good. - pass(); - return; - } - - fail( - std::string("Unhandled OneOf Protobuf Descriptor '") + - entryDesc->name() + "'", - __FILE__, - __LINE__); - } - - void - validateMultiFieldDescriptor( - google::protobuf::Descriptor const* const entryDesc, - SField const* const sField) - { - // Create namespace aliases for shorter names. - namespace pbuf = google::protobuf; - - if (entryDesc->field_count() <= 1 || entryDesc->oneof_decl_count() != 0) - { - fail( - std::string("Protobuf Descriptor '") + entryDesc->name() + - "' expected to have multiple fields and nothing else", - __FILE__, - __LINE__); - return; - } - - // There are composite fields that the SFields handle differently - // from gRPC. Handle those here. - { - struct FieldContents - { - std::string_view fieldName; - google::protobuf::FieldDescriptor::Type fieldType; - - bool - operator<(FieldContents const& other) const - { - return this->fieldName < other.fieldName; - } - - bool - operator==(FieldContents const& other) const - { - return this->fieldName == other.fieldName && - this->fieldType == other.fieldType; - } - }; - - struct SpecialEntry - { - std::string_view const descriptorName; - SerializedTypeID const sFieldType; - std::set const fields; - }; - - // clang-format off - static const std::array specialEntries{ - SpecialEntry{ - "Currency", STI_UINT160, - { - {"name", fieldTYPE_STRING}, - {"code", fieldTYPE_BYTES} - } - }, - SpecialEntry{ - "Memo", STI_OBJECT, - { - {"memo_data", fieldTYPE_BYTES}, - {"memo_format", fieldTYPE_BYTES}, - {"memo_type", fieldTYPE_BYTES} - } - } - }; - // clang-format on - - // If we're handling a SpecialEntry... - if (auto const iter = std::find_if( - specialEntries.begin(), - specialEntries.end(), - [entryDesc, sField](SpecialEntry const& entry) { - return entryDesc->name() == entry.descriptorName && - sField->fieldType == entry.sFieldType; - }); - iter != specialEntries.end()) - { - // Verify the SField. - if (!BEAST_EXPECT(sField->fieldType == iter->sFieldType)) - return; - - // Verify all of the fields in the entryDesc. - if (!BEAST_EXPECT( - entryDesc->field_count() == iter->fields.size())) - return; - - for (int i = 0; i < entryDesc->field_count(); ++i) - { - pbuf::FieldDescriptor const* const fieldDesc = - entryDesc->field(i); - - FieldContents const contents{ - fieldDesc->name(), fieldDesc->type()}; - - if (!BEAST_EXPECT( - iter->fields.find(contents) != iter->fields.end())) - return; - } - - // This field is good. - pass(); - return; - } - } - - // If the field was not one of the SpecialEntries, we expect it to be - // an InnerObjectFormat. - SOTemplate const* const innerFormat = - InnerObjectFormats::getInstance().findSOTemplateBySField(*sField); - if (innerFormat == nullptr) - { - fail( - "SOTemplate for field '" + sField->getName() + "' not found", - __FILE__, - __LINE__); - return; - } - - // Create a map we can use use to correlate each field in the - // gRPC Descriptor to its corresponding SField. - std::map sFields = - soTemplateToSFields(*innerFormat, 0); - - // Compare the SFields to the FieldDescriptor->Descriptors. - validateDescriptorAgainstSFields( - entryDesc, nullptr, sField->getName(), std::move(sFields)); - } - - // Compare a protobuf descriptor with only one field to an SField. - void - validateOneDescriptor( - google::protobuf::Descriptor const* const entryDesc, - SField const* const sField) - { - // Create namespace aliases for shorter names. - namespace pbuf = google::protobuf; - - // Note that it's not okay to compare names because SFields and - // gRPC do not always agree on the names. - if (entryDesc->field_count() != 1 || entryDesc->oneof_decl_count() != 0) - { - fail( - std::string("Protobuf Descriptor '") + entryDesc->name() + - "' expected to be one field and nothing else", - __FILE__, - __LINE__); - return; - } - - pbuf::FieldDescriptor const* const fieldDesc = entryDesc->field(0); - if (fieldDesc == nullptr) - { - fail( - std::string("Internal test failure. Unhandled nullptr " - "in FieldDescriptor for '") + - entryDesc->name() + "'", - __FILE__, - __LINE__); - return; - } - - // Create a map from SerializedTypeID to pbuf::FieldDescriptor::Type. - // - // This works for most, but not all, types because of divergence - // between the gRPC and LedgerFormat implementations. We deal - // with the special cases later. - // clang-format off - static const std::map - sTypeToFieldDescType{ - {STI_UINT8, fieldTYPE_UINT32}, - {STI_UINT16, fieldTYPE_UINT32}, - {STI_UINT32, fieldTYPE_UINT32}, - - {STI_UINT64, fieldTYPE_UINT64}, - - {STI_ACCOUNT, fieldTYPE_STRING}, - - {STI_AMOUNT, fieldTYPE_BYTES}, - {STI_UINT128, fieldTYPE_BYTES}, - {STI_UINT160, fieldTYPE_BYTES}, - {STI_UINT256, fieldTYPE_BYTES}, - {STI_VL, fieldTYPE_BYTES}, - }; - //clang-format on - - // If the SField and FieldDescriptor::Type correlate we're good. - if (auto const iter = sTypeToFieldDescType.find(sField->fieldType); - iter != sTypeToFieldDescType.end() && - iter->second == fieldDesc->type()) - { - pass(); - return; - } - - // Handle special cases for specific SFields. - static const std::map - sFieldCodeToFieldDescType{ - {sfDomain.fieldCode, fieldTYPE_STRING}, - {sfFee.fieldCode, fieldTYPE_UINT64}, - {sfURI.fieldCode, fieldTYPE_STRING}}; - - if (auto const iter = sFieldCodeToFieldDescType.find(sField->fieldCode); - iter != sFieldCodeToFieldDescType.end() && - iter->second == fieldDesc->type()) - { - pass(); - return; - } - - // Special handling for all Message types. - if (fieldDesc->type() == fieldTYPE_MESSAGE) - { - // We need to recurse to get to the bottom of the field(s) - // in question. - - // Start by identifying which fields we need to be handling. - // clang-format off - static const std::map messageMap{ - {sfAccount.fieldCode, "AccountAddress"}, - {sfAmount.fieldCode, "CurrencyAmount"}, - {sfAuthorize.fieldCode, "AccountAddress"}, - {sfBalance.fieldCode, "CurrencyAmount"}, - {sfDestination.fieldCode, "AccountAddress"}, - {sfFee.fieldCode, "XRPDropsAmount"}, - {sfHighLimit.fieldCode, "CurrencyAmount"}, - {sfLowLimit.fieldCode, "CurrencyAmount"}, - {sfOwner.fieldCode, "AccountAddress"}, - {sfRegularKey.fieldCode, "AccountAddress"}, - {sfSendMax.fieldCode, "CurrencyAmount"}, - {sfTakerGets.fieldCode, "CurrencyAmount"}, - {sfTakerGetsCurrency.fieldCode, "Currency"}, - {sfTakerPays.fieldCode, "CurrencyAmount"}, - {sfTakerPaysCurrency.fieldCode, "Currency"}, - }; - // clang-format on - if (messageMap.count(sField->fieldCode)) - { - pbuf::Descriptor const* const entry2Desc = - fieldDesc->message_type(); - - if (entry2Desc == nullptr) - { - fail( - std::string("Unexpected gRPC. ") + fieldDesc->name() + - " MESSAGE with null Descriptor", - __FILE__, - __LINE__); - return; - } - - // The Descriptor name should match the messageMap name. - if (messageMap.at(sField->fieldCode) != entry2Desc->name()) - { - fail( - std::string( - "Internal test error. Mismatch between SField '") + - sField->getName() + "' and gRPC Descriptor name '" + - entry2Desc->name() + "'", - __FILE__, - __LINE__); - return; - } - pass(); - - // Recurse to the next lower Descriptor. - validateDescriptor(entry2Desc, sField); - } - return; - } - - fail( - std::string("Internal test error. Unhandled FieldDescriptor '") + - entryDesc->name() + "' has type `" + fieldDesc->type_name() + - "` and label " + std::to_string(fieldDesc->label()), - __FILE__, - __LINE__); - } - - // Compare a repeated protobuf FieldDescriptor to an SField. - void - validateRepeatedField( - google::protobuf::FieldDescriptor const* const fieldDesc, - SField const* const sField) - { - // Create namespace aliases for shorter names. - namespace pbuf = google::protobuf; - - pbuf::Descriptor const* const entryDesc = fieldDesc->message_type(); - if (entryDesc == nullptr) - { - fail( - std::string("Expected Descriptor for repeated type ") + - sField->getName(), - __FILE__, - __LINE__); - return; - } - - // The following repeated types provide no further structure for their - // in-ledger representation. We just have to trust that the gRPC - // representation is reasonable for what the ledger implements. - static const std::set noFurtherDetail{ - {sfPaths.getName()}, - }; - - if (noFurtherDetail.count(sField->getName())) - { - // There is no Format representation for further details of this - // repeated type. We've done the best we can. - pass(); - return; - } - - // All of the repeated types that the test currently supports. - static const std::map repeatsWhat{ - {sfAmendments.getName(), &sfAmendment}, - {sfDisabledValidators.getName(), &sfDisabledValidator}, - {sfHashes.getName(), &sfLedgerHash}, - {sfIndexes.getName(), &sfLedgerIndex}, - {sfMajorities.getName(), &sfMajority}, - {sfMemos.getName(), &sfMemo}, - {sfNFTokens.getName(), &sfNFToken}, - {sfSignerEntries.getName(), &sfSignerEntry}, - {sfSigners.getName(), &sfSigner}, - {sfNFTokenOffers.getName(), &sfLedgerIndex}}; - - if (!repeatsWhat.count(sField->getName())) - { - fail( - std::string("Unexpected repeated type ") + fieldDesc->name(), - __FILE__, - __LINE__); - return; - } - pass(); - - // Process the type contained by the repeated type. - validateDescriptor(entryDesc, repeatsWhat.at(sField->getName())); - } - - // Determine which of the Descriptor validators to dispatch to. - void - validateDescriptor( - google::protobuf::Descriptor const* const entryDesc, - SField const* const sField) - { - if (entryDesc->nested_type_count() != 0 || - entryDesc->enum_type_count() != 0 || - entryDesc->extension_range_count() != 0 || - entryDesc->reserved_range_count() != 0) - { - fail( - std::string("Protobuf Descriptor '") + entryDesc->name() + - "' uses unsupported protobuf features", - __FILE__, - __LINE__); - return; - } - - // Dispatch to the correct validator - if (entryDesc->oneof_decl_count() > 0) - return validateOneOfDescriptor(entryDesc, sField); - - if (entryDesc->field_count() > 1) - return validateMultiFieldDescriptor(entryDesc, sField); - - return validateOneDescriptor(entryDesc, sField); - } - - // Compare a protobuf descriptor to a KnownFormat::Item - template - void - validateFields( - google::protobuf::Descriptor const* const pbufDescriptor, - google::protobuf::Descriptor const* const commonFields, - typename KnownFormats::Item const* const - knownFormatItem) - { - // Create namespace aliases for shorter names. - namespace pbuf = google::protobuf; - - // The names should usually be the same, but the bpufDescriptor - // name might have "Object" appended. - if (knownFormatItem->getName() != pbufDescriptor->name() && - knownFormatItem->getName() + "Object" != pbufDescriptor->name()) - { - fail( - std::string("Protobuf Descriptor '") + pbufDescriptor->name() + - "' and KnownFormat::Item '" + knownFormatItem->getName() + - "' don't have the same name", - __FILE__, - __LINE__); - return; - } - pass(); - - // Create a map we can use use to correlate each field in the - // gRPC Descriptor to its corresponding SField. - std::map sFields = soTemplateToSFields( - knownFormatItem->getSOTemplate(), knownFormatItem->getType()); - - // Compare the SFields to the FieldDescriptor->Descriptors. - validateDescriptorAgainstSFields( - pbufDescriptor, - commonFields, - knownFormatItem->getName(), - std::move(sFields)); - } - - template - void - testKnownFormats( - KnownFormats const& knownFormat, - std::string const& knownFormatName, - google::protobuf::Descriptor const* const commonFields, - google::protobuf::OneofDescriptor const* const oneOfDesc) - { - // Create namespace aliases for shorter names. - namespace grpc = org::xrpl::rpc::v1; - namespace pbuf = google::protobuf; - - if (!BEAST_EXPECT(oneOfDesc != nullptr)) - return; - - // Get corresponding names for all KnownFormat Items. - std::map< - std::string, - typename KnownFormats::Item const*> - formatTypes; - - for (auto const& item : knownFormat) - { - if constexpr (std::is_same_v) - { - // Skip LedgerEntryTypes that gRPC does not currently support. - static constexpr std::array notSupported{}; - - if (std::find( - notSupported.begin(), - notSupported.end(), - item.getType()) != notSupported.end()) - continue; - } - - if constexpr (std::is_same_v) - { - // Skip TxTypes that gRPC does not currently support. - static constexpr std::array notSupported{ - ttAMENDMENT, ttFEE, ttUNL_MODIFY}; - - if (std::find( - notSupported.begin(), - notSupported.end(), - item.getType()) != notSupported.end()) - continue; - } - - BEAST_EXPECT( - formatTypes - .insert({formatNameToEntryTypeName(item.getName()), &item}) - .second == true); - } - - // Verify that the OneOf objects match. Start by comparing - // KnownFormat vs gRPC OneOf counts. - { - BEAST_EXPECT(formatTypes.size() == oneOfDesc->field_count()); - } - - // This loop - // 1. Iterates through the gRPC OneOfs, - // 2. Finds each gRPC OneOf's matching KnownFormat::Item, - // 3. Sanity checks that the fields of the objects align well. - for (auto i = 0; i < oneOfDesc->field_count(); ++i) - { - pbuf::FieldDescriptor const* const fieldDesc = oneOfDesc->field(i); - - // The Field should be a TYPE_MESSAGE, which means we can get its - // descriptor. - if (fieldDesc->type() != fieldTYPE_MESSAGE) - { - fail( - std::string("gRPC OneOf '") + fieldDesc->name() + - "' is not TYPE_MESSAGE", - __FILE__, - __LINE__); - continue; - } - - auto const fmtIter = formatTypes.find(fieldDesc->name()); - - if (fmtIter == formatTypes.cend()) - { - fail( - std::string("gRPC OneOf '") + fieldDesc->name() + - "' not found in " + knownFormatName, - __FILE__, - __LINE__); - continue; - } - - // Validate that the gRPC and KnownFormat fields align. - validateFields( - fieldDesc->message_type(), commonFields, fmtIter->second); - - // Remove the checked KnownFormat from the map. This way we - // can check for leftovers when we're done processing. - formatTypes.erase(fieldDesc->name()); - } - - // Report any KnownFormats that don't have gRPC OneOfs. - for (auto const& spare : formatTypes) - { - fail( - knownFormatName + " '" + spare.second->getName() + - "' does not have a corresponding gRPC OneOf", - __FILE__, - __LINE__); - } - } - -public: - void - testLedgerObjectGRPCOneOfs() - { - testcase("Ledger object validation"); - - org::xrpl::rpc::v1::LedgerObject const ledgerObject; - - testKnownFormats( - LedgerFormats::getInstance(), - "LedgerFormats", - ledgerObject.GetDescriptor(), - ledgerObject.GetDescriptor()->FindOneofByName("object")); - - return; - } - - void - testTransactionGRPCOneOfs() - { - testcase("Transaction validation"); - - org::xrpl::rpc::v1::Transaction const txData; - - testKnownFormats( - TxFormats::getInstance(), - "TxFormats", - txData.GetDescriptor(), - txData.GetDescriptor()->FindOneofByName("transaction_data")); - - return; - } - - void - run() override - { - testLedgerObjectGRPCOneOfs(); - testTransactionGRPCOneOfs(); - } -}; - -BEAST_DEFINE_TESTSUITE(KnownFormatToGRPC, protocol, ripple); - -} // namespace ripple diff --git a/src/test/rpc/AccountInfo_test.cpp b/src/test/rpc/AccountInfo_test.cpp index 8ce8270ad20..9772a0ffb70 100644 --- a/src/test/rpc/AccountInfo_test.cpp +++ b/src/test/rpc/AccountInfo_test.cpp @@ -491,227 +491,6 @@ class AccountInfo_test : public beast::unit_test::suite } } - // gRPC stuff - class GetAccountInfoClient : public GRPCTestClientBase - { - public: - org::xrpl::rpc::v1::GetAccountInfoRequest request; - org::xrpl::rpc::v1::GetAccountInfoResponse reply; - - explicit GetAccountInfoClient(std::string const& port) - : GRPCTestClientBase(port) - { - } - - void - GetAccountInfo() - { - status = stub_->GetAccountInfo(&context, request, &reply); - } - }; - - void - testSimpleGrpc() - { - testcase("gRPC simple"); - - using namespace jtx; - std::unique_ptr config = envconfig(addGrpcConfig); - std::string grpcPort = *(*config)["port_grpc"].get("port"); - Env env(*this, std::move(config)); - Account const alice{"alice"}; - env.fund(drops(1000 * 1000 * 1000), alice); - - { - // most simple case - GetAccountInfoClient client(grpcPort); - client.request.mutable_account()->set_address(alice.human()); - client.GetAccountInfo(); - if (!BEAST_EXPECT(client.status.ok())) - { - return; - } - BEAST_EXPECT( - client.reply.account_data().account().value().address() == - alice.human()); - } - { - GetAccountInfoClient client(grpcPort); - client.request.mutable_account()->set_address(alice.human()); - client.request.set_queue(true); - client.request.mutable_ledger()->set_sequence(3); - client.GetAccountInfo(); - if (!BEAST_EXPECT(client.status.ok())) - return; - BEAST_EXPECT( - client.reply.account_data() - .balance() - .value() - .xrp_amount() - .drops() == 1000 * 1000 * 1000); - BEAST_EXPECT( - client.reply.account_data().account().value().address() == - alice.human()); - BEAST_EXPECT( - client.reply.account_data().sequence().value() == - env.seq(alice)); - BEAST_EXPECT(client.reply.queue_data().txn_count() == 0); - } - } - - void - testErrorsGrpc() - { - testcase("gRPC errors"); - - using namespace jtx; - std::unique_ptr config = envconfig(addGrpcConfig); - std::string grpcPort = *(*config)["port_grpc"].get("port"); - Env env(*this, std::move(config)); - auto getClient = [&grpcPort]() { - return GetAccountInfoClient(grpcPort); - }; - Account const alice{"alice"}; - env.fund(drops(1000 * 1000 * 1000), alice); - - { - // bad address - auto client = getClient(); - client.request.mutable_account()->set_address("deadbeef"); - client.GetAccountInfo(); - BEAST_EXPECT(!client.status.ok()); - } - { - // no account - Account const bogie{"bogie"}; - auto client = getClient(); - client.request.mutable_account()->set_address(bogie.human()); - client.GetAccountInfo(); - BEAST_EXPECT(!client.status.ok()); - } - { - // bad ledger_index - auto client = getClient(); - client.request.mutable_account()->set_address(alice.human()); - client.request.mutable_ledger()->set_sequence(0); - client.GetAccountInfo(); - BEAST_EXPECT(!client.status.ok()); - } - } - - void - testSignerListsGrpc() - { - testcase("gRPC singer lists"); - - using namespace jtx; - std::unique_ptr config = envconfig(addGrpcConfig); - std::string grpcPort = *(*config)["port_grpc"].get("port"); - Env env(*this, std::move(config)); - auto getClient = [&grpcPort]() { - return GetAccountInfoClient(grpcPort); - }; - - Account const alice{"alice"}; - env.fund(drops(1000 * 1000 * 1000), alice); - - { - auto client = getClient(); - client.request.mutable_account()->set_address(alice.human()); - client.request.set_signer_lists(true); - client.GetAccountInfo(); - if (!BEAST_EXPECT(client.status.ok())) - return; - BEAST_EXPECT(client.reply.signer_list().signer_entries_size() == 0); - } - - // Give alice a SignerList. - Account const bogie{"bogie"}; - Json::Value const smallSigners = signers(alice, 2, {{bogie, 3}}); - env(smallSigners); - { - auto client = getClient(); - client.request.mutable_account()->set_address(alice.human()); - client.request.set_signer_lists(false); - client.GetAccountInfo(); - if (!BEAST_EXPECT(client.status.ok())) - return; - BEAST_EXPECT(client.reply.signer_list().signer_entries_size() == 0); - } - { - auto client = getClient(); - client.request.mutable_account()->set_address(alice.human()); - client.request.set_signer_lists(true); - client.GetAccountInfo(); - if (!BEAST_EXPECT(client.status.ok())) - { - return; - } - BEAST_EXPECT( - client.reply.account_data().owner_count().value() == 1); - BEAST_EXPECT(client.reply.signer_list().signer_entries_size() == 1); - } - - // Give alice a big signer list - Account const demon{"demon"}; - Account const ghost{"ghost"}; - Account const haunt{"haunt"}; - Account const jinni{"jinni"}; - Account const phase{"phase"}; - Account const shade{"shade"}; - Account const spook{"spook"}; - Json::Value const bigSigners = signers( - alice, - 4, - { - {bogie, 1}, - {demon, 1}, - {ghost, 1}, - {haunt, 1}, - {jinni, 1}, - {phase, 1}, - {shade, 1}, - {spook, 1}, - }); - env(bigSigners); - - std::set accounts; - accounts.insert(bogie.human()); - accounts.insert(demon.human()); - accounts.insert(ghost.human()); - accounts.insert(haunt.human()); - accounts.insert(jinni.human()); - accounts.insert(phase.human()); - accounts.insert(shade.human()); - accounts.insert(spook.human()); - { - auto client = getClient(); - client.request.mutable_account()->set_address(alice.human()); - client.request.set_signer_lists(true); - client.GetAccountInfo(); - if (!BEAST_EXPECT(client.status.ok())) - { - return; - } - BEAST_EXPECT( - client.reply.account_data().owner_count().value() == 1); - auto& signerList = client.reply.signer_list(); - BEAST_EXPECT(signerList.signer_quorum().value() == 4); - BEAST_EXPECT(signerList.signer_entries_size() == 8); - for (int i = 0; i < 8; ++i) - { - BEAST_EXPECT( - signerList.signer_entries(i).signer_weight().value() == 1); - BEAST_EXPECT( - accounts.erase(signerList.signer_entries(i) - .account() - .value() - .address()) == 1); - } - BEAST_EXPECT(accounts.size() == 0); - } - } - void run() override { @@ -719,9 +498,6 @@ class AccountInfo_test : public beast::unit_test::suite testSignerLists(); testSignerListsApiVersion2(); testSignerListsV2(); - testSimpleGrpc(); - testErrorsGrpc(); - testSignerListsGrpc(); } }; diff --git a/src/test/rpc/Fee_test.cpp b/src/test/rpc/Fee_test.cpp deleted file mode 100644 index 17ada929e2e..00000000000 --- a/src/test/rpc/Fee_test.cpp +++ /dev/null @@ -1,138 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of rippled: https://github.com/ripple/rippled - Copyright (c) 2020 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace ripple { -namespace test { - -class Fee_test : public beast::unit_test::suite -{ - class GrpcFeeClient : public GRPCTestClientBase - { - public: - org::xrpl::rpc::v1::GetFeeRequest request; - org::xrpl::rpc::v1::GetFeeResponse reply; - - explicit GrpcFeeClient(std::string const& grpcPort) - : GRPCTestClientBase(grpcPort) - { - } - - void - GetFee() - { - status = stub_->GetFee(&context, request, &reply); - } - }; - - std::pair - grpcGetFee(std::string const& grpcPort) - { - GrpcFeeClient client(grpcPort); - client.GetFee(); - return std::pair( - client.status.ok(), client.reply); - } - - void - testFeeGrpc() - { - testcase("Test Fee Grpc"); - - using namespace test::jtx; - std::unique_ptr config = envconfig(addGrpcConfig); - std::string grpcPort = *(*config)["port_grpc"].get("port"); - Env env(*this, std::move(config)); - Account A1{"A1"}; - Account A2{"A2"}; - env.fund(XRP(10000), A1); - env.fund(XRP(10000), A2); - env.close(); - env.trust(A2["USD"](1000), A1); - env.close(); - for (int i = 0; i < 7; ++i) - { - env(pay(A2, A1, A2["USD"](100))); - if (i == 4) - env.close(); - } - - auto view = env.current(); - - auto const metrics = env.app().getTxQ().getMetrics(*env.current()); - - auto const result = grpcGetFee(grpcPort); - - BEAST_EXPECT(result.first == true); - - auto reply = result.second; - - // current ledger data - BEAST_EXPECT(reply.current_ledger_size() == metrics.txInLedger); - BEAST_EXPECT(reply.current_queue_size() == metrics.txCount); - BEAST_EXPECT(reply.expected_ledger_size() == metrics.txPerLedger); - BEAST_EXPECT(reply.ledger_current_index() == view->info().seq); - BEAST_EXPECT(reply.max_queue_size() == *metrics.txQMaxSize); - - // fee levels data - org::xrpl::rpc::v1::FeeLevels& levels = *reply.mutable_levels(); - BEAST_EXPECT(levels.median_level() == metrics.medFeeLevel); - BEAST_EXPECT(levels.minimum_level() == metrics.minProcessingFeeLevel); - BEAST_EXPECT(levels.open_ledger_level() == metrics.openLedgerFeeLevel); - BEAST_EXPECT(levels.reference_level() == metrics.referenceFeeLevel); - - // fee data - org::xrpl::rpc::v1::Fee& fee = *reply.mutable_fee(); - auto const baseFee = view->fees().base; - BEAST_EXPECT( - fee.base_fee().drops() == - toDrops(metrics.referenceFeeLevel, baseFee)); - BEAST_EXPECT( - fee.minimum_fee().drops() == - toDrops(metrics.minProcessingFeeLevel, baseFee)); - BEAST_EXPECT( - fee.median_fee().drops() == toDrops(metrics.medFeeLevel, baseFee)); - auto openLedgerFee = - toDrops(metrics.openLedgerFeeLevel - FeeLevel64{1}, baseFee) + 1; - BEAST_EXPECT(fee.open_ledger_fee().drops() == openLedgerFee.drops()); - } - -public: - void - run() override - { - testFeeGrpc(); - } -}; - -BEAST_DEFINE_TESTSUITE(Fee, app, ripple); - -} // namespace test -} // namespace ripple diff --git a/src/test/rpc/ReportingETL_test.cpp b/src/test/rpc/ReportingETL_test.cpp index 36b2f9b0b69..d8e6fc684fd 100644 --- a/src/test/rpc/ReportingETL_test.cpp +++ b/src/test/rpc/ReportingETL_test.cpp @@ -773,25 +773,6 @@ class ReportingETL_test : public beast::unit_test::suite testNeedCurrentOrClosed() { testcase("NeedCurrentOrClosed"); - { - org::xrpl::rpc::v1::GetAccountInfoRequest request; - request.mutable_ledger()->set_sequence(1); - BEAST_EXPECT(!needCurrentOrClosed(request)); - request.mutable_ledger()->set_hash(""); - BEAST_EXPECT(!needCurrentOrClosed(request)); - request.mutable_ledger()->set_shortcut( - org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_VALIDATED); - BEAST_EXPECT(!needCurrentOrClosed(request)); - request.mutable_ledger()->set_shortcut( - org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_UNSPECIFIED); - BEAST_EXPECT(!needCurrentOrClosed(request)); - request.mutable_ledger()->set_shortcut( - org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_CURRENT); - BEAST_EXPECT(needCurrentOrClosed(request)); - request.mutable_ledger()->set_shortcut( - org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_CLOSED); - BEAST_EXPECT(needCurrentOrClosed(request)); - } { org::xrpl::rpc::v1::GetLedgerRequest request; @@ -904,18 +885,6 @@ class ReportingETL_test : public beast::unit_test::suite org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_CURRENT); BEAST_EXPECT(needCurrentOrClosed(request)); } - - { - org::xrpl::rpc::v1::GetFeeRequest feeRequest; - BEAST_EXPECT(!needCurrentOrClosed(feeRequest)); - - org::xrpl::rpc::v1::GetAccountTransactionHistoryRequest - accountTxRequest; - BEAST_EXPECT(!needCurrentOrClosed(accountTxRequest)); - - org::xrpl::rpc::v1::GetTransactionRequest txRequest; - BEAST_EXPECT(!needCurrentOrClosed(txRequest)); - } } void diff --git a/src/test/rpc/Submit_test.cpp b/src/test/rpc/Submit_test.cpp deleted file mode 100644 index 252e1c32a8a..00000000000 --- a/src/test/rpc/Submit_test.cpp +++ /dev/null @@ -1,276 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of rippled: https://github.com/ripple/rippled - Copyright (c) 2020 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 -#include -#include -#include -#include - -#include -#include -#include -#include - -namespace ripple { -namespace test { - -class Submit_test : public beast::unit_test::suite -{ -public: - class SubmitClient : public GRPCTestClientBase - { - public: - org::xrpl::rpc::v1::SubmitTransactionRequest request; - org::xrpl::rpc::v1::SubmitTransactionResponse reply; - - explicit SubmitClient(std::string const& port) - : GRPCTestClientBase(port) - { - } - - void - SubmitTransaction() - { - status = stub_->SubmitTransaction(&context, request, &reply); - } - }; - - struct TestData - { - std::string xrpTxBlob; - std::string xrpTxHash; - std::string usdTxBlob; - std::string usdTxHash; - const static int fund = 10000; - } testData; - - void - fillTestData() - { - testcase("fill test data"); - - using namespace jtx; - Env env(*this, envconfig(addGrpcConfig)); - auto const alice = Account("alice"); - auto const bob = Account("bob"); - env.fund(XRP(TestData::fund), "alice", "bob"); - env.trust(bob["USD"](TestData::fund), alice); - env.close(); - - auto toBinary = [this](std::string const& text) { - auto blob = strUnHex(text); - BEAST_EXPECT(blob); - return std::string{ - reinterpret_cast(blob->data()), blob->size()}; - }; - - // use a websocket client to fill transaction blobs - auto wsc = makeWSClient(env.app().config()); - { - Json::Value jrequestXrp; - jrequestXrp[jss::secret] = toBase58(generateSeed("alice")); - jrequestXrp[jss::tx_json] = - pay("alice", "bob", XRP(TestData::fund / 2)); - Json::Value jreply_xrp = wsc->invoke("sign", jrequestXrp); - - if (!BEAST_EXPECT(jreply_xrp.isMember(jss::result))) - return; - if (!BEAST_EXPECT(jreply_xrp[jss::result].isMember(jss::tx_blob))) - return; - testData.xrpTxBlob = - toBinary(jreply_xrp[jss::result][jss::tx_blob].asString()); - if (!BEAST_EXPECT(jreply_xrp[jss::result].isMember(jss::tx_json))) - return; - if (!BEAST_EXPECT( - jreply_xrp[jss::result][jss::tx_json].isMember(jss::hash))) - return; - testData.xrpTxHash = toBinary( - jreply_xrp[jss::result][jss::tx_json][jss::hash].asString()); - } - { - Json::Value jrequestUsd; - jrequestUsd[jss::secret] = toBase58(generateSeed("bob")); - jrequestUsd[jss::tx_json] = - pay("bob", "alice", bob["USD"](TestData::fund / 2)); - Json::Value jreply_usd = wsc->invoke("sign", jrequestUsd); - - if (!BEAST_EXPECT(jreply_usd.isMember(jss::result))) - return; - if (!BEAST_EXPECT(jreply_usd[jss::result].isMember(jss::tx_blob))) - return; - testData.usdTxBlob = - toBinary(jreply_usd[jss::result][jss::tx_blob].asString()); - if (!BEAST_EXPECT(jreply_usd[jss::result].isMember(jss::tx_json))) - return; - if (!BEAST_EXPECT( - jreply_usd[jss::result][jss::tx_json].isMember(jss::hash))) - return; - testData.usdTxHash = toBinary( - jreply_usd[jss::result][jss::tx_json][jss::hash].asString()); - } - } - - void - testSubmitGoodBlobGrpc() - { - testcase("Submit good blobs, XRP, USD, and same transaction twice"); - - using namespace jtx; - std::unique_ptr config = envconfig(addGrpcConfig); - std::string grpcPort = *(*config)["port_grpc"].get("port"); - Env env(*this, std::move(config)); - auto const alice = Account("alice"); - auto const bob = Account("bob"); - env.fund(XRP(TestData::fund), "alice", "bob"); - env.trust(bob["USD"](TestData::fund), alice); - env.close(); - - auto getClient = [&grpcPort]() { return SubmitClient(grpcPort); }; - - // XRP - { - auto client = getClient(); - client.request.set_signed_transaction(testData.xrpTxBlob); - client.SubmitTransaction(); - if (!BEAST_EXPECT(client.status.ok())) - { - return; - } - BEAST_EXPECT(client.reply.engine_result().result() == "tesSUCCESS"); - BEAST_EXPECT(client.reply.engine_result_code() == 0); - BEAST_EXPECT(client.reply.hash() == testData.xrpTxHash); - } - // USD - { - auto client = getClient(); - client.request.set_signed_transaction(testData.usdTxBlob); - client.SubmitTransaction(); - if (!BEAST_EXPECT(client.status.ok())) - { - return; - } - BEAST_EXPECT(client.reply.engine_result().result() == "tesSUCCESS"); - BEAST_EXPECT(client.reply.engine_result_code() == 0); - BEAST_EXPECT(client.reply.hash() == testData.usdTxHash); - } - // USD, error, same transaction again - { - auto client = getClient(); - client.request.set_signed_transaction(testData.usdTxBlob); - client.SubmitTransaction(); - if (!BEAST_EXPECT(client.status.ok())) - { - return; - } - BEAST_EXPECT( - client.reply.engine_result().result() == "tefPAST_SEQ"); - BEAST_EXPECT(client.reply.engine_result_code() == -190); - } - } - - void - testSubmitErrorBlobGrpc() - { - testcase("Submit error, bad blob, no account"); - - using namespace jtx; - std::unique_ptr config = envconfig(addGrpcConfig); - std::string grpcPort = *(*config)["port_grpc"].get("port"); - Env env(*this, std::move(config)); - - auto getClient = [&grpcPort]() { return SubmitClient(grpcPort); }; - - // short transaction blob, cannot parse - { - auto client = getClient(); - client.request.set_signed_transaction("deadbeef"); - client.SubmitTransaction(); - BEAST_EXPECT(!client.status.ok()); - } - // bad blob with correct length, cannot parse - { - auto client = getClient(); - auto xrpTxBlobCopy(testData.xrpTxBlob); - std::reverse(xrpTxBlobCopy.begin(), xrpTxBlobCopy.end()); - client.request.set_signed_transaction(xrpTxBlobCopy); - client.SubmitTransaction(); - BEAST_EXPECT(!client.status.ok()); - } - // good blob, can parse but no account - { - auto client = getClient(); - client.request.set_signed_transaction(testData.xrpTxBlob); - client.SubmitTransaction(); - if (!BEAST_EXPECT(client.status.ok())) - { - return; - } - BEAST_EXPECT( - client.reply.engine_result().result() == "terNO_ACCOUNT"); - BEAST_EXPECT(client.reply.engine_result_code() == -96); - } - } - - void - testSubmitInsufficientFundsGrpc() - { - testcase("Submit good blobs but insufficient funds"); - - using namespace jtx; - std::unique_ptr config = envconfig(addGrpcConfig); - std::string grpcPort = *(*config)["port_grpc"].get("port"); - Env env(*this, std::move(config)); - - auto const alice = Account("alice"); - auto const bob = Account("bob"); - // fund 1000 (TestData::fund/10) XRP, the transaction sends 5000 - // (TestData::fund/2) XRP, so insufficient funds - env.fund(XRP(TestData::fund / 10), "alice", "bob"); - env.trust(bob["USD"](TestData::fund), alice); - env.close(); - - { - SubmitClient client(grpcPort); - client.request.set_signed_transaction(testData.xrpTxBlob); - client.SubmitTransaction(); - if (!BEAST_EXPECT(client.status.ok())) - { - return; - } - BEAST_EXPECT( - client.reply.engine_result().result() == "tecUNFUNDED_PAYMENT"); - BEAST_EXPECT(client.reply.engine_result_code() == 104); - } - } - - void - run() override - { - fillTestData(); - testSubmitGoodBlobGrpc(); - testSubmitErrorBlobGrpc(); - testSubmitInsufficientFundsGrpc(); - } -}; - -BEAST_DEFINE_TESTSUITE(Submit, app, ripple); - -} // namespace test -} // namespace ripple diff --git a/src/test/rpc/Tx_test.cpp b/src/test/rpc/Tx_test.cpp deleted file mode 100644 index 8cfd36c5d86..00000000000 --- a/src/test/rpc/Tx_test.cpp +++ /dev/null @@ -1,829 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of rippled: https://github.com/ripple/rippled - Copyright (c) 2020 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -namespace ripple { -namespace test { - -class Tx_test : public beast::unit_test::suite -{ - template - std::string - toByteString(T const& data) - { - const char* bytes = reinterpret_cast(data.data()); - return {bytes, data.size()}; - } - - void - cmpAmount( - const org::xrpl::rpc::v1::CurrencyAmount& proto_amount, - STAmount amount) - { - if (amount.native()) - { - if (!BEAST_EXPECT(proto_amount.has_xrp_amount())) - return; - BEAST_EXPECT( - proto_amount.xrp_amount().drops() == amount.xrp().drops()); - } - else - { - if (!BEAST_EXPECT(proto_amount.has_issued_currency_amount())) - return; - - org::xrpl::rpc::v1::IssuedCurrencyAmount issuedCurrency = - proto_amount.issued_currency_amount(); - Issue const& issue = amount.issue(); - Currency currency = issue.currency; - BEAST_EXPECT( - issuedCurrency.currency().name() == to_string(currency)); - BEAST_EXPECT( - issuedCurrency.currency().code() == toByteString(currency)); - BEAST_EXPECT(issuedCurrency.value() == to_string(amount.iou())); - BEAST_EXPECT( - issuedCurrency.issuer().address() == toBase58(issue.account)); - } - } - - void - cmpPaymentTx( - const org::xrpl::rpc::v1::Transaction& proto, - std::shared_ptr txnSt) - { - if (!BEAST_EXPECT(proto.has_payment())) - return; - - if (!BEAST_EXPECT( - safe_cast(txnSt->getFieldU16(sfTransactionType)) == - TxType::ttPAYMENT)) - return; - - AccountID account = txnSt->getAccountID(sfAccount); - - if (!BEAST_EXPECT(proto.has_account())) - return; - BEAST_EXPECT(proto.account().value().address() == toBase58(account)); - - STAmount amount = txnSt->getFieldAmount(sfAmount); - if (!BEAST_EXPECT(proto.payment().has_amount())) - return; - cmpAmount(proto.payment().amount().value(), amount); - - AccountID accountDest = txnSt->getAccountID(sfDestination); - if (!BEAST_EXPECT(proto.payment().has_destination())) - return; - BEAST_EXPECT( - proto.payment().destination().value().address() == - toBase58(accountDest)); - - STAmount fee = txnSt->getFieldAmount(sfFee); - if (!BEAST_EXPECT(proto.has_fee())) - return; - BEAST_EXPECT(proto.fee().drops() == fee.xrp().drops()); - - if (!BEAST_EXPECT(proto.has_sequence())) - return; - BEAST_EXPECT( - proto.sequence().value() == txnSt->getFieldU32(sfSequence)); - - if (!BEAST_EXPECT(proto.has_signing_public_key())) - return; - - Blob signingPubKey = txnSt->getFieldVL(sfSigningPubKey); - BEAST_EXPECT( - proto.signing_public_key().value() == toByteString(signingPubKey)); - - if (txnSt->isFieldPresent(sfFlags)) - { - if (!BEAST_EXPECT(proto.has_flags())) - return; - BEAST_EXPECT(proto.flags().value() == txnSt->getFieldU32(sfFlags)); - } - else - { - BEAST_EXPECT(!proto.has_flags()); - } - - if (txnSt->isFieldPresent(sfLastLedgerSequence)) - { - if (!BEAST_EXPECT(proto.has_last_ledger_sequence())) - return; - - BEAST_EXPECT( - proto.last_ledger_sequence().value() == - txnSt->getFieldU32(sfLastLedgerSequence)); - } - else - { - BEAST_EXPECT(!proto.has_last_ledger_sequence()); - } - - if (txnSt->isFieldPresent(sfTxnSignature)) - { - if (!BEAST_EXPECT(proto.has_transaction_signature())) - return; - - Blob blob = txnSt->getFieldVL(sfTxnSignature); - BEAST_EXPECT( - proto.transaction_signature().value() == toByteString(blob)); - } - - if (txnSt->isFieldPresent(sfSendMax)) - { - if (!BEAST_EXPECT(proto.payment().has_send_max())) - return; - STAmount const& send_max = txnSt->getFieldAmount(sfSendMax); - cmpAmount(proto.payment().send_max().value(), send_max); - } - else - { - BEAST_EXPECT(!proto.payment().has_send_max()); - } - - if (txnSt->isFieldPresent(sfAccountTxnID)) - { - if (!BEAST_EXPECT(proto.has_account_transaction_id())) - return; - auto field = txnSt->getFieldH256(sfAccountTxnID); - BEAST_EXPECT( - proto.account_transaction_id().value() == toByteString(field)); - } - else - { - BEAST_EXPECT(!proto.has_account_transaction_id()); - } - - if (txnSt->isFieldPresent(sfSourceTag)) - { - if (!BEAST_EXPECT(proto.has_source_tag())) - return; - BEAST_EXPECT( - proto.source_tag().value() == txnSt->getFieldU32(sfSourceTag)); - } - else - { - BEAST_EXPECT(!proto.has_source_tag()); - } - - if (txnSt->isFieldPresent(sfDestinationTag)) - { - if (!BEAST_EXPECT(proto.payment().has_destination_tag())) - return; - - BEAST_EXPECT( - proto.payment().destination_tag().value() == - txnSt->getFieldU32(sfDestinationTag)); - } - else - { - BEAST_EXPECT(!proto.payment().has_destination_tag()); - } - - if (txnSt->isFieldPresent(sfInvoiceID)) - { - if (!BEAST_EXPECT(proto.payment().has_invoice_id())) - return; - - auto field = txnSt->getFieldH256(sfInvoiceID); - BEAST_EXPECT( - proto.payment().invoice_id().value() == toByteString(field)); - } - else - { - BEAST_EXPECT(!proto.payment().has_invoice_id()); - } - - if (txnSt->isFieldPresent(sfDeliverMin)) - { - if (!BEAST_EXPECT(proto.payment().has_deliver_min())) - return; - STAmount const& deliverMin = txnSt->getFieldAmount(sfDeliverMin); - cmpAmount(proto.payment().deliver_min().value(), deliverMin); - } - else - { - BEAST_EXPECT(!proto.payment().has_deliver_min()); - } - - STPathSet const& pathset = txnSt->getFieldPathSet(sfPaths); - if (!BEAST_EXPECT(pathset.size() == proto.payment().paths_size())) - return; - - int ind = 0; - for (auto it = pathset.begin(); it < pathset.end(); ++it) - { - STPath const& path = *it; - - const org::xrpl::rpc::v1::Payment_Path& protoPath = - proto.payment().paths(ind++); - if (!BEAST_EXPECT(protoPath.elements_size() == path.size())) - continue; - - int ind2 = 0; - for (auto it2 = path.begin(); it2 != path.end(); ++it2) - { - const org::xrpl::rpc::v1::Payment_PathElement& protoElement = - protoPath.elements(ind2++); - STPathElement const& elt = *it2; - - if (elt.isOffer()) - { - if (elt.hasCurrency()) - { - Currency const& currency = elt.getCurrency(); - if (BEAST_EXPECT(protoElement.has_currency())) - { - BEAST_EXPECT( - protoElement.currency().name() == - to_string(currency)); - } - } - else - { - BEAST_EXPECT(!protoElement.has_currency()); - } - if (elt.hasIssuer()) - { - AccountID const& issuer = elt.getIssuerID(); - if (BEAST_EXPECT(protoElement.has_issuer())) - { - BEAST_EXPECT( - protoElement.issuer().address() == - toBase58(issuer)); - } - } - else - { - BEAST_EXPECT(!protoElement.has_issuer()); - } - } - else - { - if (BEAST_EXPECT(protoElement.has_account())) - { - AccountID const& path_account = elt.getAccountID(); - BEAST_EXPECT( - protoElement.account().address() == - toBase58(path_account)); - } - else - { - BEAST_EXPECT(!protoElement.has_account()); - } - - BEAST_EXPECT(!protoElement.has_issuer()); - BEAST_EXPECT(!protoElement.has_currency()); - } - } - } - - if (txnSt->isFieldPresent(sfMemos)) - { - auto arr = txnSt->getFieldArray(sfMemos); - if (BEAST_EXPECT(proto.memos_size() == arr.size())) - { - for (size_t i = 0; i < arr.size(); ++i) - { - auto protoMemo = proto.memos(i); - auto stMemo = arr[i]; - - if (stMemo.isFieldPresent(sfMemoData)) - { - if (BEAST_EXPECT(protoMemo.has_memo_data())) - { - BEAST_EXPECT( - protoMemo.memo_data().value() == - toByteString(stMemo.getFieldVL(sfMemoData))); - } - } - else - { - BEAST_EXPECT(!protoMemo.has_memo_data()); - } - - if (stMemo.isFieldPresent(sfMemoType)) - { - if (BEAST_EXPECT(protoMemo.has_memo_type())) - { - BEAST_EXPECT( - protoMemo.memo_type().value() == - toByteString(stMemo.getFieldVL(sfMemoType))); - } - } - else - { - BEAST_EXPECT(!protoMemo.has_memo_type()); - } - - if (stMemo.isFieldPresent(sfMemoFormat)) - { - if (BEAST_EXPECT(protoMemo.has_memo_format())) - { - BEAST_EXPECT( - protoMemo.memo_format().value() == - toByteString(stMemo.getFieldVL(sfMemoFormat))); - } - } - else - { - BEAST_EXPECT(!protoMemo.has_memo_format()); - } - } - } - } - else - { - BEAST_EXPECT(proto.memos_size() == 0); - } - - if (txnSt->isFieldPresent(sfSigners)) - { - auto arr = txnSt->getFieldArray(sfSigners); - if (BEAST_EXPECT(proto.signers_size() == arr.size())) - { - for (size_t i = 0; i < arr.size(); ++i) - { - auto protoSigner = proto.signers(i); - auto stSigner = arr[i]; - - if (stSigner.isFieldPresent(sfAccount)) - { - if (BEAST_EXPECT(protoSigner.has_account())) - { - BEAST_EXPECT( - protoSigner.account().value().address() == - toBase58(stSigner.getAccountID(sfAccount))); - } - } - else - { - BEAST_EXPECT(!protoSigner.has_account()); - } - - if (stSigner.isFieldPresent(sfTxnSignature)) - { - if (BEAST_EXPECT( - protoSigner.has_transaction_signature())) - { - Blob blob = stSigner.getFieldVL(sfTxnSignature); - BEAST_EXPECT( - protoSigner.transaction_signature().value() == - toByteString(blob)); - } - } - else - { - BEAST_EXPECT(!protoSigner.has_transaction_signature()); - } - - if (stSigner.isFieldPresent(sfSigningPubKey)) - { - if (BEAST_EXPECT(protoSigner.has_signing_public_key())) - { - Blob signingPubKey = - stSigner.getFieldVL(sfSigningPubKey); - BEAST_EXPECT( - protoSigner.signing_public_key().value() == - toByteString(signingPubKey)); - } - } - else - { - BEAST_EXPECT(!protoSigner.has_signing_public_key()); - } - } - } - } - else - { - BEAST_EXPECT(proto.signers_size() == 0); - } - } - - void - cmpMeta( - const org::xrpl::rpc::v1::Meta& proto, - std::shared_ptr txMeta) - { - BEAST_EXPECT(proto.transaction_index() == txMeta->getIndex()); - BEAST_EXPECT( - proto.transaction_result().result() == - transToken(txMeta->getResultTER())); - - org::xrpl::rpc::v1::TransactionResult r; - - RPC::convert(r, txMeta->getResultTER()); - - BEAST_EXPECT( - proto.transaction_result().result_type() == r.result_type()); - } - - void - cmpDeliveredAmount( - const org::xrpl::rpc::v1::Meta& meta, - const org::xrpl::rpc::v1::Transaction& txn, - const std::shared_ptr expMeta, - const std::shared_ptr expTxn, - bool checkAmount = true) - { - if (expMeta->hasDeliveredAmount()) - { - if (!BEAST_EXPECT(meta.has_delivered_amount())) - return; - cmpAmount( - meta.delivered_amount().value(), expMeta->getDeliveredAmount()); - } - else - { - if (expTxn->isFieldPresent(sfAmount)) - { - using namespace std::chrono_literals; - if (checkAmount) - { - cmpAmount( - meta.delivered_amount().value(), - expTxn->getFieldAmount(sfAmount)); - } - } - else - { - BEAST_EXPECT(!meta.has_delivered_amount()); - } - } - } - - // gRPC stuff - class GrpcTxClient : public GRPCTestClientBase - { - public: - org::xrpl::rpc::v1::GetTransactionRequest request; - org::xrpl::rpc::v1::GetTransactionResponse reply; - - explicit GrpcTxClient(std::string const& port) - : GRPCTestClientBase(port) - { - } - - void - Tx() - { - status = stub_->GetTransaction(&context, request, &reply); - } - }; - - class GrpcAccountTxClient : public GRPCTestClientBase - { - public: - org::xrpl::rpc::v1::GetAccountTransactionHistoryRequest request; - org::xrpl::rpc::v1::GetAccountTransactionHistoryResponse reply; - - explicit GrpcAccountTxClient(std::string const& port) - : GRPCTestClientBase(port) - { - } - - void - AccountTx() - { - status = - stub_->GetAccountTransactionHistory(&context, request, &reply); - } - }; - - void - testTxGrpc() - { - testcase("Test Tx Grpc"); - - using namespace test::jtx; - std::unique_ptr config = envconfig(addGrpcConfig); - std::string grpcPort = *(*config)["port_grpc"].get("port"); - Env env(*this, std::move(config)); - - using namespace std::chrono_literals; - // Set time to this value (or greater) to get delivered_amount in meta - env.timeKeeper().set(NetClock::time_point{446000001s}); - - auto grpcTx = [&grpcPort](auto hash, auto binary) { - GrpcTxClient client(grpcPort); - client.request.set_hash(&hash, sizeof(hash)); - client.request.set_binary(binary); - client.Tx(); - return std::pair( - client.status.ok(), client.reply); - }; - - Account A1{"A1"}; - Account A2{"A2"}; - Account A3{"A3"}; - env.fund(XRP(10000), A1); - env.fund(XRP(10000), A2); - env.close(); - env.trust(A2["USD"](1000), A1); - env.close(); - env(fset(A2, 5)); // set asfAccountTxnID flag - - // SignerListSet - env(signers(A2, 1, {{"bogie", 1}, {"demon", 1}, {A1, 1}, {A3, 1}}), - sig(A2)); - env.close(); - std::vector> txns; - auto const startLegSeq = env.current()->info().seq; - - uint256 prevHash; - for (int i = 0; i < 14; ++i) - { - auto const baseFee = env.current()->fees().base; - auto txfee = fee(i + (2 * baseFee)); - auto lls = last_ledger_seq(i + startLegSeq + 20); - auto dsttag = dtag(i * 456); - auto srctag = stag(i * 321); - auto sm = sendmax(A2["USD"](1000)); - auto dm = delivermin(A2["USD"](50)); - auto txf = txflags(131072); // partial payment flag - auto txnid = account_txn_id(prevHash); - auto inv = invoice_id(prevHash); - auto mem1 = memo("foo", "bar", "baz"); - auto mem2 = memo("dragons", "elves", "goblins"); - - if (i & 1) - { - if (i & 2) - { - env(pay(A2, A1, A2["USD"](100)), - txfee, - srctag, - dsttag, - lls, - sm, - dm, - txf, - txnid, - inv, - mem1, - mem2, - sig(A2)); - } - else - { - env(pay(A2, A1, A2["USD"](100)), - txfee, - srctag, - dsttag, - lls, - sm, - dm, - txf, - txnid, - inv, - mem1, - mem2, - msig(A3)); - } - } - else - { - if (i & 2) - { - env(pay(A2, A1, A2["XRP"](200)), - txfee, - srctag, - dsttag, - lls, - txnid, - inv, - mem1, - mem2, - sig(A2)); - } - else - { - env(pay(A2, A1, A2["XRP"](200)), - txfee, - srctag, - dsttag, - lls, - txnid, - inv, - mem1, - mem2, - msig(A3)); - } - } - txns.emplace_back(env.tx()); - prevHash = txns.back()->getTransactionID(); - env.close(); - } - - // Payment with Paths - auto const gw = Account("gateway"); - auto const USD = gw["USD"]; - env.fund(XRP(10000), "alice", "bob", gw); - env.trust(USD(600), "alice"); - env.trust(USD(700), "bob"); - env(pay(gw, "alice", USD(70))); - txns.emplace_back(env.tx()); - env.close(); - env(pay(gw, "bob", USD(50))); - txns.emplace_back(env.tx()); - env.close(); - env(pay("alice", "bob", Account("bob")["USD"](5)), path(gw)); - txns.emplace_back(env.tx()); - env.close(); - - auto const endLegSeq = env.closed()->info().seq; - - // Find the existing transactions - auto& ledgerMaster = env.app().getLedgerMaster(); - int index = startLegSeq; - for (auto&& tx : txns) - { - auto id = tx->getTransactionID(); - auto ledger = ledgerMaster.getLedgerBySeq(index); - - for (bool b : {false, true}) - { - auto const result = grpcTx(id, b); - - BEAST_EXPECT(result.first == true); - BEAST_EXPECT(result.second.ledger_index() == index); - BEAST_EXPECT(result.second.validated() == true); - if (b) - { - Serializer s = tx->getSerializer(); - BEAST_EXPECT( - result.second.transaction_binary() == toByteString(s)); - } - else - { - cmpPaymentTx(result.second.transaction(), tx); - } - - if (!ledger || b) - continue; - - auto rawMeta = ledger->txRead(id).second; - if (!rawMeta) - continue; - - auto txMeta = - std::make_shared(id, ledger->seq(), *rawMeta); - - cmpMeta(result.second.meta(), txMeta); - cmpDeliveredAmount( - result.second.meta(), - result.second.transaction(), - txMeta, - tx); - - auto grpcAccountTx = [&grpcPort]( - uint256 const& id, - bool binary, - AccountID const& account) - -> std:: - pair { - GrpcAccountTxClient client(grpcPort); - client.request.set_binary(binary); - client.request.mutable_account()->set_address( - toBase58(account)); - client.AccountTx(); - org::xrpl::rpc::v1::GetTransactionResponse res; - - for (auto const& tx : client.reply.transactions()) - { - if (uint256::fromVoid(tx.hash().data()) == id) - { - return {client.status.ok(), tx}; - } - } - return {false, res}; - }; - - // Compare result to result from account_tx - auto mentioned = tx->getMentionedAccounts(); - - if (!BEAST_EXPECT(mentioned.size())) - continue; - - auto account = *mentioned.begin(); - auto const accountTxResult = grpcAccountTx(id, b, account); - - if (!BEAST_EXPECT(accountTxResult.first)) - continue; - - cmpPaymentTx(accountTxResult.second.transaction(), tx); - cmpMeta(accountTxResult.second.meta(), txMeta); - cmpDeliveredAmount( - accountTxResult.second.meta(), - accountTxResult.second.transaction(), - txMeta, - tx); - } - index++; - } - - // Find not existing transaction - auto const tx = env.jt(noop(A1), seq(env.seq(A1))).stx; - for (bool b : {false, true}) - { - auto const result = grpcTx(tx->getTransactionID(), b); - - BEAST_EXPECT(result.first == false); - } - - // Delete one transaction - const auto deletedLedger = (startLegSeq + endLegSeq) / 2; - { - // Remove one of the ledgers from the database directly - dynamic_cast(&env.app().getRelationalDatabase()) - ->deleteTransactionByLedgerSeq(deletedLedger); - } - - for (bool b : {false, true}) - { - auto const result = grpcTx(tx->getTransactionID(), b); - - BEAST_EXPECT(result.first == false); - } - - // non final transaction - env(pay(A2, A1, A2["XRP"](200))); - auto res = grpcTx(env.tx()->getTransactionID(), false); - BEAST_EXPECT(res.first); - BEAST_EXPECT(res.second.has_transaction()); - if (!BEAST_EXPECT(res.second.has_meta())) - return; - if (!BEAST_EXPECT(res.second.meta().has_transaction_result())) - return; - - BEAST_EXPECT( - res.second.meta().transaction_result().result() == "tesSUCCESS"); - BEAST_EXPECT( - res.second.meta().transaction_result().result_type() == - org::xrpl::rpc::v1::TransactionResult::RESULT_TYPE_TES); - BEAST_EXPECT(!res.second.validated()); - BEAST_EXPECT(!res.second.meta().has_delivered_amount()); - env.close(); - - res = grpcTx(env.tx()->getTransactionID(), false); - BEAST_EXPECT(res.first); - BEAST_EXPECT(res.second.has_transaction()); - if (!BEAST_EXPECT(res.second.has_meta())) - return; - if (!BEAST_EXPECT(res.second.meta().has_transaction_result())) - return; - - BEAST_EXPECT( - res.second.meta().transaction_result().result() == "tesSUCCESS"); - BEAST_EXPECT( - res.second.meta().transaction_result().result_type() == - org::xrpl::rpc::v1::TransactionResult::RESULT_TYPE_TES); - BEAST_EXPECT(res.second.validated()); - BEAST_EXPECT(res.second.meta().has_delivered_amount()); - } - -public: - void - run() override - { - testTxGrpc(); - } -}; - -BEAST_DEFINE_TESTSUITE(Tx, app, ripple); -} // namespace test -} // namespace ripple