Implement keetanetwork-block crate with block and operation types#3
Implement keetanetwork-block crate with block and operation types#3
Conversation
keetanetwork-block/src/types.rs
Outdated
| /// Ed25519: 32-byte pubkey | ||
| pub const ED25519: u8 = 0x01; | ||
| /// secp256r1 (NIST P-256): 33-byte compressed pubkey | ||
| pub const SECP256R1: u8 = 0x02; |
There was a problem hiding this comment.
| pub const SECP256R1: u8 = 0x02; | |
| pub const SECP256R1: u8 = 0x06; |
keetanetwork-block/src/types.rs
Outdated
| /// Destination account | ||
| pub to: &'a [u8], | ||
| /// Amount to send | ||
| pub amount: u64, |
There was a problem hiding this comment.
The amount may exceed u64's range and a bigint type is really required
Same is true of all below
There was a problem hiding this comment.
This types are shared with a Ledger device app (no_std, no alloc). I'm already using &'a [u8] for addresses, tokens, and other fields to reference the raw DER bytes directly (zero-copy). The same approach works for integers, &'a [u8] stores the big-endian DER integer bytes, representing arbitrary-precision values without allocation.
There was a problem hiding this comment.
He is referring to amount which will overflow.
There was a problem hiding this comment.
Would https://github.com/RustCrypto/crypto-bigint work? PS, this is re-exported in keetanetwork-crypto.
There was a problem hiding this comment.
From docs.keeta.com/components/ledger: "balances are maintained on a per-token basis on each account and are maintained as an arbitrary large big integer." but in other 3rd-party websites like https://coingecko.com/learn/what-is-keeta-network I can see "KTA is the native token of the Keeta Network and the backbone of its economy. It has a fixed maximum supply of 1 billion tokens" in this case we can safely use crypto-bigint U128
There was a problem hiding this comment.
That only refers to that native KTA token, other tokens exist on the network.
There was a problem hiding this comment.
In this case, we will get back to the reference approach since all crypto-bigint types are limited.
There was a problem hiding this comment.
Pull request overview
This PR introduces a new keetanetwork-block crate that provides foundational block and operation type definitions for the Keeta blockchain. The implementation emphasizes zero-copy design with lifetime parameters to support no_std environments while maintaining flexibility through optional alloc and std features.
Changes:
- Added shared type definitions for blocks (V1 and V2) and all 11 blockchain operations
- Implemented address validation based on algorithm prefix (secp256k1, Ed25519, secp256r1)
- Configured feature flags to support
no_std,alloc, andstdenvironments
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| keetanetwork-block/Cargo.toml | Defines feature flags for std/alloc/no_std support and removes unused dependencies |
| keetanetwork-block/src/lib.rs | Exports public API with conditional compilation for alloc-dependent types |
| keetanetwork-block/src/types.rs | Implements all block types, operation structures, and address validation logic |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
@rkeene do you suggest to put the remaining types here or in different PR? |
keetanetwork-block/src/types.rs
Outdated
| #[derive(Debug, Clone, Copy, PartialEq, Eq)] | ||
| pub enum AdjustMethod { | ||
| Add, | ||
| Remove, |
There was a problem hiding this comment.
The TS uses Subtract not Remove. We should probably keep the naming consistent.
There was a problem hiding this comment.
ASN.1 uses Remove instead of Subtract, I was confused by this one too.
There was a problem hiding this comment.
should I change it for AdjustMethodRelative too?
There was a problem hiding this comment.
Yes, naming should be the same
| pub struct BlockHeader<'a> { | ||
| /// Network ID | ||
| pub network: u64, | ||
| /// Subnet ID (optional) | ||
| pub subnet: Option<u64>, | ||
| /// Idempotent key for deduplication (optional) | ||
| pub idempotent: Option<&'a [u8]>, | ||
| /// Date as GeneralizedTime raw bytes | ||
| pub date: &'a [u8], | ||
| /// Block purpose (V2 only, defaults to Generic for V1) | ||
| pub purpose: BlockPurpose, | ||
| /// Account public key with type prefix | ||
| pub account: &'a [u8], | ||
| /// Signer public key with type prefix (may be same as account) | ||
| pub signer: &'a [u8], | ||
| /// Previous block hash (32 bytes) | ||
| pub previous: &'a [u8], | ||
| } |
There was a problem hiding this comment.
The signatures are currently missing. Is this going to be added later?
There was a problem hiding this comment.
I will add signatures next
keetanetwork-block/src/types.rs
Outdated
| /// [5] TOKEN_ADMIN_SUPPLY operation - Modify token supply | ||
| #[derive(Debug, Clone, Copy)] | ||
| pub struct TokenAdminSupplyOp<'a> { | ||
| /// Amount to modify | ||
| pub amount: &'a [u8], | ||
| /// Method (add/remove/set) | ||
| pub method: AdjustMethod, | ||
| } | ||
|
|
||
| /// [6] TOKEN_MODIFY_BALANCE operation - Modify account token balance | ||
| #[derive(Debug, Clone)] | ||
| pub struct TokenModifyBalanceOp<'a> { | ||
| /// Token to modify balance of | ||
| pub token: &'a [u8], | ||
| /// Amount to modify | ||
| pub amount: &'a [u8], | ||
| /// Method (add/remove/set) | ||
| pub method: AdjustMethod, | ||
| } | ||
|
|
There was a problem hiding this comment.
You used TOKEN_ADMIN_SUPPLY but not TOKEN_ADMIN_MODIFY_BALANCE. We could probably make it consistent.
I think it's fine to include that change in this PR since it's a dependency -- otherwise you would need to re-org and re-base but without much gained from it here. |
keetanetwork-block/src/types.rs
Outdated
| impl From<u8> for AdjustMethodRelative { | ||
| fn from(value: u8) -> Self { | ||
| match value { | ||
| 0 => AdjustMethodRelative::Add, | ||
| 1 => AdjustMethodRelative::Remove, | ||
| n => AdjustMethodRelative::Unknown(n), | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
This should reject/throw since its invalid otherwise
There was a problem hiding this comment.
It cannot so it will need to be a TryFrom instead.
There was a problem hiding this comment.
I used TryFrom instead
keetanetwork-block/src/types.rs
Outdated
| #[derive(Debug, Clone)] | ||
| pub enum Operation<'a> { | ||
| /// [0] Send tokens | ||
| Send(SendOp<'a>), | ||
| /// [1] Set representative | ||
| SetRep(SetRepOp<'a>), | ||
| /// [2] Set account info | ||
| SetInfo(SetInfoOp<'a>), | ||
| /// [3] Modify permissions | ||
| ModifyPermissions(ModifyPermissionsOp<'a>), | ||
| /// [4] Create identifier (token, multisig, swap) | ||
| CreateIdentifier(CreateIdentifierOp<'a>), | ||
| /// [5] Token admin supply | ||
| TokenAdminSupply(TokenAdminSupplyOp<'a>), | ||
| /// [6] Token modify balance | ||
| TokenModifyBalance(TokenModifyBalanceOp<'a>), | ||
| /// [7] Receive tokens | ||
| Receive(ReceiveOp<'a>), | ||
| /// [8] Manage certificate | ||
| ManageCertificate(ManageCertificateOp<'a>), | ||
| /// [9] Match swap | ||
| MatchSwap(MatchSwapOp<'a>), | ||
| /// [10] Cancel swap | ||
| CancelSwap(CancelSwapOp<'a>), | ||
| /// Unknown operation type | ||
| Unknown(u32), |
There was a problem hiding this comment.
The operation IDs would need to be explicitly defined with implemented DER.
There was a problem hiding this comment.
Moreover, I don't know if this would work as expected. We would need explicit context tagging.
There was a problem hiding this comment.
I plan to address that by adding #[derive(Choice)] with #[asn1(context_specific = "N")] attributes - the der crate handles explicit tagging automatically
| pub enum AdjustMethodRelative { | ||
| Add, | ||
| Remove, | ||
| Unknown(u8), | ||
| } |
There was a problem hiding this comment.
I am not sure this is a good approach. We should just return Result instead when using an unsupported AdjustMethod.
keetanetwork-block/src/types.rs
Outdated
| 0 => AdjustMethod::Add, | ||
| 1 => AdjustMethod::Remove, | ||
| 2 => AdjustMethod::Set, | ||
| n => AdjustMethod::Unknown(n), |
There was a problem hiding this comment.
We should return Result not use Unknown.
keetanetwork-block/src/types.rs
Outdated
| pub fn new(header: BlockHeader<'a>, operations: Vec<Operation<'a>>) -> Self { | ||
| Self { version: BlockVersion::V1, header, operations } | ||
| } | ||
|
|
||
| /// Create a new V2 block | ||
| pub fn new_v2(header: BlockHeader<'a>, operations: Vec<Operation<'a>>) -> Self { | ||
| Self { version: BlockVersion::V2, header, operations } | ||
| } |
There was a problem hiding this comment.
We may want a KeetaBlockBuilder instead of new_v*
let block = KeetaBlockBuilder::from(BlockVersion::V*)
.with_block_header(header)
.with_operations(operations)
.build();
Something like so.
There was a problem hiding this comment.
I added KeetaBlockBuilder but I set header in constructor since it's not optional for both versions
keetanetwork-block/src/types.rs
Outdated
| pub enum BlockPurpose { | ||
| Generic, | ||
| Fee, | ||
| Unknown(u8), |
There was a problem hiding this comment.
There should be no Unknowns.
keetanetwork-block/src/types.rs
Outdated
| /// Expected key sizes (prefix + pubkey) | ||
| const SECP256K1_KEY_SIZE: usize = 34; // 1 + 33 | ||
| const ED25519_KEY_SIZE: usize = 33; // 1 + 32 | ||
| const SECP256R1_KEY_SIZE: usize = 34; // 1 + 33 |
There was a problem hiding this comment.
These things should probably be in keetanetwork-crypto if they are not already.
There was a problem hiding this comment.
We can feature gate minimal items like constants and utils
keetanetwork-block/src/types.rs
Outdated
| pub fn is_valid_address(addr: &[u8]) -> bool { | ||
| if addr.is_empty() { | ||
| return false; | ||
| } | ||
| match addr[0] { | ||
| algo_prefix::SECP256K1 => addr.len() == SECP256K1_KEY_SIZE, | ||
| algo_prefix::ED25519 => addr.len() == ED25519_KEY_SIZE, | ||
| algo_prefix::SECP256R1 => addr.len() == SECP256R1_KEY_SIZE, | ||
| _ => false, // Unknown algorithm prefix | ||
| } | ||
| } |
There was a problem hiding this comment.
This should also probably be in keetanetwork-accounts.
There was a problem hiding this comment.
We can feature gate minimal items like constants and utils.
keetanetwork-block/src/types.rs
Outdated
| #[derive(Debug, Clone)] | ||
| pub struct CancelSwapOp<'a> { | ||
| /// Swap account to cancel | ||
| pub swap: &'a [u8], |
There was a problem hiding this comment.
Should this be a reference to an account instead?
There was a problem hiding this comment.
Using &[u8] for accounts/addresses is intentional, this is a zero-copy design for Ledger (no alloc). The field name and doc comment convey the semantic type.
|
I think the changes covers the keetanetwork-block work we scoped. Summary of implementation:
Unrelated Changes
All tests passing. Ready for review. |
| #[derive(Debug, Clone, Copy, Sequence)] | ||
| pub struct TokenRate<'a> { | ||
| /// Token public key | ||
| pub token: Bytes<'a>, |
There was a problem hiding this comment.
Why do we use undifferentiated Bytes here instead of something higher-level and more specific (account) ?
There was a problem hiding this comment.
This layer mirrors the ASN.1 (all OCTET STRING); semantic validation happens upstream in TS via assertKeyType()
can add aliases for clarity: pub type TokenId<'a> = Bytes<'a>; No compile-time safety, but documents intent. Prefer newtype wrappers instead?
| pub signature: &'a [u8], | ||
| } | ||
|
|
||
| /// Vote staple - bundles blocks with their votes |
There was a problem hiding this comment.
Vote Staples make few other guarantees as well:
- All votes have the same set of block hashes in the same order
- All blocks are referenced by the votes
- All blocks referenced in the votes are present
- All votes are of the same level of permanence (temporary or permanent)
There was a problem hiding this comment.
Interesting design for packaging - I'm familiar with OCSP stapling, which bundles certificate status proofs so verifiers don't need extra roundtrips, similar concept here with votes and blocks.
These invariants make sense for that model, want me to add them as doc comments on VoteStaple, implement a validate() method or both?
There was a problem hiding this comment.
Either is fine at this point, but the validation is important to do at some point because it's not a valid vote staple unless those conditions are met
|



This PR adds the following features:
keetanetwork-blockcrate for block and operation typesTODO