public override Task <TransactionalBlockEssense> GetLastTransactionalBlock(TransactionalBlockRequest request, ServerCallContext context) { if (request.PublicKey == null) { throw new ArgumentNullException(nameof(request.PublicKey)); } byte[] keyBytes = request.PublicKey.ToByteArray(); if (keyBytes.Length != Globals.NODE_PUBLIC_KEY_SIZE) { throw new ArgumentException($"Public key size must be of {Globals.NODE_PUBLIC_KEY_SIZE} bytes"); } IKey key = _identityKeyProvider.GetKey(keyBytes); TransactionalPacketBase transactionalBlockBase = (TransactionalPacketBase)_transactionalDataService.GetLastBlock(key); TransactionalBlockEssense transactionalBlockEssense = new TransactionalBlockEssense { Height = transactionalBlockBase?.BlockHeight ?? 0, //TODO: need to reconsider hash calculation here since it is potential point of DoS attack Hash = ByteString.CopyFrom(transactionalBlockBase != null ? _hashCalculation.CalculateHash(transactionalBlockBase.RawData) : new byte[Globals.DEFAULT_HASH_SIZE]), UpToDateFunds = transactionalBlockBase?.UptodateFunds ?? 0 }; return(Task.FromResult(transactionalBlockEssense)); }
protected override Memory <byte> ParseTransactional(ushort version, Memory <byte> spanBody, out TransactionalPacketBase transactionalBlockBase) { TransactionalPacketBase block = null; if (version == 1) { byte[] target = spanBody.Slice(0, Globals.DEFAULT_HASH_SIZE).ToArray(); block = new TransferFundsBlock { TargetOriginalHash = target }; transactionalBlockBase = block; return(spanBody.Slice(Globals.DEFAULT_HASH_SIZE)); } throw new BlockVersionNotSupportedException(version, BlockType); }
protected override Memory <byte> ParseTransactional(ushort version, Memory <byte> spanBody, out TransactionalPacketBase transactionalBlockBase) { TransactionalPacketBase block = null; if (version == 1) { byte[] origin = spanBody.Slice(0, Globals.DEFAULT_HASH_SIZE).ToArray(); ulong funds = BinaryPrimitives.ReadUInt64LittleEndian(spanBody.Span.Slice(Globals.DEFAULT_HASH_SIZE)); block = new AcceptFundsBlock() { SourceOriginalHash = origin, UptodateFunds = funds, }; transactionalBlockBase = block; return(spanBody.Slice(Globals.DEFAULT_HASH_SIZE + 8)); } throw new BlockVersionNotSupportedException(version, BlockType); }
protected override Memory <byte> ParseTransactional(ushort version, Memory <byte> spanBody, out TransactionalPacketBase transactionalBlockBase) { if (version == 1) { int readBytes = 0; ushort acceptedUnblindingAssetABsLength = BinaryPrimitives.ReadUInt16LittleEndian(spanBody.Slice(readBytes).Span); readBytes += sizeof(ushort); ushort acceptedUnblindingAssetUtxosLength = BinaryPrimitives.ReadUInt16LittleEndian(spanBody.Slice(readBytes).Span); readBytes += sizeof(ushort); AcceptedAssetUnblindingAB[] acceptedUnblindingAssetABs = new AcceptedAssetUnblindingAB[acceptedUnblindingAssetABsLength]; AcceptedAssetUnblindingUtxo[] acceptedUnblindingAssetUtxos = new AcceptedAssetUnblindingUtxo[acceptedUnblindingAssetUtxosLength]; for (int i = 0; i < acceptedUnblindingAssetABsLength; i++) { byte[] assetId = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray(); readBytes += Globals.NODE_PUBLIC_KEY_SIZE; byte[] blindingFactor = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray(); readBytes += Globals.NODE_PUBLIC_KEY_SIZE; byte[] sourceAddress = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray(); readBytes += Globals.NODE_PUBLIC_KEY_SIZE; ulong height = BinaryPrimitives.ReadUInt64LittleEndian(spanBody.Slice(readBytes).Span); readBytes += sizeof(ulong); acceptedUnblindingAssetABs[i] = new AcceptedAssetUnblindingAB { AcceptedAssetsUnblinding = new AcceptedAssetUnblinding { AssetId = assetId, BlindingFactor = blindingFactor }, SourceAddress = sourceAddress, SourceHeight = height }; } for (int i = 0; i < acceptedUnblindingAssetUtxosLength; i++) { byte[] assetId = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray(); readBytes += Globals.NODE_PUBLIC_KEY_SIZE; byte[] blindingFactor = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray(); readBytes += Globals.NODE_PUBLIC_KEY_SIZE; byte[] sourceKey = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray(); readBytes += Globals.NODE_PUBLIC_KEY_SIZE; acceptedUnblindingAssetUtxos[i] = new AcceptedAssetUnblindingUtxo { AcceptedAssetsUnblinding = new AcceptedAssetUnblinding { AssetId = assetId, BlindingFactor = blindingFactor }, SourceKey = sourceKey }; } ushort assetsGroupsLength = BinaryPrimitives.ReadUInt16LittleEndian(spanBody.Slice(readBytes).Span); readBytes += sizeof(ushort); AssetsGroup[] assetsGroups = new AssetsGroup[assetsGroupsLength]; for (int i = 0; i < assetsGroupsLength; i++) { uint groupId = BinaryPrimitives.ReadUInt32LittleEndian(spanBody.Slice(readBytes).Span); readBytes += sizeof(uint); ushort totalAssetIdsCount = BinaryPrimitives.ReadUInt16LittleEndian(spanBody.Slice(readBytes).Span); readBytes += sizeof(ushort); byte[][] assetIds = new byte[totalAssetIdsCount][]; ulong[] amounts = new ulong[totalAssetIdsCount]; for (int j = 0; j < totalAssetIdsCount; i++) { assetIds[j] = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray(); readBytes += Globals.NODE_PUBLIC_KEY_SIZE; } for (int j = 0; j < totalAssetIdsCount; i++) { amounts[j] = BinaryPrimitives.ReadUInt64LittleEndian(spanBody.Slice(readBytes).Span); readBytes += sizeof(ulong); } assetsGroups[i] = new AssetsGroup { GroupId = groupId, AssetIds = assetIds, AssetAmounts = amounts }; } AcceptAssets acceptAssetTransitionBlock = new AcceptAssets { AcceptedAssetUnblindingABs = acceptedUnblindingAssetABs, AcceptedAssetUnblindingUtxos = acceptedUnblindingAssetUtxos, AssetsGroups = assetsGroups }; transactionalBlockBase = acceptAssetTransitionBlock; return(spanBody.Slice(readBytes)); } throw new BlockVersionNotSupportedException(version, BlockType); }
protected override Memory <byte> ParseTransactional(ushort version, Memory <byte> spanBody, out TransactionalPacketBase transactionalBlockBase) { int readBytes = 0; byte[] target = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray(); readBytes += Globals.NODE_PUBLIC_KEY_SIZE; Memory <byte> spanPostBody = ParseTransactionalNonTransitional(version, spanBody.Slice(readBytes), out TransactionalNonTransitionalPacketBase transactionalNonTransitionalPacketBase); transactionalNonTransitionalPacketBase.Target = target; transactionalBlockBase = transactionalNonTransitionalPacketBase; return(spanPostBody); }
protected abstract Memory <byte> ParseTransactional(ushort version, Memory <byte> spanBody, out TransactionalPacketBase transactionalBlockBase);
protected override Memory <byte> ParseTransactional(ushort version, Memory <byte> spanBody, out TransactionalPacketBase transactionalBlockBase) { IssueAsset block = null; if (version == 1) { int readBytes = 0; byte[] assetId = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray(); readBytes += Globals.NODE_PUBLIC_KEY_SIZE; byte strLen = spanBody.Slice(readBytes, 1).ToArray()[0]; readBytes++; string issuedAssetInfo = Encoding.ASCII.GetString(spanBody.Slice(readBytes, strLen).ToArray()); readBytes += strLen; AssetIssuance assetIssuance = new AssetIssuance { AssetId = assetId, IssuedAssetInfo = issuedAssetInfo }; block = new IssueAsset { AssetIssuance = assetIssuance }; transactionalBlockBase = block; return(spanBody.Slice(readBytes)); } throw new BlockVersionNotSupportedException(version, BlockType); }
protected override Memory <byte> ParseTransactional(ushort version, Memory <byte> spanBody, out TransactionalPacketBase transactionalBlockBase) { IssueGroupedAssets block = null; if (version == 1) { int readBytes = 0; ushort assetsIssuanceGroupsLength = BinaryPrimitives.ReadUInt16LittleEndian(spanBody.Slice(readBytes).Span); readBytes += sizeof(ushort); ushort blindedAssetsIssuanceGroupsLength = BinaryPrimitives.ReadUInt16LittleEndian(spanBody.Slice(readBytes).Span); readBytes += sizeof(ushort); AssetsIssuanceGroup[] assetsIssuanceGroups = new AssetsIssuanceGroup[assetsIssuanceGroupsLength]; BlindedAssetsIssuanceGroup[] blindedAssetsIssuanceGroups = new BlindedAssetsIssuanceGroup[blindedAssetsIssuanceGroupsLength]; for (int i = 0; i < assetsIssuanceGroupsLength; i++) { uint groupId = BinaryPrimitives.ReadUInt32LittleEndian(spanBody.Slice(readBytes).Span); readBytes += sizeof(uint); ushort assetIdsLength = BinaryPrimitives.ReadUInt16LittleEndian(spanBody.Slice(readBytes).Span); readBytes += sizeof(ushort); AssetIssuance[] assetIssuances = new AssetIssuance[assetIdsLength]; for (int j = 0; j < assetIdsLength; j++) { byte[] assetId = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray(); readBytes += Globals.NODE_PUBLIC_KEY_SIZE; byte strLen = spanBody.Slice(readBytes, 1).ToArray()[0]; readBytes++; string issuedAssetInfo = Encoding.ASCII.GetString(spanBody.Slice(readBytes, strLen).ToArray()); readBytes += strLen; assetIssuances[j] = new AssetIssuance { AssetId = assetId, IssuedAssetInfo = issuedAssetInfo }; } assetsIssuanceGroups[i] = new AssetsIssuanceGroup { GroupId = groupId, AssetIssuances = assetIssuances }; } for (int i = 0; i < blindedAssetsIssuanceGroupsLength; i++) { uint groupId = BinaryPrimitives.ReadUInt32LittleEndian(spanBody.Slice(readBytes).Span); readBytes += sizeof(uint); ushort assetCommitmentsLength = BinaryPrimitives.ReadUInt16LittleEndian(spanBody.Slice(readBytes).Span); readBytes += sizeof(ushort); byte[][] assetCommitments = new byte[assetCommitmentsLength][]; for (int j = 0; j < assetCommitmentsLength; j++) { assetCommitments[j] = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray(); readBytes += Globals.NODE_PUBLIC_KEY_SIZE; } AssetIssuance[] blindedAssetIssuances = new AssetIssuance[assetCommitmentsLength]; for (int j = 0; j < assetCommitmentsLength; j++) { byte[] assetId = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray(); readBytes += Globals.NODE_PUBLIC_KEY_SIZE; byte strLen = spanBody.Slice(readBytes, 1).ToArray()[0]; readBytes++; string issuedAssetInfo = Encoding.ASCII.GetString(spanBody.Slice(readBytes, strLen).ToArray()); readBytes += strLen; blindedAssetIssuances[i] = new AssetIssuance { AssetId = assetId, IssuedAssetInfo = issuedAssetInfo }; } IssuanceProof[] issuanceProofs = new IssuanceProof[assetCommitmentsLength]; for (int j = 0; j < assetCommitmentsLength; j++) { SurjectionProof surjectionProof = ReadSurjectionProof(spanBody.Slice(readBytes).Span, out int count); readBytes += count; byte[] mask = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray(); readBytes += Globals.NODE_PUBLIC_KEY_SIZE; issuanceProofs[j] = new IssuanceProof { SurjectionProof = surjectionProof, Mask = mask, }; } blindedAssetsIssuanceGroups[i] = new BlindedAssetsIssuanceGroup { GroupId = groupId, AssetCommitments = assetCommitments, AssetIssuances = blindedAssetIssuances, IssuanceProofs = issuanceProofs }; } byte strLen2 = spanBody.Slice(readBytes, 1).ToArray()[0]; readBytes++; string issuanceInfo = Encoding.ASCII.GetString(spanBody.Slice(readBytes, strLen2).ToArray()); readBytes += strLen2; ushort assetsGroupsLength = BinaryPrimitives.ReadUInt16LittleEndian(spanBody.Slice(readBytes).Span); readBytes += sizeof(ushort); ushort blindedAssetGroupsLength = BinaryPrimitives.ReadUInt16LittleEndian(spanBody.Slice(readBytes).Span); readBytes += sizeof(ushort); AssetsGroup[] assetsGroups = new AssetsGroup[assetsGroupsLength]; BlindedAssetsGroup[] blindedAssetsGroups = new BlindedAssetsGroup[blindedAssetGroupsLength]; for (int i = 0; i < assetsGroupsLength; i++) { uint groupId = BinaryPrimitives.ReadUInt32LittleEndian(spanBody.Slice(readBytes).Span); readBytes += sizeof(uint); ushort assetIdsLength = BinaryPrimitives.ReadUInt16LittleEndian(spanBody.Slice(readBytes).Span); readBytes += sizeof(ushort); byte[][] assetIds = new byte[assetIdsLength][]; ulong[] amounts = new ulong[assetIdsLength]; for (int j = 0; j < assetIdsLength; j++) { assetIds[j] = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray(); readBytes += Globals.NODE_PUBLIC_KEY_SIZE; amounts[j] = BinaryPrimitives.ReadUInt64LittleEndian(spanBody.Slice(readBytes).Span); readBytes += sizeof(ulong); } assetsGroups[i] = new AssetsGroup { GroupId = groupId, AssetIds = assetIds, AssetAmounts = amounts }; } for (int i = 0; i < blindedAssetGroupsLength; i++) { uint groupId = BinaryPrimitives.ReadUInt32LittleEndian(spanBody.Slice(readBytes).Span); readBytes += sizeof(uint); ushort assetCommitmentsLength = BinaryPrimitives.ReadUInt16LittleEndian(spanBody.Slice(readBytes).Span); readBytes += sizeof(ushort); byte[][] assetCommitments = new byte[assetCommitmentsLength][]; for (int j = 0; j < assetCommitmentsLength; j++) { assetCommitments[j] = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray(); readBytes += Globals.NODE_PUBLIC_KEY_SIZE; } blindedAssetsGroups[i] = new BlindedAssetsGroup { GroupId = groupId, AssetCommitments = assetCommitments }; } block = new IssueGroupedAssets { AssetsIssuanceGroups = assetsIssuanceGroups, BlindedAssetsIssuanceGroups = blindedAssetsIssuanceGroups, IssuanceInfo = issuanceInfo, AssetsGroups = assetsGroups, BlindedAssetsGroups = blindedAssetsGroups }; transactionalBlockBase = block; return(spanBody.Slice(readBytes)); } throw new BlockVersionNotSupportedException(version, BlockType); }
protected override Memory <byte> ParseTransactional(ushort version, Memory <byte> spanBody, out TransactionalPacketBase transactionalBlockBase) { IssueBlindedAsset block = null; if (version == 1) { int readBytes = 0; byte[] groupId = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray(); readBytes += Globals.NODE_PUBLIC_KEY_SIZE; byte[] assetCommitment = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray(); readBytes += Globals.NODE_PUBLIC_KEY_SIZE; byte[] keyImage = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray(); readBytes += Globals.NODE_PUBLIC_KEY_SIZE; byte[] ringSignatureC = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray(); readBytes += Globals.NODE_PUBLIC_KEY_SIZE; byte[] ringSignatureR = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray(); readBytes += Globals.NODE_PUBLIC_KEY_SIZE; block = new IssueBlindedAsset { GroupId = groupId, AssetCommitment = assetCommitment, KeyImage = keyImage, UniquencessProof = new RingSignature { C = ringSignatureC, R = ringSignatureR } }; transactionalBlockBase = block; return(spanBody.Slice(readBytes)); } throw new BlockVersionNotSupportedException(version, BlockType); }
protected override Memory <byte> ParseTransactional(ushort version, Memory <byte> spanBody, out TransactionalPacketBase transactionalBlockBase) { BlindAsset block = null; if (version == 1) { int readBytes = 0; byte[] assetCommitment = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray(); readBytes += Globals.NODE_PUBLIC_KEY_SIZE; byte[] mask = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray(); readBytes += Globals.NODE_PUBLIC_KEY_SIZE; byte[] encryptedAssetId = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray(); readBytes += Globals.NODE_PUBLIC_KEY_SIZE; ushort assetCommitmentsCount = BinaryPrimitives.ReadUInt16LittleEndian(spanBody.Slice(readBytes).Span); readBytes += sizeof(ushort); byte[][] assetCommitments = new byte[assetCommitmentsCount][]; for (int i = 0; i < assetCommitmentsCount; i++) { assetCommitments[i] = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray(); readBytes += Globals.NODE_PUBLIC_KEY_SIZE; } byte[] e = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray(); readBytes += Globals.NODE_PUBLIC_KEY_SIZE; byte[][] s = new byte[assetCommitmentsCount][]; for (int i = 0; i < assetCommitmentsCount; i++) { s[i] = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray(); readBytes += Globals.NODE_PUBLIC_KEY_SIZE; } block = new BlindAsset { EncryptedAsset = new DataModel.Transactional.Internal.EncryptedAsset { AssetCommitment = assetCommitment, EcdhTuple = new Wist.Core.Cryptography.EcdhTupleCA { Mask = mask, AssetId = encryptedAssetId } }, SurjectionProof = new Wist.Core.Cryptography.SurjectionProof { AssetCommitments = assetCommitments, Rs = new Wist.Core.Cryptography.BorromeanRingSignature { E = e, S = s } } }; transactionalBlockBase = block; return(spanBody.Slice(readBytes)); } throw new BlockVersionNotSupportedException(version, BlockType); }
protected override Memory <byte> ParseTransactional(ushort version, Memory <byte> spanBody, out TransactionalPacketBase transactionalBlockBase) { TransferGroupedAssets block = null; if (version == 1) { int readBytes = 0; byte[] target = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray(); readBytes += Globals.NODE_PUBLIC_KEY_SIZE; ushort transferredAssetsLength = BinaryPrimitives.ReadUInt16LittleEndian(spanBody.Slice(readBytes).Span); readBytes += sizeof(ushort); EncryptedAsset[] transferedAssets = new EncryptedAsset[transferredAssetsLength]; for (int i = 0; i < transferredAssetsLength; i++) { byte[] assetCommitment = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray(); readBytes += Globals.NODE_PUBLIC_KEY_SIZE; byte[] assetId = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray(); readBytes += Globals.NODE_PUBLIC_KEY_SIZE; byte[] mask = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray(); readBytes += Globals.NODE_PUBLIC_KEY_SIZE; transferedAssets[i] = new EncryptedAsset { AssetCommitment = assetCommitment, EcdhTuple = new EcdhTupleCA { AssetId = assetId, Mask = mask } }; } ushort blindedAssetsGroupsLength = BinaryPrimitives.ReadUInt16LittleEndian(spanBody.Slice(readBytes).Span); readBytes += sizeof(ushort); BlindedAssetsGroup[] blindedAssetsGroups = new BlindedAssetsGroup[blindedAssetsGroupsLength]; ushort totalCommitments = 0; for (int i = 0; i < blindedAssetsGroupsLength; i++) { uint groupId = BinaryPrimitives.ReadUInt32LittleEndian(spanBody.Slice(readBytes).Span); readBytes += sizeof(uint); ushort assetCommitmentsLength = BinaryPrimitives.ReadUInt16LittleEndian(spanBody.Slice(readBytes).Span); readBytes += sizeof(ushort); totalCommitments += assetCommitmentsLength; byte[][] assetCommitments = new byte[assetCommitmentsLength][]; for (int j = 0; j < assetCommitmentsLength; i++) { assetCommitments[j] = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray(); readBytes += Globals.NODE_PUBLIC_KEY_SIZE; } blindedAssetsGroups[i] = new BlindedAssetsGroup { GroupId = groupId, AssetCommitments = assetCommitments }; } InversedSurjectionProof[] inversedSurjectionProofs = new InversedSurjectionProof[transferredAssetsLength + totalCommitments]; for (int i = 0; i < inversedSurjectionProofs.Length; i++) { inversedSurjectionProofs[i] = ReadInversedSurjectionProof(spanBody.Slice(readBytes).Span, out int count); readBytes += count; } block = new TransferGroupedAssets { TransferedAssets = transferedAssets, BlindedAssetsGroups = blindedAssetsGroups, InversedSurjectionProofs = inversedSurjectionProofs }; transactionalBlockBase = block; return(spanBody.Slice(readBytes)); } throw new BlockVersionNotSupportedException(version, BlockType); }
protected override Memory <byte> ParseTransactional(ushort version, Memory <byte> spanBody, out TransactionalPacketBase transactionalBlockBase) { IssueAssociatedBlindedAsset block = null; if (version == 1) { int readBytes = 0; byte[] groupId = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray(); readBytes += Globals.NODE_PUBLIC_KEY_SIZE; byte[] assetCommitment = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray(); readBytes += Globals.NODE_PUBLIC_KEY_SIZE; byte[] rootAssetCommitment = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray(); readBytes += Globals.NODE_PUBLIC_KEY_SIZE; block = new IssueAssociatedBlindedAsset { GroupId = groupId, AssetCommitment = assetCommitment, RootAssetCommitment = rootAssetCommitment }; transactionalBlockBase = block; return(spanBody.Slice(readBytes)); } throw new BlockVersionNotSupportedException(version, BlockType); }