Skip to content

Commit 2e67706

Browse files
jferranthstove
authored andcommitted
Add StateMachineUpdateContent::V1 which inculdes a vector of replay_transactions
Signed-off-by: Jacinta Ferrant <jacinta.ferrant@gmail.com>
1 parent 2bea12c commit 2e67706

File tree

9 files changed

+284
-57
lines changed

9 files changed

+284
-57
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ and this project adheres to the versioning scheme outlined in the [README.md](RE
77

88
## [Unreleased]
99

10+
### Added
11+
12+
- Added new `ValidateRejectCode` values to the `/v3/block_proposal` endpoint
13+
- Added `StateMachineUpdateContent::V1` to support a vector of `StacksTransaction` expected to be replayed in subsequent Stacks blocks
14+
1015
### Changed
1116

1217
- Reduce the default `block_rejection_timeout_steps` configuration so that miners will retry faster when blocks fail to reach 70% approved or 30% rejected.

libsigner/src/v0/messages.rs

Lines changed: 120 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,17 @@ pub enum StateMachineUpdateContent {
571571
/// The signer's view of who the current miner should be (and their tenure building info)
572572
current_miner: StateMachineUpdateMinerState,
573573
},
574+
/// Version 1
575+
V1 {
576+
/// The tip burn block (i.e., the latest bitcoin block) seen by this signer
577+
burn_block: ConsensusHash,
578+
/// The tip burn block height (i.e., the latest bitcoin block) seen by this signer
579+
burn_block_height: u64,
580+
/// The signer's view of who the current miner should be (and their tenure building info)
581+
current_miner: StateMachineUpdateMinerState,
582+
/// The replay transactions
583+
replay_transactions: Vec<StacksTransaction>,
584+
},
574585
}
575586

576587
/// Message for update the Signer State infos
@@ -676,6 +687,7 @@ impl StateMachineUpdateContent {
676687
fn is_protocol_version_compatible(&self, version: u64) -> bool {
677688
match self {
678689
Self::V0 { .. } => version == 0,
690+
Self::V1 { .. } => version == 1,
679691
}
680692
}
681693

@@ -690,6 +702,17 @@ impl StateMachineUpdateContent {
690702
burn_block_height.consensus_serialize(fd)?;
691703
current_miner.consensus_serialize(fd)?;
692704
}
705+
Self::V1 {
706+
burn_block,
707+
burn_block_height,
708+
current_miner,
709+
replay_transactions,
710+
} => {
711+
burn_block.consensus_serialize(fd)?;
712+
burn_block_height.consensus_serialize(fd)?;
713+
current_miner.consensus_serialize(fd)?;
714+
replay_transactions.consensus_serialize(fd)?;
715+
}
693716
}
694717
Ok(())
695718
}
@@ -705,6 +728,18 @@ impl StateMachineUpdateContent {
705728
current_miner,
706729
})
707730
}
731+
1 => {
732+
let burn_block = read_next(fd)?;
733+
let burn_block_height = read_next(fd)?;
734+
let current_miner = read_next(fd)?;
735+
let replay_transactions = read_next(fd)?;
736+
Ok(Self::V1 {
737+
burn_block,
738+
burn_block_height,
739+
current_miner,
740+
replay_transactions,
741+
})
742+
}
708743
other => Err(CodecError::DeserializeError(format!(
709744
"Unknown state machine update version: {other}"
710745
))),
@@ -1716,15 +1751,17 @@ impl From<StateMachineUpdate> for SignerMessage {
17161751
mod test {
17171752
use blockstack_lib::chainstate::nakamoto::NakamotoBlockHeader;
17181753
use blockstack_lib::chainstate::stacks::{
1719-
TransactionAnchorMode, TransactionAuth, TransactionPayload, TransactionPostConditionMode,
1720-
TransactionSmartContract, TransactionVersion,
1754+
TransactionAnchorMode, TransactionAuth, TransactionContractCall, TransactionPayload,
1755+
TransactionPostConditionMode, TransactionSmartContract, TransactionSpendingCondition,
1756+
TransactionVersion,
17211757
};
17221758
use blockstack_lib::util_lib::strings::StacksString;
17231759
use clarity::consts::CHAIN_ID_MAINNET;
1724-
use clarity::types::chainstate::{ConsensusHash, StacksBlockId, TrieHash};
1760+
use clarity::types::chainstate::{ConsensusHash, StacksAddress, StacksBlockId, TrieHash};
17251761
use clarity::types::PrivateKey;
17261762
use clarity::util::hash::{hex_bytes, MerkleTree};
17271763
use clarity::util::secp256k1::MessageSignature;
1764+
use clarity::vm::{ClarityName, ContractName};
17281765
use rand::rngs::mock;
17291766
use rand::{thread_rng, Rng, RngCore};
17301767
use rand_core::OsRng;
@@ -2316,4 +2353,84 @@ mod test {
23162353

23172354
assert_eq!(signer_message, signer_message_deserialized);
23182355
}
2356+
2357+
#[test]
2358+
fn deserialize_state_machine_update_v1() {
2359+
let signer_message = StateMachineUpdate::new(
2360+
1,
2361+
3,
2362+
StateMachineUpdateContent::V1 {
2363+
burn_block: ConsensusHash([0x55; 20]),
2364+
burn_block_height: 100,
2365+
current_miner: StateMachineUpdateMinerState::ActiveMiner {
2366+
current_miner_pkh: Hash160([0xab; 20]),
2367+
tenure_id: ConsensusHash([0x44; 20]),
2368+
parent_tenure_id: ConsensusHash([0x22; 20]),
2369+
parent_tenure_last_block: StacksBlockId([0x33; 32]),
2370+
parent_tenure_last_block_height: 1,
2371+
},
2372+
replay_transactions: vec![],
2373+
},
2374+
)
2375+
.unwrap();
2376+
2377+
let mut bytes = vec![];
2378+
signer_message.consensus_serialize(&mut bytes).unwrap();
2379+
2380+
// check for raw content for avoiding regressions when structure changes
2381+
let raw_signer_message: Vec<&[u8]> = vec![
2382+
/* active_signer_protocol_version*/ &[0, 0, 0, 0, 0, 0, 0, 1],
2383+
/* local_supported_signer_protocol_version*/ &[0, 0, 0, 0, 0, 0, 0, 3],
2384+
/* content_len*/ &[0, 0, 0, 133],
2385+
/* burn_block*/ &[0x55; 20],
2386+
/* burn_block_height*/ &[0, 0, 0, 0, 0, 0, 0, 100],
2387+
/* current_miner_variant */ &[0x01],
2388+
/* current_miner_pkh */ &[0xab; 20],
2389+
/* tenure_id*/ &[0x44; 20],
2390+
/* parent_tenure_id*/ &[0x22; 20],
2391+
/* parent_tenure_last_block */ &[0x33; 32],
2392+
/* parent_tenure_last_block_height*/ &[0, 0, 0, 0, 0, 0, 0, 1],
2393+
/* replay_transactions */ &[0, 0, 0, 0],
2394+
];
2395+
2396+
assert_eq!(bytes, raw_signer_message.concat());
2397+
2398+
let signer_message_deserialized =
2399+
StateMachineUpdate::consensus_deserialize(&mut &bytes[..]).unwrap();
2400+
2401+
assert_eq!(signer_message, signer_message_deserialized);
2402+
2403+
let signer_message = StateMachineUpdate::new(
2404+
1,
2405+
4,
2406+
StateMachineUpdateContent::V1 {
2407+
burn_block: ConsensusHash([0x55; 20]),
2408+
burn_block_height: 100,
2409+
current_miner: StateMachineUpdateMinerState::NoValidMiner,
2410+
replay_transactions: vec![],
2411+
},
2412+
)
2413+
.unwrap();
2414+
2415+
let mut bytes = vec![];
2416+
signer_message.consensus_serialize(&mut bytes).unwrap();
2417+
2418+
// check for raw content for avoiding regressions when structure changes
2419+
let raw_signer_message: Vec<&[u8]> = vec![
2420+
/* active_signer_protocol_version*/ &[0, 0, 0, 0, 0, 0, 0, 1],
2421+
/* local_supported_signer_protocol_version*/ &[0, 0, 0, 0, 0, 0, 0, 4],
2422+
/* content_len*/ &[0, 0, 0, 33],
2423+
/* burn_block*/ &[0x55; 20],
2424+
/* burn_block_height*/ &[0, 0, 0, 0, 0, 0, 0, 100],
2425+
/* current_miner_variant */ &[0x00],
2426+
/* replay_transactions */ &[0, 0, 0, 0],
2427+
];
2428+
2429+
assert_eq!(bytes, raw_signer_message.concat());
2430+
2431+
let signer_message_deserialized =
2432+
StateMachineUpdate::consensus_deserialize(&mut &bytes[..]).unwrap();
2433+
2434+
assert_eq!(signer_message, signer_message_deserialized);
2435+
}
23192436
}

stacks-signer/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to the versioning scheme outlined in the [README.md](README.md).
77

8+
## [Unreleased]
9+
10+
### Changed
11+
12+
- Upgraded `SUPPORTED_SIGNER_PROTOCOL_VERSION` to 1
13+
814
## [3.1.0.0.8.0]
915

1016
### Changed

stacks-signer/src/client/stacks_client.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,7 @@ impl StacksClient {
463463
return Err(ClientError::RequestFailure(response.status()));
464464
}
465465
let sortition_info = response.json::<Vec<SortitionInfo>>()?;
466-
sortition_info.get(0).cloned().ok_or_else(|| {
466+
sortition_info.first().cloned().ok_or_else(|| {
467467
ClientError::InvalidResponse("No sortition info found for given consensus hash".into())
468468
})
469469
}

stacks-signer/src/signerdb.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@ use std::time::{Duration, SystemTime};
2121

2222
use blockstack_lib::chainstate::nakamoto::NakamotoBlock;
2323
use blockstack_lib::chainstate::stacks::TransactionPayload;
24+
#[cfg(any(test, feature = "testing"))]
25+
use blockstack_lib::util_lib::db::FromColumn;
2426
use blockstack_lib::util_lib::db::{
2527
query_row, query_rows, sqlite_open, table_exists, tx_begin_immediate, u64_to_sql,
26-
Error as DBError,
28+
Error as DBError, FromRow,
2729
};
28-
#[cfg(any(test, feature = "testing"))]
29-
use blockstack_lib::util_lib::db::{FromColumn, FromRow};
3030
use clarity::types::chainstate::{BurnchainHeaderHash, StacksAddress};
3131
use clarity::types::Address;
3232
use libsigner::v0::messages::{RejectReason, RejectReasonPrefix, StateMachineUpdate};

stacks-signer/src/tests/signer_state.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,10 @@ fn determine_latest_supported_signer_protocol_versions() {
8484
current_miner,
8585
},
8686
..
87-
} = local_update.clone();
87+
} = local_update.clone()
88+
else {
89+
panic!("Unexpected state machine update message version");
90+
};
8891

8992
// Let's update 3 signers (60 percent) to support seperate but greater protocol versions
9093
for (i, address) in addresses.into_iter().skip(1).take(3).enumerate() {
@@ -151,7 +154,10 @@ fn determine_global_burn_views() {
151154
current_miner,
152155
},
153156
..
154-
} = local_update.clone();
157+
} = local_update.clone()
158+
else {
159+
panic!("Unexpected state machine update message version");
160+
};
155161

156162
assert_eq!(
157163
global_eval
@@ -212,7 +218,10 @@ fn determine_global_states() {
212218
current_miner,
213219
},
214220
..
215-
} = local_update.clone();
221+
} = local_update.clone()
222+
else {
223+
panic!("Unexpected state machine update message version");
224+
};
216225

217226
let state_machine = SignerStateMachine {
218227
burn_block,
@@ -297,7 +306,10 @@ fn check_capitulate_miner_view() {
297306
current_miner,
298307
},
299308
..
300-
} = local_update.clone();
309+
} = local_update.clone()
310+
else {
311+
panic!("Unexpected state machine update message version");
312+
};
301313
// Let's create a new miner view
302314
let new_tenure_id = ConsensusHash([0x00; 20]);
303315
let new_miner = StateMachineUpdateMinerState::ActiveMiner {

0 commit comments

Comments
 (0)