feat(hooks): add dice() and random() hook APIs for consensus entropy

Port the Hook API surface from the tt-rng branch, adapted to use our
commit-reveal consensus entropy (ltCONSENSUS_ENTROPY / sfDigest).

Hook APIs:
- dice(sides): returns random int [0, sides) from consensus entropy
- random(write_ptr, write_len): fills buffer with 1-512 random bytes

Internal fairRng() derives per-execution entropy by hashing: ledger
seq + tx ID + hook hash + account + chain position + execution phase
+ consensus entropy + incrementing call counter. This ensures each
call within a single hook execution returns different values.

Quality gate: fairRng returns empty (TOO_LITTLE_ENTROPY) if fewer
than 5 validators contributed, preventing weak entropy from being
consumed by hooks.

Also adds sfEntropyCount and sfLedgerSequence to the consensus
entropy SLE and pseudo-tx, enabling the freshness and quality
checks needed by the Hook API.
This commit is contained in:
Nicholas Dudfield
2026-02-10 17:12:27 +07:00
parent 41a41ec625
commit 61a166bcb0
11 changed files with 153 additions and 4 deletions

View File

@@ -245,6 +245,8 @@ Change::applyConsensusEntropy()
sle = std::make_shared<SLE>(keylet::consensusEntropy());
sle->setFieldH256(sfDigest, entropy);
sle->setFieldU16(sfEntropyCount, ctx_.tx.getFieldU16(sfEntropyCount));
sle->setFieldU32(sfLedgerSequence, view().info().seq);
// Note: sfPreviousTxnID and sfPreviousTxnLgrSeq are set automatically
// by ApplyStateTable::threadItem() because isThreadedType() returns true
// for ledger entries that have sfPreviousTxnID in their format.