rework reward and govern hook for governance rewards, compiling untested

This commit is contained in:
Richard Holland
2023-04-11 12:40:09 +00:00
parent 1e21d9f01d
commit b3d714260f
3 changed files with 177 additions and 67 deletions

View File

@@ -70,13 +70,13 @@
#define SVAR(x) x, sizeof(x)
#define DONE(x)\
{\
accept(SVAR(x),(uint32_t)__LINE__);\
}
accept(SVAR(x),(uint32_t)__LINE__);
#define NOPE(x)\
rollback(SBUF(x), __LINE__);
#define DEBUG 1
int64_t hook(uint32_t r)
{
_g(1,1);
@@ -91,14 +91,30 @@ int64_t hook(uint32_t r)
uint8_t hook_accid[20];
hook_account(SBUF(hook_accid));
// start of hook proper
// state key 0..0 contains the member count
int64_t member_count = state(0,0, "MC", 2);
if (DEBUG)
TRACEVAR(member_count);
TRACEVAR(member_count);
// outgoing txns to other hooks allowed
// but a self ttINVOKE means rewards hook is trying to get the governance hook to distribute governance rewards
int64_t is_distribution = 0;
int64_t is_setup = member_count == DOESNT_EXIST;
if (BUFFER_EQUAL_20(hook_accid, account_field + 12))
{
uint8_t dest_acc[20];
if (otxn_field(SBUF(dest_acc), sfDestination) == 20 && !BUFFER_EQUAL_20(hook_accid, dest_acc))
DONE("Goverance: Passing outgoing txn.");
is_distribution = 1;
}
// initial execution, setup hook
if (member_count == DOESNT_EXIST)
int64_t distribution_amount;
if (is_setup)
{
// gather hook parameters
@@ -136,40 +152,62 @@ int64_t hook(uint32_t r)
// set reward delay
ASSERT(state_set(SVAR(ird), "RD", 2));
for (uint8_t i = 0; GUARD(SEAT_COUNT), i < imc; ++i)
distribution_amount = ida;
member_count = imc;
}
else if (is_distribution)
{
ASSERT(member_count > 0);
uint8_t amt[8];
ASSERT(otxn_param(SBUF(amt), "reward", 5) == 8);
distribution_amount = INT64_FROM_BUF(amt);
distribution_amount /= member_count;
ASSERT(distribution_amount > 0);
}
if (is_setup || is_distribution)
{
for (uint8_t i = 0; GUARD(SEAT_COUNT), i < member_count; ++i)
{
uint8_t member_acc[20];
uint8_t member_pkey[3] = {'I', 'S', i};
if (hook_param(SBUF(member_acc), member_pkey, 3) != 20)
NOPE("Governance: One or more initial member account ID's is missing");
if (is_setup)
{
uint8_t member_pkey[3] = {'I', 'S', i};
if (hook_param(SBUF(member_acc), member_pkey, 3) != 20)
NOPE("Governance: One or more initial member account ID's is missing");
// 0... X where X is member id started from 1
// maps to the member's account ID
// reverse key
ASSERT(state_set(SBUF(member_acc), SVAR(i)) == 20);
// reverse key
ASSERT(state_set(SBUF(member_acc), SVAR(i)) == 20);
// 0, 0... ACCOUNT ID maps to member_id (as above)
// forward key
ASSERT(state_set(SVAR(i), SBUF(member_acc)) == 1);
// forward key
ASSERT(state_set(SVAR(i), SBUF(member_acc)) == 1);
}
else if (state(SBUF(member_acc), SVAR(i)) != 20)
break;
// emit initial
uint8_t tx[PREPARE_PAYMENT_SIMPLE_SIZE];
PREPARE_PAYMENT_SIMPLE(tx, ida, member_acc, 0, 0);
PREPARE_PAYMENT_SIMPLE(tx, distribution_amount, member_acc, 0, 0);
// emit the transaction
uint8_t emithash[32];
int64_t emit_result = emit(SBUF(emithash), SBUF(tx));
ASSERT(emit_result > 0);
TRACEVAR(emit_result);
if (DEBUG)
TRACEVAR(emit_result);
}
DONE("Governance: Setup completed successfully.");
DONE(is_setup
? "Governance: Setup completed successfully."
: "Governance: Reward distribution completed successfully.");
}
// outgoing txns allowed
if (BUFFER_EQUAL_20(hook_accid, account_field + 12))
DONE("Goverance: Passing outgoing txn.");
// otherwise a normal execution (not initial)
// first let's check if the invoking party is a member
@@ -274,11 +312,13 @@ int64_t hook(uint32_t r)
uint8_t zero[32];
int topic_data_zero = BUFFER_EQUAL_32(topic_data, zero);
TRACEVAR(topic_data_zero);
TRACEVAR(votes);
TRACEVAR(member_count);
trace(SBUF("topic"), topic, 2, 1);
if (DEBUG)
{
TRACEVAR(topic_data_zero);
TRACEVAR(votes);
TRACEVAR(member_count);
trace(SBUF("topic"), topic, 2, 1);
}
// now check if we hit threshold
if (votes < (topic[0] == 'M' ? (member_count * 0.8) : member_count))
@@ -287,9 +327,9 @@ int64_t hook(uint32_t r)
// 100%/80% threshold as needed is reached
// action vote
TRACESTR("Actioning votes");
if (DEBUG)
TRACESTR("Actioning votes");
// RH UPTO:
switch (topic[0])
{
case 'R':
@@ -354,7 +394,8 @@ int64_t hook(uint32_t r)
uint8_t emithash[32];
int64_t emit_result = emit(SBUF(emithash), emit_buf, emit_size);
TRACEVAR(emit_result);
if (DEBUG)
TRACEVAR(emit_result);
if (emit_result != emit_size)
NOPE("Governance: Emit failed during hook actioning.");

View File

@@ -562,10 +562,13 @@ int out_len = 0;\
else\
{\
*buf_out++ = 0x1FU; /* HookHash */\
*buf_out++ = *hook0++; *buf_out++ = *hook0++; *buf_out++ = *hook0++; *buf_out++ = *hook0++; \
*buf_out++ = *hook0++; *buf_out++ = *hook0++; *buf_out++ = *hook0++; *buf_out++ = *hook0++; \
*buf_out++ = *hook0++; *buf_out++ = *hook0++; *buf_out++ = *hook0++; *buf_out++ = *hook0++; \
*buf_out++ = *hook0++; *buf_out++ = *hook0++; *buf_out++ = *hook0++; *buf_out++ = *hook0++; \
uint64_t* d = (uint64_t*)buf_out;\
uint64_t* s = (uint64_t*)hook0;\
*d++ = *s++;\
*d++ = *s++;\
*d++ = *s++;\
*d++ = *s++;\
buf_out+=32;\
}\
}\
*buf_out++ = 0xE1U;\

View File

@@ -10,32 +10,81 @@
#define DEBUG 1
// this txn template is sent back to this account to distribute a duplicate reward to governance members
// this distribution is handled by the governance reward hook
uint8_t txn_loopback[235] =
{
/* size,upto */
/* 3, 0 */ 0x12U, 0x00U, 0x63U, /* tt = Invoke */
/* 5, 3 */ 0x22U, 0x80U, 0x00U, 0x00U, 0x00U, /* flags = tfCanonical */
/* 5, 8 */ 0x24U, 0x00U, 0x00U, 0x00U, 0x00U, /* sequence = 0 */
/* 6, 13 */ 0x20U, 0x1AU, 0x00U, 0x00U, 0x00U, 0x00U, /* first ledger seq */
/* 6, 19 */ 0x20U, 0x1BU, 0x00U, 0x00U, 0x00U, 0x00U, /* last ledger seq */
/* 9, 25 */ 0x68U, 0x40U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, /* fee */
/* 35, 34 */ 0x73U, 0x21U, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* pubkey */
/* 22, 69 */ 0x81U, 0x14U, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* src acc */
/* 116, 91 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* emit detail */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
/* 28,207 */ 0xF0U,0x13U,0xE0U,0x17U,0x70U,0x18U,0x06U,0x72U, /* hook params */
0x65U,0x77U,0x61U,0x72U,0x64U,0x70U,0x19U,0x08U, /* reward key */
/* 223 */ 0x00U,0x00U,0x00U,0x00U,0x00U,0x00U,0x00U,0x00U, /* value/drops */
0xE1U,0xF1U,0xE1U,0xF1 /* end params */
/* 235 */
};
// this txn template is used to pay out rewards
uint8_t txn_payment[238] =
{
/* size,upto */
/* 3, 0 */ 0x12U, 0x00U, 0x00U, /* tt = Payment */
/* 5, 3*/ 0x22U, 0x80U, 0x00U, 0x00U, 0x00U, /* flags = tfCanonical */
/* 5, 8 */ 0x24U, 0x00U, 0x00U, 0x00U, 0x00U, /* sequence = 0 */
/* 6, 13 */ 0x20U, 0x1AU, 0x00U, 0x00U, 0x00U, 0x00U, /* first ledger seq */
/* 6, 19 */ 0x20U, 0x1BU, 0x00U, 0x00U, 0x00U, 0x00U, /* last ledger seq */
/* 9, 25 */ 0x61U, 0x99U, 0x99U, 0x99U, 0x99U, 0x99U, 0x99U, 0x99U, 0x99U, 0x99U, /* amount field 9 bytes */
/* 9, 34 */ 0x68U, 0x40U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, /* fee */
/* 35, 43 */ 0x73U, 0x21U, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* pubkey */
/* 22, 78 */ 0x81U, 0x14U, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* src acc */
/* 22,100 */ 0x83U, 0x14U, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* dst acc */
/* 116,122 */ /* emit details */
/* 0,238 */
};
#define HOOK_ACCOUNT (txn_loopback + 71U)
#define HOOK_ACCOUNT_2 (txn_payment + 80U)
#define ACC_FIELD (txn_payment + 102U)
#define AMOUNT_OUT (txn_payment + 26U)
#define AMOUNT_OUT_2 (txn_loopback + 223U)
uint8_t msg_buf[] = "You must wait 0000000 seconds";
int64_t hook(uint32_t r)
{
etxn_reserve(1);
_g(1,1);
uint8_t ttbuf[16];
int64_t br = otxn_field(SBUF(ttbuf), sfTransactionType);
uint32_t txntype = ((uint32_t)(ttbuf[0]) << 16U) + ((uint32_t)(ttbuf[1]));
// only process ttCLAIM_REWARD
if (txntype != 98)
if (otxn_type() != 98)
accept(SBUF("Reward: Passing non-claim txn"), __LINE__);
// get the account id
uint8_t account_field[20];
otxn_field(SBUF(account_field), sfAccount);
otxn_field(ACC_FIELD, 20, sfAccount);
uint8_t hook_accid[20];
hook_account(SBUF(hook_accid));
// write the hook account into the txn template
hook_account(HOOK_ACCOUNT, 20);
if (BUFFER_EQUAL_20(hook_accid, account_field))
// there are two txn templates so also write into the second template
hook_account(HOOK_ACCOUNT_2, 20);
if (BUFFER_EQUAL_20(HOOK_ACCOUNT, ACC_FIELD))
accept(SBUF("Reward: Passing outgoing txn"), __LINE__);
// get the account root keylet
uint8_t kl[34];
util_keylet(SBUF(kl), KEYLET_ACCOUNT, SBUF(account_field), 0,0,0,0);
util_keylet(SBUF(kl), KEYLET_ACCOUNT, ACC_FIELD, 20, 0,0,0,0);
// slot the account root, this can't fail
slot_set(SBUF(kl), 1);
@@ -55,8 +104,6 @@ int64_t hook(uint32_t r)
int64_t time_elapsed = ledger_last_time() - time;
if (time_elapsed < REWARD_DELAY)
{
uint8_t msg_buf[] = "You must wait 0000000 seconds";
//2 600 000
time_elapsed = REWARD_DELAY - time_elapsed;
msg_buf[14] += (time_elapsed / 1000000) % 10;
@@ -109,8 +156,9 @@ int64_t hook(uint32_t r)
if (DEBUG)
TRACEVAR(accumulator);
uint8_t key[32];
key[0] = 0xFFU;
// reward hook shares the same namespace as governance hook, so we can request the RR key directly
uint8_t key[2] = {'R', 'R'};
// mr = monthly reward rate
int64_t xfl_mr =
state(0,0, SBUF(key));
@@ -135,25 +183,43 @@ int64_t hook(uint32_t r)
if (DEBUG)
TRACEVAR(xfl_reward);
int64_t reward_drops = float_int(xfl_reward, 6, 0);
if (DEBUG)
TRACEVAR(reward_drops);
// write drops to paymen txn
{
uint64_t drops = float_int(xfl_reward, 6, 1);
uint8_t* b = AMOUNT_OUT;
*b++ = 0b01000000 + (( drops >> 56 ) & 0b00111111 );
*b++ = (drops >> 48) & 0xFFU;
*b++ = (drops >> 40) & 0xFFU;
*b++ = (drops >> 32) & 0xFFU;
*b++ = (drops >> 24) & 0xFFU;
*b++ = (drops >> 16) & 0xFFU;
*b++ = (drops >> 8) & 0xFFU;
*b++ = (drops >> 0) & 0xFFU;
uint8_t tx[PREPARE_PAYMENT_SIMPLE_SIZE];
PREPARE_PAYMENT_SIMPLE(tx, reward_drops, account_field, 0, 0);
// copy to other template
*((uint64_t*)AMOUNT_OUT_2) = *((uint64_t*)AMOUNT_OUT);
}
// emit the transaction
// emit the payment transaction
uint8_t emithash[32];
int64_t emit_result = emit(SBUF(emithash), SBUF(tx));
int64_t emit_result = emit(SBUF(emithash), SBUF(txn_payment));
if (DEBUG)
TRACEVAR(emit_result);
if (emit_result > 0)
accept(SBUF("Reward: Emitted reward txn successfully."), __LINE__);
// RH TODO:
// on callback pay out each of the filled gov seat
if (emit_result < 0)
rollback(SBUF("Reward: Emit reward failed."), __LINE__);
rollback(SBUF("Reward: Emit reward failed."), __LINE__);
// emit the loopback txn
emit_result = emit(SBUF(emithash), SBUF(txn_loopback));
if (DEBUG)
TRACEVAR(emit_result);
if (emit_result < 0)
rollback(SBUF("Reward: Emit loopback failed."), __LINE__);
accept(SBUF("Reward: Emitted reward txn successfully."), __LINE__);
}