mod header;
pub use header::*;
mod transactions;
pub use transactions::*;
mod bytes;
mod genesis;
mod serialize;
mod string;
use crate::{
ledger::{vm::VM, Origin, Transaction, Transition},
process::{Deployment, Execution},
};
use console::{
account::{Address, PrivateKey, Signature},
network::prelude::*,
program::Value,
types::{Field, Group},
};
#[derive(Clone, PartialEq, Eq)]
pub struct Block<N: Network> {
block_hash: N::BlockHash,
previous_hash: N::BlockHash,
header: Header<N>,
transactions: Transactions<N>,
signature: Signature<N>,
}
impl<N: Network> Block<N> {
pub fn new<R: Rng + CryptoRng>(
private_key: &PrivateKey<N>,
previous_hash: N::BlockHash,
header: Header<N>,
transactions: Transactions<N>,
rng: &mut R,
) -> Result<Self> {
ensure!(!transactions.is_empty(), "Cannot create block with no transactions");
let block_hash = N::hash_bhp1024(&[previous_hash.to_bits_le(), header.to_root()?.to_bits_le()].concat())?;
let signature = private_key.sign(&[block_hash], rng)?;
let address = Address::try_from(private_key)?;
ensure!(signature.verify(&address, &[block_hash]), "Invalid signature for block {}", header.height());
Ok(Self { block_hash: block_hash.into(), previous_hash, header, transactions, signature })
}
pub fn from(
previous_hash: N::BlockHash,
header: Header<N>,
transactions: Transactions<N>,
signature: Signature<N>,
) -> Result<Self> {
ensure!(!transactions.is_empty(), "Cannot create block with no transactions");
let block_hash = N::hash_bhp1024(&[previous_hash.to_bits_le(), header.to_root()?.to_bits_le()].concat())?;
let address = signature.to_address();
ensure!(signature.verify(&address, &[block_hash]), "Invalid signature for block {}", header.height());
Ok(Self { block_hash: block_hash.into(), previous_hash, header, transactions, signature })
}
}
impl<N: Network> Block<N> {
pub const fn hash(&self) -> N::BlockHash {
self.block_hash
}
pub const fn previous_hash(&self) -> N::BlockHash {
self.previous_hash
}
pub const fn signature(&self) -> &Signature<N> {
&self.signature
}
}
impl<N: Network> Block<N> {
pub const fn header(&self) -> &Header<N> {
&self.header
}
pub const fn previous_state_root(&self) -> &Field<N> {
self.header.previous_state_root()
}
pub const fn transactions_root(&self) -> &Field<N> {
self.header.transactions_root()
}
pub const fn metadata(&self) -> &Metadata<N> {
self.header.metadata()
}
pub const fn network(&self) -> u16 {
self.header.network()
}
pub const fn height(&self) -> u32 {
self.header.height()
}
pub const fn round(&self) -> u64 {
self.header.round()
}
pub const fn coinbase_target(&self) -> u64 {
self.header.coinbase_target()
}
pub const fn proof_target(&self) -> u64 {
self.header.proof_target()
}
pub const fn timestamp(&self) -> i64 {
self.header.timestamp()
}
}
impl<N: Network> Block<N> {
pub const fn transactions(&self) -> &Transactions<N> {
&self.transactions
}
pub fn transaction_ids(&self) -> impl '_ + Iterator<Item = &N::TransactionID> {
self.transactions.transaction_ids()
}
pub fn deployments(&self) -> impl '_ + Iterator<Item = &Deployment<N>> {
self.transactions.deployments()
}
pub fn executions(&self) -> impl '_ + Iterator<Item = &Execution<N>> {
self.transactions.executions()
}
pub fn transitions(&self) -> impl '_ + Iterator<Item = &Transition<N>> {
self.transactions.transitions()
}
pub fn transition_ids(&self) -> impl '_ + Iterator<Item = &N::TransitionID> {
self.transactions.transition_ids()
}
pub fn transition_public_keys(&self) -> impl '_ + Iterator<Item = &Group<N>> {
self.transactions.transition_public_keys()
}
pub fn origins(&self) -> impl '_ + Iterator<Item = &Origin<N>> {
self.transactions.origins()
}
pub fn tags(&self) -> impl '_ + Iterator<Item = &Field<N>> {
self.transactions.tags()
}
pub fn serial_numbers(&self) -> impl '_ + Iterator<Item = &Field<N>> {
self.transactions.serial_numbers()
}
pub fn commitments(&self) -> impl '_ + Iterator<Item = &Field<N>> {
self.transactions.commitments()
}
pub fn nonces(&self) -> impl '_ + Iterator<Item = &Group<N>> {
self.transactions.nonces()
}
pub fn fees(&self) -> impl '_ + Iterator<Item = &i64> {
self.transactions.fees()
}
}