Skip to content

Instantly share code, notes, and snippets.

@KOSASIH
Created May 29, 2023 04:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save KOSASIH/c922d664dbe5900b3eca7943d3ba838b to your computer and use it in GitHub Desktop.
Save KOSASIH/c922d664dbe5900b3eca7943d3ba838b to your computer and use it in GitHub Desktop.

Firewall

Firewall is an example of cooperating hooks: firewall hook instances filter incoming payments, based on shared state maintained by blacklist hook.

To cooperate, the hooks need information about each other, which must be obtained before deploying them, because it's passed to them as install-time parameters.

to test:

  • make sure Hooks Builder has at least 4 accounts: Alice, Bob, Carol and Carlos
  • run key.js to get a public key of the blacklist admin account, e.g. Alice; it asks for that account's secret key
    • verify the script is using it just to derive the public key
    • if you don't believe the script, or its dependencies, do the conversion in a trusted environment
  • compile blacklist.c and deploy it to Bob account
    • for ttPAYMENT + ttACCOUNT_SET
    • noting the hook namespace and saving it somewhere
      • with "admin" param set to Alice public key obtained above
  • run block-unblock.js to block an account; the script requires 4 parameters:
    1. admin is the account authorized to sign blacklist updates, i.e. Alice; the script needs its private key
    2. blacklist is the account sending AccountSet, i.e. Bob; its private key is used to sign that transaction
    3. suspect is the 3rd-party account to be blocked or unblocked, i.e. Carlos; its private key is not needed
    4. execution mode should be set to 1, to block
  • run decode.js to convert Bob account to binary form (the hook could do that, but it's extra computation that doesn't need to be replicated on chain) and save it somewhere
    • enter Bob account as the script parameter
  • compile firewall.c and deploy it to Carol account, with 2 parameters:
    1. "blaccid" parameter set to Bob binary account
    2. and "blns" parameter set to the blacklist hook namespace
  • set up payment transaction from Carlos to Carol
  • open debug stream filtered on Carol
  • run the transaction, see it rejected:
    • "Firewall: Blocking transaction from blacklisted account." in the debug stream
    • "[tecHOOK_REJECTED] Rejected by hook on sending or receiving account." in the development log
  • run block-unblock.js to unblock Carlos account; the parameters are mostly as before:
    1. admin is the account authorized to sign blacklist updates, i.e. Alice; the script needs its private key
    2. blacklist is the account sending AccountSet, i.e. Bob; its private key is used to sign that transaction
    3. suspect is the 3rd-party account to be blocked or unblocked, i.e. Carlos; its private key is not needed
    4. execution mode should be set to 0, to unblock
  • repeat the payment transaction, see it succeed:
    • "Firewall: Allowing transaction." in the debug stream
    • "[tesSUCCESS] The transaction was applied. Only final in a validated ledger." in the development log
#include "hookapi.h"
/**
* @invoke ttPAYMENT ttACCOUNT_SET
* @field admin
*/
int64_t hook(uint32_t reserved)
{
// check for the presence of a memo
uint8_t memos[2048];
int64_t memos_len = otxn_field(SBUF(memos), sfMemos);
uint32_t payload_len = 0, signature_len = 0, publickey_len = 0;
uint8_t* payload_ptr = 0, *signature_ptr = 0, *publickey_ptr = 0;
if (memos_len <= 0)
accept(SBUF("Blacklist: Passing non-memo incoming transaction."), 0);
/**
* 'Signed Memos' for hooks are supplied in triples in the following 'default' format:
* NB: The +1 identifies the payload, you may provide multiple payloads
* Memo: { MemoData: <app data>, MemoFormat: "signed/payload+1", MemoType: [application defined] }
* Memo: { MemoData: <signature>, MemoFormat: "signed/signature+1", MemoType: [application defined] }
* Memo: { MemoData: <public_key>, MemoFormat: "signed/publickey+1", MemoType: [application defined] }
**/
// loop through the three memos (if 3 are even present) to parse out the relevant fields
for (int i = 0; GUARD(3), i < 3; ++i)
{
// the memos are presented in an array object, which we must index into
int64_t memo_lookup = sto_subarray(memos, memos_len, i);
TRACEVAR(memo_lookup);
if (memo_lookup < 0)
rollback(SBUF("Blacklist: Memo transaction did not contain correct format."), 30);
// if the subfield/array lookup is successful we must extract the two pieces of returned data
// which are, respectively, the offset at which the field occurs and the field's length
uint8_t* memo_ptr = SUB_OFFSET(memo_lookup) + memos;
uint32_t memo_len = SUB_LENGTH(memo_lookup);
trace(SBUF("Memo: "), memo_ptr, memo_len, 1);
// memos are nested inside an actual memo object, so we need to subfield
// equivalently in JSON this would look like memo_array[i]["Memo"]
memo_lookup = sto_subfield(memo_ptr, memo_len, sfMemo);
memo_ptr = SUB_OFFSET(memo_lookup) + memo_ptr;
memo_len = SUB_LENGTH(memo_lookup);
// now we lookup the subfields of the memo itself
// again, equivalently this would look like memo_array[i]["Memo"]["MemoData"], ... etc.
int64_t data_lookup = sto_subfield(memo_ptr, memo_len, sfMemoData);
int64_t format_lookup = sto_subfield(memo_ptr, memo_len, sfMemoFormat);
TRACEVAR(data_lookup);
TRACEVAR(format_lookup);
// if any of these lookups fail the request is malformed
if (data_lookup < 0 || format_lookup < 0)
rollback(SBUF("Blacklist: Memo transaction did not contain correct memo format."), 40);
// care must be taken to add the correct pointer to an offset returned by sub_array or sub_field
// since we are working relative to the specific memo we must add memo_ptr, NOT memos or something else
uint8_t* data_ptr = SUB_OFFSET(data_lookup) + memo_ptr;
uint32_t data_len = SUB_LENGTH(data_lookup);
uint8_t* format_ptr = SUB_OFFSET(format_lookup) + memo_ptr;
uint32_t format_len = SUB_LENGTH(format_lookup);
// we can use a helper macro to compare the format fields and determine which MemoData is assigned
// to each pointer. Note that the last parameter here tells the macro how many times we will hit this
// line so it in turn can correctly configure its GUARD(), otherwise we will get a guard violation
int is_payload = 0, is_signature = 0, is_publickey = 0;
BUFFER_EQUAL_STR_GUARD(is_payload, format_ptr, format_len, "signed/payload+1", 3);
BUFFER_EQUAL_STR_GUARD(is_signature, format_ptr, format_len, "signed/signature+1", 3);
BUFFER_EQUAL_STR_GUARD(is_publickey, format_ptr, format_len, "signed/publickey+1", 3);
// assign the pointers according to the detected MemoFormat
if (is_payload)
{
payload_ptr = data_ptr;
payload_len = data_len;
} else if (is_signature)
{
signature_ptr = data_ptr;
signature_len = data_len;
} else if (is_publickey)
{
publickey_ptr = data_ptr;
publickey_len = data_len;
}
}
if (!(payload_ptr && signature_ptr && publickey_ptr))
rollback(SBUF("Blacklist: Memo transaction did not contain XLS14 format."), 50);
// check the public key is correct
if (publickey_len != 33)
rollback(SBUF("Blacklist: Memo public key wrong length."), 55);
uint8_t blacklist_key[33];
int64_t prv = hook_param(SBUF(blacklist_key), (uint32_t)"admin", 5);
if (prv != sizeof(blacklist_key))
{
TRACEVAR(prv);
rollback(SBUF("Blacklist: \"admin\" parameter missing"), 56);
}
TRACEHEX(blacklist_key);
int equal = 0;
BUFFER_EQUAL(equal, blacklist_key, publickey_ptr, 33);
if (!equal)
rollback(SBUF("Blacklist: Invalid admin public key."), 57);
// check the signature is valid
if (!util_verify(payload_ptr, payload_len,
signature_ptr, signature_len,
blacklist_key, 33))
rollback(SBUF("Blacklist: Invalid signature in memo."), 60);
// execution to here means that BUFFER<payload_ptr,payload_len> contains a validly signed object
// now check if it is properly constructed
// the expected format is a generic STObject containing
// - at least: sfFlags sfSequence sfTemplate(ARRAY){sfAccount}
// Flags 0 means add and Flags 1 means remove
// Sequence must be greater than the previously used Sequence (timestamp is desirable but not mandated)
// Sequence prevents replay attacks
// ARRAY must contain at least one sfAccount
int64_t lookup_flags = sto_subfield(payload_ptr, payload_len, sfFlags);
int64_t lookup_seq = sto_subfield(payload_ptr, payload_len, sfSequence);
int64_t lookup_array = sto_subfield(payload_ptr, payload_len, sfTemplate);
TRACEVAR(lookup_flags);
TRACEVAR(lookup_seq);
TRACEVAR(lookup_array);
if (lookup_seq < 0 || lookup_flags < 0 || lookup_array < 0)
rollback(SBUF("Blacklist: Validly signed memo lacked required STObject fields."), 70);
// extract the actual transaction details, again taking care to add the correct pointer to the offset
uint32_t seq = UINT32_FROM_BUF(SUB_OFFSET(lookup_seq) + payload_ptr);
uint32_t flags = UINT32_FROM_BUF(SUB_OFFSET(lookup_flags) + payload_ptr);
uint8_t* array_ptr = SUB_OFFSET(lookup_array) + payload_ptr;
int array_len = SUB_LENGTH(lookup_array);
// get the previous sequence number from the hook state (this is the 0 key)
uint8_t state_request[32];
uint8_t seq_buffer[4];
CLEARBUF(state_request);
if (state(SBUF(seq_buffer), SBUF(state_request)) != 4)
{
// first run
} else
{
if (seq <= UINT32_FROM_BUF(seq_buffer))
rollback(SBUF("Blacklist: Sequence number was less than previous sequence."), 75);
}
// update sequence number
UINT32_TO_BUF(seq_buffer, seq);
if (state_set(SBUF(seq_buffer), SBUF(state_request)) != 4)
rollback(SBUF("Blacklist: Sequence number could not be updated."), 77);
// we will accept at most 5 accounts in the array
// increasing the limit is a good way to see what happens when a hook gets too big to deploy
int processed_count = 0;
for (int i = 0; GUARD(5), i < 5; ++i)
{
int64_t lookup_array_entry = sto_subarray(array_ptr, array_len, i);
TRACEVAR(lookup_array_entry);
if (lookup_array_entry < 0)
break; // ran out of array entries to process
uint8_t* array_entry_ptr = SUB_OFFSET(lookup_array_entry) + array_ptr;
uint32_t array_entry_len = SUB_LENGTH(lookup_array_entry);
// this will return the actual payload inside the sfAccount inside the array entry
int64_t lookup_acc = sto_subfield(array_entry_ptr, array_entry_len, sfAccount);
if (lookup_acc < 0)
rollback(SBUF("Blacklist: Invalid array entry, expecting sfAccount."), 80);
uint8_t* acc_ptr = SUB_OFFSET(lookup_acc) + array_entry_ptr;
uint32_t acc_len = SUB_LENGTH(lookup_acc);
if (acc_len != 20)
rollback(SBUF("Blacklist: Invalid sfAccount, expecting length = 20."), 90);
uint8_t buffer[1] = {1}; // nominally we will simply a store a single byte = 1 for a blacklisted account
uint32_t len = flags == 1 ? 1 : 0; // we will pass length = 0 to state_set for a delete operation
if (state_set(buffer, len, acc_ptr, acc_len) == len)
processed_count++;
else
trace(SBUF("Blacklist: Failed to update state for the following account."), acc_ptr, acc_len, 1);
}
RBUF(result_buffer, result_len, "Blacklist: Processed + ", processed_count);
if (flags == 0)
result_buffer[21] = '-';
accept(result_buffer, result_len, 0);
return 0;
}
import { XrplClient } from "https://esm.sh/xrpl-client?bundle";
const lib = require("xrpl-accountlib");
const bin = require("ripple-binary-codec");
const keypairs = require("ripple-keypairs");
/**
* @input {Account.secret} admin_secret Admin Account
* @input {Account.secret} blacklist_secret Blacklist Account
* @input {Account} suspect_account Suspect Account
* @input {text} exec_mode Exec mode (Block=1, Unblock=0)
*/
const { admin_secret, blacklist_secret, suspect_account, exec_mode } = process.env
const admin_keypair = lib.derive.familySeed(admin_secret);
const blacklist_keypair = lib.derive.familySeed(blacklist_secret);
const blacklist_account = keypairs.deriveAddress(blacklist_keypair.keypair.publicKey);
if ((exec_mode !== "1") && (exec_mode !== "0"))
{
console.error("unknown execution mode \"" + exec_mode + "\" - must be either 0 or 1");
throw "invalid argument";
}
const flag = (exec_mode === "1") ? 1 : 0;
const client = new XrplClient('wss://hooks-testnet-v3.xrpl-labs.com');
const main = async () => {
let blacklist_instruction = bin.encode(
{
Sequence: Math.floor(Date.now()/1000),
Flags: flag,
Template: [
{
Account: suspect_account
}
],
NetworkID: "21338"
});
const { account_data } = await client.send({ command: 'account_info', 'account': blacklist_account });
if (!account_data) {
console.log('Blacklist account not found.');
client.close();
return;
}
console.log("sequence", account_data.Sequence);
const tx = {
Account: blacklist_account,
TransactionType: 'AccountSet',
Fee: '1200000',
Memos: [
{
Memo: {
MemoData: blacklist_instruction,
MemoFormat: "signed/payload+1",
MemoType: "liteacc/payment"
}
},
{
Memo:{
MemoData: keypairs.sign(blacklist_instruction, admin_keypair.keypair.privateKey),
MemoFormat: "signed/signature+1",
MemoType: "liteacc/signature"
}
},
{
Memo:{
MemoData: admin_keypair.keypair.publicKey,
MemoFormat: "signed/publickey+1",
MemoType: "liteacc/publickey"
}
}
],
Sequence: account_data.Sequence,
NetworkID: "21338"
};
hexlify_memos(tx);
// console.log(JSON.stringify(tx.Memos));
const {signedTransaction} = lib.sign(tx, blacklist_keypair);
const submit = await client.send({ command: 'submit', 'tx_blob': signedTransaction });
console.log(submit);
if (!submit || (submit.engine_result_code !== 0))
{
console.error("submit failed");
}
console.log('Shutting down...');
client.close();
};
function hexlify_memos(x)
{
if (!("Memos" in x))
return;
for (let y = 0; y < x["Memos"].length; ++y)
{
let Memo = x["Memos"][y]["Memo"];
let Fields = ["MemoFormat", "MemoType", "MemoData"];
for (let z = 0; z < Fields.length; ++z)
{
if (Fields[z] in Memo)
{
let u = Memo[Fields[z]].toUpperCase()
if (u.match(/^[0-9A-F]+$/))
{
Memo[Fields[z]] = u;
continue;
}
let v = Memo[Fields[z]], q = "";
for (let i = 0; i < v.length; ++i)
{
q += Number(v.charCodeAt(i)).toString(16).padStart(2, '0');
}
Memo[Fields[z]] = q.toUpperCase();
}
}
}
}
main()
const rac = require("ripple-address-codec");
/**
* @input {Account} a Account
*/
const a = process.env.a,
b = rac.decodeAccountID(a),
h = b.toString('hex').toUpperCase();
console.log(h);
// For documentation please see: https://xrpl-hooks.readme.io/reference/
// Generated using generate_error.sh
#ifndef HOOK_ERROR_CODES
#define SUCCESS 0
#define OUT_OF_BOUNDS -1
#define INTERNAL_ERROR -2
#define TOO_BIG -3
#define TOO_SMALL -4
#define DOESNT_EXIST -5
#define NO_FREE_SLOTS -6
#define INVALID_ARGUMENT -7
#define ALREADY_SET -8
#define PREREQUISITE_NOT_MET -9
#define FEE_TOO_LARGE -10
#define EMISSION_FAILURE -11
#define TOO_MANY_NONCES -12
#define TOO_MANY_EMITTED_TXN -13
#define NOT_IMPLEMENTED -14
#define INVALID_ACCOUNT -15
#define GUARD_VIOLATION -16
#define INVALID_FIELD -17
#define PARSE_ERROR -18
#define RC_ROLLBACK -19
#define RC_ACCEPT -20
#define NO_SUCH_KEYLET -21
#define NOT_AN_ARRAY -22
#define NOT_AN_OBJECT -23
#define INVALID_FLOAT -10024
#define DIVISION_BY_ZERO -25
#define MANTISSA_OVERSIZED -26
#define MANTISSA_UNDERSIZED -27
#define EXPONENT_OVERSIZED -28
#define EXPONENT_UNDERSIZED -29
#define OVERFLOW -30
#define NOT_IOU_AMOUNT -31
#define NOT_AN_AMOUNT -32
#define CANT_RETURN_NEGATIVE -33
#define NOT_AUTHORIZED -34
#define PREVIOUS_FAILURE_PREVENTS_RETRY -35
#define TOO_MANY_PARAMS -36
#define INVALID_TXN -37
#define RESERVE_INSUFFICIENT -38
#define COMPLEX_NOT_SUPPORTED -39
#define DOES_NOT_MATCH -40
#define HOOK_ERROR_CODES
#endif //HOOK_ERROR_CODES
// For documentation please see: https://xrpl-hooks.readme.io/reference/
// Generated using generate_extern.sh
#include <stdint.h>
#ifndef HOOK_EXTERN
extern int32_t
__attribute__((noduplicate))
_g(
uint32_t guard_id,
uint32_t maxiter
);
extern int64_t
accept(
uint32_t read_ptr,
uint32_t read_len,
int64_t error_code
);
extern int64_t
emit(
uint32_t write_ptr,
uint32_t write_len,
uint32_t read_ptr,
uint32_t read_len
);
extern int64_t
etxn_burden (
void
);
extern int64_t
etxn_details(
uint32_t write_ptr,
uint32_t write_len
);
extern int64_t
etxn_fee_base(
uint32_t read_ptr,
uint32_t read_len
);
extern int64_t
etxn_generation (
void
);
extern int64_t
etxn_nonce(
uint32_t write_ptr,
uint32_t write_len
);
extern int64_t
etxn_reserve(
uint32_t count
);
extern int64_t
fee_base (
void
);
extern int64_t
float_compare(
int64_t float1,
int64_t float2,
uint32_t mode
);
extern int64_t
float_divide(
int64_t float1,
int64_t float2
);
extern int64_t
float_exponent(
int64_t float1
);
extern int64_t
float_exponent_set(
int64_t float1,
int32_t exponent
);
extern int64_t
float_int(
int64_t float1,
uint32_t decimal_places,
uint32_t abs
);
extern int64_t
float_invert(
int64_t float1
);
extern int64_t
float_log(
int64_t float1
);
extern int64_t
float_mantissa(
int64_t float1
);
extern int64_t
float_mantissa_set(
int64_t float1,
int64_t mantissa
);
extern int64_t
float_mulratio(
int64_t float1,
uint32_t round_up,
uint32_t numerator,
uint32_t denominator
);
extern int64_t
float_multiply(
int64_t float1,
int64_t float2
);
extern int64_t
float_negate(
int64_t float1
);
extern int64_t
float_one (
void
);
extern int64_t
float_root(
int64_t float1,
uint32_t n
);
extern int64_t
float_set(
int32_t exponent,
int64_t mantissa
);
extern int64_t
float_sign(
int64_t float1
);
extern int64_t
float_sign_set(
int64_t float1,
uint32_t negative
);
extern int64_t
float_sto(
uint32_t write_ptr,
uint32_t write_len,
uint32_t cread_ptr,
uint32_t cread_len,
uint32_t iread_ptr,
uint32_t iread_len,
int64_t float1,
uint32_t field_code
);
extern int64_t
float_sto_set(
uint32_t read_ptr,
uint32_t read_len
);
extern int64_t
float_sum(
int64_t float1,
int64_t float2
);
extern int64_t
hook_account(
uint32_t write_ptr,
uint32_t write_len
);
extern int64_t
hook_again (
void
);
extern int64_t
hook_hash(
uint32_t write_ptr,
uint32_t write_len,
int32_t hook_no
);
extern int64_t
hook_param(
uint32_t write_ptr,
uint32_t write_len,
uint32_t read_ptr,
uint32_t read_len
);
extern int64_t
hook_param_set(
uint32_t read_ptr,
uint32_t read_len,
uint32_t kread_ptr,
uint32_t kread_len,
uint32_t hread_ptr,
uint32_t hread_len
);
extern int64_t
hook_pos (
void
);
extern int64_t
hook_skip(
uint32_t read_ptr,
uint32_t read_len,
uint32_t flags
);
extern int64_t
ledger_keylet(
uint32_t write_ptr,
uint32_t write_len,
uint32_t lread_ptr,
uint32_t lread_len,
uint32_t hread_ptr,
uint32_t hread_len
);
extern int64_t
ledger_last_hash(
uint32_t write_ptr,
uint32_t write_len
);
extern int64_t
ledger_last_time (
void
);
extern int64_t
ledger_nonce(
uint32_t write_ptr,
uint32_t write_len
);
extern int64_t
ledger_seq (
void
);
extern int64_t
meta_slot(
uint32_t slot_no
);
extern int64_t
otxn_burden (
void
);
extern int64_t
otxn_field(
uint32_t write_ptr,
uint32_t write_len,
uint32_t field_id
);
extern int64_t
otxn_field_txt(
uint32_t write_ptr,
uint32_t write_len,
uint32_t field_id
);
extern int64_t
otxn_generation (
void
);
extern int64_t
otxn_id(
uint32_t write_ptr,
uint32_t write_len,
uint32_t flags
);
extern int64_t
otxn_slot(
uint32_t slot_no
);
extern int64_t
otxn_type (
void
);
extern int64_t
rollback(
uint32_t read_ptr,
uint32_t read_len,
int64_t error_code
);
extern int64_t
slot(
uint32_t write_ptr,
uint32_t write_len,
uint32_t slot
);
extern int64_t
slot_clear(
uint32_t slot
);
extern int64_t
slot_count(
uint32_t slot
);
extern int64_t
slot_float(
uint32_t slot_no
);
extern int64_t
slot_id(
uint32_t write_ptr,
uint32_t write_len,
uint32_t slot
);
extern int64_t
slot_set(
uint32_t read_ptr,
uint32_t read_len,
int32_t slot
);
extern int64_t
slot_size(
uint32_t slot
);
extern int64_t
slot_subarray(
uint32_t parent_slot,
uint32_t array_id,
uint32_t new_slot
);
extern int64_t
slot_subfield(
uint32_t parent_slot,
uint32_t field_id,
uint32_t new_slot
);
extern int64_t
slot_type(
uint32_t slot_no,
uint32_t flags
);
extern int64_t
state(
uint32_t write_ptr,
uint32_t write_len,
uint32_t kread_ptr,
uint32_t kread_len
);
extern int64_t
state_foreign(
uint32_t write_ptr,
uint32_t write_len,
uint32_t kread_ptr,
uint32_t kread_len,
uint32_t nread_ptr,
uint32_t nread_len,
uint32_t aread_ptr,
uint32_t aread_len
);
extern int64_t
state_foreign_set(
uint32_t read_ptr,
uint32_t read_len,
uint32_t kread_ptr,
uint32_t kread_len,
uint32_t nread_ptr,
uint32_t nread_len,
uint32_t aread_ptr,
uint32_t aread_len
);
extern int64_t
state_set(
uint32_t read_ptr,
uint32_t read_len,
uint32_t kread_ptr,
uint32_t kread_len
);
extern int64_t
sto_emplace(
uint32_t write_ptr,
uint32_t write_len,
uint32_t sread_ptr,
uint32_t sread_len,
uint32_t fread_ptr,
uint32_t fread_len,
uint32_t field_id
);
extern int64_t
sto_erase(
uint32_t write_ptr,
uint32_t write_len,
uint32_t read_ptr,
uint32_t read_len,
uint32_t field_id
);
extern int64_t
sto_subarray(
uint32_t read_ptr,
uint32_t read_len,
uint32_t array_id
);
extern int64_t
sto_subfield(
uint32_t read_ptr,
uint32_t read_len,
uint32_t field_id
);
extern int64_t
sto_validate(
uint32_t tread_ptr,
uint32_t tread_len
);
extern int64_t
trace(
uint32_t mread_ptr,
uint32_t mread_len,
uint32_t dread_ptr,
uint32_t dread_len,
uint32_t as_hex
);
extern int64_t
trace_float(
uint32_t read_ptr,
uint32_t read_len,
int64_t float1
);
extern int64_t
trace_num(
uint32_t read_ptr,
uint32_t read_len,
int64_t number
);
extern int64_t
trace_slot(
uint32_t read_ptr,
uint32_t read_len,
uint32_t slot
);
extern int64_t
util_accid(
uint32_t write_ptr,
uint32_t write_len,
uint32_t read_ptr,
uint32_t read_len
);
extern int64_t
util_keylet(
uint32_t write_ptr,
uint32_t write_len,
uint32_t keylet_type,
uint32_t a,
uint32_t b,
uint32_t c,
uint32_t d,
uint32_t e,
uint32_t f
);
extern int64_t
util_raddr(
uint32_t write_ptr,
uint32_t write_len,
uint32_t read_ptr,
uint32_t read_len
);
extern int64_t
util_sha512h(
uint32_t write_ptr,
uint32_t write_len,
uint32_t read_ptr,
uint32_t read_len
);
extern int64_t
util_verify(
uint32_t dread_ptr,
uint32_t dread_len,
uint32_t sread_ptr,
uint32_t sread_len,
uint32_t kread_ptr,
uint32_t kread_len
);
#define HOOK_EXTERN
#endif //HOOK_EXTERN
#include "hookapi.h"
/**
* @field blaccid Set to binary account
* @field blns Set to the blacklist hook namespace
*/
int64_t hook(uint32_t reserved)
{
GUARD(1);
// fetch the originating account ID
uint8_t otxn_accid[20];
if (otxn_field(otxn_accid, 20, sfAccount) != 20)
rollback(SBUF("Firewall: Could not fetch sfAccount from originating transaction!!!"), 1);
uint8_t blacklist_ns[32];
int64_t prv = hook_param(SBUF(blacklist_ns), (uint32_t)"blns", 4);
if (prv != sizeof(blacklist_ns))
{
TRACEVAR(prv);
rollback(SBUF("Firewall: \"blns\" parameter missing"), 5);
}
uint8_t blacklist_accid[32];
prv = hook_param(SBUF(blacklist_accid), (uint32_t)"blaccid", 7);
if (prv < 20)
{
TRACEVAR(prv);
rollback(SBUF("Firewall: \"blaccid\" parameter missing"), 10);
}
// look up the account ID in the foreign state (blacklist account's hook state)
uint8_t blacklist_status[1] = { 0 };
int64_t lookup = state_foreign(SBUF(blacklist_status), SBUF(otxn_accid), SBUF(blacklist_ns), blacklist_accid, 20);
if (lookup == INVALID_ACCOUNT)
trace(SBUF("Firewall: Warning specified blacklist account does not exist."), 0, 0, 0);
if (blacklist_status[0] == 0)
accept(SBUF("Firewall: Allowing transaction."), 0);
rollback(SBUF("Firewall: Blocking transaction from blacklisted account."), 1);
return 0;
}
/**
* Hook API include file
*
* Note to the reader:
* This include defines two types of things: external functions and macros
* Functions are used sparingly because a non-inlining compiler may produce
* undesirable output.
*
* Find documentation here: https://xrpl-hooks.readme.io/reference/
*/
#ifndef HOOKAPI_INCLUDED
#define HOOKAPI_INCLUDED 1
#define KEYLET_HOOK 1
#define KEYLET_HOOK_STATE 2
#define KEYLET_ACCOUNT 3
#define KEYLET_AMENDMENTS 4
#define KEYLET_CHILD 5
#define KEYLET_SKIP 6
#define KEYLET_FEES 7
#define KEYLET_NEGATIVE_UNL 8
#define KEYLET_LINE 9
#define KEYLET_OFFER 10
#define KEYLET_QUALITY 11
#define KEYLET_EMITTED_DIR 12
#define KEYLET_TICKET 13
#define KEYLET_SIGNERS 14
#define KEYLET_CHECK 15
#define KEYLET_DEPOSIT_PREAUTH 16
#define KEYLET_UNCHECKED 17
#define KEYLET_OWNER_DIR 18
#define KEYLET_PAGE 19
#define KEYLET_ESCROW 20
#define KEYLET_PAYCHAN 21
#define KEYLET_EMITTED 22
#define COMPARE_EQUAL 1U
#define COMPARE_LESS 2U
#define COMPARE_GREATER 4U
#include "error.h"
#include "extern.h"
#include "sfcodes.h"
#include "macro.h"
#endif
const lib = require("xrpl-accountlib");
/**
* @input {Account.secret} admin_secret Admin Account
*/
// Alice
const { admin_secret } = process.env;
const admin_keypair = lib.derive.familySeed(admin_secret);
console.log(admin_keypair.keypair.publicKey);
/**
* These are helper macros for writing hooks, all of them are optional as is including hookmacro.h at all
*/
#include <stdint.h>
#include "hookapi.h"
#include "sfcodes.h"
#ifndef HOOKMACROS_INCLUDED
#define HOOKMACROS_INCLUDED 1
#ifdef NDEBUG
#define DEBUG 0
#else
#define DEBUG 1
#endif
#define TRACEVAR(v) if (DEBUG) trace_num((uint32_t)(#v), (uint32_t)(sizeof(#v) - 1), (int64_t)v);
#define TRACEHEX(v) if (DEBUG) trace((uint32_t)(#v), (uint32_t)(sizeof(#v) - 1), (uint32_t)(v), (uint32_t)(sizeof(v)), 1);
#define TRACEXFL(v) if (DEBUG) trace_float((uint32_t)(#v), (uint32_t)(sizeof(#v) - 1), (int64_t)v);
#define TRACESTR(v) if (DEBUG) trace((uint32_t)(#v), (uint32_t)(sizeof(#v) - 1), (uint32_t)(v), sizeof(v), 0);
// hook developers should use this guard macro, simply GUARD(<maximum iterations>)
#define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1)
#define GUARDM(maxiter, n) _g(( (1ULL << 31U) + (__LINE__ << 16) + n), (maxiter)+1)
#define SBUF(str) (uint32_t)(str), sizeof(str)
#define REQUIRE(cond, str)\
{\
if (!(cond))\
rollback(SBUF(str), __LINE__);\
}
// make a report buffer as a c-string
// provide a name for a buffer to declare (buf)
// provide a static string
// provide an integer to print after the string
#define RBUF(buf, out_len, str, num)\
unsigned char buf[sizeof(str) + 21];\
int out_len = 0;\
{\
int i = 0;\
for (; GUARDM(sizeof(str),1),i < sizeof(str); ++i)\
(buf)[i] = str[i];\
if ((buf)[sizeof(str)-1] == 0) i--;\
if ((num) < 0) (buf)[i++] = '-';\
uint64_t unsigned_num = (uint64_t)( (num) < 0 ? (num) * -1 : (num) );\
uint64_t j = 10000000000000000000ULL;\
int start = 1;\
for (; GUARDM(20,2), unsigned_num > 0 && j > 0; j /= 10)\
{\
unsigned char digit = ( unsigned_num / j ) % 10;\
if (digit == 0 && start)\
continue;\
start = 0;\
(buf)[i++] = '0' + digit;\
}\
(buf)[i] = '\0';\
out_len = i;\
}
#define RBUF2(buff, out_len, str, num, str2, num2)\
unsigned char buff[sizeof(str) + sizeof(str2) + 42];\
int out_len = 0;\
{\
unsigned char* __buf__ = buff;\
int i = 0;\
for (; GUARDM(sizeof(str),1),i < sizeof(str); ++i)\
(__buf__)[i] = str[i];\
if ((__buf__)[sizeof(str)-1] == 0) i--;\
if ((num) < 0) (__buf__)[i++] = '-';\
uint64_t unsigned_num = (uint64_t)( (num) < 0 ? (num) * -1 : (num) );\
uint64_t j = 10000000000000000000ULL;\
int start = 1;\
for (; GUARDM(20,2), unsigned_num > 0 && j > 0; j /= 10)\
{\
unsigned char digit = ( unsigned_num / j ) % 10;\
if (digit == 0 && start)\
continue;\
start = 0;\
(__buf__)[i++] = '0' + digit;\
}\
__buf__ += i;\
out_len += i;\
i = 0;\
for (; GUARDM(sizeof(str2),3),i < sizeof(str2); ++i)\
(__buf__)[i] = str2[i];\
if ((__buf__)[sizeof(str2)-1] == 0) i--;\
if ((num2) < 0) (__buf__)[i++] = '-';\
unsigned_num = (uint64_t)( (num2) < 0 ? (num2) * -1 : (num2) );\
j = 10000000000000000000ULL;\
start = 1;\
for (; GUARDM(20,4), unsigned_num > 0 && j > 0; j /= 10)\
{\
unsigned char digit = ( unsigned_num / j ) % 10;\
if (digit == 0 && start)\
continue;\
start = 0;\
(__buf__)[i++] = '0' + digit;\
}\
(__buf__)[i] = '\0';\
out_len += i;\
}
#define CLEARBUF(b)\
{\
for (int x = 0; GUARD(sizeof(b)), x < sizeof(b); ++x)\
b[x] = 0;\
}
// returns an in64_t, negative if error, non-negative if valid drops
#define AMOUNT_TO_DROPS(amount_buffer)\
(((amount_buffer)[0] >> 7) ? -2 : (\
((((uint64_t)((amount_buffer)[0])) & 0xb00111111) << 56) +\
(((uint64_t)((amount_buffer)[1])) << 48) +\
(((uint64_t)((amount_buffer)[2])) << 40) +\
(((uint64_t)((amount_buffer)[3])) << 32) +\
(((uint64_t)((amount_buffer)[4])) << 24) +\
(((uint64_t)((amount_buffer)[5])) << 16) +\
(((uint64_t)((amount_buffer)[6])) << 8) +\
(((uint64_t)((amount_buffer)[7])))))
#define SUB_OFFSET(x) ((int32_t)(x >> 32))
#define SUB_LENGTH(x) ((int32_t)(x & 0xFFFFFFFFULL))
// when using this macro buf1len may be dynamic but buf2len must be static
// provide n >= 1 to indicate how many times the macro will be hit on the line of code
// e.g. if it is in a loop that loops 10 times n = 10
#define BUFFER_EQUAL_GUARD(output, buf1, buf1len, buf2, buf2len, n)\
{\
output = ((buf1len) == (buf2len) ? 1 : 0);\
for (int x = 0; GUARDM( (buf2len) * (n), 1 ), output && x < (buf2len);\
++x)\
output = (buf1)[x] == (buf2)[x];\
}
#define BUFFER_SWAP(x,y)\
{\
uint8_t* __z__ = x;\
x = y;\
y = __z__;\
}
#define ACCOUNT_COMPARE(compare_result, buf1, buf2)\
{\
compare_result = 0;\
for (int i = 0; GUARD(20), i < 20; ++i)\
{\
if (buf1[i] > buf2[i])\
{\
compare_result = 1;\
break;\
}\
else if (buf1[i] < buf2[i])\
{\
compare_result = -1;\
break;\
}\
}\
}
#define BUFFER_EQUAL_STR_GUARD(output, buf1, buf1len, str, n)\
BUFFER_EQUAL_GUARD(output, buf1, buf1len, str, (sizeof(str)-1), n)
#define BUFFER_EQUAL_STR(output, buf1, buf1len, str)\
BUFFER_EQUAL_GUARD(output, buf1, buf1len, str, (sizeof(str)-1), 1)
#define BUFFER_EQUAL(output, buf1, buf2, compare_len)\
BUFFER_EQUAL_GUARD(output, buf1, compare_len, buf2, compare_len, 1)
#define UINT16_TO_BUF(buf_raw, i)\
{\
unsigned char* __buf__ = (unsigned char*)buf_raw;\
__buf__[0] = (((uint64_t)i) >> 8) & 0xFFUL;\
__buf__[1] = (((uint64_t)i) >> 0) & 0xFFUL;\
}
#define UINT16_FROM_BUF(buf)\
(((uint64_t)((buf)[0]) << 8) +\
((uint64_t)((buf)[1]) << 0))
#define UINT32_TO_BUF(buf_raw, i)\
{\
unsigned char* __buf__ = (unsigned char*)buf_raw;\
__buf__[0] = (((uint64_t)i) >> 24) & 0xFFUL;\
__buf__[1] = (((uint64_t)i) >> 16) & 0xFFUL;\
__buf__[2] = (((uint64_t)i) >> 8) & 0xFFUL;\
__buf__[3] = (((uint64_t)i) >> 0) & 0xFFUL;\
}
#define UINT32_FROM_BUF(buf)\
(((uint64_t)((buf)[0]) << 24) +\
((uint64_t)((buf)[1]) << 16) +\
((uint64_t)((buf)[2]) << 8) +\
((uint64_t)((buf)[3]) << 0))
#define UINT64_TO_BUF(buf_raw, i)\
{\
unsigned char* __buf__ = (unsigned char*)buf_raw;\
__buf__[0] = (((uint64_t)i) >> 56) & 0xFFUL;\
__buf__[1] = (((uint64_t)i) >> 48) & 0xFFUL;\
__buf__[2] = (((uint64_t)i) >> 40) & 0xFFUL;\
__buf__[3] = (((uint64_t)i) >> 32) & 0xFFUL;\
__buf__[4] = (((uint64_t)i) >> 24) & 0xFFUL;\
__buf__[5] = (((uint64_t)i) >> 16) & 0xFFUL;\
__buf__[6] = (((uint64_t)i) >> 8) & 0xFFUL;\
__buf__[7] = (((uint64_t)i) >> 0) & 0xFFUL;\
}
#define UINT64_FROM_BUF(buf)\
(((uint64_t)((buf)[0]) << 56) +\
((uint64_t)((buf)[1]) << 48) +\
((uint64_t)((buf)[2]) << 40) +\
((uint64_t)((buf)[3]) << 32) +\
((uint64_t)((buf)[4]) << 24) +\
((uint64_t)((buf)[5]) << 16) +\
((uint64_t)((buf)[6]) << 8) +\
((uint64_t)((buf)[7]) << 0))
#define INT64_FROM_BUF(buf)\
((((uint64_t)((buf)[0] & 0x7FU) << 56) +\
((uint64_t)((buf)[1]) << 48) +\
((uint64_t)((buf)[2]) << 40) +\
((uint64_t)((buf)[3]) << 32) +\
((uint64_t)((buf)[4]) << 24) +\
((uint64_t)((buf)[5]) << 16) +\
((uint64_t)((buf)[6]) << 8) +\
((uint64_t)((buf)[7]) << 0)) * (buf[0] & 0x80U ? -1 : 1))
#define INT64_TO_BUF(buf_raw, i)\
{\
unsigned char* __buf__ = (unsigned char*)buf_raw;\
__buf__[0] = (((uint64_t)i) >> 56) & 0x7FUL;\
__buf__[1] = (((uint64_t)i) >> 48) & 0xFFUL;\
__buf__[2] = (((uint64_t)i) >> 40) & 0xFFUL;\
__buf__[3] = (((uint64_t)i) >> 32) & 0xFFUL;\
__buf__[4] = (((uint64_t)i) >> 24) & 0xFFUL;\
__buf__[5] = (((uint64_t)i) >> 16) & 0xFFUL;\
__buf__[6] = (((uint64_t)i) >> 8) & 0xFFUL;\
__buf__[7] = (((uint64_t)i) >> 0) & 0xFFUL;\
if (i < 0) __buf__[0] |= 0x80U;\
}
#define ttPAYMENT 0
#define ttESCROW_CREATE 1
#define ttESCROW_FINISH 2
#define ttACCOUNT_SET 3
#define ttESCROW_CANCEL 4
#define ttREGULAR_KEY_SET 5
#define ttOFFER_CREATE 7
#define ttOFFER_CANCEL 8
#define ttTICKET_CREATE 10
#define ttSIGNER_LIST_SET 12
#define ttPAYCHAN_CREATE 13
#define ttPAYCHAN_FUND 14
#define ttPAYCHAN_CLAIM 15
#define ttCHECK_CREATE 16
#define ttCHECK_CASH 17
#define ttCHECK_CANCEL 18
#define ttDEPOSIT_PREAUTH 19
#define ttTRUST_SET 20
#define ttACCOUNT_DELETE 21
#define ttHOOK_SET 22
#define ttNFTOKEN_MINT 25
#define ttNFTOKEN_BURN 26
#define ttNFTOKEN_CREATE_OFFER 27
#define ttNFTOKEN_CANCEL_OFFER 28
#define ttNFTOKEN_ACCEPT_OFFER 29
#define ttURITOKEN_MINT 45
#define ttURITOKEN_BURN 46
#define ttURITOKEN_BUY 47
#define ttURITOKEN_CREATE_SELL_OFFER 48
#define ttURITOKEN_CANCEL_SELL_OFFER 49
#define ttCLAIM_REWARD 98
#define ttINVOKE 99
#define ttAMENDMENT 100
#define ttFEE 101
#define ttUNL_MODIFY 102
#define ttEMIT_FAILURE 103
#define tfCANONICAL 0x80000000UL
#define atACCOUNT 1U
#define atOWNER 2U
#define atDESTINATION 3U
#define atISSUER 4U
#define atAUTHORIZE 5U
#define atUNAUTHORIZE 6U
#define atTARGET 7U
#define atREGULARKEY 8U
#define atPSEUDOCALLBACK 9U
#define amAMOUNT 1U
#define amBALANCE 2U
#define amLIMITAMOUNT 3U
#define amTAKERPAYS 4U
#define amTAKERGETS 5U
#define amLOWLIMIT 6U
#define amHIGHLIMIT 7U
#define amFEE 8U
#define amSENDMAX 9U
#define amDELIVERMIN 10U
#define amMINIMUMOFFER 16U
#define amRIPPLEESCROW 17U
#define amDELIVEREDAMOUNT 18U
/**
* RH NOTE -- PAY ATTENTION
*
* ALL 'ENCODE' MACROS INCREMENT BUF_OUT
* THIS IS TO MAKE CHAINING EASY
* BUF_OUT IS A SACRIFICIAL POINTER
*
* 'ENCODE' MACROS WITH CONSTANTS HAVE
* ALIASING TO ASSIST YOU WITH ORDER
* _TYPECODE_FIELDCODE_ENCODE_MACRO
* TO PRODUCE A SERIALIZED OBJECT
* IN CANONICAL FORMAT YOU MUST ORDER
* FIRST BY TYPE CODE THEN BY FIELD CODE
*
* ALL 'PREPARE' MACROS PRESERVE POINTERS
*
**/
#define ENCODE_TL_SIZE 49
#define ENCODE_TL(buf_out, tlamt, amount_type)\
{\
uint8_t __uat__ = amount_type; \
buf_out[0] = 0x60U +(__uat__ & 0x0FU ); \
for (int i = 1; GUARDM(48, 1), i < 49; ++i)\
buf_out[i] = tlamt[i-1];\
buf_out += ENCODE_TL_SIZE;\
}
#define _06_XX_ENCODE_TL(buf_out, drops, amount_type )\
ENCODE_TL(buf_out, drops, amount_type );
#define ENCODE_TL_AMOUNT(buf_out, drops )\
ENCODE_TL(buf_out, drops, amAMOUNT );
#define _06_01_ENCODE_TL_AMOUNT(buf_out, drops )\
ENCODE_TL_AMOUNT(buf_out, drops );
// Encode drops to serialization format
// consumes 9 bytes
#define ENCODE_DROPS_SIZE 9
#define ENCODE_DROPS(buf_out, drops, amount_type ) \
{\
uint8_t __uat__ = amount_type; \
uint64_t __udrops__ = drops; \
buf_out[0] = 0x60U +(__uat__ & 0x0FU ); \
buf_out[1] = 0b01000000 + (( __udrops__ >> 56 ) & 0b00111111 ); \
buf_out[2] = (__udrops__ >> 48) & 0xFFU; \
buf_out[3] = (__udrops__ >> 40) & 0xFFU; \
buf_out[4] = (__udrops__ >> 32) & 0xFFU; \
buf_out[5] = (__udrops__ >> 24) & 0xFFU; \
buf_out[6] = (__udrops__ >> 16) & 0xFFU; \
buf_out[7] = (__udrops__ >> 8) & 0xFFU; \
buf_out[8] = (__udrops__ >> 0) & 0xFFU; \
buf_out += ENCODE_DROPS_SIZE; \
}
#define _06_XX_ENCODE_DROPS(buf_out, drops, amount_type )\
ENCODE_DROPS(buf_out, drops, amount_type );
#define ENCODE_DROPS_AMOUNT(buf_out, drops )\
ENCODE_DROPS(buf_out, drops, amAMOUNT );
#define _06_01_ENCODE_DROPS_AMOUNT(buf_out, drops )\
ENCODE_DROPS_AMOUNT(buf_out, drops );
#define ENCODE_DROPS_FEE(buf_out, drops )\
ENCODE_DROPS(buf_out, drops, amFEE );
#define _06_08_ENCODE_DROPS_FEE(buf_out, drops )\
ENCODE_DROPS_FEE(buf_out, drops );
#define ENCODE_TT_SIZE 3
#define ENCODE_TT(buf_out, tt )\
{\
uint8_t __utt__ = tt;\
buf_out[0] = 0x12U;\
buf_out[1] =(__utt__ >> 8 ) & 0xFFU;\
buf_out[2] =(__utt__ >> 0 ) & 0xFFU;\
buf_out += ENCODE_TT_SIZE; \
}
#define _01_02_ENCODE_TT(buf_out, tt)\
ENCODE_TT(buf_out, tt);
#define ENCODE_ACCOUNT_SIZE 22
#define ENCODE_ACCOUNT(buf_out, account_id, account_type)\
{\
uint8_t __uat__ = account_type;\
buf_out[0] = 0x80U + __uat__;\
buf_out[1] = 0x14U;\
*(uint64_t*)(buf_out + 2) = *(uint64_t*)(account_id + 0);\
*(uint64_t*)(buf_out + 10) = *(uint64_t*)(account_id + 8);\
*(uint32_t*)(buf_out + 18) = *(uint32_t*)(account_id + 16);\
buf_out += ENCODE_ACCOUNT_SIZE;\
}
#define _08_XX_ENCODE_ACCOUNT(buf_out, account_id, account_type)\
ENCODE_ACCOUNT(buf_out, account_id, account_type);
#define ENCODE_ACCOUNT_SRC_SIZE 22
#define ENCODE_ACCOUNT_SRC(buf_out, account_id)\
ENCODE_ACCOUNT(buf_out, account_id, atACCOUNT);
#define _08_01_ENCODE_ACCOUNT_SRC(buf_out, account_id)\
ENCODE_ACCOUNT_SRC(buf_out, account_id);
#define ENCODE_ACCOUNT_DST_SIZE 22
#define ENCODE_ACCOUNT_DST(buf_out, account_id)\
ENCODE_ACCOUNT(buf_out, account_id, atDESTINATION);
#define _08_03_ENCODE_ACCOUNT_DST(buf_out, account_id)\
ENCODE_ACCOUNT_DST(buf_out, account_id);
#define ENCODE_ACCOUNT_OWNER_SIZE 22
#define ENCODE_ACCOUNT_OWNER(buf_out, account_id) \
ENCODE_ACCOUNT(buf_out, account_id, atOWNER);
#define _08_02_ENCODE_ACCOUNT_OWNER(buf_out, account_id) \
ENCODE_ACCOUNT_OWNER(buf_out, account_id);
#define ENCODE_UINT32_COMMON_SIZE 5U
#define ENCODE_UINT32_COMMON(buf_out, i, field)\
{\
uint32_t __ui__ = i; \
uint8_t __uf__ = field; \
buf_out[0] = 0x20U +(__uf__ & 0x0FU); \
buf_out[1] =(__ui__ >> 24 ) & 0xFFU; \
buf_out[2] =(__ui__ >> 16 ) & 0xFFU; \
buf_out[3] =(__ui__ >> 8 ) & 0xFFU; \
buf_out[4] =(__ui__ >> 0 ) & 0xFFU; \
buf_out += ENCODE_UINT32_COMMON_SIZE; \
}
#define _02_XX_ENCODE_UINT32_COMMON(buf_out, i, field)\
ENCODE_UINT32_COMMON(buf_out, i, field)\
#define ENCODE_UINT32_UNCOMMON_SIZE 6U
#define ENCODE_UINT32_UNCOMMON(buf_out, i, field)\
{\
uint32_t __ui__ = i; \
uint8_t __uf__ = field; \
buf_out[0] = 0x20U; \
buf_out[1] = __uf__; \
buf_out[2] =(__ui__ >> 24 ) & 0xFFU; \
buf_out[3] =(__ui__ >> 16 ) & 0xFFU; \
buf_out[4] =(__ui__ >> 8 ) & 0xFFU; \
buf_out[5] =(__ui__ >> 0 ) & 0xFFU; \
buf_out += ENCODE_UINT32_UNCOMMON_SIZE; \
}
#define _02_XX_ENCODE_UINT32_UNCOMMON(buf_out, i, field)\
ENCODE_UINT32_UNCOMMON(buf_out, i, field)\
#define ENCODE_LLS_SIZE 6U
#define ENCODE_LLS(buf_out, lls )\
ENCODE_UINT32_UNCOMMON(buf_out, lls, 0x1B );
#define _02_27_ENCODE_LLS(buf_out, lls )\
ENCODE_LLS(buf_out, lls );
#define ENCODE_FLS_SIZE 6U
#define ENCODE_FLS(buf_out, fls )\
ENCODE_UINT32_UNCOMMON(buf_out, fls, 0x1A );
#define _02_26_ENCODE_FLS(buf_out, fls )\
ENCODE_FLS(buf_out, fls );
#define ENCODE_TAG_SRC_SIZE 5
#define ENCODE_TAG_SRC(buf_out, tag )\
ENCODE_UINT32_COMMON(buf_out, tag, 0x3U );
#define _02_03_ENCODE_TAG_SRC(buf_out, tag )\
ENCODE_TAG_SRC(buf_out, tag );
#define ENCODE_TAG_DST_SIZE 5
#define ENCODE_TAG_DST(buf_out, tag )\
ENCODE_UINT32_COMMON(buf_out, tag, 0xEU );
#define _02_14_ENCODE_TAG_DST(buf_out, tag )\
ENCODE_TAG_DST(buf_out, tag );
#define ENCODE_SEQUENCE_SIZE 5
#define ENCODE_SEQUENCE(buf_out, sequence )\
ENCODE_UINT32_COMMON(buf_out, sequence, 0x4U );
#define _02_04_ENCODE_SEQUENCE(buf_out, sequence )\
ENCODE_SEQUENCE(buf_out, sequence );
#define ENCODE_FLAGS_SIZE 5
#define ENCODE_FLAGS(buf_out, tag )\
ENCODE_UINT32_COMMON(buf_out, tag, 0x2U );
#define _02_02_ENCODE_FLAGS(buf_out, tag )\
ENCODE_FLAGS(buf_out, tag );
#define ENCODE_SIGNING_PUBKEY_SIZE 35
#define ENCODE_SIGNING_PUBKEY(buf_out, pkey )\
{\
buf_out[0] = 0x73U;\
buf_out[1] = 0x21U;\
*(uint64_t*)(buf_out + 2) = *(uint64_t*)(pkey + 0);\
*(uint64_t*)(buf_out + 10) = *(uint64_t*)(pkey + 8);\
*(uint64_t*)(buf_out + 18) = *(uint64_t*)(pkey + 16);\
*(uint64_t*)(buf_out + 26) = *(uint64_t*)(pkey + 24);\
buf[34] = pkey[32];\
buf_out += ENCODE_SIGNING_PUBKEY_SIZE;\
}
#define _07_03_ENCODE_SIGNING_PUBKEY(buf_out, pkey )\
ENCODE_SIGNING_PUBKEY(buf_out, pkey );
#define ENCODE_SIGNING_PUBKEY_NULL_SIZE 35
#define ENCODE_SIGNING_PUBKEY_NULL(buf_out )\
{\
buf_out[0] = 0x73U;\
buf_out[1] = 0x21U;\
*(uint64_t*)(buf_out+2) = 0;\
*(uint64_t*)(buf_out+10) = 0;\
*(uint64_t*)(buf_out+18) = 0;\
*(uint64_t*)(buf_out+25) = 0;\
buf_out += ENCODE_SIGNING_PUBKEY_NULL_SIZE;\
}
#define _07_03_ENCODE_SIGNING_PUBKEY_NULL(buf_out )\
ENCODE_SIGNING_PUBKEY_NULL(buf_out );
#ifdef HAS_CALLBACK
#define PREPARE_PAYMENT_SIMPLE_SIZE 270U
#else
#define PREPARE_PAYMENT_SIMPLE_SIZE 248U
#endif
#define PREPARE_PAYMENT_SIMPLE(buf_out_master, drops_amount_raw, to_address, dest_tag_raw, src_tag_raw)\
{\
uint8_t* __buf_out__ = buf_out_master;\
uint8_t __acc__[20];\
uint64_t __drops_amount__ = (drops_amount_raw);\
uint32_t __dest_tag__ = (dest_tag_raw);\
uint32_t __src_tag__ = (src_tag_raw);\
uint32_t __cls__ = (uint32_t)ledger_seq();\
hook_account(SBUF(__acc__));\
_01_02_ENCODE_TT (__buf_out__, ttPAYMENT ); /* uint16 | size 3 */ \
_02_02_ENCODE_FLAGS (__buf_out__, tfCANONICAL ); /* uint32 | size 5 */ \
_02_03_ENCODE_TAG_SRC (__buf_out__, __src_tag__ ); /* uint32 | size 5 */ \
_02_04_ENCODE_SEQUENCE (__buf_out__, 0 ); /* uint32 | size 5 */ \
_02_14_ENCODE_TAG_DST (__buf_out__, __dest_tag__ ); /* uint32 | size 5 */ \
_02_26_ENCODE_FLS (__buf_out__, __cls__ + 1 ); /* uint32 | size 6 */ \
_02_27_ENCODE_LLS (__buf_out__, __cls__ + 5 ); /* uint32 | size 6 */ \
_06_01_ENCODE_DROPS_AMOUNT (__buf_out__, __drops_amount__ ); /* amount | size 9 */ \
uint8_t* __fee_ptr__ = __buf_out__;\
_06_08_ENCODE_DROPS_FEE (__buf_out__, 0 ); /* amount | size 9 */ \
_07_03_ENCODE_SIGNING_PUBKEY_NULL (__buf_out__ ); /* pk | size 35 */ \
_08_01_ENCODE_ACCOUNT_SRC (__buf_out__, __acc__ ); /* account | size 22 */ \
_08_03_ENCODE_ACCOUNT_DST (__buf_out__, to_address ); /* account | size 22 */ \
int64_t __buf_size__ = PREPARE_PAYMENT_SIMPLE_SIZE - (__buf_out__ - buf_out_master); \
int64_t __edlen__ = etxn_details((uint32_t)__buf_out__, __buf_size__); /* emitdet | size 1?? */ \
int64_t __fee__ = etxn_fee_base(buf_out_master, PREPARE_PAYMENT_SIMPLE_SIZE); \
_06_08_ENCODE_DROPS_FEE (__fee_ptr__, __fee__ ); \
}
#ifdef HAS_CALLBACK
#define PREPARE_PAYMENT_SIMPLE_TRUSTLINE_SIZE 309
#else
#define PREPARE_PAYMENT_SIMPLE_TRUSTLINE_SIZE 288
#endif
#define PREPARE_PAYMENT_SIMPLE_TRUSTLINE(buf_out_master, tlamt, to_address, dest_tag_raw, src_tag_raw)\
{\
uint8_t* __buf_out__ = buf_out_master;\
uint8_t __acc__[20];\
uint32_t __dest_tag__ = (dest_tag_raw);\
uint32_t __src_tag__ = (src_tag_raw);\
uint32_t __cls__ = (uint32_t)ledger_seq();\
hook_account(SBUF(__acc__));\
_01_02_ENCODE_TT (__buf_out__, ttPAYMENT ); /* uint16 | size 3 */ \
_02_02_ENCODE_FLAGS (__buf_out__, tfCANONICAL ); /* uint32 | size 5 */ \
_02_03_ENCODE_TAG_SRC (__buf_out__, __src_tag__ ); /* uint32 | size 5 */ \
_02_04_ENCODE_SEQUENCE (__buf_out__, 0 ); /* uint32 | size 5 */ \
_02_14_ENCODE_TAG_DST (__buf_out__, __dest_tag__ ); /* uint32 | size 5 */ \
_02_26_ENCODE_FLS (__buf_out__, __cls__ + 1 ); /* uint32 | size 6 */ \
_02_27_ENCODE_LLS (__buf_out__, __cls__ + 5 ); /* uint32 | size 6 */ \
_06_01_ENCODE_TL_AMOUNT (__buf_out__, tlamt ); /* amount | size 48 */ \
uint8_t* __fee_ptr__ = __buf_out__;\
_06_08_ENCODE_DROPS_FEE (__buf_out__, 0 ); /* amount | size 9 */ \
_07_03_ENCODE_SIGNING_PUBKEY_NULL (__buf_out__ ); /* pk | size 35 */ \
_08_01_ENCODE_ACCOUNT_SRC (__buf_out__, __acc__ ); /* account | size 22 */ \
_08_03_ENCODE_ACCOUNT_DST (__buf_out__, to_address ); /* account | size 22 */ \
int64_t __buf_size__ = PREPARE_PAYMENT_SIMPLE_TRUSTLINE_SIZE - (__buf_out__ - buf_out_master); \
etxn_details((uint32_t)__buf_out__, __buf_size__); /* emitdet | size 1?? */ \
int64_t __fee__ = etxn_fee_base(buf_out_master, PREPARE_PAYMENT_SIMPLE_TRUSTLINE_SIZE); \
_06_08_ENCODE_DROPS_FEE (__fee_ptr__, __fee__ ); \
}
#endif
// For documentation please see: https://xrpl-hooks.readme.io/reference/
// Generated using generate_sfcodes.sh
#define sfCloseResolution ((16U << 16U) + 1U)
#define sfMethod ((16U << 16U) + 2U)
#define sfTransactionResult ((16U << 16U) + 3U)
#define sfTickSize ((16U << 16U) + 16U)
#define sfUNLModifyDisabling ((16U << 16U) + 17U)
#define sfHookResult ((16U << 16U) + 18U)
#define sfLedgerEntryType ((1U << 16U) + 1U)
#define sfTransactionType ((1U << 16U) + 2U)
#define sfSignerWeight ((1U << 16U) + 3U)
#define sfTransferFee ((1U << 16U) + 4U)
#define sfVersion ((1U << 16U) + 16U)
#define sfHookStateChangeCount ((1U << 16U) + 17U)
#define sfHookEmitCount ((1U << 16U) + 18U)
#define sfHookExecutionIndex ((1U << 16U) + 19U)
#define sfHookApiVersion ((1U << 16U) + 20U)
#define sfNetworkID ((2U << 16U) + 1U)
#define sfFlags ((2U << 16U) + 2U)
#define sfSourceTag ((2U << 16U) + 3U)
#define sfSequence ((2U << 16U) + 4U)
#define sfPreviousTxnLgrSeq ((2U << 16U) + 5U)
#define sfLedgerSequence ((2U << 16U) + 6U)
#define sfCloseTime ((2U << 16U) + 7U)
#define sfParentCloseTime ((2U << 16U) + 8U)
#define sfSigningTime ((2U << 16U) + 9U)
#define sfExpiration ((2U << 16U) + 10U)
#define sfTransferRate ((2U << 16U) + 11U)
#define sfWalletSize ((2U << 16U) + 12U)
#define sfOwnerCount ((2U << 16U) + 13U)
#define sfDestinationTag ((2U << 16U) + 14U)
#define sfHighQualityIn ((2U << 16U) + 16U)
#define sfHighQualityOut ((2U << 16U) + 17U)
#define sfLowQualityIn ((2U << 16U) + 18U)
#define sfLowQualityOut ((2U << 16U) + 19U)
#define sfQualityIn ((2U << 16U) + 20U)
#define sfQualityOut ((2U << 16U) + 21U)
#define sfStampEscrow ((2U << 16U) + 22U)
#define sfBondAmount ((2U << 16U) + 23U)
#define sfLoadFee ((2U << 16U) + 24U)
#define sfOfferSequence ((2U << 16U) + 25U)
#define sfFirstLedgerSequence ((2U << 16U) + 26U)
#define sfLastLedgerSequence ((2U << 16U) + 27U)
#define sfTransactionIndex ((2U << 16U) + 28U)
#define sfOperationLimit ((2U << 16U) + 29U)
#define sfReferenceFeeUnits ((2U << 16U) + 30U)
#define sfReserveBase ((2U << 16U) + 31U)
#define sfReserveIncrement ((2U << 16U) + 32U)
#define sfSetFlag ((2U << 16U) + 33U)
#define sfClearFlag ((2U << 16U) + 34U)
#define sfSignerQuorum ((2U << 16U) + 35U)
#define sfCancelAfter ((2U << 16U) + 36U)
#define sfFinishAfter ((2U << 16U) + 37U)
#define sfSignerListID ((2U << 16U) + 38U)
#define sfSettleDelay ((2U << 16U) + 39U)
#define sfTicketCount ((2U << 16U) + 40U)
#define sfTicketSequence ((2U << 16U) + 41U)
#define sfNFTokenTaxon ((2U << 16U) + 42U)
#define sfMintedNFTokens ((2U << 16U) + 43U)
#define sfBurnedNFTokens ((2U << 16U) + 44U)
#define sfHookStateCount ((2U << 16U) + 45U)
#define sfEmitGeneration ((2U << 16U) + 46U)
#define sfLockCount ((2U << 16U) + 47U)
#define sfRewardTime ((2U << 16U) + 98U)
#define sfRewardLgrFirst ((2U << 16U) + 99U)
#define sfRewardLgrLast ((2U << 16U) + 100U)
#define sfIndexNext ((3U << 16U) + 1U)
#define sfIndexPrevious ((3U << 16U) + 2U)
#define sfBookNode ((3U << 16U) + 3U)
#define sfOwnerNode ((3U << 16U) + 4U)
#define sfBaseFee ((3U << 16U) + 5U)
#define sfExchangeRate ((3U << 16U) + 6U)
#define sfLowNode ((3U << 16U) + 7U)
#define sfHighNode ((3U << 16U) + 8U)
#define sfDestinationNode ((3U << 16U) + 9U)
#define sfCookie ((3U << 16U) + 10U)
#define sfServerVersion ((3U << 16U) + 11U)
#define sfNFTokenOfferNode ((3U << 16U) + 12U)
#define sfEmitBurden ((3U << 16U) + 13U)
#define sfHookInstructionCount ((3U << 16U) + 17U)
#define sfHookReturnCode ((3U << 16U) + 18U)
#define sfReferenceCount ((3U << 16U) + 19U)
#define sfRewardAccumulator ((3U << 16U) + 100U)
#define sfEmailHash ((4U << 16U) + 1U)
#define sfTakerPaysCurrency ((10U << 16U) + 1U)
#define sfTakerPaysIssuer ((10U << 16U) + 2U)
#define sfTakerGetsCurrency ((10U << 16U) + 3U)
#define sfTakerGetsIssuer ((10U << 16U) + 4U)
#define sfLedgerHash ((5U << 16U) + 1U)
#define sfParentHash ((5U << 16U) + 2U)
#define sfTransactionHash ((5U << 16U) + 3U)
#define sfAccountHash ((5U << 16U) + 4U)
#define sfPreviousTxnID ((5U << 16U) + 5U)
#define sfLedgerIndex ((5U << 16U) + 6U)
#define sfWalletLocator ((5U << 16U) + 7U)
#define sfRootIndex ((5U << 16U) + 8U)
#define sfAccountTxnID ((5U << 16U) + 9U)
#define sfNFTokenID ((5U << 16U) + 10U)
#define sfEmitParentTxnID ((5U << 16U) + 11U)
#define sfEmitNonce ((5U << 16U) + 12U)
#define sfEmitHookHash ((5U << 16U) + 13U)
#define sfBookDirectory ((5U << 16U) + 16U)
#define sfInvoiceID ((5U << 16U) + 17U)
#define sfNickname ((5U << 16U) + 18U)
#define sfAmendment ((5U << 16U) + 19U)
#define sfHookOn ((5U << 16U) + 20U)
#define sfDigest ((5U << 16U) + 21U)
#define sfChannel ((5U << 16U) + 22U)
#define sfConsensusHash ((5U << 16U) + 23U)
#define sfCheckID ((5U << 16U) + 24U)
#define sfValidatedHash ((5U << 16U) + 25U)
#define sfPreviousPageMin ((5U << 16U) + 26U)
#define sfNextPageMin ((5U << 16U) + 27U)
#define sfNFTokenBuyOffer ((5U << 16U) + 28U)
#define sfNFTokenSellOffer ((5U << 16U) + 29U)
#define sfHookStateKey ((5U << 16U) + 30U)
#define sfHookHash ((5U << 16U) + 31U)
#define sfHookNamespace ((5U << 16U) + 32U)
#define sfHookSetTxnID ((5U << 16U) + 33U)
#define sfOfferID ((5U << 16U) + 34U)
#define sfEscrowID ((5U << 16U) + 35U)
#define sfURITokenID ((5U << 16U) + 36U)
#define sfAmount ((6U << 16U) + 1U)
#define sfBalance ((6U << 16U) + 2U)
#define sfLimitAmount ((6U << 16U) + 3U)
#define sfTakerPays ((6U << 16U) + 4U)
#define sfTakerGets ((6U << 16U) + 5U)
#define sfLowLimit ((6U << 16U) + 6U)
#define sfHighLimit ((6U << 16U) + 7U)
#define sfFee ((6U << 16U) + 8U)
#define sfSendMax ((6U << 16U) + 9U)
#define sfDeliverMin ((6U << 16U) + 10U)
#define sfMinimumOffer ((6U << 16U) + 16U)
#define sfRippleEscrow ((6U << 16U) + 17U)
#define sfDeliveredAmount ((6U << 16U) + 18U)
#define sfNFTokenBrokerFee ((6U << 16U) + 19U)
#define sfHookCallbackFee ((6U << 16U) + 20U)
#define sfLockedBalance ((6U << 16U) + 21U)
#define sfPublicKey ((7U << 16U) + 1U)
#define sfMessageKey ((7U << 16U) + 2U)
#define sfSigningPubKey ((7U << 16U) + 3U)
#define sfTxnSignature ((7U << 16U) + 4U)
#define sfURI ((7U << 16U) + 5U)
#define sfSignature ((7U << 16U) + 6U)
#define sfDomain ((7U << 16U) + 7U)
#define sfFundCode ((7U << 16U) + 8U)
#define sfRemoveCode ((7U << 16U) + 9U)
#define sfExpireCode ((7U << 16U) + 10U)
#define sfCreateCode ((7U << 16U) + 11U)
#define sfMemoType ((7U << 16U) + 12U)
#define sfMemoData ((7U << 16U) + 13U)
#define sfMemoFormat ((7U << 16U) + 14U)
#define sfFulfillment ((7U << 16U) + 16U)
#define sfCondition ((7U << 16U) + 17U)
#define sfMasterSignature ((7U << 16U) + 18U)
#define sfUNLModifyValidator ((7U << 16U) + 19U)
#define sfValidatorToDisable ((7U << 16U) + 20U)
#define sfValidatorToReEnable ((7U << 16U) + 21U)
#define sfHookStateData ((7U << 16U) + 22U)
#define sfHookReturnString ((7U << 16U) + 23U)
#define sfHookParameterName ((7U << 16U) + 24U)
#define sfHookParameterValue ((7U << 16U) + 25U)
#define sfBlob ((7U << 16U) + 26U)
#define sfAccount ((8U << 16U) + 1U)
#define sfOwner ((8U << 16U) + 2U)
#define sfDestination ((8U << 16U) + 3U)
#define sfIssuer ((8U << 16U) + 4U)
#define sfAuthorize ((8U << 16U) + 5U)
#define sfUnauthorize ((8U << 16U) + 6U)
#define sfRegularKey ((8U << 16U) + 8U)
#define sfNFTokenMinter ((8U << 16U) + 9U)
#define sfEmitCallback ((8U << 16U) + 10U)
#define sfHookAccount ((8U << 16U) + 16U)
#define sfIndexes ((19U << 16U) + 1U)
#define sfHashes ((19U << 16U) + 2U)
#define sfAmendments ((19U << 16U) + 3U)
#define sfNFTokenOffers ((19U << 16U) + 4U)
#define sfHookNamespaces ((19U << 16U) + 5U)
#define sfPaths ((18U << 16U) + 1U)
#define sfTransactionMetaData ((14U << 16U) + 2U)
#define sfCreatedNode ((14U << 16U) + 3U)
#define sfDeletedNode ((14U << 16U) + 4U)
#define sfModifiedNode ((14U << 16U) + 5U)
#define sfPreviousFields ((14U << 16U) + 6U)
#define sfFinalFields ((14U << 16U) + 7U)
#define sfNewFields ((14U << 16U) + 8U)
#define sfTemplateEntry ((14U << 16U) + 9U)
#define sfMemo ((14U << 16U) + 10U)
#define sfSignerEntry ((14U << 16U) + 11U)
#define sfNFToken ((14U << 16U) + 12U)
#define sfEmitDetails ((14U << 16U) + 13U)
#define sfHook ((14U << 16U) + 14U)
#define sfSigner ((14U << 16U) + 16U)
#define sfMajority ((14U << 16U) + 18U)
#define sfDisabledValidator ((14U << 16U) + 19U)
#define sfEmittedTxn ((14U << 16U) + 20U)
#define sfHookExecution ((14U << 16U) + 21U)
#define sfHookDefinition ((14U << 16U) + 22U)
#define sfHookParameter ((14U << 16U) + 23U)
#define sfHookGrant ((14U << 16U) + 24U)
#define sfSigners ((15U << 16U) + 3U)
#define sfSignerEntries ((15U << 16U) + 4U)
#define sfTemplate ((15U << 16U) + 5U)
#define sfNecessary ((15U << 16U) + 6U)
#define sfSufficient ((15U << 16U) + 7U)
#define sfAffectedNodes ((15U << 16U) + 8U)
#define sfMemos ((15U << 16U) + 9U)
#define sfNFTokens ((15U << 16U) + 10U)
#define sfHooks ((15U << 16U) + 11U)
#define sfMajorities ((15U << 16U) + 16U)
#define sfDisabledValidators ((15U << 16U) + 17U)
#define sfHookExecutions ((15U << 16U) + 18U)
#define sfHookParameters ((15U << 16U) + 19U)
#define sfHookGrants ((15U << 16U) + 20U)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment