public static async Task MiningAsync(string minerName, string walletAddress) { while (true) { try { Console.WriteLine("new mining start"); bool isStop = false; bool isHeightChanged = false; ApiResponse response = await BlockChainEngineApi.GenerateNewBlock(minerName, walletAddress, 1); if (!response.HasError) { BlockInfoOM block = response.GetResult <BlockInfoOM>(); List <byte> blockData = new List <byte>(); foreach (BlockTransactionsOM tx in block.Transactions) { blockData.AddRange(tx.Serialize()); } string strDifficulty = string.Empty; ApiResponse difficultyResponse = await BlockChainEngineApi.GetDifficulty(); if (!difficultyResponse.HasError) { BlockDifficultyOM blockDifficulty = difficultyResponse.GetResult <BlockDifficultyOM>(); strDifficulty = blockDifficulty.HashTarget; } else { Logger.Singleton.Error(difficultyResponse.Error.Code.ToString()); Logger.Singleton.Error(difficultyResponse.Error.Message); Console.WriteLine(response.Error.Message); return; } //var cts = new CancellationTokenSource(); //var ct = cts.Token; //开启新线程 /* * Task task1 = Task.Run(async () => * { * try * { * Console.WriteLine("new thread validate block height"); * int count = 0; * while (!isStop) * { * ApiResponse tempResponse = await BlockChainEngineApi.GetBlockCount(); * if (!tempResponse.HasError) * { * count = 0; * Logger.Singleton.Info($"current count is {count}, current datetime is {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:ms")}"); * long height = tempResponse.GetResult<long>(); * Console.WriteLine($"current height of the chain is {height}"); * if (height >= block.Header.Height) * { * isStop = true; * isHeightChanged = true; * ct.ThrowIfCancellationRequested(); * cts.Cancel(); * } * } * else * { * count++; * Logger.Singleton.Warn($"current count is {count}, current datetime is {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:ms")}"); * if (count >= 5) * { * Logger.Singleton.Error(tempResponse.Error.Code.ToString()); * Logger.Singleton.Error(tempResponse.Error.Message); * isStop = true; * ct.ThrowIfCancellationRequested(); * cts.Cancel(); * } * } * * Console.WriteLine("thread will sleep 5 seconds"); * Thread.Sleep(3000); * } * } * catch (Exception ex) * { * cts.Cancel(); * Console.WriteLine($"something wrong with the application interface, {ex.ToString()}"); * isStop = true; * } * }, ct); */ Thread checkHeightThread = new Thread(async() => { try { Console.WriteLine("new thread validate block height"); int count = 0; while (!isStop) { ApiResponse tempResponse = await BlockChainEngineApi.GetBlockCount(); if (!tempResponse.HasError) { count = 0; //Logger.Singleton.Info($"current count is {count}, current datetime is {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:ms")}"); long height = tempResponse.GetResult <long>(); Console.WriteLine($"current height of the chain is {height}"); if (height >= block.Header.Height) { isStop = true; isHeightChanged = true; //ct.ThrowIfCancellationRequested(); //cts.Cancel(); } } else { count++; Logger.Singleton.Warn($"current count is {count}, current datetime is {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:ms")}"); if (count >= 3) { Logger.Singleton.Error(tempResponse.Error.Code.ToString()); Logger.Singleton.Error(tempResponse.Error.Message); isStop = true; //ct.ThrowIfCancellationRequested(); //cts.Cancel(); } } Console.WriteLine("thread will sleep 5 seconds"); Thread.Sleep(3000); } } catch (Exception ex) { //cts.Cancel(); Console.WriteLine($"something wrong with the application interface, {ex.ToString()}"); isStop = true; } }); checkHeightThread.Priority = ThreadPriority.Highest; checkHeightThread.Start(); Parallel.For(0L, Int64.MaxValue, new ParallelOptions { MaxDegreeOfParallelism = 10 }, async(i, loopState) => { if (isStop) { Console.WriteLine($"new thread has been stopped, stop main thread"); loopState.Stop(); return; } List <byte> newBuffer = new List <byte>(blockData.ToArray()); byte[] nonceBytes = BitConverter.GetBytes(i); if (BitConverter.IsLittleEndian) { Array.Reverse(nonceBytes); } newBuffer.AddRange(nonceBytes); string result = Base16.Encode( HashHelper.Hash( newBuffer.ToArray() )); Console.WriteLine($"current nonce is {i}, current datetime is {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:ms")}"); if (BlockInfoOM.Verify(strDifficulty, result)) { loopState.Stop(); //区块头的时间戳 block.Header.Timestamp = TimeHelper.EpochTime; //区块头的随机数 block.Header.Nonce = i; //区块头的hash block.Header.Hash = block.Header.GetHash(); //提交区块 Console.WriteLine($"verify success. nonce is {i}, block hash is {block.Header.Hash}"); ApiResponse submitResponse = await BlockChainEngineApi.SubmitBlock(Base16.Encode(block.Serialize())); if (!submitResponse.HasError) { //停止循环 //break; Logger.Singleton.Debug("A New Block " + block.Header.Height + "has been created, the correct nonce is " + i); } else { Console.WriteLine(submitResponse.Error.Message); Console.WriteLine(submitResponse.Error.Code.ToString()); if (submitResponse.Error.Code == 2060001) { isStop = true; isHeightChanged = true; } else { Environment.Exit(0); } } } }); if (isStop) { if (isHeightChanged) { Console.WriteLine("block height changed, new loop will start"); continue; } else { Console.WriteLine("something wrong with the application interface, system exit"); Environment.Exit(0); return; } } } else { Logger.Singleton.Error(response.Error.Code.ToString()); Logger.Singleton.Error(response.Error.Message); Console.WriteLine(response.Error.Message); Environment.Exit(0); return; } } catch (Exception ex) { Logger.Singleton.Error(ex.ToString()); Logger.Singleton.Error(ex.ToString()); Environment.Exit(0); return; } } }
public void Decode_ExceptionTest(string hex) { Assert.Throws <ArgumentException>(() => Base16.Decode(hex)); }
public void Encode_ExceptionTest() { Assert.Throws <ArgumentNullException>(() => Base16.Encode(null)); }
public void ValidateToken_V2_S_1() { const string token = "v2.public.eyJkYXRhIjoidGhpcyBpcyBhIHNpZ25lZCBtZXNzYWdlIiwiZXhwIjoiMjAxOS0wMS0wMVQwMDowMDowMCswMDowMCJ9HQr8URrGntTu7Dz9J2IF23d1M7-9lH9xiqdGyJNvzp4angPW5Esc7C5huy_M8I8_DjJK2ZXC2SUYuOFM-Q_5Cw"; const string publicKeyHex = "1eb9dbbbbc047c03fd70604e0071f0987e16b28b757225c11f00415d0e20b1a2"; // payload = {"data":"this is a signed message", "exp":"2019-01-01T00:00:00+00:00"} var handler = new PasetoTokenHandler(); var result = handler.ValidateToken(token, new TokenValidationParameters { ValidateIssuer = false, ValidateAudience = false, ValidateLifetime = false, IssuerSigningKey = new EdDsaSecurityKey(new Ed25519PublicKeyParameters(Base16.Decode(publicKeyHex), 0)) }); result.IsValid.Should().BeTrue(); }
public void IsValid_FalseTest(string hex) { Assert.False(Base16.IsValid(hex)); }
internal void RendezvousIntroduce(Circuit rendezvous_circuit, byte[] rendezvous_cookie) { Globals.Assert(rendezvous_cookie.Length == 20); OnionRouter introduction_point = FinalCircuitNode.OnionRouter; OnionRouter introducee = rendezvous_circuit.FinalCircuitNode.OnionRouter; Logger.Debug("circuit::rendezvous_introduce() [or: {0}, state: introducing]", introduction_point.Name); this.State = Circuit.CircuitState.rendezvous_introducing; Logger.Debug("circuit::rendezvous_introduce() [or: {0}, state: completing]", introduction_point.Name); rendezvous_circuit.State = CircuitState.rendezvous_completing; // payload of the RELAY_COMMAND_INTRODUCE1 // command: // // PK_ID Identifier for Bob's PK [20 octets] // VER Version byte: set to 2. [1 octet] // IP Rendezvous point's address [4 octets] // PORT Rendezvous point's OR port [2 octets] // ID Rendezvous point identity ID [20 octets] // KLEN Length of onion key [2 octets] // KEY Rendezvous point onion key [KLEN octets] // RC Rendezvous cookie [20 octets] // g^x Diffie-Hellman data, part 1 [128 octets] // // compute PK_ID, aka hash of the service key. byte[] service_key_hash = SHA1.Hash(introduction_point.ServiceKey); // create rest of the payload in separate buffer; // it will be encrypted. byte[] handshake_bytes = new byte[] { (byte)( 1 + // version 4 + // ip address 2 + // port Constants.HASH_LEN + // identity_fingerprint 2 + // onion key size introducee.OnionKey.Length + // onion key 20 + // rendezvous cookie 128) }; // DH MemoryStream handshake_stream = new MemoryStream(handshake_bytes); StreamWrapper handshake_buffer = new StreamWrapper(handshake_stream, Endianness.big_endian); rendezvous_circuit._extend_node = CreateCircuitNode(introduction_point, CircuitNode.Type.introduction_point); handshake_buffer.Write((byte)2); handshake_buffer.Write(introducee.IPAddress.GetAddressBytes().SwapEndianness()); handshake_buffer.Write(introducee.ORPort); handshake_buffer.Write(Base16.Decode(introducee.IdentityFingerprint)); handshake_buffer.Write((ushort)(introducee.OnionKey.Length)); handshake_buffer.Write(introducee.OnionKey); handshake_buffer.Write(rendezvous_cookie); handshake_buffer.Write(rendezvous_circuit._extend_node.KeyAgreement.PublicKey.ToBytes()); byte[] handshake_encrypted = HybridEncryptor.Encrypt(handshake_bytes, introduction_point.ServiceKey); // compose the final payload. List <byte> relay_payload_bytes = new List <byte>(); relay_payload_bytes.AddRange(service_key_hash); relay_payload_bytes.AddRange(handshake_encrypted); // send the cell. SendRelayCell(0, CellCommand.relay_command_introduce1, relay_payload_bytes.ToArray()); WaitForState(Circuit.CircuitState.rendezvous_introduced); Logger.Debug("circuit::rendezvous_introduce() [or: {0}, state: introduced]", introduction_point.Name); rendezvous_circuit.WaitForState(Circuit.CircuitState.rendezvous_completed); Logger.Debug("circuit::rendezvous_introduce() [or: {0}, state: completed]", introduction_point.Name); }
private static CalendarHashChain GetCalendarHashChain(bool excludeLastRightLink = false, bool addExtraRightLink = false) { TlvTagBuilder builder = new TlvTagBuilder(Constants.CalendarHashChain.TagType, false, false); builder.AddChildTag(new IntegerTag(Constants.CalendarHashChain.PublicationTimeTagType, false, false, 1455494400)); builder.AddChildTag(new IntegerTag(Constants.CalendarHashChain.AggregationTimeTagType, false, false, 1455478441)); builder.AddChildTag(new ImprintTag(Constants.CalendarHashChain.InputHashTagType, false, false, new DataHash(Base16.Decode("012C8149F374FDDCD5443456BC7E8FFA310B7FE090DAA98C0980B81EC2407FD013")))); builder.AddChildTag(new RawTag((uint)LinkDirection.Right, false, false, Base16.Decode("011A039DE0761EEC75F6CCB4B17720E0565AC694BB8B2211BB30B22DD9AC45F931"))); builder.AddChildTag(new RawTag((uint)LinkDirection.Left, false, false, Base16.Decode("013A23B4518A0A73BB2BED9087857D9D27E2B36BDEAE2BB75600D97A7FB278B93F"))); builder.AddChildTag(new RawTag((uint)LinkDirection.Left, false, false, Base16.Decode("01AAFF5F7AC584B2BDDCC60F5920259D1726399EA5B72F3EE52F0F343FDEFBA44A"))); builder.AddChildTag(new RawTag((uint)LinkDirection.Right, false, false, Base16.Decode("01F7D776798EFF2A0B75FFD135D45F2717C25909BAF482A04CF15F70C4E2BD75A7"))); builder.AddChildTag(new RawTag((uint)LinkDirection.Left, false, false, Base16.Decode("01F06569DB8E8370014BFDD867FBA440717D3207EA8629A15918EDD20772DF7ADF"))); builder.AddChildTag(new RawTag((uint)LinkDirection.Right, false, false, Base16.Decode("01E994F25C01928F616C1D4B5F3715CD70586FAC3DF056E40FC88B5E7F3D11FBBF"))); builder.AddChildTag(new RawTag((uint)LinkDirection.Left, false, false, Base16.Decode("015251B1496CABF85D2FB6E7D029AE026FBAAF69018ECBD480C746174ACCF3974B"))); builder.AddChildTag(new RawTag((uint)LinkDirection.Right, false, false, Base16.Decode("01F5B1B5665B31B1CBE0EA66222E5905A43D7CB735ACDCF9D6C2931A23C1798797"))); builder.AddChildTag(new RawTag((uint)LinkDirection.Left, false, false, Base16.Decode("011C392604BA9550C81028BFD12C41A8CD880FACF1970B2F1FE03F616D06257C19"))); builder.AddChildTag(new RawTag((uint)LinkDirection.Right, false, false, Base16.Decode("01E47589DA097DA8C79A2B79D98A4DEA1484F28DB52A513AFD92166BF4894379C3"))); builder.AddChildTag(new RawTag((uint)LinkDirection.Right, false, false, Base16.Decode("01F4C67A2D3BD0C46CF9064C3909A41A0D3178CCE6B729E700CFA240E4CF049841"))); builder.AddChildTag(new RawTag((uint)LinkDirection.Left, false, false, Base16.Decode("0137E949ABAF6636312569F29CAB705E9A45DB96A15BFB26BC26403F60D4894162"))); builder.AddChildTag(new RawTag((uint)LinkDirection.Right, false, false, Base16.Decode("0102459F392EBEE422991B251625C9E9E63C6394A8D1307EC9036BFCEB48E3F431"))); builder.AddChildTag(new RawTag((uint)LinkDirection.Left, false, false, Base16.Decode("01255FE067AFB88E68FA9957626FD72553C3ADFC85B6072145DDFCDE94CC22FE51"))); builder.AddChildTag(new RawTag((uint)LinkDirection.Right, false, false, Base16.Decode("0182E16E325B51C2D8B29494DDB9DE3CB2718A8F135D8F2B1D1D2AD240A60B306F"))); builder.AddChildTag(new RawTag((uint)LinkDirection.Right, false, false, Base16.Decode("015234BB37CEAA00A36D44AABFC25215B1899573CE1A76827F070D7D2C68AF9DE6"))); builder.AddChildTag(new RawTag((uint)LinkDirection.Left, false, false, Base16.Decode("015786F1B0135C3A37C66C3958A32F7E90123BB9C8137A98861C6307C70079842C"))); builder.AddChildTag(new RawTag((uint)LinkDirection.Right, false, false, Base16.Decode("0136E2E89E8F3928F80A6D89AD666354E145473B2C6FF683F0796DAA68F2004545"))); builder.AddChildTag(new RawTag((uint)LinkDirection.Right, false, false, Base16.Decode("01E44F0A3EA272C03DEFC1825D3148F0DC4060CF6BAF04F3ACD0B9AFA9EE52CAD5"))); builder.AddChildTag(new RawTag((uint)LinkDirection.Right, false, false, Base16.Decode("01A0698E6B45EDEEAF9037E49F668114617CA60124F0FC416D017D06D78CA4295A"))); builder.AddChildTag(new RawTag((uint)LinkDirection.Right, false, false, Base16.Decode("01A6F082B82280F3A6AFB14C8E39B7F57860B857B70CA57AFD35F40395EEB32458"))); builder.AddChildTag(new RawTag((uint)LinkDirection.Right, false, false, Base16.Decode("01496FC0120D854E7534B992AB32EC3045B20D4BEE1BFBE4564FD092CEAFA08B72"))); if (!excludeLastRightLink) { builder.AddChildTag(new RawTag((uint)LinkDirection.Right, false, false, Base16.Decode("01BB44FD36A5F3CDEE7B5C6DF3A6098A09E353335B6029F1477502588A7E37BE00"))); } if (addExtraRightLink) { builder.AddChildTag(new RawTag((uint)LinkDirection.Right, false, false, Base16.Decode("012C8149F374FDDCD5443456BC7E8FFA310B7FE090DAA98C0980B81EC2407FD013"))); } return(new CalendarHashChain(builder.BuildTag())); }
public IRpcMethodResult ListTransactions(string account, int count, int skip = 0, bool includeWatchOnly = true) { try { var txComponent = new TransactionComponent(); var accountComponent = new AccountComponent(); var addressBookComponent = new AddressBookComponent(); var utxoComponent = new UtxoComponent(); var blockComponent = new BlockComponent(); var transactionCommentComponent = new TransactionCommentComponent(); List <PaymentOM> result = new List <PaymentOM>(); var accounts = accountComponent.GetAllAccounts(); var paymentAccountIds = accounts.Where(a => !string.IsNullOrWhiteSpace(a.PrivateKey)).Select(a => a.Id).ToList(); var allAccountIds = accounts.Select(a => a.Id).ToList(); var addressBook = addressBookComponent.GetWholeAddressBook(); var latestHeight = blockComponent.GetLatestHeight(); var data = txComponent.SearchTransactionEntities(account, count, skip, includeWatchOnly); foreach (var tx in data) { long totalInput = 0; long selfTotalOutput = 0; long otherUserTotalOutput = 0; bool coibase = false; if (tx.Inputs.Count == 1 && tx.Outputs.Count == 1 && tx.Inputs[0].OutputTransactionHash == Base16.Encode(HashHelper.EmptyHash())) { coibase = true; } if (!coibase) { foreach (var input in tx.Inputs) { var oldOutput = txComponent.GetOutputEntiyByIndexAndTxHash(input.OutputTransactionHash, input.OutputIndex); if (oldOutput != null && paymentAccountIds.Contains(oldOutput.ReceiverId)) { totalInput += input.Amount; } else { totalInput = 0; break; } } } foreach (var output in tx.Outputs) { if (allAccountIds.Contains(output.ReceiverId)) { selfTotalOutput += output.Amount; } else { otherUserTotalOutput += output.Amount; } } BlockMsg block = null; if (tx.BlockHash != null) { block = blockComponent.GetBlockMsgByHash(tx.BlockHash); } if (coibase) { var payment = new PaymentOM(); payment.address = tx.Outputs[0].ReceiverId; payment.account = accounts.Where(a => a.Id == payment.address).Select(a => a.Tag).FirstOrDefault(); payment.category = "generate"; payment.totalInput = totalInput; payment.totalOutput = selfTotalOutput; payment.amount = selfTotalOutput; payment.fee = 0; payment.txId = tx.Hash; payment.vout = 0; payment.time = tx.Timestamp; payment.size = tx.Size; var txComment = transactionCommentComponent.GetByTransactionHashAndIndex(tx.Hash, 0); if (txComment != null) { payment.comment = txComment.Comment; } if (block != null) { payment.blockHash = tx.BlockHash; payment.blockIndex = 0;// block.Transactions.FindIndex(t=>t.Hash == tx.Hash); payment.blockTime = block.Header.Timestamp; payment.confirmations = latestHeight - block.Header.Height + 1; } else { payment.confirmations = 0; } result.Add(payment); } else if (totalInput > 0 && otherUserTotalOutput == 0) { var payment = new PaymentOM(); payment.address = null; payment.account = null; payment.category = "self"; payment.totalInput = totalInput; payment.totalOutput = tx.Outputs[0].Amount;// selfTotalOutput; payment.fee = totalInput - selfTotalOutput; payment.amount = payment.fee; payment.txId = tx.Hash; payment.vout = 0; payment.time = tx.Timestamp; payment.size = tx.Size; var txComments = transactionCommentComponent.GetByTransactionHash(tx.Hash); if (txComments.Count > 0) { payment.comment = ""; foreach (var item in txComments) { if (!string.IsNullOrWhiteSpace(item.Comment)) { payment.comment += item.Comment + ";"; } } } if (block != null) { payment.blockHash = tx.BlockHash; payment.blockIndex = block.Transactions.FindIndex(t => t.Hash == tx.Hash); payment.blockTime = block.Header.Timestamp; payment.confirmations = latestHeight - block.Header.Height + 1; } else { payment.confirmations = 0; } result.Add(payment); } else if (totalInput > 0) { for (int i = 0; i < tx.Outputs.Count; i++) { if (!allAccountIds.Contains(tx.Outputs[i].ReceiverId)) { var payment = new PaymentOM(); payment.address = tx.Outputs[i].ReceiverId; payment.account = addressBook.Where(a => a.Address == payment.address && !string.IsNullOrWhiteSpace(a.Tag)).Select(a => a.Tag).FirstOrDefault(); payment.category = "send"; payment.totalInput = totalInput; payment.totalOutput = tx.Outputs[i].Amount; payment.fee = totalInput - (selfTotalOutput + otherUserTotalOutput); payment.amount = (i == 0 ? tx.Outputs[i].Amount + payment.fee : tx.Outputs[i].Amount); payment.txId = tx.Hash; payment.vout = i; payment.time = tx.Timestamp; payment.size = tx.Size; var txComment = transactionCommentComponent.GetByTransactionHashAndIndex(tx.Hash, i); if (txComment != null) { payment.comment = txComment.Comment; } if (block != null) { payment.blockHash = tx.BlockHash; payment.blockIndex = block.Transactions.FindIndex(t => t.Hash == tx.Hash); payment.blockTime = block.Header.Timestamp; payment.confirmations = latestHeight - block.Header.Height + 1; } else { payment.confirmations = 0; } result.Add(payment); } } } else { for (int i = 0; i < tx.Outputs.Count; i++) { if (allAccountIds.Contains(tx.Outputs[i].ReceiverId)) { var payment = new PaymentOM(); payment.address = tx.Outputs[i].ReceiverId; payment.account = accounts.Where(a => a.Id == payment.address).Select(a => a.Tag).FirstOrDefault();; payment.category = "receive"; payment.totalInput = totalInput; payment.totalOutput = tx.Outputs[i].Amount; payment.fee = totalInput - (selfTotalOutput + otherUserTotalOutput); payment.amount = tx.Outputs[i].Amount; payment.txId = tx.Hash; payment.vout = i; payment.time = tx.Timestamp; payment.size = tx.Size; var txComment = transactionCommentComponent.GetByTransactionHashAndIndex(tx.Hash, i); if (txComment != null) { payment.comment = txComment.Comment; } if (block != null) { payment.blockHash = tx.BlockHash; payment.blockIndex = block.Transactions.FindIndex(t => t.Hash == tx.Hash); payment.blockTime = block.Header.Timestamp; payment.confirmations = latestHeight - block.Header.Height + 1; } else { payment.confirmations = 0; } result.Add(payment); } } } } return(Ok(result)); } catch (CommonException ce) { return(Error(ce.ErrorCode, ce.Message, ce)); } catch (Exception ex) { return(Error(ErrorCode.UNKNOWN_ERROR, ex.Message, ex)); } }
public void Decode(Base16 encoder, byte[] expectedOutput, string input) { var result = encoder.Decode(input); CollectionAssert.AreEqual(expectedOutput, result.ToArray()); }
public IRpcMethodResult SendMany(string fromAccount, SendManyOutputIM[] receivers, string[] feeDeductAddresses) { try { string result = null; var utxoComponent = new UtxoComponent(); var txComponent = new TransactionComponent(); var settingComponent = new SettingComponent(); var addressBookComponent = new AddressBookComponent(); var accountComponent = new AccountComponent(); var transactionCommentComponent = new TransactionCommentComponent(); var blockComponent = new BlockComponent(); var lastBlockHeight = blockComponent.GetLatestHeight(); var setting = settingComponent.GetSetting(); var utxos = utxoComponent.GetAllConfirmedOutputs(); var tx = new TransactionMsg(); double totalOutput = 0; var totalSize = tx.Serialize().Length; if (receivers == null || receivers.Length == 0) { throw new CommonException(ErrorCode.Service.Transaction.TO_ADDRESS_INVALID); } foreach (var receiver in receivers) { if (!AccountIdHelper.AddressVerify(receiver.address)) { throw new CommonException(ErrorCode.Service.Transaction.TO_ADDRESS_INVALID); } var output = new OutputMsg(); output.Amount = receiver.amount; output.Index = tx.Outputs.Count; output.LockScript = Script.BuildLockScipt(receiver.address); output.Size = output.LockScript.Length; tx.Outputs.Add(output); totalSize += output.Serialize().Length; totalOutput += receiver.amount; } foreach (var address in feeDeductAddresses) { if (receivers.Where(r => r.address == address).Count() == 0) { throw new CommonException(ErrorCode.Service.Transaction.FEE_DEDUCT_ADDRESS_INVALID); } } var totalInput = 0L; var index = 0; double totalFee = setting.FeePerKB * ((double)totalSize / 1024.0); double totalAmount = totalOutput; while (index < utxos.Count) { var account = accountComponent.GetAccountById(utxos[index].AccountId); if (account != null && !string.IsNullOrWhiteSpace(account.PrivateKey)) { var utxoTX = txComponent.GetTransactionMsgByHash(utxos[index].TransactionHash); Block utxoBlock = blockComponent.GetBlockEntiytByHash(utxos[index].BlockHash); if (utxoTX == null || utxoBlock == null) { index++; continue; } if (!utxoBlock.IsVerified) { index++; continue; } if (Time.EpochTime < utxoTX.Locktime) { index++; continue; } if (utxoTX.InputCount == 1 && utxoTX.Inputs[0].OutputTransactionHash == Base16.Encode(HashHelper.EmptyHash())) { var blockHeight = utxoBlock.Height; if (lastBlockHeight - blockHeight < 100L) { index++; continue; } } var input = new InputMsg(); input.OutputTransactionHash = utxos[index].TransactionHash; input.OutputIndex = utxos[index].OutputIndex; input.UnlockScript = Script.BuildUnlockScript(input.OutputTransactionHash, input.OutputIndex, Base16.Decode(decryptPrivateKey(account.PrivateKey)), Base16.Decode(account.PublicKey)); input.Size = input.UnlockScript.Length; tx.Inputs.Add(input); var size = input.Serialize().Length; totalSize += size; totalFee += setting.FeePerKB * ((double)size / 1024.0); totalInput += utxos[index].Amount; } else { index++; continue; } if (feeDeductAddresses == null || feeDeductAddresses.Length == 0) { totalAmount = totalOutput + totalFee; } if (totalInput >= (long)Math.Ceiling(totalAmount)) { var size = tx.Outputs[0].Serialize().Length; if ((totalInput - (long)Math.Ceiling(totalAmount)) > (setting.FeePerKB * (double)size / 1024.0)) { totalSize += size; totalFee += setting.FeePerKB * ((double)size / 1024.0); if (feeDeductAddresses == null || feeDeductAddresses.Length == 0) { totalAmount = totalOutput + totalFee; } var newAccount = accountComponent.GenerateNewAccount(); if (setting.Encrypt) { if (!string.IsNullOrWhiteSpace(_cache.Get <string>("WalletPassphrase"))) { newAccount.PrivateKey = AES128.Encrypt(newAccount.PrivateKey, _cache.Get <string>("WalletPassphrase")); accountComponent.UpdatePrivateKeyAr(newAccount); } else { throw new CommonException(ErrorCode.Service.Wallet.WALLET_HAS_BEEN_LOCKED); } } var newOutput = new OutputMsg(); newOutput.Amount = totalInput - (long)Math.Ceiling(totalAmount); newOutput.Index = tx.Outputs.Count; newOutput.LockScript = Script.BuildLockScipt(newAccount.Id); newOutput.Size = newOutput.LockScript.Length; tx.Outputs.Add(newOutput); } break; } index++; } if (totalInput < totalAmount) { throw new CommonException(ErrorCode.Service.Transaction.BALANCE_NOT_ENOUGH); } if (feeDeductAddresses != null && feeDeductAddresses.Length > 0) { var averageFee = totalFee / feeDeductAddresses.Length; for (int i = 0; i < receivers.Length; i++) { if (feeDeductAddresses.Contains(receivers[i].address)) { tx.Outputs[i].Amount -= (long)Math.Ceiling(averageFee); if (tx.Outputs[i].Amount <= 0) { throw new CommonException(ErrorCode.Service.Transaction.SEND_AMOUNT_LESS_THAN_FEE); } } } } tx.Timestamp = Time.EpochTime; tx.Hash = tx.GetHash(); txComponent.AddTransactionToPool(tx); Startup.P2PBroadcastTransactionAction(tx.Hash); result = tx.Hash; for (int i = 0; i < receivers.Length; i++) { var receiver = receivers[i]; if (!string.IsNullOrWhiteSpace(receiver.tag)) { addressBookComponent.SetTag(receiver.address, receiver.tag); } if (!string.IsNullOrWhiteSpace(receiver.comment)) { transactionCommentComponent.Add(tx.Hash, i, receiver.comment); } } return(Ok(result)); } catch (CommonException ce) { return(Error(ce.ErrorCode, ce.Message, ce)); } catch (Exception ex) { return(Error(ErrorCode.UNKNOWN_ERROR, ex.Message, ex)); } }
public IRpcMethodResult EstimateTxFeeForSendToAddress(string toAddress, long amount, string comment, string commentTo, bool deductFeeFromAmount) { try { EstimateTxFeeOM result = new EstimateTxFeeOM(); var utxoComponent = new UtxoComponent(); var txComponent = new TransactionComponent(); var settingComponent = new SettingComponent(); var addressBookComponent = new AddressBookComponent(); var accountComponent = new AccountComponent(); if (!AccountIdHelper.AddressVerify(toAddress)) { throw new CommonException(ErrorCode.Service.Transaction.TO_ADDRESS_INVALID); } var setting = settingComponent.GetSetting(); var utxos = utxoComponent.GetAllConfirmedOutputs(); var tx = new TransactionMsg(); var totalSize = tx.Serialize().Length; var output = new OutputMsg(); output.Amount = amount; output.Index = 0; output.LockScript = Script.BuildLockScipt(toAddress); output.Size = output.LockScript.Length; tx.Outputs.Add(output); totalSize += output.Serialize().Length; var blockComponent = new BlockComponent(); var lastBlockHeight = blockComponent.GetLatestHeight(); var totalInput = 0L; var index = 0; double totalAmount = amount; double totalFee = setting.FeePerKB * ((double)totalSize / 1024.0); while (index < utxos.Count) { var account = accountComponent.GetAccountById(utxos[index].AccountId); if (account != null && !string.IsNullOrWhiteSpace(account.PrivateKey)) { var utxoTX = txComponent.GetTransactionMsgByHash(utxos[index].TransactionHash); Block utxoBlock = blockComponent.GetBlockEntiytByHash(utxos[index].BlockHash); if (utxoTX == null || utxoBlock == null) { index++; continue; } if (!utxoBlock.IsVerified) { index++; continue; } if (Time.EpochTime < utxoTX.Locktime) { index++; continue; } if (utxoTX.InputCount == 1 && utxoTX.Inputs[0].OutputTransactionHash == Base16.Encode(HashHelper.EmptyHash())) { var blockHeight = utxoBlock.Height; if (lastBlockHeight - blockHeight < 100L) { index++; continue; } } var input = new InputMsg(); input.OutputTransactionHash = utxos[index].TransactionHash; input.OutputIndex = utxos[index].OutputIndex; input.UnlockScript = Script.BuildUnlockScript(input.OutputTransactionHash, input.OutputIndex, Base16.Decode(decryptPrivateKey(account.PrivateKey)), Base16.Decode(account.PublicKey)); input.Size = input.UnlockScript.Length; tx.Inputs.Add(input); var size = input.Serialize().Length; totalSize += size; totalFee += setting.FeePerKB * ((double)size / 1024.0); totalInput += utxos[index].Amount; } else { index++; continue; } if (!deductFeeFromAmount) { totalAmount = amount + totalFee; } if (totalInput >= (long)Math.Ceiling(totalAmount)) { var size = output.Serialize().Length; if ((totalInput - (long)Math.Ceiling(totalAmount)) > (setting.FeePerKB * (double)size / 1024.0)) { totalSize += size; totalFee += setting.FeePerKB * ((double)size / 1024.0); } break; } index++; } if (totalInput < totalAmount) { throw new CommonException(ErrorCode.Service.Transaction.BALANCE_NOT_ENOUGH); } if (deductFeeFromAmount) { output.Amount -= (long)Math.Ceiling(totalFee); if (output.Amount <= 0) { throw new CommonException(ErrorCode.Service.Transaction.SEND_AMOUNT_LESS_THAN_FEE); } } result.totalFee = Convert.ToInt64(totalFee); result.totalSize = Convert.ToInt32(totalSize); return(Ok(result)); } catch (CommonException ce) { return(Error(ce.ErrorCode, ce.Message, ce)); } catch (Exception ex) { return(Error(ErrorCode.UNKNOWN_ERROR, ex.Message, ex)); } }
public void TestCreateAggregationHashChainWithLinksOk() { ReadOnlyCollection <AggregationHashChain.Link> links = GetAggregationHashChainFromFile(Resources.AggregationHashChain_Ok).GetChainLinks(); AggregationHashChain newAggregationHashChain = new AggregationHashChain(1, new ulong[] { 1 }, new DataHash(Base16.Decode("01404572B3A03FCBB57D265903A153B24237F277723D1B24A199F9F009A4EB23BE")), 1, links.ToArray()); Assert.AreEqual(links.Count, newAggregationHashChain.GetChainLinks().Count, "Unexpected links count"); Assert.AreEqual(LinkDirection.Left, links[0].Direction, "Unexpected link direction"); Assert.AreEqual(new DataHash(Base16.Decode("01E8EE4A17C22DFA36839998F24DEC73E78DA7B0A92FF3530570AF98117F406DDF")), links[0].SiblingHash, "Unexpected sibling hash"); Assert.IsNull(links[0].Metadata, "Unexpected metadata"); }
private void DumpBlocks(Chain chain) { Console.WriteLine($"Analysing blocks on {chain.Name} chain"); var blockList = new List <BlockEntry>(); var txList = new List <TxEntry>(); var eventList = new List <EventEntry>(); var transferList = new List <TransferEntry>(); var addresses = new Dictionary <string, AddressEntry>(); var balances = new Dictionary <string, BigInteger>(); for (uint i = 1; i < chain.Height; i++) { var blockHash = chain.GetBlockHashAtHeight(i); var block = chain.GetBlockByHash(blockHash); blockList.Add(new BlockEntry(block.Height, block.Hash.ToString(), block.Timestamp.Value, block.TransactionCount)); foreach (var txHash in block.TransactionHashes) { var tx = chain.GetTransactionByHash(txHash); var fee = chain.GetTransactionFee(tx); var events = block.GetEventsForTransaction(txHash); var txType = DetectTransactionType(events.Where(x => x.Contract != "gas")); txList.Add(new TxEntry(block.Height, tx.Hash.ToString(), block.Timestamp.Value, UnitConversion.ToDecimal(fee, DomainSettings.FuelTokenDecimals), txType)); foreach (var evt in events) { var addr = evt.Address.Text; eventList.Add(new EventEntry(block.Height, tx.Hash.ToString(), block.Timestamp.Value, evt.Kind, addr, evt.Contract, Base16.Encode(evt.Data))); if (!addresses.ContainsKey(addr)) { addresses[addr] = new AddressEntry(addr, block.Timestamp.Value); } int mult = 0; switch (evt.Kind) { case EventKind.TokenReceive: case EventKind.TokenClaim: case EventKind.TokenMint: mult = 1; break; case EventKind.TokenStake: case EventKind.TokenBurn: case EventKind.TokenSend: mult = -1; break; } if (mult != 0) { var data = Serialization.Unserialize <TokenEventData>(evt.Data); var amount = data.Value * mult; var key = addr + data.Symbol; BigInteger balance = balances.ContainsKey(key) ? balances[key] : 0; transferList.Add(new TransferEntry(block.Height, tx.Hash.ToString(), block.Timestamp.Value, evt.Kind, addr, data.Symbol, amount.ToString(), balance.ToString())); balance += amount; balances[key] = balance; } } } } var lines = new List <string>(); blockList.ForEach(x => lines.Add($"{x.height},{x.hash},{x.timestamp},{x.txCount}")); File.WriteAllLines($"{outputFolder}/{chain.Name}_blocks.csv", lines); lines.Clear(); txList.ForEach(x => lines.Add($"{x.height},{x.hash},{x.timestamp},{x.fee},{x.type}")); File.WriteAllLines($"{outputFolder}/{chain.Name}_transactions.csv", lines); lines.Clear(); eventList.ForEach(x => lines.Add($"{x.height},{x.hash},{x.timestamp},{x.kind},{x.contract},{x.address},{x.data}")); File.WriteAllLines($"{outputFolder}/{chain.Name}_events.csv", lines); lines.Clear(); transferList.ForEach(x => lines.Add($"{x.height},{x.hash},{x.timestamp},{x.kind},{x.address},{x.symbol},{x.amount},{x.balance}")); File.WriteAllLines($"{outputFolder}/{chain.Name}_transfers.csv", lines); var addressList = addresses.Values.ToList(); addressList.Sort((x, y) => x.timestamp.CompareTo(y.timestamp)); lines.Clear(); addressList.ForEach(x => lines.Add($"{x.timestamp},{x.address}")); File.WriteAllLines($"{outputFolder}/{chain.Name}_addresses.csv", lines); /*string connstring = string.Format("Server={0}; database={1}; UID={2}; password={3}", "localhost", "phantasma", "root", "root"); * var connection = new MySqlConnection(connstring); * connection.Open(); * * ExecuteQuery(connection, "DROP TABLE IF EXISTS `events`;);*/ }
public static byte[] GenerateMultisigScript(MultisigSettings settings) { var scriptHead = new List <string>(); bool isTrue = true; bool isFalse = false; for (int i = 0; i < settings.addressArray.Length; i++) { scriptHead.Add($"load r1 { i }"); scriptHead.Add($"load r2 0x{ Base16.Encode(settings.addressArray[i].PublicKey) }"); scriptHead.Add($"put r2 r3 r1"); } // needs to check send/receive triggers! NOT YET DONE var scriptTail = new string[] { "alias r4 $minSigned", "alias r5 $addrCount", "alias r6 $i", "alias r7 $loopResult", "alias r8 $interResult", "alias r9 $result", "alias r10 $signed", "alias r11 $temp", "alias r12 $true", // check if we are sending/receiving "alias r13 $triggerSend", "alias r14 $currentTrigger", "alias r15 $false", $"load $false { isFalse }", $@"load $triggerSend, ""{AccountContract.TriggerSend}""", $"pop $currentTrigger", $"equal $triggerSend, $currentTrigger, $result", $"jmpnot $result, @finishNotSend", $"load $minSigned { settings.signeeCount }", $"load $addrCount { settings.addressArray.Length }", "load $signed 0", $"load $true { isTrue }", "load $i 0", "@loop: ", "lt $i $addrCount $loopResult", "jmpnot $loopResult @checkSigned", // get address from array "get r3 $temp $i", // push address to stack "push $temp", // convert to address object "extcall \"Address()\"", "call @checkWitness", "equal $interResult, $true, $result", "jmpif $result @increm", "inc $i", "jmp @loop", "@increm:", "inc $signed", "inc $i", "jmp @loop", "@checkSigned: ", "gte $signed $minSigned $result", "jmpif $result @finish", "jmpnot $result @break", "ret", "@finish:", "push $result", "ret", "@finishNotSend:", "push $true", "ret", "@break:", "throw", "@checkWitness: ", "extcall \"CheckWitness()\"", "pop $interResult", "ret", }; var scriptString = scriptHead.Concat(scriptTail.ToArray()).ToArray(); // temp test log to verify script List <string> tempList = new List <string>(scriptString); tempList.ForEach(Console.WriteLine); // build script var script = AssemblerUtils.BuildScript(scriptString); return(script); }
public void GetHashCode_ReturnsAlphabetHashCode([ValueSource(nameof(encoders))] Base16 encoder) { Assert.That(encoder.GetHashCode(), Is.EqualTo(encoder.Alphabet.GetHashCode())); }
public void Decode_OtherCase_StillPasses(Base16 encoder, byte[] expectedOutput, string input) { var result = encoder.Decode(input.ToUpperInvariant()); CollectionAssert.AreEqual(expectedOutput, result.ToArray()); }
public void Encode(Base16 encoder, byte[] input, string expectedOutput) { var result = encoder.Encode(input); Assert.That(result, Is.EqualTo(expectedOutput)); }
public void Decode_InvalidChar_Throws( [ValueSource(nameof(encoders))] Base16 encoder, [Values("AZ12", "ZAAA", "!AAA", "=AAA")] string input) { _ = Assert.Throws <ArgumentException>(() => encoder.Decode(input)); }
private void receiveDataAsync(IAsyncResult ar) { IPEndPoint remote = null; byte[] buffer = null; try { buffer = server.EndReceive(ar, ref remote); this.TotalBytesReceived += buffer.Length; var peer = this.Peers.Where(p => p.IP == remote.Address.ToString() && p.Port == remote.Port).FirstOrDefault(); if (peer != null) { peer.TotalBytesReceived += buffer.Length; peer.LastReceivedTime = Time.EpochTime; } LogHelper.Debug(DateTime.Now + " Received cmd from " + remote.Address + ", Data:" + Base16.Encode(buffer)); var prefix = new byte[4]; var suffix = new byte[4]; bool isBufferEnd = false; var key = remote.Address + ":" + remote.Port; if (buffer.Length > 4) { Array.Copy(buffer, 0, prefix, 0, 4); Array.Copy(buffer, buffer.Length - 4, suffix, 0, 4); if (!this.receivedMessageBuffer.ContainsKey(key)) { this.receivedMessageBuffer.Add(key, new List <byte>()); } //first data package if (P2PCommand.BytesEquals(P2PCommand.DefaultPrefixBytes, prefix)) { this.receivedMessageBuffer[key] = new List <byte>(); this.receivedMessageBuffer[key].AddRange(buffer); //last data package if (P2PCommand.BytesEquals(P2PCommand.DefaultSuffixBytes, suffix)) { isBufferEnd = true; } else { } } else if (P2PCommand.BytesEquals(P2PCommand.DefaultSuffixBytes, suffix)) { this.receivedMessageBuffer[key].AddRange(buffer); isBufferEnd = true; } //other data package else { this.receivedMessageBuffer[key].AddRange(buffer); } } else { this.receivedMessageBuffer[key].AddRange(buffer); isBufferEnd = true; } if (isBufferEnd) { var command = P2PCommand.ConvertBytesToMessage(this.receivedMessageBuffer[key].ToArray()); P2PState state = new P2PState(); state.IP = remote.Address.ToString(); state.Port = remote.Port; state.Command = command; if (command != null) { LogHelper.Debug(DateTime.Now + " Received cmd from " + remote.Address + ", Command:" + command.CommandName); if (peer == null && command.CommandName != CommandNames.P2P.Ping) { this.ConnectToNewPeer(remote.Address.ToString(), remote.Port); return; } switch (command.CommandName) { case CommandNames.P2P.Ping: this.pingMsgHandle(state); break; case CommandNames.P2P.Pong: this.pongMsgHandle(state); break; case CommandNames.P2P.Version: this.versionMsgHandle(state); break; case CommandNames.P2P.VerAck: this.verAckMsgHandle(state); break; case CommandNames.P2P.GetAddr: this.getAddrMsgHandle(state); break; case CommandNames.P2P.Addr: this.addrMsgHandle(state); break; case CommandNames.P2P.Heartbeat: this.heartbeatMsgHandle(state); break; case CommandNames.Other.Reject: this.rejectMsgHandle(state); break; default: raiseDataReceived(state); break; } } } } catch (Exception ex) { LogHelper.Error(ex.Message, ex); raiseOtherException(null); } finally { if (this.IsRunning && this.server != null) { server.BeginReceive(receiveDataAsync, null); } } }
public void Decode_InvalidLength_Throws( [ValueSource(nameof(encoders))] Base16 encoder, [Values("123", "12345")] string input) { _ = Assert.Throws <ArgumentException>(() => encoder.Decode(input)); }
public void ValidateToken_V2_S_2() { const string token = "v2.public.eyJkYXRhIjoidGhpcyBpcyBhIHNpZ25lZCBtZXNzYWdlIiwiZXhwIjoiMjAxOS0wMS0wMVQwMDowMDowMCswMDowMCJ9flsZsx_gYCR0N_Ec2QxJFFpvQAs7h9HtKwbVK2n1MJ3Rz-hwe8KUqjnd8FAnIJZ601tp7lGkguU63oGbomhoBw.eyJraWQiOiJ6VmhNaVBCUDlmUmYyc25FY1Q3Z0ZUaW9lQTlDT2NOeTlEZmdMMVc2MGhhTiJ9"; const string publicKeyHex = "1eb9dbbbbc047c03fd70604e0071f0987e16b28b757225c11f00415d0e20b1a2"; // payload = {"data":"this is a signed message", "exp":"2019-01-01T00:00:00+00:00"} // footer = {"kid":"zVhMiPBP9fRf2snEcT7gFTioeA9COcNy9DfgL1W60haN"} var handler = new PasetoTokenHandler(); var result = handler.ValidateToken(token, new TokenValidationParameters { ValidateIssuer = false, ValidateAudience = false, ValidateLifetime = false, IssuerSigningKey = new EdDsaSecurityKey(new Ed25519PublicKeyParameters(Base16.Decode(publicKeyHex), 0)) }); result.IsValid.Should().BeTrue(); }
public void GetSafeCharCountForEncoding_ReturnsCorrectValue(Base16 encoder) { var input = new byte[5]; Assert.That(encoder.GetSafeCharCountForEncoding(input), Is.EqualTo(10)); }
public void IsValidTest(string hex) { Assert.True(Base16.IsValid(hex)); }
public void GetSafeByteCountForDecoding_ReturnsCorrectValues(Base16 encoder) { var input = new char[10]; Assert.That(encoder.GetSafeByteCountForDecoding(input), Is.EqualTo(5)); }
public void DecodeTest(byte[] expected, string hex) { byte[] actual = Base16.Decode(hex); Assert.Equal(expected, actual); }
public void GetSafeByteCountForDecoding_InvalidBufferSize_ReturnsZero(Base16 encoder) { var input = new char[11]; Assert.That(encoder.GetSafeByteCountForDecoding(input), Is.EqualTo(0)); }
public void EncodeTest(byte[] ba, string expected) { string actual = Base16.Encode(ba); Assert.Equal(expected, actual); }
public void ToString_ReturnsNameWithAlphabet([ValueSource(nameof(encoders))] Base16 encoder) { Assert.That(encoder.ToString(), Is.EqualTo($"Base16_{encoder.Alphabet}")); }
private Message HandleMessage(Peer peer, Message msg) { if (msg.IsSigned && msg.Address != Address.Null) { peer.SetAddress(msg.Address); } else { return(new ErrorMessage(Address, P2PError.MessageShouldBeSigned)); } switch (msg.Opcode) { case Opcode.REQUEST: { var request = (RequestMessage)msg; if (request.NexusName != Nexus.Name) { return(new ErrorMessage(Address, P2PError.InvalidNexus)); } if (request.Kind == RequestKind.None) { return(null); } var answer = new ListMessage(this.Address, request.Kind); if (request.Kind.HasFlag(RequestKind.Peers)) { answer.SetPeers(this.Peers.Where(x => x != peer).Select(x => x.Endpoint)); } if (request.Kind.HasFlag(RequestKind.Chains)) { var chains = Nexus.Chains.Select(x => new ChainInfo(x.Name, x.ParentChain != null ? x.ParentChain.Name: "", x.LastBlock != null ? x.LastBlock.Height : 0)); answer.SetChains(chains); } if (request.Kind.HasFlag(RequestKind.Mempool)) { var txs = _mempool.GetTransactions().Select(x => Base16.Encode(x.ToByteArray(true))); answer.SetMempool(txs); } if (request.Kind.HasFlag(RequestKind.Blocks)) { foreach (var entry in request.Blocks) { var chain = this.Nexus.FindChainByName(entry.Key); if (chain == null) { continue; } var startBlock = entry.Value; if (startBlock > chain.BlockHeight) { continue; } var blockList = new List <string>(); var currentBlock = startBlock; while (blockList.Count < 50 && currentBlock <= chain.BlockHeight) { var block = chain.FindBlockByHeight(currentBlock); var bytes = block.ToByteArray(); var str = Base16.Encode(bytes); foreach (var tx in chain.GetBlockTransactions(block)) { var txBytes = tx.ToByteArray(true); str += "/" + Base16.Encode(txBytes); } blockList.Add(str); currentBlock++; } answer.AddBlockRange(chain.Name, startBlock, blockList); } } return(answer); } case Opcode.LIST: { var listMsg = (ListMessage)msg; var outKind = RequestKind.None; if (listMsg.Kind.HasFlag(RequestKind.Peers)) { var newPeers = listMsg.Peers.Where(x => !IsKnown(x)); foreach (var entry in listMsg.Peers) { Logger.Message("New peer: " + entry.ToString()); } QueueEndpoints(newPeers); } var blockFetches = new Dictionary <string, uint>(); if (listMsg.Kind.HasFlag(RequestKind.Chains)) { foreach (var entry in listMsg.Chains) { var chain = Nexus.FindChainByName(entry.name); // NOTE if we dont find this chain then it is too soon for ask for blocks from that chain if (chain != null && chain.BlockHeight < entry.height) { blockFetches[entry.name] = chain.BlockHeight + 1; } } } if (listMsg.Kind.HasFlag(RequestKind.Mempool)) { int submittedCount = 0; foreach (var txStr in listMsg.Mempool) { var bytes = Base16.Decode(txStr); var tx = Transaction.Unserialize(bytes); try { _mempool.Submit(tx); submittedCount++; } catch { } Logger.Message(submittedCount + " new transactions"); } } if (listMsg.Kind.HasFlag(RequestKind.Blocks)) { bool addedBlocks = false; foreach (var entry in listMsg.Blocks) { var chain = Nexus.FindChainByName(entry.Key); if (chain == null) { continue; } var blockRange = entry.Value; var currentBlock = blockRange.startHeight; foreach (var rawBlock in blockRange.rawBlocks) { var temp = rawBlock.Split('/'); var block = Block.Unserialize(Base16.Decode(temp[0])); var transactions = new List <Transaction>(); for (int i = 1; i < temp.Length; i++) { var tx = Transaction.Unserialize(Base16.Decode(temp[i])); transactions.Add(tx); } try { chain.AddBlock(block, transactions); } catch (Exception e) { throw new Exception("block add failed"); } Logger.Message($"Added block #{currentBlock} to {chain.Name}"); addedBlocks = true; currentBlock++; } } if (addedBlocks) { outKind |= RequestKind.Chains; } } if (blockFetches.Count > 0) { outKind |= RequestKind.Blocks; } if (outKind != RequestKind.None) { var answer = new RequestMessage(outKind, Nexus.Name, this.Address); if (blockFetches.Count > 0) { answer.SetBlocks(blockFetches); } return(answer); } break; } case Opcode.MEMPOOL_Add: { var memtx = (MempoolAddMessage)msg; var prevSize = _mempool.Size; foreach (var tx in memtx.Transactions) { _mempool.Submit(tx); } var count = _mempool.Size - prevSize; Logger.Message($"Added {count} txs to the mempool"); break; } case Opcode.BLOCKS_List: { break; } case Opcode.ERROR: { var errorMsg = (ErrorMessage)msg; if (string.IsNullOrEmpty(errorMsg.Text)) { Logger.Error($"ERROR: {errorMsg.Code}"); } else { Logger.Error($"ERROR: {errorMsg.Code} ({errorMsg.Text})"); } break; } } Logger.Message("No answer sent."); return(null); }
public override string ToString() { return("0x" + Base16.Encode(ByteArrayUtils.ReverseBytes(_data))); }