-
Notifications
You must be signed in to change notification settings - Fork 671
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement PoX-4 Locking via Special Contract-Call Handler #4106
Conversation
Codecov ReportAttention:
Additional details and impacted files@@ Coverage Diff @@
## next #4106 +/- ##
===========================================
+ Coverage 17.17% 38.23% +21.06%
===========================================
Files 418 418
Lines 295319 295319
===========================================
+ Hits 50718 112921 +62203
+ Misses 244601 182398 -62203 ☔ View full report in Codecov by Sentry. |
Following this issue on Clarinet: hirosystems/clarinet#1267, we brainstormed with @lgalabru for a clean way to handle the pox-4.clar contract on Clarinet (regarding the concatenation with While we all agree that it would be nice to have a standard way to handle such use cases at the Clarity or Clarinet level, it may take a bit of time to get there. In the meantime, regarding the pox-4 contract specifically, what about leveraging (define-constant PREPARE_CYCLE_LENGTH (if is-in-mainnet u100 u50)) |
b838908
to
c5d04d1
Compare
@moodmosaic I managed to fix one test
I still don't understand why these block heights work, but the tests clearly show STX are being locked for a couple cycles, then unlocked, so it looks okay to me Also, going to give you write access to this branch so you can push (since it's in my repo) |
@@ -0,0 +1,4399 @@ | |||
use std::collections::{HashMap, HashSet, VecDeque}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Per our meeting earlier, I think the only things that this file needs to test are:
- PoX 4 instantiates
- STX locked in PoX 3 unlock automatically
- Once PoX 4 is active, only PoX 4 stacking methods work. PoX 3 ones fail.
There's no reason to test PoX 2 and PoX behavior, since both these contracts have been defunct for some time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- PoX 4 instantiates
does get_pox_addrs
captures this? If it does, I would like to start the current pox_4_tests.rs
(in this PR) from a clean state and start by just adding this test, and then keep adding to it.
d297bcb
to
f9fe643
Compare
pox_4.rs
from pox_3.rs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM -- I would just recommend using from_seed
to initialize the necessary new StacksPrivateKeys in nakamoto::coordinator::tests
for _ in 0..burnchain.pox_constants.reward_cycle_length { | ||
latest_block = peer.tenure_with_txs(&[], &mut coinbase_nonce); | ||
// Should all be burn because no stackers | ||
assert_latest_was_burn(&mut peer); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you check the tx receipts to verify that stacking actually failed because pox-3 was defunct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Trying to figure out how to do this, I think I understand, but want to check:
- Get
StacksTransactionReceipt
s from latest block after executing transactions - Filter the ones that contain a
StacksTransactionEvent
with apox-3
call - Check that
StacksTransactionReceipt.result
is an error value
Does this sound right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes; if possible, also test that we specifically fail because contract was defunct (as opposed to some other error that might arise due to a regression in the test).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure that the StacksTransactionReceipt
s will be very discerning for these checks -- runtime errors (like these should be) just return a receipt with a result of err_none
, an empty assetmap, and an empty event list. But, you could usefully assert that a runtime error occurs by checking the receipt.
This is how pox_3_tests
does this:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm actually seeing something like this in StacksTransactionReceipt.result
:
(ok (tuple (lock-amount u10240000000000) (stacker ST3DYDR173ZWF79YJ40JEHDPVAR2815PDZ0PF8C67) (unlock-burn-height u125)))
So the contract call looks to be returning okay, but the other checks suggest that the STX are not actually locked
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, that's because pox-3
doesn't seem to actually be marked defunct in these changes. You need to do something like:
diff --git a/pox-locking/src/lib.rs b/pox-locking/src/lib.rs
index 05303a4d9..057667341 100644
--- a/pox-locking/src/lib.rs
+++ b/pox-locking/src/lib.rs
@@ -107,6 +107,19 @@ pub fn handle_contract_call_special_cases(
result,
);
} else if *contract_id == boot_code_id(POX_3_NAME, global_context.mainnet) {
+ if !pox_3::is_read_only(function_name) && global_context.epoch_id >= StacksEpochId::Epoch25
+ {
+ warn!("PoX-3 function call attempted on an account after Epoch 2.5";
+ "v3_unlock_ht" => global_context.database.get_v3_unlock_height(),
+ "current_burn_ht" => global_context.database.get_current_burnchain_block_height(),
+ "function_name" => function_name,
+ "contract_id" => %contract_id
+ );
+ return Err(ClarityError::Runtime(
+ RuntimeErrorType::DefunctPoxContract,
+ None,
+ ));
+ }
return pox_3::handle_contract_call(
global_context,
sender,
diff --git a/pox-locking/src/pox_3.rs b/pox-locking/src/pox_3.rs
index cccfbb264..e0110987e 100644
--- a/pox-locking/src/pox_3.rs
+++ b/pox-locking/src/pox_3.rs
@@ -32,6 +32,33 @@ use crate::pox_2::{parse_pox_extend_result, parse_pox_increase, parse_pox_stacki
use crate::{LockingError, POX_3_NAME};
/////////////////////// PoX-3 /////////////////////////////////
+/// is a PoX-3 function call read only?
+pub(crate) fn is_read_only(func_name: &str) -> bool {
+ "get-pox-rejection" == func_name
+ || "is-pox-active" == func_name
+ || "burn-height-to-reward-cycle" == func_name
+ || "reward-cycle-to-burn-height" == func_name
+ || "current-pox-reward-cycle" == func_name
+ || "get-stacker-info" == func_name
+ || "get-check-delegation" == func_name
+ || "get-reward-set-size" == func_name
+ || "next-cycle-rejection-votes" == func_name
+ || "get-total-ustx-stacked" == func_name
+ || "get-reward-set-pox-address" == func_name
+ || "get-stacking-minimum" == func_name
+ || "check-pox-addr-version" == func_name
+ || "check-pox-addr-hashbytes" == func_name
+ || "check-pox-lock-period" == func_name
+ || "can-stack-stx" == func_name
+ || "minimal-can-stack-stx" == func_name
+ || "get-pox-info" == func_name
+ || "get-delegation-info" == func_name
+ || "get-allowance-contract-callers" == func_name
+ || "get-num-reward-set-pox-addresses" == func_name
+ || "get-partial-stacked-by-cycle" == func_name
+ || "get-total-pox-rejection" == func_name
+}
+
/// Lock up STX for PoX for a time. Does NOT touch the account nonce.
pub fn pox_lock_v3(
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @kantai, that fixed it! Will check in and merge this ASAP
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM; just please address my remaining concerns before merging. Thanks!
85ea13a
to
3187062
Compare
…eedless_return)]`
3187062
to
7fb7a07
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, just a couple tweaks to the test case.
This pull request has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
Description
Copy/paste
pox_3.rs
topox_4.rs
and rename things as needed. Also, fixclippy::needless_return
lintApplicable issues
pox_locking::pox_4
lockup methods #4090handle_contract_call_special_cases()
instackslib/src/clarity_vm/special.rs
to handle PoX-4 #4091Additional info (benefits, drawbacks, caveats)
Checklist
delegate_extend_pox_3
delegate_stack_increase
get_pox_addrs
->pox_lock_unlock
pox_3_delegate_stx_addr_validation
pox_3_getters
pox_auto_unlock_ab
pox_auto_unlock_ba
pox_extend_transition
simple_pox_lockup_transition_pox_2
stack_aggregation_increase
stack_increase
stack_with_segwit
pox_3_fails
)