diff --git a/bamboo-c/src/publish/error.rs b/bamboo-c/src/publish/error.rs index 99ecf0e51..fb51ab043 100644 --- a/bamboo-c/src/publish/error.rs +++ b/bamboo-c/src/publish/error.rs @@ -5,7 +5,7 @@ use bamboo_rs_core::entry::publish::Error as BambooPublishError; pub enum PublishError { NoError, - PublishWithoutKeypair, + PublishWithInvalidKeypair, PublishAfterEndOfFeed, PublishWithIncorrectLogId, PublishWithoutSecretKey, @@ -23,7 +23,6 @@ pub enum PublishError { impl From for PublishError { fn from(err: BambooPublishError) -> PublishError { match err { - BambooPublishError::PublishWithoutKeypair => PublishError::PublishWithoutKeypair, BambooPublishError::PublishAfterEndOfFeed => PublishError::PublishAfterEndOfFeed, BambooPublishError::PublishWithIncorrectBacklinkLogId => { PublishError::PublishWithIncorrectLogId @@ -41,10 +40,14 @@ impl From for PublishError { } BambooPublishError::PublishWithoutBacklinkEntry => { PublishError::PublishWithoutBacklinkEntry - }, + } BambooPublishError::DecodeLipmaaEntry { .. } => PublishError::DecodeLipmaaEntry, - BambooPublishError::PublishKeypairDidNotMatchBacklinkPublicKey => PublishError::PublishKeypairDidNotMatchBacklinkPublicKey, - BambooPublishError::PublishKeypairDidNotMatchLipmaaLinkPublicKey => PublishError::PublishKeypairDidNotMatchLipmaaLinkPublicKey, + BambooPublishError::PublishKeypairDidNotMatchBacklinkPublicKey => { + PublishError::PublishKeypairDidNotMatchBacklinkPublicKey + } + BambooPublishError::PublishKeypairDidNotMatchLipmaaLinkPublicKey => { + PublishError::PublishKeypairDidNotMatchLipmaaLinkPublicKey + } } } } diff --git a/bamboo-c/src/publish/mod.rs b/bamboo-c/src/publish/mod.rs index e137bcdab..3f666a557 100644 --- a/bamboo-c/src/publish/mod.rs +++ b/bamboo-c/src/publish/mod.rs @@ -57,12 +57,12 @@ pub extern "C" fn publish_ed25519_blake2b_entry( let key_pair = Keypair::from_bytes(&key_pair_bytes[..]); if let Err(_) = key_pair { - return PublishError::PublishWithoutKeypair; + return PublishError::PublishWithInvalidKeypair; } match publish( out, - Some(&key_pair.unwrap()), + &key_pair.unwrap(), args.log_id, payload, args.is_end_of_feed, diff --git a/bamboo-c/src/verify/error.rs b/bamboo-c/src/verify/error.rs index bd4c1137e..523385d51 100644 --- a/bamboo-c/src/verify/error.rs +++ b/bamboo-c/src/verify/error.rs @@ -57,7 +57,7 @@ impl From for VerifyError { BambooVerifyError::BacklinkAuthorDoesNotMatch => { VerifyError::BacklinkAuthorDoesNotMatch } - BambooVerifyError::UnknownError => VerifyError::UnknownError + BambooVerifyError::UnknownError => VerifyError::UnknownError, } } } diff --git a/bamboo-rs-cli/src/main.rs b/bamboo-rs-cli/src/main.rs index 82efaf16c..679b9ef3d 100644 --- a/bamboo-rs-cli/src/main.rs +++ b/bamboo-rs-cli/src/main.rs @@ -69,7 +69,7 @@ fn main() -> Result<()> { let entry_size = publish( &mut entry_buff, - Some(&key_pair), + &key_pair, log_id, &payload_bytes, is_end_of_feed, diff --git a/bamboo-rs-core-test/benches/bench.rs b/bamboo-rs-core-test/benches/bench.rs index 6744e8652..f7a4f09f9 100644 --- a/bamboo-rs-core-test/benches/bench.rs +++ b/bamboo-rs-core-test/benches/bench.rs @@ -26,7 +26,7 @@ fn encoding_benches(c: &mut Criterion) { let size = publish( &mut out, - Some(&key_pair), + &key_pair, 0, payload.as_bytes(), false, @@ -52,7 +52,7 @@ fn encoding_benches(c: &mut Criterion) { let size = publish( &mut out, - Some(&key_pair), + &key_pair, 0, payload.as_bytes(), false, @@ -78,7 +78,7 @@ fn publish_benches(c: &mut Criterion) { let size = publish( &mut out, - Some(&key_pair), + &key_pair, 0, payload.as_bytes(), false, @@ -92,7 +92,7 @@ fn publish_benches(c: &mut Criterion) { let mut out2 = [0u8; 512]; let _ = publish( &mut out2, - Some(&key_pair), + &key_pair, 0, payload.as_bytes(), false, @@ -115,7 +115,7 @@ fn verify_signature_benches(c: &mut Criterion) { let size = publish( &mut out, - Some(&key_pair), + &key_pair, 0, payload.as_bytes(), false, @@ -138,7 +138,7 @@ fn verify_signature_benches(c: &mut Criterion) { let size = publish( &mut out, - Some(&key_pair), + &key_pair, 0, payload.as_bytes(), false, diff --git a/bamboo-rs-core-test/src/entry/mod.rs b/bamboo-rs-core-test/src/entry/mod.rs index f37ea4ea5..13ba37ff5 100644 --- a/bamboo-rs-core-test/src/entry/mod.rs +++ b/bamboo-rs-core-test/src/entry/mod.rs @@ -88,7 +88,7 @@ mod tests { let size = publish( &mut out, - Some(&key_pair), + &key_pair, 0, payload.as_bytes(), false, @@ -112,7 +112,7 @@ mod tests { let size = publish( &mut out, - Some(&key_pair), + &key_pair, 0, payload.as_bytes(), false, @@ -125,7 +125,7 @@ mod tests { let mut out2 = [0u8; 512]; let size2 = publish( &mut out2, - Some(&key_pair), + &key_pair, 0, payload.as_bytes(), false, @@ -148,7 +148,7 @@ mod tests { let size = publish( &mut out, - Some(&key_pair), + &key_pair, 0, payload.as_bytes(), false, @@ -162,7 +162,7 @@ mod tests { match publish( &mut out2, - Some(&key_pair), + &key_pair, 0, payload.as_bytes(), false, @@ -184,7 +184,7 @@ mod tests { let size = publish( &mut out, - Some(&key_pair), + &key_pair, 0, payload.as_bytes(), false, @@ -198,7 +198,7 @@ mod tests { match publish( &mut out2, - Some(&key_pair), + &key_pair, 0, payload.as_bytes(), false, @@ -221,7 +221,7 @@ mod tests { let size = publish( &mut out, - Some(&key_pair), + &key_pair, 0, payload.as_bytes(), true, @@ -234,7 +234,7 @@ mod tests { let mut out2 = [0u8; 512]; match publish( &mut out2, - Some(&key_pair), + &key_pair, 0, payload.as_bytes(), false, @@ -256,7 +256,7 @@ mod tests { match publish( &mut out, - Some(&key_pair), + &key_pair, 0, payload.as_bytes(), false, @@ -269,25 +269,6 @@ mod tests { } } - #[test] - fn publish_without_secret_key_errors() { - let payload = "hello bamboo!"; - let mut out = [0u8; 512]; - - match publish( - &mut out, - None, - 0, - payload.as_bytes(), - false, - None, - None, - None, - ) { - Err(PublishError::PublishWithoutKeypair) => {} - _ => panic!(), - } - } #[test] fn publish_with_different_log_id_to_previous_errors() { let mut csprng: OsRng = OsRng {}; @@ -297,7 +278,7 @@ mod tests { let mut out = [0u8; 512]; let size = publish( &mut out, - Some(&key_pair), + &key_pair, 0, payload.as_bytes(), false, @@ -310,7 +291,7 @@ mod tests { let mut out2 = [0u8; 512]; match publish( &mut out2, - Some(&key_pair), + &key_pair, 1, payload.as_bytes(), false, @@ -333,7 +314,7 @@ mod tests { let size = publish( &mut out, - Some(&key_pair), + &key_pair, 0, payload.as_bytes(), false, @@ -362,7 +343,7 @@ mod tests { let size = publish( &mut out, - Some(&key_pair), + &key_pair, 0, payload.as_bytes(), false, @@ -375,7 +356,7 @@ mod tests { let mut out2 = [0u8; 512]; let size2 = publish( &mut out2, - Some(&key_pair), + &key_pair, 0, payload.as_bytes(), false, @@ -407,7 +388,7 @@ mod tests { let size = publish( &mut out, - Some(&key_pair), + &key_pair, 0, payload.as_bytes(), false, @@ -420,7 +401,7 @@ mod tests { let mut out2 = [0u8; 512]; let size2 = publish( &mut out2, - Some(&key_pair), + &key_pair, 0, payload.as_bytes(), false, @@ -454,7 +435,7 @@ mod tests { let size = publish( &mut out, - Some(&key_pair), + &key_pair, 0, payload.as_bytes(), false, @@ -467,7 +448,7 @@ mod tests { let mut out2 = [0u8; 512]; let size2 = publish( &mut out2, - Some(&key_pair), + &key_pair, 0, payload.as_bytes(), false, @@ -506,7 +487,7 @@ mod tests { let size = publish( &mut out, - Some(&key_pair), + &key_pair, 0, payload.as_bytes(), false, @@ -520,7 +501,7 @@ mod tests { let mut out2 = [0u8; 512]; publish( &mut out2, - Some(&key_pair), + &key_pair, 0, payload.as_bytes(), false, diff --git a/bamboo-rs-core/CHANGELOG.md b/bamboo-rs-core/CHANGELOG.md index e4180264b..a29c02e44 100644 --- a/bamboo-rs-core/CHANGELOG.md +++ b/bamboo-rs-core/CHANGELOG.md @@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.1.0-pre-30] - 2021-1-17 +### Changed +- change api of publish to take &Keypair, not Option<&Keypair> + ## [0.1.0-pre-29] - 2021-1-13 ### Changed - Move c bindings out into new module bamboo-c. Breaking change to name of libraries. diff --git a/bamboo-rs-core/Cargo.toml b/bamboo-rs-core/Cargo.toml index 8efebaea7..450990576 100644 --- a/bamboo-rs-core/Cargo.toml +++ b/bamboo-rs-core/Cargo.toml @@ -24,3 +24,6 @@ snafu = { version = "0.6.10", default-features = false } static_assertions = "0.3" varu64 = { version ="0.6.2", default-features = false } yamf-hash = { version = "0.1.2", default-features = false } + +[dev-dependencies] +rand = {version = "0.7.0", default-features = false} diff --git a/bamboo-rs-core/src/entry/decode/error.rs b/bamboo-rs-core/src/entry/decode/error.rs index 9632dfa2c..0cd4ad509 100644 --- a/bamboo-rs-core/src/entry/decode/error.rs +++ b/bamboo-rs-core/src/entry/decode/error.rs @@ -7,17 +7,13 @@ use yamf_hash::error::Error as YamfHashError; pub enum Error { #[snafu(display("Could not decode payload hash {}", source))] DecodePayloadHashError { source: YamfHashError }, - #[snafu(display( - "Could not decode payload size, error with varu64 encoding" - ))] + #[snafu(display("Could not decode payload size, error with varu64 encoding"))] DecodePayloadSizeError, #[snafu(display("Could not decode log_id, error with varu64 encoding"))] DecodeLogIdError, #[snafu(display("Could not decode author public key from bytes"))] DecodeAuthorError, - #[snafu(display( - "Could not decode entry sequence number, error with varu64 encoding" - ))] + #[snafu(display("Could not decode entry sequence number, error with varu64 encoding"))] DecodeSeqError, #[snafu(display("Entry sequence must be larger than 0 but was {}", seq_num))] DecodeSeqIsZero { seq_num: u64 }, diff --git a/bamboo-rs-core/src/entry/decode/mod.rs b/bamboo-rs-core/src/entry/decode/mod.rs index 4d247dedf..be0db30fc 100644 --- a/bamboo-rs-core/src/entry/decode/mod.rs +++ b/bamboo-rs-core/src/entry/decode/mod.rs @@ -6,11 +6,14 @@ use crate::signature::Signature; use crate::yamf_hash::YamfHash; use super::{is_lipmaa_required, Entry}; -use snafu::{ensure, ResultExt, NoneError}; +use snafu::{ensure, NoneError, ResultExt}; pub mod error; pub use error::*; +/// Try and decode `bytes` as an [Entry]. +/// +/// Returned [Entry] references `bytes`. pub fn decode<'a>(bytes: &'a [u8]) -> Result, Error> { ensure!(bytes.len() > 0, DecodeInputIsLengthZero); diff --git a/bamboo-rs-core/src/entry/encode/error.rs b/bamboo-rs-core/src/entry/encode/error.rs index bd2b7105c..a05671527 100644 --- a/bamboo-rs-core/src/entry/encode/error.rs +++ b/bamboo-rs-core/src/entry/encode/error.rs @@ -11,7 +11,9 @@ pub enum Error { EncodeLipmaaError { source: YamfHashError }, #[snafu(display("Encode back link to yamf hash failed: {}", source))] EncodeBacklinkError { source: YamfHashError }, - #[snafu(display("Lipmaa or backlinks were provided for first entry which should be impossible"))] + #[snafu(display( + "Lipmaa or backlinks were provided for first entry which should be impossible" + ))] EncodeEntryHasLinksWhenSeqZero, #[snafu(display("Encode payload size failed"))] EncodePayloadSizeError, diff --git a/bamboo-rs-core/src/entry/publish/error.rs b/bamboo-rs-core/src/entry/publish/error.rs index 395cfa734..fd204c156 100644 --- a/bamboo-rs-core/src/entry/publish/error.rs +++ b/bamboo-rs-core/src/entry/publish/error.rs @@ -13,24 +13,20 @@ pub enum Error { PublishWithIncorrectLipmaaLinkLogId, #[snafu(display("Attempting to publish using a keypair that does not have a secret key"))] PublishWithoutSecretKey, - #[snafu(display("Attempting to publish without a keypair"))] - PublishWithoutKeypair, #[snafu(display("Attempting to publish an entry with a different keypair than the backlink"))] PublishKeypairDidNotMatchBacklinkPublicKey, - #[snafu(display("Attempting to publish an entry with a different keypair than the lipmaa link"))] + #[snafu(display( + "Attempting to publish an entry with a different keypair than the lipmaa link" + ))] PublishKeypairDidNotMatchLipmaaLinkPublicKey, #[snafu(display("Attempting to publish an entry that needs a lipmaa link but None provided"))] PublishWithoutLipmaaEntry, #[snafu(display("Attempting to publish an entry that needs a backlink but None provided"))] PublishWithoutBacklinkEntry, #[snafu(display("Failed to decode backlink, encoding error: {}", source))] - DecodeBacklinkEntry { - source: EntryDecodeError, - }, + DecodeBacklinkEntry { source: EntryDecodeError }, #[snafu(display("Failed to decode lipmaa link, encoding error: {}", source))] - DecodeLipmaaEntry { - source: EntryDecodeError, - }, + DecodeLipmaaEntry { source: EntryDecodeError }, #[snafu(display( "Could not encode the entry into the out buffer. Buffer len: {}, Encoding error: {}", buffer_size, diff --git a/bamboo-rs-core/src/entry/publish/mod.rs b/bamboo-rs-core/src/entry/publish/mod.rs index adb4b0eb7..8e7febc84 100644 --- a/bamboo-rs-core/src/entry/publish/mod.rs +++ b/bamboo-rs-core/src/entry/publish/mod.rs @@ -10,26 +10,35 @@ use snafu::{ensure, ResultExt}; pub mod error; pub use error::*; +/// Publish a new entry into the `out` buffer. +/// +/// - `out`: A buffer to encode the entry into. Must be >= MAX_ENTRY_SIZE. +/// - `key_pair`: The ed25519 cryptographic key pair used to sign the entry. +/// - `log_id`: The integer that distinguishes different logs by the same author. +/// - `payload`: The payload of the entry. Note that only the hash of the payload becomes part of the entry. It's up to the caller to store the actual payload somewhere. +/// - `is_end_of_feed`: Is this entry the final entry for this `log_id`? +/// - `previous_seq_num`: The seq num of the previous entry. `None` if this is the first entry. +/// - `lipmaa_entry_bytes`: The encoded lipmaa_entry. `None` if this is the first entry. +/// - `backlink_bytes`: The encoded backlkink. `None` if this is the first entry. +/// +/// Returns a `Result` of the size of the entry encoded into `out`. pub fn publish( out: &mut [u8], - key_pair: Option<&Keypair>, + key_pair: &Keypair, log_id: u64, payload: &[u8], is_end_of_feed: bool, - last_seq_num: Option, + previous_seq_num: Option, lipmaa_entry_bytes: Option<&[u8]>, backlink_bytes: Option<&[u8]>, ) -> Result { - let author = key_pair - .as_ref() - .map(|keys| keys.public.clone()) - .ok_or(Error::PublishWithoutKeypair)?; + let author = key_pair.public; // calc the payload hash let payload_hash = new_blake2b(payload); let payload_size = payload.len() as u64; - let seq_num = last_seq_num.unwrap_or(0) + 1; + let seq_num = previous_seq_num.unwrap_or(0) + 1; let mut entry: Entry<_, &[u8]> = Entry { log_id, @@ -45,7 +54,6 @@ pub fn publish( // if the seq is larger than 1, we need to append the lipmaa and backlink hashes. if seq_num > 1 { - let backlink_entry = decode(&backlink_bytes.ok_or(Error::PublishWithoutBacklinkEntry)?[..]) .context(DecodeBacklinkEntry)?; @@ -55,16 +63,28 @@ pub fn publish( ensure!(!backlink_entry.is_end_of_feed, PublishAfterEndOfFeed); // Avoid publishing to a feed using an incorrect log_id - ensure!(log_id == backlink_entry.log_id, PublishWithIncorrectBacklinkLogId); - - // Avoid publishing using a different public key to the backlink - ensure!(author == backlink_entry.author, PublishKeypairDidNotMatchBacklinkPublicKey); - - // Avoid publishing using a different public key to the lipmaa link - ensure!(author == lipmaa_entry.author, PublishKeypairDidNotMatchBacklinkPublicKey); + ensure!( + log_id == backlink_entry.log_id, + PublishWithIncorrectBacklinkLogId + ); + + // Avoid publishing using a different public key to the backlink + ensure!( + author == backlink_entry.author, + PublishKeypairDidNotMatchBacklinkPublicKey + ); + + // Avoid publishing using a different public key to the lipmaa link + ensure!( + author == lipmaa_entry.author, + PublishKeypairDidNotMatchBacklinkPublicKey + ); // Avoid publishing to a feed using an incorrect log_id - ensure!(log_id == lipmaa_entry.log_id, PublishWithIncorrectLipmaaLinkLogId); + ensure!( + log_id == lipmaa_entry.log_id, + PublishWithIncorrectLipmaaLinkLogId + ); let backlink = new_blake2b(backlink_bytes.ok_or(Error::PublishWithoutBacklinkEntry)?); entry.backlink = Some(backlink); @@ -72,8 +92,8 @@ pub fn publish( // If the lipmaalink and backlink would be different, we should append the lipmaalink, // otherwise we're allowed to omit it to save some bytes. if is_lipmaa_required(seq_num) { - - let lipmaa_link = new_blake2b(lipmaa_entry_bytes.ok_or(Error::PublishWithoutLipmaaEntry)?); + let lipmaa_link = + new_blake2b(lipmaa_entry_bytes.ok_or(Error::PublishWithoutLipmaaEntry)?); entry.lipmaa_link = Some(lipmaa_link); } } @@ -82,10 +102,7 @@ pub fn publish( buffer_size: out.len(), })?; - let signature = key_pair - .as_ref() - .ok_or(Error::PublishWithoutSecretKey)? - .sign(&out[..buff_size]); + let signature = key_pair.sign(&out[..buff_size]); let sig_bytes = &signature.to_bytes()[..]; let signature = Signature(sig_bytes.into()); diff --git a/bamboo-rs-core/src/entry/verify/error.rs b/bamboo-rs-core/src/entry/verify/error.rs index 6a0626645..9c69edab0 100644 --- a/bamboo-rs-core/src/entry/verify/error.rs +++ b/bamboo-rs-core/src/entry/verify/error.rs @@ -13,11 +13,17 @@ pub enum Error { PayloadHashDidNotMatch {}, #[snafu(display("The payload length encoded in the entry (expected) does not match the payload provided (actual). Expected: {}, actual: {}", expected, actual))] PayloadLengthDidNotMatch { actual: usize, expected: u64 }, - #[snafu(display("The lipmaa hash encoded in the entry does not match the lipmaa entry provided"))] + #[snafu(display( + "The lipmaa hash encoded in the entry does not match the lipmaa entry provided" + ))] LipmaaHashDoesNotMatch {}, #[snafu(display("Decode lipmaa entry failed: {}", source))] DecodeLipmaaEntry { source: DecodeError }, - #[snafu(display("Lipmaa entry log_id does not match entry log_id: entry log_id: {}, lipmaa log_id: {}", expected, actual))] + #[snafu(display( + "Lipmaa entry log_id does not match entry log_id: entry log_id: {}, lipmaa log_id: {}", + expected, + actual + ))] LipmaaLogIdDoesNotMatch { actual: u64, expected: u64 }, #[snafu(display("Lipmaa author does not match entry author"))] LipmaaAuthorDoesNotMatch {}, @@ -25,13 +31,19 @@ pub enum Error { LipmaaLinkRequired, #[snafu(display("Failed to decode backlink entry: {}", source))] DecodeBacklinkEntry { source: DecodeError }, - #[snafu(display("Backlink entry log_id does not match entry log_id: entry log_id: {}, lipmaa log_id: {}", expected, actual))] + #[snafu(display( + "Backlink entry log_id does not match entry log_id: entry log_id: {}, lipmaa log_id: {}", + expected, + actual + ))] BacklinkLogIdDoesNotMatch { actual: u64, expected: u64 }, #[snafu(display("Backlink author does not match entry author"))] BacklinkAuthorDoesNotMatch, #[snafu(display("Entry was published after the feed was declared ended by setting the `is_end_of_feed` bit in a previous message"))] PublishedAfterEndOfFeed, - #[snafu(display("The backlink hash encoded in the entry does not match the lipmaa entry provided"))] + #[snafu(display( + "The backlink hash encoded in the entry does not match the lipmaa entry provided" + ))] BacklinkHashDoesNotMatch {}, #[snafu(display("Backlink link required but not provided"))] BackLinkRequired, diff --git a/bamboo-rs-core/src/entry/verify/mod.rs b/bamboo-rs-core/src/entry/verify/mod.rs index 4bb4d09e2..16d089d48 100644 --- a/bamboo-rs-core/src/entry/verify/mod.rs +++ b/bamboo-rs-core/src/entry/verify/mod.rs @@ -140,6 +140,19 @@ pub fn verify_links_and_payload( Ok(()) } +/// verify `entry_bytes` is valid. +/// +/// - `entry_bytes`: bytes of an encoded bamboo entry to verify. +/// - `payload`: [Option] of the payload bytes. It's ok to omit the payload if you don't have it +/// (happens when doing partial replication.) +/// - `lipmaa_link`: [Option] of the lipmaa_link bytes. Will be none when `entry_bytes` is the first entry. +/// - `backlink`: [Option] of the backlink bytes. Will be none when `entry_bytes` is the first entry. +/// +/// Verfies: +/// - the cryptographic signature +/// - the hash of `payload` matches what's encoded in `entry_bytes` (if provided). +/// - the chain of hashes formed from this entry back to the `backlink` and `lipmaa_link`. +/// pub fn verify( entry_bytes: &[u8], payload: Option<&[u8]>, diff --git a/bamboo-rs-core/src/lib.rs b/bamboo-rs-core/src/lib.rs index 13de95bf9..04f438251 100644 --- a/bamboo-rs-core/src/lib.rs +++ b/bamboo-rs-core/src/lib.rs @@ -1,8 +1,60 @@ //! # bamboo-rs-core //! -//! Verify, and Publish [bamboo](https://github.com/AljoschaMeyer/bamboo) messages. +//! Verify, Publish and Decode [bamboo](https://github.com/AljoschaMeyer/bamboo) entries. //! +//! ## About //! +//! From the [spec](https://github.com/AljoschaMeyer/bamboo): +//! +//! > A cryptographically secure, distributed, single-writer append-only log that supports transitive partial replication and local deletion of data. +//! > +//! > Powered by science, this log format can serve as a more efficient alternative to secure-scuttlebutt's linked lists or hypercore's merkle forests. +//! +//! `bamboo-rs-core` exposes low level functions and types which can be built with `no_std`. +//! +//! ## Example +//! +//! [publish](publish()), [verify](verify()) and [decode](decode()) the first [Entry] in a bamboo log. +//! +//! NB: Publishing and verifying the first entry is the most simple case. The subsequent entries +//! require passing the previous seq_num, the previous entry, and lipmaa_link. +//! +//! ``` +//! use bamboo_rs_core::{publish, verify, decode, yamf_hash::new_blake2b, Entry, Signature, YamfHash, Keypair, entry::MAX_ENTRY_SIZE}; +//! use rand::rngs::OsRng; +//! +//! let mut csprng: OsRng = OsRng {}; +//! let key_pair: Keypair = Keypair::generate(&mut csprng); +//! let log_id = 0; +//! +//! let payload = "hello bamboo!"; +//! let mut out = [0u8; MAX_ENTRY_SIZE]; +//! +//! let size = publish( +//! &mut out, +//! &key_pair, +//! log_id, +//! payload.as_bytes(), +//! false, +//! None, +//! None, +//! None, +//! ) +//! .unwrap(); +//! +//! let entry = decode(&out[..size]).unwrap(); +//! +//! let is_verified = verify(&out[..size], Some(payload.as_bytes()), None, None).is_ok(); +//! let payload_hash = new_blake2b(payload.as_bytes()); +//! +//! assert!(is_verified); +//! assert_eq!(entry.log_id, log_id); +//! assert_eq!(entry.payload_hash, payload_hash); +//! assert_eq!(entry.author, key_pair.public); +//! assert_eq!(entry.lipmaa_link, None); +//! assert_eq!(entry.backlink, None); +//! assert_eq!(entry.is_end_of_feed, false); +//! ``` #![cfg_attr(not(feature = "std"), no_std)] #[macro_use] diff --git a/bamboo-rs-log/src/log/error.rs b/bamboo-rs-log/src/log/error.rs index 7b9784a1f..d57721758 100644 --- a/bamboo-rs-log/src/log/error.rs +++ b/bamboo-rs-log/src/log/error.rs @@ -17,4 +17,5 @@ pub enum Error { PublishEntryGetBacklinkEntry{source: ES::Error}, PublishNewEntryFailed{source: PublishError}, PublishEntryAppendFailed{source: ES::Error}, + PublishWithoutKeypair, } diff --git a/bamboo-rs-log/src/log/publish.rs b/bamboo-rs-log/src/log/publish.rs index 8c56b108a..71404aa04 100644 --- a/bamboo-rs-log/src/log/publish.rs +++ b/bamboo-rs-log/src/log/publish.rs @@ -3,7 +3,7 @@ use lipmaa_link::lipmaa; use crate::entry_store::EntryStore; use bamboo_rs_core::entry::publish; -use snafu::ResultExt; +use snafu::{ResultExt, OptionExt}; use super::Log; use super::error::*; @@ -12,6 +12,7 @@ impl Log { pub fn publish(&mut self, payload: &[u8], is_end_of_feed: bool) -> Result<(), Error> { let mut buff = [0u8; 512]; + let key_pair = self.key_pair.as_ref().context(PublishWithoutKeypair)?; let last_seq_num = self.store.get_last_seq(); let seq_num = last_seq_num.unwrap_or(0) + 1; let lipmaa_link_seq = lipmaa(seq_num); @@ -28,7 +29,7 @@ impl Log { let length = publish( &mut buff, - self.key_pair.as_ref(), + key_pair, self.log_id, payload, is_end_of_feed, diff --git a/bamboo-wasm/src/lib.rs b/bamboo-wasm/src/lib.rs index 18a55f844..eff9833cc 100644 --- a/bamboo-wasm/src/lib.rs +++ b/bamboo-wasm/src/lib.rs @@ -147,7 +147,6 @@ pub fn publish( lipmaa_entry_vec: Option>, backlink_vec: Option>, ) -> Result, JsValue> { - let mut out = Vec::with_capacity(bamboo_rs_core::entry::MAX_ENTRY_SIZE); out.resize(bamboo_rs_core::entry::MAX_ENTRY_SIZE, 0); @@ -164,7 +163,7 @@ pub fn publish( publish_entry( &mut out[..], - Some(&key_pair), + &key_pair, log_id, payload, is_end_of_feed, @@ -177,7 +176,6 @@ pub fn publish( out.truncate(entry_size); out }) - } //TODO: keygen.