use borsh::{BorshSerialize, BorshDeserialize};
use crate::serialization::{Serializable, Deserializable};
use crate::cryptography::{Keypair, PublicKey, PublicAddress, SignatureBytes, Signer, Verifier, Sha256Hash, BloomFilter, sha256};
use crate::runtime::*;
#[derive(BorshSerialize, BorshDeserialize, Clone)]
pub struct Block {
pub header : BlockHeader,
pub transactions : Vec<Transaction>,
pub receipts : Vec<Receipt>,
}
impl Serializable for Block {}
impl Deserializable for Block {}
#[derive(Clone, BorshSerialize, BorshDeserialize)]
pub struct BlockHeader {
pub hash: Sha256Hash,
pub height: u64,
pub justify: hotstuff_rs::types::QuorumCertificate,
pub data_hash: hotstuff_rs::types::CryptoHash,
pub chain_id: hotstuff_rs::types::ChainID,
pub proposer: PublicAddress,
pub timestamp: u32,
pub base_fee: u64,
pub gas_used: u64,
pub txs_hash: Sha256Hash,
pub receipts_hash: Sha256Hash,
pub state_hash: Sha256Hash,
pub log_bloom: BloomFilter,
}
impl Serializable for BlockHeader {}
impl Deserializable for BlockHeader {}
#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)]
pub struct Transaction {
pub signer: PublicAddress,
pub nonce: u64,
pub commands: Vec<Command>,
pub gas_limit: u64,
pub max_base_fee_per_gas: u64,
pub priority_fee_per_gas: u64,
pub signature: SignatureBytes,
pub hash: Sha256Hash,
}
impl Transaction {
pub fn new(signer: &Keypair, nonce: u64, commands: Vec<Command>, gas_limit: u64, max_base_fee_per_gas: u64, priority_fee_per_gas: u64) -> Transaction {
let mut transaction = Transaction {
signer: signer.public.to_bytes(),
nonce,
commands,
gas_limit,
max_base_fee_per_gas,
priority_fee_per_gas,
signature: [0u8; 64],
hash: [0u8; 32],
};
let signature = signer.sign(&Serializable::serialize(&transaction));
transaction.signature = signature.into();
let hash = sha256(ed25519_dalek::ed25519::signature::Signature::as_bytes(&signature));
transaction.hash = hash;
transaction
}
pub fn is_cryptographically_correct(&self) -> Result<(), CryptographicallyIncorrectTransactionError> {
let public_key = PublicKey::from_bytes(&self.signer)
.map_err(|_| CryptographicallyIncorrectTransactionError::InvalidSigner)?;
let signature = ed25519_dalek::Signature::from_bytes(&self.signature)
.map_err(|_| CryptographicallyIncorrectTransactionError::InvalidSignature)?;
let signed_msg = {
let intermediate_txn = Transaction {
signature: [0u8; 64],
hash: [0u8; 32],
..self.to_owned()
};
Serializable::serialize(&intermediate_txn)
};
public_key.verify(&signed_msg, &signature).map_err(|_| CryptographicallyIncorrectTransactionError::WrongSignature)?;
if self.hash != sha256(ed25519_dalek::ed25519::signature::Signature::as_bytes(&signature)) {
return Err(CryptographicallyIncorrectTransactionError::WrongHash)
}
Ok(())
}
}
pub enum CryptographicallyIncorrectTransactionError {
InvalidSigner,
InvalidSignature,
WrongSignature,
WrongHash,
}
impl Serializable for Transaction {}
impl Deserializable for Transaction {}
#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)]
pub enum Command {
Transfer(TransferInput),
Deploy(DeployInput),
Call(CallInput),
CreatePool(CreatePoolInput),
SetPoolSettings(SetPoolSettingsInput),
DeletePool,
CreateDeposit(CreateDepositInput),
SetDepositSettings(SetDepositSettingsInput),
TopUpDeposit(TopUpDepositInput),
WithdrawDeposit(WithdrawDepositInput),
StakeDeposit(StakeDepositInput),
UnstakeDeposit(UnstakeDepositInput),
NextEpoch,
}
impl Serializable for Command {}
impl Deserializable for Command {}
#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)]
pub struct Log {
pub topic: Vec<u8>,
pub value: Vec<u8>,
}
impl Serializable for Log {}
impl Deserializable for Log {}
pub type Receipt = Vec<CommandReceipt>;
#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)]
pub struct CommandReceipt {
pub exit_status: ExitStatus,
pub gas_used: u64,
pub return_values: Vec<u8>,
pub logs: Vec<Log>,
}
impl Serializable for CommandReceipt {}
impl Deserializable for CommandReceipt {}
#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)]
pub enum ExitStatus {
Success,
Failed,
GasExhausted,
}
impl Serializable for ExitStatus {}
impl Deserializable for ExitStatus {}