-
Notifications
You must be signed in to change notification settings - Fork 0
feat(proto): add sign_digest() to commit and vote extension #20
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
Merged
Merged
Changes from 2 commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
45014e9
refactor(proto)!: replace flex_error with thiserror
lklimek 6947580
feat(proto): add sign_bytes() to commit and vote
lklimek 5de378e
Revert "refactor(proto)!: replace flex_error with thiserror"
lklimek c3a731a
chore(proto): adjust errors
lklimek d08bf1e
feat(proto): impl SignBytes for VoteExtension
lklimek f2287f8
refactor(proto): delete SignContext
lklimek 2325088
feat(proto): add SignDigest trait for commit
lklimek 8b890fb
chore(proto): sign_digest borrows quorum hash
lklimek ae1a809
test(proto): test sign_digest()
lklimek 4793aa6
fix(proto): writing &Vec instead of &[\_]
lklimek 648c35e
chore(proto): self-review
lklimek ad697e3
chore(proto): make SignBytes public for tests
lklimek File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,197 @@ | ||
| use alloc::{string::String, vec::Vec}; | ||
|
|
||
| use bytes::BufMut; | ||
| use prost::Message; | ||
|
|
||
| use crate::{ | ||
| types::{BlockId, CanonicalBlockId, Commit, SignedMsgType, StateId, Vote}, | ||
| Error, | ||
| }; | ||
|
|
||
| #[derive(Clone, Debug)] | ||
| pub struct SignContext { | ||
| pub chain_id: String, | ||
| } | ||
|
|
||
| impl SignContext {} | ||
| pub trait SignBytes { | ||
| /// Generate bytes that will be signed. | ||
| fn sign_bytes(&self, ctx: &SignContext) -> Result<Vec<u8>, Error>; | ||
|
|
||
| /// Generate hash of data to sign | ||
| fn sha256(&self, ctx: &SignContext) -> Result<Vec<u8>, Error> { | ||
| // todo!() | ||
| let sb = self.sign_bytes(ctx)?; | ||
| let result = lhash::sha256(&sb); | ||
| Ok(Vec::from(result)) | ||
| } | ||
| } | ||
|
|
||
| impl SignBytes for StateId { | ||
| fn sign_bytes(&self, _ctx: &SignContext) -> Result<Vec<u8>, Error> { | ||
| let mut buf = Vec::new(); | ||
| self.encode_length_delimited(&mut buf) | ||
| .map_err(Error::EncodeMessage)?; | ||
|
|
||
| Ok(buf.to_vec()) | ||
| } | ||
| } | ||
|
|
||
| impl SignBytes for BlockId { | ||
| fn sign_bytes(&self, _ctx: &SignContext) -> Result<Vec<u8>, Error> { | ||
| let part_set_header = self.part_set_header.clone().unwrap_or_default(); | ||
|
|
||
| let block_id = CanonicalBlockId { | ||
| hash: self.hash.clone(), | ||
| part_set_header: Some(crate::types::CanonicalPartSetHeader { | ||
| total: part_set_header.total, | ||
| hash: part_set_header.hash, | ||
| }), | ||
| }; | ||
| let mut buf = Vec::new(); | ||
| block_id | ||
| .encode_length_delimited(&mut buf) | ||
| .map_err(Error::EncodeMessage)?; | ||
|
|
||
| Ok(buf) | ||
| } | ||
| } | ||
|
|
||
| impl SignBytes for Vote { | ||
| fn sign_bytes(&self, ctx: &SignContext) -> Result<Vec<u8>, Error> { | ||
| let block_id = self | ||
| .block_id | ||
| .clone() | ||
| .ok_or(Error::CreateCanonical(String::from( | ||
| "missing vote.block id", | ||
| )))?; | ||
|
|
||
| vote_sign_bytes(ctx, block_id, self.r#type, self.height, self.round as i64) | ||
| } | ||
| } | ||
|
|
||
| impl SignBytes for Commit { | ||
| fn sign_bytes(&self, ctx: &SignContext) -> Result<Vec<u8>, Error> { | ||
| // we just use some rough guesstimate of intial capacity | ||
| let block_id = self | ||
| .block_id | ||
| .clone() | ||
| .ok_or(Error::CreateCanonical(String::from( | ||
| "missing vote.block id", | ||
| )))?; | ||
|
|
||
| vote_sign_bytes( | ||
| ctx, | ||
| block_id, | ||
| SignedMsgType::Precommit.into(), | ||
| self.height, | ||
| self.round as i64, | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| /// Generate sign bytes for a vote / commit | ||
| /// | ||
| /// See https://github.com/dashpay/tenderdash/blob/bcb623bcf002ac54b26ed1324b98116872dd0da7/proto/tendermint/types/types.go#L56 | ||
| fn vote_sign_bytes( | ||
| ctx: &SignContext, | ||
| block_id: BlockId, | ||
| vote_type: i32, | ||
| height: i64, | ||
| round: i64, | ||
| ) -> Result<Vec<u8>, Error> { | ||
| // we just use some rough guesstimate of intial capacity | ||
| let mut buf = Vec::with_capacity(80); | ||
|
|
||
| let state_id = block_id.state_id.clone(); | ||
| let block_id = block_id.sha256(ctx)?; | ||
|
|
||
| buf.put_i32_le(vote_type.into()); | ||
| buf.put_i64_le(height); | ||
| buf.put_i64_le(round); | ||
|
|
||
| buf.extend(block_id); | ||
| buf.extend(state_id); | ||
| buf.put(ctx.chain_id.as_bytes()); | ||
|
|
||
| Ok(buf.to_vec()) | ||
| } | ||
|
|
||
| #[cfg(test)] | ||
| pub mod tests { | ||
| use alloc::string::ToString; | ||
|
|
||
| use super::SignBytes; | ||
| use crate::types::{Commit, PartSetHeader, SignedMsgType, Vote}; | ||
|
|
||
| #[test] | ||
| /// Compare sign bytes for Vote with sign bytes generated by Tenderdash and | ||
| /// put into `expect_sign_bytes`. | ||
| fn vote_sign_bytes() { | ||
| let h = [1u8, 2, 3, 4].repeat(8); | ||
|
|
||
| let state_id_hash = | ||
| hex::decode("d7509905b5407ee72dadd93b4ae70a24ad8a7755fc677acd2b215710a05cfc47") | ||
| .unwrap(); | ||
| let expect_sign_bytes = hex::decode("0100000001000000000000000200000000000000fb\ | ||
| 7c89bf010a91d50f890455582b7fed0c346e53ab33df7da0bcd85c10fa92ead7509905b5407ee72dadd93b\ | ||
| 4ae70a24ad8a7755fc677acd2b215710a05cfc47736f6d652d636861696e") | ||
| .unwrap(); | ||
|
|
||
| let vote = Vote { | ||
| r#type: SignedMsgType::Prevote as i32, | ||
| height: 1, | ||
| round: 2, | ||
| block_id: Some(crate::types::BlockId { | ||
| hash: h.clone(), | ||
| part_set_header: Some(PartSetHeader { | ||
| total: 1, | ||
| hash: h.clone(), | ||
| }), | ||
| state_id: state_id_hash, | ||
| }), | ||
| ..Default::default() | ||
| }; | ||
| let ctx = super::SignContext { | ||
| chain_id: "some-chain".to_string(), | ||
| }; | ||
|
|
||
| let actual = vote.sign_bytes(&ctx).unwrap(); | ||
|
|
||
| assert_eq!(expect_sign_bytes, actual); | ||
| } | ||
|
|
||
| #[test] | ||
| fn commit_sign_bytes() { | ||
| let h = [1u8, 2, 3, 4].repeat(8); | ||
|
|
||
| let state_id_hash = | ||
| hex::decode("d7509905b5407ee72dadd93b4ae70a24ad8a7755fc677acd2b215710a05cfc47") | ||
| .unwrap(); | ||
| let expect_sign_bytes = hex::decode("0200000001000000000000000200000000000000fb7c89bf010a91d5\ | ||
| 0f890455582b7fed0c346e53ab33df7da0bcd85c10fa92ead7509905b5407ee72dadd93b4ae70a24ad8a7755fc677acd2b215710\ | ||
| a05cfc47736f6d652d636861696e") | ||
| .unwrap(); | ||
|
|
||
| let commit = Commit { | ||
| height: 1, | ||
| round: 2, | ||
| block_id: Some(crate::types::BlockId { | ||
| hash: h.clone(), | ||
| part_set_header: Some(PartSetHeader { | ||
| total: 1, | ||
| hash: h.clone(), | ||
| }), | ||
| state_id: state_id_hash, | ||
| }), | ||
| ..Default::default() | ||
| }; | ||
| let ctx = super::SignContext { | ||
| chain_id: "some-chain".to_string(), | ||
| }; | ||
|
|
||
| let actual = commit.sign_bytes(&ctx).unwrap(); | ||
|
|
||
| assert_eq!(expect_sign_bytes, actual); | ||
| } | ||
| } | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.