Skip to content

Commit 2a10013

Browse files
authored
Support 'cron' with ledger_entry RPC (#608)
1 parent 6f148a8 commit 2a10013

File tree

4 files changed

+115
-1
lines changed

4 files changed

+115
-1
lines changed

src/ripple/protocol/impl/Indexes.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ enum class LedgerNameSpace : std::uint16_t {
7272
URI_TOKEN = 'U',
7373
IMPORT_VLSEQ = 'I',
7474
UNL_REPORT = 'R',
75-
CRON = 'A',
75+
CRON = 'L',
7676

7777
// No longer used or supported. Left here to reserve the space
7878
// to avoid accidental reuse.

src/ripple/protocol/jss.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,7 @@ JSS(coins);
256256
JSS(children);
257257
JSS(ctid); // in/out: Tx RPC
258258
JSS(cres);
259+
JSS(cron);
259260
JSS(currency_a); // out: BookChanges
260261
JSS(currency_b); // out: BookChanges
261262
JSS(currentShard); // out: NodeToShardStatus

src/ripple/rpc/handlers/LedgerEntry.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,36 @@ doLedgerEntry(RPC::JsonContext& context)
506506
jvResult[jss::error] = "malformedRequest";
507507
}
508508
}
509+
else if (context.params.isMember(jss::cron))
510+
{
511+
expectedType = ltCRON;
512+
if (!context.params[jss::cron].isObject())
513+
{
514+
if (!uNodeIndex.parseHex(context.params[jss::cron].asString()))
515+
{
516+
uNodeIndex = beast::zero;
517+
jvResult[jss::error] = "malformedRequest";
518+
}
519+
}
520+
else if (
521+
!context.params[jss::cron].isMember(jss::owner) ||
522+
!context.params[jss::cron].isMember(jss::time))
523+
{
524+
jvResult[jss::error] = "malformedRequest";
525+
}
526+
else
527+
{
528+
auto const id = parseBase58<AccountID>(
529+
context.params[jss::cron][jss::owner].asString());
530+
if (!id)
531+
jvResult[jss::error] = "malformedAddress";
532+
else
533+
uNodeIndex =
534+
keylet::cron(
535+
context.params[jss::cron][jss::time].asUInt(), *id)
536+
.key;
537+
}
538+
}
509539
else
510540
{
511541
if (context.params.isMember("params") &&

src/test/rpc/LedgerRPC_test.cpp

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1839,6 +1839,88 @@ class LedgerRPC_test : public beast::unit_test::suite
18391839
}
18401840
}
18411841

1842+
void
1843+
testLedgerEntryCron()
1844+
{
1845+
testcase("ledger_entry Request Cron");
1846+
using namespace test::jtx;
1847+
1848+
Env env{*this};
1849+
1850+
Account const alice{"alice"};
1851+
env.fund(XRP(10000), alice);
1852+
env.close();
1853+
1854+
auto const startTime =
1855+
env.current()->parentCloseTime().time_since_epoch().count() + 100;
1856+
env(cron::set(alice),
1857+
cron::startTime(startTime),
1858+
cron::delay(100),
1859+
cron::repeat(200),
1860+
fee(XRP(1)),
1861+
ter(tesSUCCESS));
1862+
env.close();
1863+
1864+
std::string const ledgerHash{to_string(env.closed()->info().hash)};
1865+
1866+
uint256 const cronIndex{keylet::cron(startTime, alice).key};
1867+
{
1868+
// Request the cron using its index.
1869+
Json::Value jvParams;
1870+
jvParams[jss::cron] = to_string(cronIndex);
1871+
jvParams[jss::ledger_hash] = ledgerHash;
1872+
Json::Value const jrr = env.rpc(
1873+
"json", "ledger_entry", to_string(jvParams))[jss::result];
1874+
BEAST_EXPECT(jrr[jss::node][sfOwner.jsonName] == alice.human());
1875+
BEAST_EXPECT(jrr[jss::node][sfStartTime.jsonName] == startTime);
1876+
BEAST_EXPECT(jrr[jss::node][sfDelaySeconds.jsonName] == 100);
1877+
BEAST_EXPECT(jrr[jss::node][sfRepeatCount.jsonName] == 200);
1878+
}
1879+
{
1880+
// Request the cron using its owner and time.
1881+
Json::Value jvParams;
1882+
jvParams[jss::cron] = Json::objectValue;
1883+
jvParams[jss::cron][jss::owner] = alice.human();
1884+
jvParams[jss::cron][jss::time] = startTime;
1885+
jvParams[jss::ledger_hash] = ledgerHash;
1886+
Json::Value const jrr = env.rpc(
1887+
"json", "ledger_entry", to_string(jvParams))[jss::result];
1888+
BEAST_EXPECT(jrr[jss::node][sfOwner.jsonName] == alice.human());
1889+
BEAST_EXPECT(jrr[jss::node][sfStartTime.jsonName] == startTime);
1890+
BEAST_EXPECT(jrr[jss::node][sfDelaySeconds.jsonName] == 100);
1891+
BEAST_EXPECT(jrr[jss::node][sfRepeatCount.jsonName] == 200);
1892+
}
1893+
{
1894+
// Malformed uritoken object. Missing owner member.
1895+
Json::Value jvParams;
1896+
jvParams[jss::cron] = Json::objectValue;
1897+
jvParams[jss::cron][jss::time] = startTime;
1898+
jvParams[jss::ledger_hash] = ledgerHash;
1899+
Json::Value const jrr = env.rpc(
1900+
"json", "ledger_entry", to_string(jvParams))[jss::result];
1901+
checkErrorValue(jrr, "malformedRequest", "");
1902+
}
1903+
{
1904+
// Malformed uritoken object. Missing time member.
1905+
Json::Value jvParams;
1906+
jvParams[jss::cron] = Json::objectValue;
1907+
jvParams[jss::cron][jss::owner] = alice.human();
1908+
jvParams[jss::ledger_hash] = ledgerHash;
1909+
Json::Value const jrr = env.rpc(
1910+
"json", "ledger_entry", to_string(jvParams))[jss::result];
1911+
checkErrorValue(jrr, "malformedRequest", "");
1912+
}
1913+
{
1914+
// Request an index that is not a uritoken.
1915+
Json::Value jvParams;
1916+
jvParams[jss::cron] = ledgerHash;
1917+
jvParams[jss::ledger_hash] = ledgerHash;
1918+
Json::Value const jrr = env.rpc(
1919+
"json", "ledger_entry", to_string(jvParams))[jss::result];
1920+
checkErrorValue(jrr, "entryNotFound", "");
1921+
}
1922+
}
1923+
18421924
void
18431925
testLedgerEntryUnknownOption()
18441926
{
@@ -2365,6 +2447,7 @@ class LedgerRPC_test : public beast::unit_test::suite
23652447
testLedgerEntryTicket();
23662448
testLedgerEntryURIToken();
23672449
testLedgerEntryImportVLSeq();
2450+
testLedgerEntryCron();
23682451
testLedgerEntryUnknownOption();
23692452
testLookupLedger();
23702453
testNoQueue();

0 commit comments

Comments
 (0)