Skip to content

Commit 175a85d

Browse files
committed
Add block_pre_commit table and update schema version to 17
Signed-off-by: Jacinta Ferrant <[email protected]>
1 parent 8c8e44f commit 175a85d

File tree

1 file changed

+130
-1
lines changed

1 file changed

+130
-1
lines changed

stacks-signer/src/signerdb.rs

Lines changed: 130 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -673,6 +673,18 @@ CREATE TABLE IF NOT EXISTS block_rejection_signer_addrs (
673673
PRIMARY KEY (signer_signature_hash, signer_addr)
674674
) STRICT;"#;
675675

676+
static CREATE_BLOCK_PRE_COMMITS_TABLE: &str = r#"
677+
CREATE TABLE IF NOT EXISTS block_pre_commits (
678+
-- The block sighash commits to all of the stacks and burnchain state as of its parent,
679+
-- as well as the tenure itself so there's no need to include the reward cycle. Just
680+
-- the sighash is sufficient to uniquely identify the block across all burnchain, PoX,
681+
-- and stacks forks.
682+
signer_signature_hash TEXT NOT NULL,
683+
-- signer address committing to sign the block
684+
signer_addr TEXT NOT NULL,
685+
PRIMARY KEY (signer_signature_hash, signer_addr)
686+
) STRICT;"#;
687+
676688
static SCHEMA_1: &[&str] = &[
677689
DROP_SCHEMA_0,
678690
CREATE_DB_CONFIG,
@@ -786,6 +798,11 @@ static SCHEMA_16: &[&str] = &[
786798
"INSERT INTO db_config (version) VALUES (16);",
787799
];
788800

801+
static SCHEMA_17: &[&str] = &[
802+
CREATE_BLOCK_PRE_COMMITS_TABLE,
803+
"INSERT INTO db_config (version) VALUES (17);",
804+
];
805+
789806
struct Migration {
790807
version: u32,
791808
statements: &'static [&'static str],
@@ -856,11 +873,15 @@ static MIGRATIONS: &[Migration] = &[
856873
version: 16,
857874
statements: SCHEMA_16,
858875
},
876+
Migration {
877+
version: 17,
878+
statements: SCHEMA_17,
879+
},
859880
];
860881

861882
impl SignerDb {
862883
/// The current schema version used in this build of the signer binary.
863-
pub const SCHEMA_VERSION: u32 = 16;
884+
pub const SCHEMA_VERSION: u32 = 17;
864885

865886
/// Create a new `SignerState` instance.
866887
/// This will create a new SQLite database at the given path
@@ -1821,6 +1842,62 @@ impl SignerDb {
18211842

18221843
Ok(None)
18231844
}
1845+
1846+
/// Record an observed block pre commit
1847+
pub fn add_block_pre_commit(
1848+
&self,
1849+
block_sighash: &Sha512Trunc256Sum,
1850+
address: &StacksAddress,
1851+
) -> Result<(), DBError> {
1852+
let qry = "INSERT OR REPLACE INTO block_pre_commits (signer_signature_hash, signer_addr) VALUES (?1, ?2);";
1853+
let args = params![block_sighash, address.to_string()];
1854+
1855+
debug!("Inserting block pre commit.";
1856+
"signer_signature_hash" => %block_sighash,
1857+
"signer_addr" => %address);
1858+
1859+
self.db.execute(qry, args)?;
1860+
Ok(())
1861+
}
1862+
1863+
/// Check if the given address has already committed to sign the block identified by block_sighash
1864+
pub fn has_committed(
1865+
&self,
1866+
block_sighash: &Sha512Trunc256Sum,
1867+
address: &StacksAddress,
1868+
) -> Result<bool, DBError> {
1869+
let qry_check = "
1870+
SELECT 1 FROM block_pre_commits
1871+
WHERE signer_signature_hash = ?1 AND signer_addr = ?2
1872+
LIMIT 1;";
1873+
1874+
let exists: Option<u8> = self
1875+
.db
1876+
.query_row(
1877+
qry_check,
1878+
params![block_sighash, address.to_string()],
1879+
|row| row.get(0),
1880+
)
1881+
.optional()?;
1882+
1883+
Ok(exists.is_some())
1884+
}
1885+
1886+
/// Get all pre committers for a block
1887+
pub fn get_block_pre_committers(
1888+
&self,
1889+
block_sighash: &Sha512Trunc256Sum,
1890+
) -> Result<Vec<StacksAddress>, DBError> {
1891+
let qry = "SELECT signer_addr FROM block_pre_commits WHERE signer_signature_hash = ?1";
1892+
let args = params![block_sighash];
1893+
let addrs_txt: Vec<String> = query_rows(&self.db, qry, args)?;
1894+
1895+
let res: Result<Vec<_>, _> = addrs_txt
1896+
.into_iter()
1897+
.map(|addr| StacksAddress::from_string(&addr).ok_or(DBError::Corruption))
1898+
.collect();
1899+
res
1900+
}
18241901
}
18251902

18261903
fn try_deserialize<T>(s: Option<String>) -> Result<Option<T>, DBError>
@@ -3381,4 +3458,56 @@ pub mod tests {
33813458

33823459
assert!(result_3.is_none());
33833460
}
3461+
3462+
#[test]
3463+
fn insert_and_get_state_block_pre_commits() {
3464+
let db_path = tmp_db_path();
3465+
let db = SignerDb::new(db_path).expect("Failed to create signer db");
3466+
let block_sighash1 = Sha512Trunc256Sum([1u8; 32]);
3467+
let address1 = StacksAddress::p2pkh(
3468+
false,
3469+
&StacksPublicKey::from_private(&StacksPrivateKey::random()),
3470+
);
3471+
let block_sighash2 = Sha512Trunc256Sum([2u8; 32]);
3472+
let address2 = StacksAddress::p2pkh(
3473+
false,
3474+
&StacksPublicKey::from_private(&StacksPrivateKey::random()),
3475+
);
3476+
let address3 = StacksAddress::p2pkh(
3477+
false,
3478+
&StacksPublicKey::from_private(&StacksPrivateKey::random()),
3479+
);
3480+
assert!(db
3481+
.get_block_pre_committers(&block_sighash1)
3482+
.unwrap()
3483+
.is_empty());
3484+
3485+
db.add_block_pre_commit(&block_sighash1, &address1).unwrap();
3486+
assert_eq!(
3487+
db.get_block_pre_committers(&block_sighash1).unwrap(),
3488+
vec![address1]
3489+
);
3490+
3491+
db.add_block_pre_commit(&block_sighash1, &address2).unwrap();
3492+
let commits = db.get_block_pre_committers(&block_sighash1).unwrap();
3493+
assert_eq!(commits.len(), 2);
3494+
assert!(commits.contains(&address2));
3495+
assert!(commits.contains(&address1));
3496+
3497+
db.add_block_pre_commit(&block_sighash2, &address3).unwrap();
3498+
let commits = db.get_block_pre_committers(&block_sighash1).unwrap();
3499+
assert_eq!(commits.len(), 2);
3500+
assert!(commits.contains(&address2));
3501+
assert!(commits.contains(&address1));
3502+
let commits = db.get_block_pre_committers(&block_sighash2).unwrap();
3503+
assert_eq!(commits.len(), 1);
3504+
assert!(commits.contains(&address3));
3505+
3506+
assert!(db.has_committed(&block_sighash1, &address1).unwrap());
3507+
assert!(db.has_committed(&block_sighash1, &address2).unwrap());
3508+
assert!(!db.has_committed(&block_sighash1, &address3).unwrap());
3509+
assert!(!db.has_committed(&block_sighash2, &address1).unwrap());
3510+
assert!(!db.has_committed(&block_sighash2, &address2).unwrap());
3511+
assert!(db.has_committed(&block_sighash2, &address3).unwrap());
3512+
}
33843513
}

0 commit comments

Comments
 (0)