import { Serializable , UInt64 , BufferWriter , BufferReader , serialize } from '@uniqys/serialize' ; import { Hash , Hashable } from '@uniqys/signature' ; import { TransactionList } from './transaction' ; import { Consensus , ValidatorSet } from './consensus' ; export class BlockHeader implements Hashable , Serializable { public readonly hash : Hash ; constructor ( public readonly height , public readonly timestamp , public readonly lastBlockHash , public readonly transactionRoot , public readonly lastBlockConsensusRoot , public readonly nextValidatorSetRoot , public readonly appStateHash ) { this . hash = Hash . fromData ( serialize ( this ) ) ; } public static deserialize ( reader ) { const height = UInt64 . deserialize ( reader ) ; const timestamp = UInt64 . deserialize ( reader ) ; const lastBlockHash = Hash . deserialize ( reader ) ; const transactionRoot = Hash . deserialize ( reader ) ; const lastBlockConsensusRoot = Hash . deserialize ( reader ) ; const nextValidatorSetRoot = Hash . deserialize ( reader ) ; const appStateHash = Hash . deserialize ( reader ) ; return new BlockHeader ( height , timestamp , lastBlockHash , transactionRoot , lastBlockConsensusRoot , nextValidatorSetRoot , appStateHash ) ; } public serialize ( writer ) { UInt64 . serialize ( this . height , writer ) ; UInt64 . serialize ( this . timestamp , writer ) ; this . lastBlockHash . serialize ( writer ) ; this . transactionRoot . serialize ( writer ) ; this . lastBlockConsensusRoot . serialize ( writer ) ; this . nextValidatorSetRoot . serialize ( writer ) ; this . appStateHash . serialize ( writer ) ; } } export class BlockBody implements Serializable { constructor ( public readonly transactionList , public readonly lastBlockConsensus , public readonly nextValidatorSet ) { } public static deserialize ( reader ) { const transactions = TransactionList . deserialize ( reader ) ; const consensus = Consensus . deserialize ( reader ) ; const validatorSet = ValidatorSet . deserialize ( reader ) ; return new BlockBody ( transactions , consensus , validatorSet ) ; } public serialize ( writer ) { this . transactionList . serialize ( writer ) ; this . lastBlockConsensus . serialize ( writer ) ; this . nextValidatorSet . serialize ( writer ) ; } public validate ( header ) { if ( ! header . transactionRoot . equals ( this . transactionList . hash ) ) { throw new Error ( 'invalid transactionRoot' ) ; } if ( ! header . lastBlockConsensusRoot . equals ( this . lastBlockConsensus . hash ) ) { throw new Error ( 'invalid lastBlockConsensusHash' ) ; } if ( ! header . nextValidatorSetRoot . equals ( this . nextValidatorSet . hash ) ) { throw new Error ( 'invalid nextValidatorSetRoot' ) ; } } } export class Block implements Hashable , Serializable { public readonly hash : Hash ; constructor ( public readonly header , public readonly body ) { this . hash = header . hash ; } public static construct ( height , timestamp , lastBlockHash , appStateHash , transactions , lastBlockConsensus , nextValidatorSet ) { const body = new BlockBody ( transactions , lastBlockConsensus , nextValidatorSet ) ; const header = new BlockHeader ( height , timestamp , lastBlockHash , body . transactionList . hash , body . lastBlockConsensus . hash , body . nextValidatorSet . hash , appStateHash ) ; return new Block ( header , body ) ; } public static deserialize ( reader ) { const header = BlockHeader . deserialize ( reader ) ; const body = BlockBody . deserialize ( reader ) ; return new Block ( header , body ) ; } public serialize ( writer ) { this . header . serialize ( writer ) ; this . body . serialize ( writer ) ; } public validate ( ) { this . body . validate ( this . header ) ; } }