Skip to content

Feat/sip 031 boot contract #6261

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

Open
wants to merge 6 commits into
base: release/3.2.0.0.0-rc1
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 43 additions & 1 deletion stacks-node/src/tests/nakamoto_integrations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,10 @@ use crate::{tests, BitcoinRegtestController, BurnchainController, Config, Config
pub static POX_4_DEFAULT_STACKER_BALANCE: u64 = 100_000_000_000_000;
pub static POX_4_DEFAULT_STACKER_STX_AMT: u128 = 99_000_000_000_000;

use clarity::vm::database::STXBalance;
use stacks::chainstate::stacks::boot::SIP_031_NAME;
use stacks::clarity_vm::clarity::SIP_031_INITIAL_MINT;

use crate::clarity::vm::clarity::ClarityConnection;

lazy_static! {
Expand Down Expand Up @@ -12635,7 +12639,7 @@ fn write_signer_update(
/// Test SIP-031 activation
///
/// - check epoch 3.2 is active
/// - TODO: check sip031 boot contract has a balance of 200_000_000 STX (TODO)
/// - check sip031 boot contract has a balance of 200_000_000 STX (TODO)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// - check sip031 boot contract has a balance of 200_000_000 STX (TODO)
/// - check sip031 boot contract has a balance of 200_000_000 STX

#[test]
#[ignore]
fn test_sip_031_activation() {
Expand Down Expand Up @@ -12756,6 +12760,44 @@ fn test_sip_031_activation() {

assert_eq!(epoch_version, Some(StacksEpochId::Epoch32));

// check if sip-031 boot contract has been deployed
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you also add a check that the liquid ustx supply has incremented correctly?

let sip_031_boot_contract_exists = chainstate.with_read_only_clarity_tx(
&sortdb
.index_handle_at_block(&chainstate, &latest_stacks_block_id)
.unwrap(),
&latest_stacks_block_id,
|conn| {
conn.with_clarity_db_readonly(|db| {
db.has_contract(&boot_code_id(SIP_031_NAME, naka_conf.is_mainnet()))
})
},
);

assert_eq!(sip_031_boot_contract_exists, Some(true));

// check if sip-031 boot contract has a balance of 200_000_000 STX
let sip_031_boot_contract_balance = chainstate.with_read_only_clarity_tx(
&sortdb
.index_handle_at_block(&chainstate, &latest_stacks_block_id)
.unwrap(),
&latest_stacks_block_id,
|conn| {
conn.with_clarity_db_readonly(|db| {
db.get_account_stx_balance(&PrincipalData::Contract(boot_code_id(
SIP_031_NAME,
naka_conf.is_mainnet(),
)))
})
},
);

assert_eq!(
sip_031_boot_contract_balance,
Some(Ok(STXBalance::Unlocked {
amount: SIP_031_INITIAL_MINT
}))
);

coord_channel
.lock()
.expect("Mutex poisoned")
Expand Down
2 changes: 2 additions & 0 deletions stackslib/src/chainstate/stacks/boot/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ pub const POX_4_NAME: &str = "pox-4";
pub const SIGNERS_NAME: &str = "signers";
pub const SIGNERS_VOTING_NAME: &str = "signers-voting";
pub const SIGNERS_VOTING_FUNCTION_NAME: &str = "vote-for-aggregate-public-key";
pub const SIP_031_NAME: &str = "sip-031";
/// This is the name of a variable in the `.signers` contract which tracks the most recently updated
/// reward cycle number.
pub const SIGNERS_UPDATE_STATE: &str = "last-set-cycle";
Expand All @@ -76,6 +77,7 @@ pub const SIGNERS_BODY: &str = std::include_str!("signers.clar");
pub const SIGNERS_DB_0_BODY: &str = std::include_str!("signers-0-xxx.clar");
pub const SIGNERS_DB_1_BODY: &str = std::include_str!("signers-1-xxx.clar");
pub const SIGNERS_VOTING_BODY: &str = std::include_str!("signers-voting.clar");
pub const SIP_031_BODY: &str = std::include_str!("sip-031.clar");

pub const COSTS_1_NAME: &str = "costs";
pub const COSTS_2_NAME: &str = "costs-2";
Expand Down
11 changes: 11 additions & 0 deletions stackslib/src/chainstate/stacks/boot/sip-031.clar
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
(define-data-var recipient principal 'ST000000000000000000002AMW42H)

(define-public (update-recipient (new-recipient principal)) (begin
(asserts! (is-eq tx-sender (var-get recipient)) (err u101))
(var-set recipient new-recipient)
(ok true)
)) ;; Returns (response bool uint)

(define-read-only (get-recipient) (ok (var-get recipient))) ;; Returns (response principal uint)

(define-public (claim) (ok true) ) ;; Returns (response uint uint)
89 changes: 86 additions & 3 deletions stackslib/src/clarity_vm/clarity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ use clarity::vm::database::{
RollbackWrapperPersistedLog, STXBalance, NULL_BURN_STATE_DB, NULL_HEADER_DB,
};
use clarity::vm::errors::Error as InterpreterError;
use clarity::vm::events::{STXEventType, STXMintEventData};
use clarity::vm::representations::SymbolicExpression;
use clarity::vm::types::{PrincipalData, QualifiedContractIdentifier, Value};
use clarity::vm::{ClarityVersion, ContractName};
Expand All @@ -42,7 +43,8 @@ use crate::chainstate::stacks::boot::{
BOOT_CODE_COST_VOTING_TESTNET as BOOT_CODE_COST_VOTING, BOOT_CODE_POX_TESTNET, COSTS_2_NAME,
COSTS_3_NAME, POX_2_MAINNET_CODE, POX_2_NAME, POX_2_TESTNET_CODE, POX_3_MAINNET_CODE,
POX_3_NAME, POX_3_TESTNET_CODE, POX_4_CODE, POX_4_NAME, SIGNERS_BODY, SIGNERS_DB_0_BODY,
SIGNERS_DB_1_BODY, SIGNERS_NAME, SIGNERS_VOTING_BODY, SIGNERS_VOTING_NAME,
SIGNERS_DB_1_BODY, SIGNERS_NAME, SIGNERS_VOTING_BODY, SIGNERS_VOTING_NAME, SIP_031_BODY,
SIP_031_NAME,
};
use crate::chainstate::stacks::db::{StacksAccount, StacksChainState};
use crate::chainstate::stacks::events::{StacksTransactionEvent, StacksTransactionReceipt};
Expand All @@ -57,6 +59,8 @@ use crate::util_lib::boot::{boot_code_acc, boot_code_addr, boot_code_id, boot_co
use crate::util_lib::db::Error as DatabaseError;
use crate::util_lib::strings::StacksString;

pub const SIP_031_INITIAL_MINT: u128 = 200_000_000_000_000;

///
/// A high-level interface for interacting with the Clarity VM.
///
Expand Down Expand Up @@ -1617,10 +1621,89 @@ impl<'a> ClarityBlockConnection<'a, '_> {
tx_conn.epoch = StacksEpochId::Epoch32;
});

// TODO: SIP-031 setup (minting and transfer to the boot contract)
let mut receipts = vec![];

let boot_code_account = self
.get_boot_code_account()
.expect("FATAL: did not get boot account");

let mainnet = self.mainnet;
let tx_version = if mainnet {
TransactionVersion::Mainnet
} else {
TransactionVersion::Testnet
};

let boot_code_address = boot_code_addr(mainnet);
let boot_code_auth = boot_code_tx_auth(boot_code_address.clone());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let boot_code_auth = boot_code_tx_auth(boot_code_address.clone());
let boot_code_auth = boot_code_tx_auth(boot_code_address);


// SIP-031 setup (deploy of the boot contract, minting and transfer to the boot contract)
let sip_031_contract_id = boot_code_id(SIP_031_NAME, mainnet);
let payload = TransactionPayload::SmartContract(
TransactionSmartContract {
name: ContractName::try_from(SIP_031_NAME)
.expect("FATAL: invalid boot-code contract name"),
code_body: StacksString::from_str(SIP_031_BODY)
.expect("FATAL: invalid boot code body"),
},
Some(ClarityVersion::Clarity3),
);

let sip_031_contract_tx =
StacksTransaction::new(tx_version.clone(), boot_code_auth, payload);

let mut sip_031_initialization_receipt = self.as_transaction(|tx_conn| {
// initialize with a synthetic transaction
debug!("Instantiate {} contract", &sip_031_contract_id);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might as well make this info! -- we only expect this to happen the one time.

let receipt = StacksChainState::process_transaction_payload(
tx_conn,
&sip_031_contract_tx,
&boot_code_account,
ASTRules::PrecheckSize,
None,
)
.expect("FATAL: Failed to process .sip031 contract initialization");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
.expect("FATAL: Failed to process .sip031 contract initialization");
.expect("FATAL: Failed to process .sip-031 contract initialization");

receipt
});

if sip_031_initialization_receipt.result != Value::okay_true()
|| sip_031_initialization_receipt.post_condition_aborted
{
panic!(
"FATAL: Failure processing sip031 contract initialization: {:#?}",
&sip_031_initialization_receipt
);
}

let recipient = PrincipalData::Contract(boot_code_id(SIP_031_NAME, mainnet));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let recipient = PrincipalData::Contract(boot_code_id(SIP_031_NAME, mainnet));
let recipient = PrincipalData::Contract(sip_031_contract_id);


self.as_transaction(|tx_conn| {
tx_conn
.with_clarity_db(|db| {
db.increment_ustx_liquid_supply(SIP_031_INITIAL_MINT)
.map_err(|e| e.into())
})
.expect("FATAL: `SIP-031 initial mint` overflowed");
StacksChainState::account_credit(
tx_conn,
&recipient,
u64::try_from(SIP_031_INITIAL_MINT)
.expect("FATAL: transferred more STX than exist"),
);
});

let event = STXEventType::STXMintEvent(STXMintEventData {
recipient,
amount: SIP_031_INITIAL_MINT,
});
sip_031_initialization_receipt
.events
.push(StacksTransactionEvent::STXEvent(event));

receipts.push(sip_031_initialization_receipt);

debug!("Epoch 3.2 initialized");
(old_cost_tracker, Ok(vec![]))
(old_cost_tracker, Ok(receipts))
})
}

Expand Down
Loading