mirror of
https://github.com/alexgo-io/stacks-puppet-node.git
synced 2026-04-29 04:05:21 +08:00
PR review feedback
This commit is contained in:
@@ -541,13 +541,13 @@ operations on Bitcoin as well as on the Stacks blockchain. The Stacks
|
|||||||
chain also allows addresses to submit STX transfers on the Bitcoin
|
chain also allows addresses to submit STX transfers on the Bitcoin
|
||||||
chain. Such operations are only evaluated by the miner of an anchor block
|
chain. Such operations are only evaluated by the miner of an anchor block
|
||||||
elected in the burn block that immediately follows the burn block that included the
|
elected in the burn block that immediately follows the burn block that included the
|
||||||
operations. For example, if a TransferStxOp occurs in burnchain block 100, then the
|
operations. For example, if a `TransferStxOp` occurs in burnchain block 100, then the
|
||||||
Stacks block elected by burnchain block 101 will process that transfer.
|
Stacks block elected by burnchain block 101 will process that transfer.
|
||||||
|
|
||||||
In order to submit on the Bitcoin chain, stackers must submit two Bitcoin transactions:
|
In order to submit on the Bitcoin chain, stackers must submit two Bitcoin transactions:
|
||||||
|
|
||||||
* `PreStxOp`: this operation prepares the Stacks blockchain node to validate the subsequent
|
* `PreStxOp`: this operation prepares the Stacks blockchain node to validate the subsequent
|
||||||
StackStxOp or TransferStxOp.
|
`StackStxOp` or `TransferStxOp`.
|
||||||
* `StackStxOp`: this operation executes the `stack-stx` operation.
|
* `StackStxOp`: this operation executes the `stack-stx` operation.
|
||||||
* `TransferStxOp`: this operation transfers STX from a sender to a recipient
|
* `TransferStxOp`: this operation transfers STX from a sender to a recipient
|
||||||
|
|
||||||
@@ -606,4 +606,6 @@ Where `op = $` (ascii encoded).
|
|||||||
|
|
||||||
Where the unsigned integer is big-endian encoded.
|
Where the unsigned integer is big-endian encoded.
|
||||||
|
|
||||||
The second Bitcoin output is the B58-encoding of the recipient Stacks address.
|
The second Bitcoin output is either a `p2pkh` or `p2sh` output such
|
||||||
|
that the recipient Stacks address can be derived from the
|
||||||
|
corresponding 20-byte hash (hash160).
|
||||||
|
|||||||
@@ -520,6 +520,9 @@ impl BitcoinTxInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn to_txid(txin: &BtcTxIn) -> (Txid, u32) {
|
fn to_txid(txin: &BtcTxIn) -> (Txid, u32) {
|
||||||
|
// bitcoin-rs library (which deps::bitcoin is based on)
|
||||||
|
// operates in a different endian-ness for txids than the rest of
|
||||||
|
// the codebase. so this method reverses the txid bits.
|
||||||
let mut bits = txin.previous_output.txid.0.clone();
|
let mut bits = txin.previous_output.txid.0.clone();
|
||||||
bits.reverse();
|
bits.reverse();
|
||||||
(Txid(bits), txin.previous_output.vout)
|
(Txid(bits), txin.previous_output.vout)
|
||||||
|
|||||||
@@ -641,7 +641,7 @@ impl Burnchain {
|
|||||||
|
|
||||||
/// Try to parse a burnchain transaction into a Blockstack operation
|
/// Try to parse a burnchain transaction into a Blockstack operation
|
||||||
/// `pre_stx_op_map` should contain any valid PreStxOps that occurred before
|
/// `pre_stx_op_map` should contain any valid PreStxOps that occurred before
|
||||||
/// the currently-being-evaluated tx.
|
/// the currently-being-evaluated tx in the same burn block.
|
||||||
pub fn classify_transaction(
|
pub fn classify_transaction(
|
||||||
burnchain_db: &BurnchainDB,
|
burnchain_db: &BurnchainDB,
|
||||||
block_header: &BurnchainBlockHeader,
|
block_header: &BurnchainBlockHeader,
|
||||||
|
|||||||
@@ -146,7 +146,6 @@ impl TransferStxOp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// parse a StackStxOp
|
/// parse a StackStxOp
|
||||||
/// `pox_sunset_ht` is the height at which PoX *disables*
|
|
||||||
pub fn parse_from_tx(
|
pub fn parse_from_tx(
|
||||||
block_height: u64,
|
block_height: u64,
|
||||||
block_hash: &BurnchainHeaderHash,
|
block_hash: &BurnchainHeaderHash,
|
||||||
|
|||||||
@@ -1718,50 +1718,54 @@ fn test_stx_transfer_btc_ops() {
|
|||||||
let stacks_tip =
|
let stacks_tip =
|
||||||
SortitionDB::get_canonical_stacks_chain_tip_hash(sort_db.conn()).unwrap();
|
SortitionDB::get_canonical_stacks_chain_tip_hash(sort_db.conn()).unwrap();
|
||||||
let mut chainstate = get_chainstate(path);
|
let mut chainstate = get_chainstate(path);
|
||||||
let (sender_balance, burn_height) = chainstate.with_read_only_clarity_tx(
|
let (sender_balance, burn_height) = chainstate
|
||||||
&sort_db.index_conn(),
|
.with_read_only_clarity_tx(
|
||||||
&StacksBlockId::new(&stacks_tip.0, &stacks_tip.1),
|
&sort_db.index_conn(),
|
||||||
|conn| {
|
&StacksBlockId::new(&stacks_tip.0, &stacks_tip.1),
|
||||||
conn.with_clarity_db_readonly(|db| {
|
|conn| {
|
||||||
(
|
conn.with_clarity_db_readonly(|db| {
|
||||||
db.get_account_stx_balance(&stacker.clone().into()),
|
(
|
||||||
db.get_current_block_height(),
|
db.get_account_stx_balance(&stacker.clone().into()),
|
||||||
)
|
db.get_current_block_height(),
|
||||||
})
|
)
|
||||||
},
|
})
|
||||||
);
|
},
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let (recipient_balance, burn_height) = chainstate.with_read_only_clarity_tx(
|
let (recipient_balance, burn_height) = chainstate
|
||||||
&sort_db.index_conn(),
|
.with_read_only_clarity_tx(
|
||||||
&StacksBlockId::new(&stacks_tip.0, &stacks_tip.1),
|
&sort_db.index_conn(),
|
||||||
|conn| {
|
&StacksBlockId::new(&stacks_tip.0, &stacks_tip.1),
|
||||||
conn.with_clarity_db_readonly(|db| {
|
|conn| {
|
||||||
(
|
conn.with_clarity_db_readonly(|db| {
|
||||||
db.get_account_stx_balance(&recipient.clone().into()),
|
(
|
||||||
db.get_current_block_height(),
|
db.get_account_stx_balance(&recipient.clone().into()),
|
||||||
)
|
db.get_current_block_height(),
|
||||||
})
|
)
|
||||||
},
|
})
|
||||||
);
|
},
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
if ix > 2 {
|
if ix > 2 {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
sender_balance.get_available_balance_at_block(burn_height as u64),
|
sender_balance.get_available_balance_at_burn_block(burn_height as u64),
|
||||||
(balance as u128) - transfer_amt,
|
(balance as u128) - transfer_amt,
|
||||||
"Transfer should have decremented balance"
|
"Transfer should have decremented balance"
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
recipient_balance.get_available_balance_at_block(burn_height as u64),
|
recipient_balance.get_available_balance_at_burn_block(burn_height as u64),
|
||||||
transfer_amt,
|
transfer_amt,
|
||||||
"Recipient should have incremented balance"
|
"Recipient should have incremented balance"
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
sender_balance.get_available_balance_at_block(burn_height as u64),
|
sender_balance.get_available_balance_at_burn_block(burn_height as u64),
|
||||||
balance as u128,
|
balance as u128,
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
recipient_balance.get_available_balance_at_block(burn_height as u64),
|
recipient_balance.get_available_balance_at_burn_block(burn_height as u64),
|
||||||
0,
|
0,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1814,17 +1818,19 @@ fn test_stx_transfer_btc_ops() {
|
|||||||
let stacks_tip = SortitionDB::get_canonical_stacks_chain_tip_hash(sort_db.conn()).unwrap();
|
let stacks_tip = SortitionDB::get_canonical_stacks_chain_tip_hash(sort_db.conn()).unwrap();
|
||||||
let mut chainstate = get_chainstate(path);
|
let mut chainstate = get_chainstate(path);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
chainstate.with_read_only_clarity_tx(
|
chainstate
|
||||||
&sort_db.index_conn(),
|
.with_read_only_clarity_tx(
|
||||||
&StacksBlockId::new(&stacks_tip.0, &stacks_tip.1),
|
&sort_db.index_conn(),
|
||||||
|conn| conn
|
&StacksBlockId::new(&stacks_tip.0, &stacks_tip.1),
|
||||||
.with_readonly_clarity_env(
|
|conn| conn
|
||||||
PrincipalData::parse("SP3Q4A5WWZ80REGBN0ZXNE540ECJ9JZ4A765Q5K2Q").unwrap(),
|
.with_readonly_clarity_env(
|
||||||
LimitedCostTracker::new_free(),
|
PrincipalData::parse("SP3Q4A5WWZ80REGBN0ZXNE540ECJ9JZ4A765Q5K2Q").unwrap(),
|
||||||
|env| env.eval_raw("block-height")
|
LimitedCostTracker::new_free(),
|
||||||
)
|
|env| env.eval_raw("block-height")
|
||||||
.unwrap()
|
)
|
||||||
),
|
.unwrap()
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
Value::UInt(50)
|
Value::UInt(50)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -3793,44 +3793,43 @@ impl StacksChainState {
|
|||||||
clarity_tx: &mut ClarityTx,
|
clarity_tx: &mut ClarityTx,
|
||||||
operations: Vec<TransferStxOp>,
|
operations: Vec<TransferStxOp>,
|
||||||
) -> Vec<StacksTransactionReceipt> {
|
) -> Vec<StacksTransactionReceipt> {
|
||||||
let mut all_receipts = vec![];
|
let (all_receipts, _) =
|
||||||
// NOTE: do _not_ return from this function without replacing this original tracker
|
clarity_tx.with_temporary_cost_tracker(LimitedCostTracker::new_free(), |clarity_tx| {
|
||||||
let original_tracker = clarity_tx.set_cost_tracker(LimitedCostTracker::new_free());
|
operations
|
||||||
for transfer_stx_op in operations.into_iter() {
|
.into_iter()
|
||||||
let TransferStxOp {
|
.filter_map(|transfer_stx_op| {
|
||||||
sender,
|
let TransferStxOp {
|
||||||
recipient,
|
sender,
|
||||||
transfered_ustx,
|
recipient,
|
||||||
txid,
|
transfered_ustx,
|
||||||
burn_header_hash,
|
txid,
|
||||||
..
|
burn_header_hash,
|
||||||
} = transfer_stx_op;
|
..
|
||||||
let result = clarity_tx.connection().as_transaction(|tx| {
|
} = transfer_stx_op;
|
||||||
tx.run_stx_transfer(&sender.into(), &recipient.into(), transfered_ustx)
|
let result = clarity_tx.connection().as_transaction(|tx| {
|
||||||
|
tx.run_stx_transfer(&sender.into(), &recipient.into(), transfered_ustx)
|
||||||
|
});
|
||||||
|
match result {
|
||||||
|
Ok((value, _, events)) => Some(StacksTransactionReceipt {
|
||||||
|
transaction: TransactionOrigin::Burn(txid),
|
||||||
|
events,
|
||||||
|
result: value,
|
||||||
|
post_condition_aborted: false,
|
||||||
|
stx_burned: 0,
|
||||||
|
contract_analysis: None,
|
||||||
|
execution_cost: ExecutionCost::zero(),
|
||||||
|
}),
|
||||||
|
Err(e) => {
|
||||||
|
info!("TransferStx burn op processing error.";
|
||||||
|
"error" => ?e,
|
||||||
|
"txid" => %txid,
|
||||||
|
"burn_block" => %burn_header_hash);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
});
|
});
|
||||||
match result {
|
|
||||||
Ok((value, _, events)) => {
|
|
||||||
let receipt = StacksTransactionReceipt {
|
|
||||||
transaction: TransactionOrigin::Burn(txid),
|
|
||||||
events,
|
|
||||||
result: value,
|
|
||||||
post_condition_aborted: false,
|
|
||||||
stx_burned: 0,
|
|
||||||
contract_analysis: None,
|
|
||||||
execution_cost: ExecutionCost::zero(),
|
|
||||||
};
|
|
||||||
all_receipts.push(receipt);
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
info!("TransferStx burn op processing error.";
|
|
||||||
"error" => ?e,
|
|
||||||
"txid" => %txid,
|
|
||||||
"burn_block" => %burn_header_hash);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
clarity_tx.set_cost_tracker(original_tracker);
|
|
||||||
|
|
||||||
all_receipts
|
all_receipts
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -302,12 +302,28 @@ impl<'a> ClarityTx<'a> {
|
|||||||
self.block.cost_so_far()
|
self.block.cost_so_far()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// set the clarity tx's cost tracker
|
/// Set the ClarityTx's cost tracker.
|
||||||
/// returns the replaced cost tracker
|
/// Returns the replaced cost tracker.
|
||||||
pub fn set_cost_tracker(&mut self, new_tracker: LimitedCostTracker) -> LimitedCostTracker {
|
fn set_cost_tracker(&mut self, new_tracker: LimitedCostTracker) -> LimitedCostTracker {
|
||||||
self.block.set_cost_tracker(new_tracker)
|
self.block.set_cost_tracker(new_tracker)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Run `todo` in this ClarityTx with `new_tracker`.
|
||||||
|
/// Returns the result of `todo` and the `new_tracker`
|
||||||
|
pub fn with_temporary_cost_tracker<F, R>(
|
||||||
|
&mut self,
|
||||||
|
new_tracker: LimitedCostTracker,
|
||||||
|
todo: F,
|
||||||
|
) -> (R, LimitedCostTracker)
|
||||||
|
where
|
||||||
|
F: FnOnce(&mut ClarityTx) -> R,
|
||||||
|
{
|
||||||
|
let original_tracker = self.set_cost_tracker(new_tracker);
|
||||||
|
let result = todo(self);
|
||||||
|
let new_tracker = self.set_cost_tracker(original_tracker);
|
||||||
|
(result, new_tracker)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub fn commit_block(self) -> () {
|
pub fn commit_block(self) -> () {
|
||||||
self.block.commit_block();
|
self.block.commit_block();
|
||||||
|
|||||||
@@ -1074,10 +1074,6 @@ impl InitializedNeonNode {
|
|||||||
debug!("Using key {:?}", &key.vrf_public_key);
|
debug!("Using key {:?}", &key.vrf_public_key);
|
||||||
// sleep a little before building the anchor block, to give any broadcasted
|
// sleep a little before building the anchor block, to give any broadcasted
|
||||||
// microblocks time to propagate.
|
// microblocks time to propagate.
|
||||||
info!(
|
|
||||||
"Sleeping {} before issuing tenure",
|
|
||||||
self.sleep_before_tenure
|
|
||||||
);
|
|
||||||
thread::sleep(std::time::Duration::from_millis(self.sleep_before_tenure));
|
thread::sleep(std::time::Duration::from_millis(self.sleep_before_tenure));
|
||||||
self.relay_channel
|
self.relay_channel
|
||||||
.send(RelayerDirective::RunTenure(key.clone(), burnchain_tip))
|
.send(RelayerDirective::RunTenure(key.clone(), burnchain_tip))
|
||||||
|
|||||||
Reference in New Issue
Block a user