import { ByteArray , BytesReader , CompactInt } from 'as-scale-codec' ; import { ExecutionPhase , ext_trie_blake2_256_ordered_root_version_1 , Header , Phase , Serialiser , Storage , Utils } from 'subsembly-core' ; import { AccountInfoType , BlockNumber , ExtrinsicDataType , ExtrinsicIndexType , HashType , HeaderType , SystemConfig , UncheckedExtrinsic , VecEvent } from '../runtime/runtime' ; import { StorageEntry } from './models/storage-entry' ; export enum SystemEvents { ExtrinsicSuccess = 0 , ExtrinsicFailure = 1 } description export namespace SystemStorageEntries { description storage_map export function Account ( ) { return new StorageEntry < AccountInfoType > ( "System" , "Account" ) ; } ; description storage export function ExtrinsicCount ( ) { return new StorageEntry < ExtrinsicIndexType > ( "System" , "ExtrinsicCount" ) ; } ; description storage export function AllExtrinsicsLen ( ) { return new StorageEntry < ExtrinsicIndexType > ( "System" , "AllExtrinsicsLen" ) ; } ; description storage_map export function ParentHash ( ) { return new StorageEntry < HashType > ( "System" , "ParentHash" ) ; } ; description storage export function ExtrinsicsRoot ( ) { return new StorageEntry < HashType > ( "System" , "ExtrinsicsRoot" ) ; } ; description storage export function Digest ( ) { return new StorageEntry < ByteArray > ( "System" , "Digest" ) ; } ; description storage_map export function ExtrinsicData ( ) { return new StorageEntry < ExtrinsicDataType > ( "System" , "ExtrinsicData" ) ; } ; description storage_map export function BlockHash ( ) { return new StorageEntry < HashType > ( "System" , "BlockHash" ) ; } ; description storage export function Number ( ) { return new StorageEntry < BlockNumber > ( "System" , "Number" ) ; } ; description storage export function ExtrinsicIndex ( ) { return new StorageEntry < ExtrinsicIndexType > ( "System" , "ExtrinsicsRoot" ) ; } ; description storage export function ExecutionPhase ( ) { return new StorageEntry < Phase < ExtrinsicIndexType > > ( "System" , "ExecutionPhase" ) ; } ; description storage export function Events ( ) { return new StorageEntry < VecEvent > ( "System" , "Events" ) ; } } ; description export class System { /**
     * number of all modules in the runtime that creates inherents (timestamp, for now)
     * array is encoded as CompactInt
    */ static readonly ALL_MODULES : u8 [ ] = [ 4 ] ; /**
     * NOTE: Hard-coded in this iteration
     * Needs to be removed after Events support in subsembly-core
     * Extrinsic success of system
     */ static readonly EXTRINSIC_SUCCESS : u8 [ ] = [ 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] ; static readonly EXTRINSIC_FAILURE : u8 [ ] = [ 0 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] ; description param header static _initialize ( header ) { SystemStorageEntries . ExtrinsicIndex ( ) . set ( instantiate < ExtrinsicIndexType > ( 0 ) ) ; SystemStorageEntries . ExecutionPhase ( ) . set ( new Phase < ExtrinsicIndexType > ( ExecutionPhase . Initialization ) ) ; SystemStorageEntries . ParentHash ( ) . set ( header . getParentHash ( ) ) ; SystemStorageEntries . Number ( ) . set ( header . getNumber ( ) ) ; SystemStorageEntries . ExtrinsicsRoot ( ) . set ( header . getExtrinsicsRoot ( ) ) ; let digestsArr = header . getDigests ( ) ; let digests = ( new CompactInt ( digestsArr . length ) ) . toU8a ( ) ; for ( let i = 0 ; i < digestsArr . length ; i ++ ) { digests = digests . concat ( digestsArr [ i ] . toU8a ( ) ) ; } SystemStorageEntries . Digest ( ) . set ( new ByteArray ( digests ) ) ; const blockNumber = instantiate < BlockNumber > ( ( < BlockNumber > header . getNumber ( ) ) . unwrap ( ) - 1 ) ; SystemStorageEntries . BlockHash ( ) . set ( header . getParentHash ( ) , blockNumber ) ; Storage . clear ( Utils . getHashedKey ( "System" , "Events" , null ) ) ; } description static _finalize ( ) { SystemStorageEntries . ExecutionPhase ( ) . clear ( ) ; SystemStorageEntries . ExtrinsicCount ( ) . clear ( ) ; let blockNumber = SystemStorageEntries . Number ( ) . take ( ) ; let parentHash = SystemStorageEntries . ParentHash ( ) . take ( ) ; let digests = SystemStorageEntries . Digest ( ) . take ( ) ; let extrinsicsRoot = SystemStorageEntries . ExtrinsicsRoot ( ) . take ( ) ; let blockHashCount = SystemConfig . BlockHashCount ( ) ; if ( blockNumber && blockNumber . unwrap ( ) > blockHashCount . unwrap ( ) ) { let toRemove = blockNumber . unwrap ( ) - blockHashCount . unwrap ( ) - 1 ; if ( toRemove != 0 ) { SystemStorageEntries . BlockHash ( ) . clear ( instantiate < BlockNumber > ( toRemove ) ) ; } } const root = BytesReader . decodeInto < HashType > ( Storage . storageRoot ( ) ) ; const digest = Header . decodeOptionalDigest ( digests . unwrap ( ) ) ; return instantiate < HeaderType > ( parentHash , blockNumber , root , extrinsicsRoot , digest . getResult ( ) ) ; } description param data static _computeExtrinsicsRoot ( ) { const extcsData = SystemStorageEntries . ExtrinsicData ( ) . take ( ) ; const extcsRoot = this . _extrinsicsDataRoot ( extcsData . toEnumeratedValues ( ) ) ; SystemStorageEntries . ExtrinsicsRoot ( ) . set ( extcsRoot ) ; } description param data static _extrinsicsDataRoot ( data ) { let dataPtr = data . dataStart ; let dataLen = data . length ; __retain ( dataPtr ) ; const dataU64 = ( ( dataLen as u64 ) << 32 ) | dataPtr ; let extrinsicRoot = ext_trie_blake2_256_ordered_root_version_1 ( dataU64 ) ; const hashU8a = Serialiser . deserialiseInput ( extrinsicRoot , 32 ) ; return BytesReader . decodeInto < HashType > ( hashU8a ) ; } description param ext static _noteAppliedExtrinsic ( ext ) { const extrinsics = SystemStorageEntries . ExtrinsicData ( ) . get ( ) ; const extIndex = SystemStorageEntries . ExtrinsicIndex ( ) . get ( ) ; extrinsics . insert ( extIndex , new ByteArray ( ext . toU8a ( ) ) ) ; SystemStorageEntries . ExtrinsicData ( ) . set ( extrinsics ) ; SystemStorageEntries . ExtrinsicIndex ( ) . set ( instantiate < ExtrinsicIndexType > ( extIndex . unwrap ( ) + 1 ) ) ; if ( ext . isSigned ( ) ) { System . _depositEvent ( SystemEvents . ExtrinsicSuccess , [ ] ) ; } const nextIndex = instantiate < ExtrinsicIndexType > ( extIndex . unwrap ( ) + 1 ) ; SystemStorageEntries . ExecutionPhase ( ) . set ( new Phase < ExtrinsicIndexType > ( ExecutionPhase . ApplyExtrinsic , nextIndex ) ) ; } description static _noteFinishedExtrinsics ( ) { SystemStorageEntries . ExtrinsicCount ( ) . set ( SystemStorageEntries . ExtrinsicIndex ( ) . get ( ) ) ; SystemStorageEntries . ExecutionPhase ( ) . set ( new Phase < ExtrinsicIndexType > ( ExecutionPhase . Finalization ) ) ; } description param name param args static _depositEvent ( type , args ) { /**
         * TO-DO: Make event deposit dynamic
         * Currently it's hard-coded for two types of events:
         * ExtrinsicSuccess and ExtrinsicFailed
         */ switch ( type ) { case SystemEvents . ExtrinsicSuccess : { System . _addEventInStorage ( this . EXTRINSIC_SUCCESS ) ; } case SystemEvents . ExtrinsicFailure : { System . _addEventInStorage ( this . EXTRINSIC_FAILURE ) ; } default : return ; } } description param event static _addEventInStorage ( event ) { const index = SystemStorageEntries . ExtrinsicIndex ( ) . get ( ) ; const events = Storage . get ( Utils . getHashedKey ( "System" , "Events" , null ) ) ; const eventsRaw = events . isSome ( ) ? ( < ByteArray > events . unwrap ( ) ) . unwrap ( ) : [ 0 ] ; const bytesReader = new BytesReader ( eventsRaw ) ; const len = < i32 > bytesReader . readInto < CompactInt > ( ) . unwrap ( ) ; const phase = new Phase < ExtrinsicIndexType > ( ExecutionPhase . ApplyExtrinsic , index ) ; const newEvents = new CompactInt ( len + 1 ) . toU8a ( ) . concat ( bytesReader . getLeftoverBytes ( ) ) . concat ( phase . toU8a ( ) ) . concat ( event ) ; Storage . set ( Utils . getHashedKey ( "System" , "Events" , null ) , newEvents ) ; } }