reintroduce L2 functionality into the governance hook, compiling not tested

This commit is contained in:
Richard Holland
2023-07-14 13:45:53 +00:00
parent 17df89c075
commit d0295da992

View File

@@ -66,14 +66,20 @@
* Hook Invocation:
* ttINVOKE:
* First time:
* Behaviour: Setup hook, fund initial accounts, end (accept).
* Behaviour: Setup hook, setup initial accounts, end (accept).
*
* Subsequent:
* Behaviour: Vote on a topic, if the votes meet the topic vote threshold, action the topic.
*
* Parameter Name: {'L'}
* Parameter Value: Which layer the vote is inteded for
* { '1' a vote cast by an L2 member about an L1 topic }, or
* { '2' a vote cast by an L2 member about an L2 topic }
*
*
* Parameter Name: {'T'}
* Parameter Value: The topic to vote on <2 bytes>
* { 'S|H' (seat L1, hook L1), '\0 + topic id' }, or
* { 'S|H' (seat, hook), '\0 + topic id' }, or
* { 'R' (reward), 'R|D' (rate, delay) }
*
* Parameter Name: {'V'}
@@ -83,7 +89,7 @@
#define SVAR(x) &x, sizeof(x)
#define DONE(x)\
accept(SVAR(x),(uint32_t)__LINE__);
accept(SBUF(x),__LINE__);
#define NOPE(x)\
rollback(SBUF(x), __LINE__);
@@ -101,6 +107,8 @@ int64_t hook(uint32_t r)
{
_g(1,1);
etxn_reserve(1);
int64_t tt = otxn_type();
if (tt != 99) // ttINVOKE only
@@ -121,11 +129,10 @@ int64_t hook(uint32_t r)
DONE("Goverance: Passing outgoing txn.");
}
int64_t is_L1 = BUFFER_EQUAL_20(hook_accid + 12, genesis);
if (!is_L1)
NOPE("Governance: This is the L1 governance hook. It can only be used on genesis account.");
int64_t is_L1_table = BUFFER_EQUAL_20(hook_accid + 12, genesis);
if (is_L1_table)
trace(SBUF("Governance: Starting governance logic on L1 table."), 0,0,0);
int64_t member_count = state(0,0, "MC", 2);
if (DEBUG)
@@ -208,8 +215,8 @@ int64_t hook(uint32_t r)
uint8_t n = topic[1]; // number (seats) (or R/D for reward rate/delay)
if (result != 2 || (
t != 'S' && // topic type: seat (L1)
t != 'H' && // topic type: hook (L1)
t != 'S' && // topic type: seat
t != 'H' && // topic type: hook
t != 'R')) // topic type: reward
NOPE("Governance: Valid TOPIC must be specified as otxn parameter.");
@@ -223,9 +230,26 @@ int64_t hook(uint32_t r)
if (t == 'R' && n != 'R' && n != 'D')
NOPE("Governance: Valid reward topics are R (rate) and D (delay).");
// is their vote for the L2 table or the L1 table?
uint8_t l = 1;
if (!is_L1_table)
{
result = otxn_param(SVAR(l), "L", 1);
if (result != 1)
NOPE("Governance: Missing L parameter. Which layer are you voting for?");
if (l != '1' && l != '2')
NOPE("Governance: Layer parameter must be '1' or '2'.");
l -= '0'; // now it will be 1/2 rather than '1'/'2'.
}
if (l == 2 && t == 'R')
NOPE("Governance: L2s cannot vote on RR/RD at L2, did you mean to set L=1?");
// RH TODO: validate RR/RD xfl > 0
uint8_t topic_data[32];
uint8_t topic_data[56 /* there's a 24 byte pad on the back for later logic */];
uint8_t topic_size =
t == 'H' ? 32 : // hook topics are a 32 byte hook hash
t == 'S' ? 20 : // account topics are a 20 byte account ID
@@ -242,6 +266,7 @@ int64_t hook(uint32_t r)
account_field[0] = 'V';
account_field[1] = t;
account_field[2] = n;
account_field[3] = l;
// get their previous vote if any on this topic
uint8_t previous_topic_data[32];
@@ -260,6 +285,7 @@ int64_t hook(uint32_t r)
// write vote to their voting key
ASSERT(state_set(topic_data, topic_size, SBUF(account_field)) == topic_size);
uint8_t previous_votes = 0;
// decrement old vote counter for this option
if (previous_topic_size > 0)
{
@@ -268,9 +294,11 @@ int64_t hook(uint32_t r)
previous_topic_data[0] = 'C';
previous_topic_data[1] = t;
previous_topic_data[2] = n;
previous_topic_data[3] = l;
if (state(&votes, 1, SBUF(previous_topic_data)) && votes > 0)
{
previous_votes = votes;
votes--;
// delete the state entry if votes hit zero
ASSERT(state_set(votes == 0 ? 0 : &votes, votes == 0 ? 0 : 1, SBUF(previous_topic_data)));
@@ -286,6 +314,7 @@ int64_t hook(uint32_t r)
topic_data[0] = 'C';
topic_data[1] = t;
topic_data[2] = n;
topic_data[3] = l;
state(&votes, 1, SBUF(topic_data));
votes++;
@@ -308,21 +337,115 @@ int64_t hook(uint32_t r)
trace(SBUF("topic"), topic, 2, 1);
}
int64_t lost_majority = 0;
int64_t q80 = member_count * 0.8;
int64_t q51 = member_count * 0.51;
if (votes <
t == 'S'
? q80 // L1s have 80% threshold for membership/seat voting
: member_count) // L1s have 100% threshold for all other voting
if (l == 2)
{
if (votes <
(t == 'S'
? q80 // L1s have 80% threshold for membership/seat voting
: member_count)) // L1s have 100% threshold for all other voting
DONE("Governance: Vote for L2 topic recorded. Not yet enough votes to action.");
}
else // l == 1
{
lost_majority = previous_votes >= q51 && votes < q51;
if (lost_majority)
trace(SBUF("Governance: Majority lost, undoing L1 vote."),0,0,0);
else if (votes < q51)
DONE("Governance: Vote for L1 topic recorded. Not yet enough votes to action.");
}
DONE("Governance: Vote recorded at L1. Not yet enough votes to action.");
// action vote
if (DEBUG)
TRACESTR("Actioning votes");
switch (t)
if (l == 1)
{
uint8_t txn_out[1024];
uint8_t* buf_out = txn_out;
uint32_t cls = (uint32_t)ledger_seq();
_01_02_ENCODE_TT (buf_out, ttINVOKE);
_02_02_ENCODE_FLAGS (buf_out, tfCANONICAL);
_02_04_ENCODE_SEQUENCE (buf_out, 0);
_02_26_ENCODE_FLS (buf_out, cls + 1);
_02_27_ENCODE_LLS (buf_out, cls + 5);
uint8_t* fee_ptr = buf_out;
_06_08_ENCODE_DROPS_FEE (buf_out, 0);
_07_03_ENCODE_SIGNING_PUBKEY_NULL (buf_out);
_08_01_ENCODE_ACCOUNT_SRC (buf_out, hook_accid + 12);
_08_03_ENCODE_ACCOUNT_DST (buf_out, genesis);
int64_t edlen = etxn_details((uint32_t)buf_out, 512);
buf_out += edlen;
/** Parameters:
* F013E017 70180154
* 701902
* <00> <two byte topic code>
* E1E0177018015670
* 19
* <topic len>
* <topic data>
* E1F1
*/
// note wasm is LE and Txns are BE so these large constants are endian flipped
// to undo the flipping on insertion into memory
*((uint64_t*)buf_out) = 0x5401187017E013F0ULL; // parameters array, first parameter preamble
buf_out += 8;
*((uint32_t*)buf_out) = 0x021970UL;
buf_out += 3;
*buf_out++ = (t << 4) + n; // topic
*((uint64_t*)buf_out) = 0x705601187017E0E1ULL;
buf_out += 8;
*buf_out++ = 0x19U;
// topic data len
*buf_out++ = topic_size;
if (lost_majority)
{
// do nothing, the array already has zeros here
}
else
{
uint64_t* d = (uint64_t*)buf_out;
uint64_t* s = (uint64_t*)(topic_data + padding);
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
}
buf_out += topic_size;
// topicdata
*((uint16_t*)buf_out) = 0xF1E1U;
int64_t txn_len = buf_out - txn_out;
// populate fee
int64_t fee = etxn_fee_base(txn_out, txn_len);
_06_08_ENCODE_DROPS_FEE (fee_ptr, fee );
trace(SBUF("Governance: Emitting invoke to L1"), txn_out, txn_len, 1);
uint8_t emit_hash[32];
int64_t emit_result = emit(SBUF(emit_hash), txn_out, txn_len);
trace_num(SBUF("Governance: Emit result"), emit_result);
if (emit_result == 32)
accept(SBUF("Governance: Successfully emitted L1 vote."), __LINE__);
NOPE("Governance: L1 vote emission failed.");
}
switch(t)
{
case 'R':
{
@@ -333,7 +456,7 @@ int64_t hook(uint32_t r)
DONE("Governance: Reward delay change actioned!");
}
case 'H':
{
// hook topics
@@ -368,7 +491,6 @@ int64_t hook(uint32_t r)
NOPE("Goverance: Hook Hash doesn't exist on ledger while actioning hook.");
// it does so now we can do the emit
etxn_reserve(1);
uint8_t* hookhash =
topic_data_zero