internal static Transaction Parse(BinaryReader bin) { Transaction t = new Transaction(); UInt16 lo = bin.ReadUInt16(); UInt32 hi = bin.ReadUInt32(); t.InnerID = (((UInt64)hi & 0x3fffffff) << 16) | lo; int len = Primitives.PublicKeySize; if ((hi & 0x80000000) != 0) { len = sizeof(UInt32); } t.Source = new Primitives.PublicKey() { Value = bin.ReadBytes(len) }; if ((hi & 0x40000000) != 0) { len = sizeof(UInt32); } t.Target = new Primitives.PublicKey() { Value = bin.ReadBytes(len) }; t.Sum = new Money(); t.Sum.Integral = bin.ReadInt32(); t.Sum.Fraction = bin.ReadUInt64(); t.MaxFee = Money.FromCommission(bin.ReadUInt16()); // skip currency bin.ReadByte(); int cnt = (int)(uint)bin.ReadByte(); if(cnt > 0) { t.UserFields = new List<UserField>(); t.UserFields = new List<UserField>(); for(int i = 0; i < cnt; i++) { t.UserFields.Add(UserField.Parse(bin)); } } t.Signature = new Primitives.Signature() { Value = bin.ReadBytes(Primitives.SignatureSize) }; t.Fee = Money.FromCommission(bin.ReadUInt16()); return t; }
internal static ResponseBlock Parse(byte[] bytes) { try { if (bytes == null) { return(new ResponseBlock() { Success = false, Message = "Input bytes array is null" }); } using (BinaryReader bin = new BinaryReader(new MemoryStream(bytes))) { int hashing_len = 0; Block block = new Block(); block.Version = bin.ReadByte(); int len = bin.ReadByte(); if (len != Primitives.HashSize) { return(new ResponseBlock() { Success = false, Message = "The hash size is not equal" }); } block.PreviousHash = new Primitives.Hash { Value = bin.ReadBytes(len) }; block.Sequence = bin.ReadUInt64(); // user fields int cnt = (int)bin.ReadByte(); if (cnt > 0) { block.UserFields = new List <UserField>(); for (int i = 0; i < cnt; i++) { block.UserFields.Add(UserField.Parse(bin)); } } // round cost block.RoundCost = new Money(); block.RoundCost.Integral = bin.ReadInt32(); block.RoundCost.Fraction = bin.ReadUInt64(); // transactions cnt = (int)bin.ReadUInt32(); if (cnt > 0) { block.Transactions = new List <Transaction>(); for (int i = 0; i < cnt; i++) { block.Transactions.Add(Transaction.Parse(bin)); } // round cost clarify if (block.RoundCost.IsZero) { foreach (var t in block.Transactions) { block.RoundCost += t.ActualFee; } } } // new wallets cnt = (int)bin.ReadUInt32(); if (cnt > 0) { block.IntroducedWallets = new List <WalletIntroduce>(); for (int i = 0; i < cnt; i++) { WalletIntroduce w = new WalletIntroduce(); Int64 v = bin.ReadInt64(); if (v < 0) { v = -v; // address is target if (v < block.Transactions.Count) { w.Key = block.Transactions[(int)v].Target; } } else { if (v < block.Transactions.Count) { w.Key = block.Transactions[(int)v].Source; } } w.Id = bin.ReadUInt32(); block.IntroducedWallets.Add(w); } } // consensus info // current RT cnt = (int)(uint)bin.ReadByte(); UInt64 bits_trusted = bin.ReadUInt64(); // count of "1" = sig_blk_cnt if (cnt > 0) { block.TrustedNodes = new List <ConsensusMember>(); for (int i = 0; i < cnt; i++) { block.TrustedNodes.Add(new ConsensusMember() { Id = new Primitives.PublicKey { Value = bin.ReadBytes(Primitives.PublicKeySize) } }); } } // previous consensus cnt = (int)(uint)bin.ReadByte(); if (cnt > 0) { block.TrustedApproval = new List <KeyValuePair <int, Primitives.Signature> >(); UInt64 bits_appr = bin.ReadUInt64(); int sig_prev_rt_cnt = CountBits(bits_appr); int isig = 0; for (int i = 0; i < cnt; i++) { if ((bits_appr & (0x1UL << i)) == 0) { continue; } if (isig >= sig_prev_rt_cnt) { break; } block.TrustedApproval.Add(new KeyValuePair <int, Primitives.Signature>( isig, new Primitives.Signature { Value = bin.ReadBytes(Primitives.SignatureSize) } )); isig++; } if (isig != sig_prev_rt_cnt) { //TODO: malformed trusted approval section } } hashing_len = (int)(uint)bin.ReadUInt64(); // continue read block.TrustedNodes (signatures) cnt = block.TrustedNodes.Count; for (int i = 0; i < cnt; i++) { if ((bits_trusted & (0x1UL << i)) == 0) { continue; } block.TrustedNodes[i].Signature = new Primitives.Signature() { Value = bin.ReadBytes(Primitives.SignatureSize) }; } // contract signatures cnt = (int)(uint)bin.ReadByte(); if (cnt > 0) { block.ContractsApproval = new List <ContractConfirmation>(); for (int i = 0; i < cnt; i++) { block.ContractsApproval.Add(ContractConfirmation.Parse(bin)); } } if (bin.BaseStream.Position == bin.BaseStream.Length) { if (hashing_len > 0) { block.Hash = new Primitives.Hash() { Value = Blake2s.ComputeHash(Primitives.HashSize, bytes.AsSpan(0, hashing_len)) }; } return(new ResponseBlock() { Success = true, Block = block }); } return(new ResponseBlock() { Success = false, Message = "The stream postion is not equal to the stream length" }); } } catch (Exception ex) { return(new ResponseBlock() { Success = false, Message = ex.Message }); } }