/// <summary> /// Creates CAN IPNS record object to point to a CAN object of the given hash with the given sequence number. /// </summary> /// <param name="Hash">Hash of the CAN object to point IPNS record to.</param> /// <param name="SequenceNumber">Sequence number of the IPNS record.</param> /// <param name="ExpirationTimeSeconds">Expiration time of the newly created record in seconds.</param> /// <returns>Valid signed CAN IPNS record object, ready to be sent to CAN server.</returns> public static CanIpnsEntry CreateIpnsRecord(byte[] Hash, UInt64 SequenceNumber, int ExpirationTimeSeconds) { log.Trace("(Hash:'{0}',SequenceNumber:{1},ExpirationTimeSeconds:{2})", Hash.ToBase58(), SequenceNumber, ExpirationTimeSeconds); string validityString = DateTime.UtcNow.AddMonths(1).ToString(Rfc3339DateTimeFormat, DateTimeFormatInfo.InvariantInfo); byte[] validityBytes = Encoding.UTF8.GetBytes(validityString); UInt64 ttlNanoSec = (UInt64)(TimeSpan.FromSeconds(ExpirationTimeSeconds).TotalMilliseconds) * (UInt64)1000000; string valueString = CanApi.CreateIpfsPathFromHash(Hash); byte[] valueBytes = Encoding.UTF8.GetBytes(valueString); CanIpnsEntry res = new CanIpnsEntry() { Sequence = SequenceNumber, ValidityType = CanIpnsEntry.Types.ValidityType.Eol, Ttl = ttlNanoSec, Validity = ProtocolHelper.ByteArrayToByteString(validityBytes), Value = ProtocolHelper.ByteArrayToByteString(valueBytes) }; res.Signature = ProtocolHelper.ByteArrayToByteString(CreateIpnsRecordSignature(res)); log.Trace("(-):{0}", res); return(res); }
/// <summary> /// Refreshes profile server's IPNS record. /// </summary> public async Task IpnsRecordRefreshAsync() { log.Trace("()"); if (canContactInformationHash == null) { log.Debug("No CAN contact information hash, can't refresh IPNS record, will try later."); log.Trace("(-)"); return; } canIpnsLastSequenceNumber++; canIpnsRecord = CanApi.CreateIpnsRecord(canContactInformationHash, canIpnsLastSequenceNumber, IpnsRecordExpirationTimeSeconds); CanRefreshIpnsResult cres = await api.RefreshIpnsRecord(canIpnsRecord, Config.Configuration.Keys.PublicKey); if (cres.Success) { using (UnitOfWork unitOfWork = new UnitOfWork()) { await unitOfWork.AcquireLockAsync(UnitOfWork.SettingsLock); try { Setting setting = new Setting("CanIpnsLastSequenceNumber", canIpnsLastSequenceNumber.ToString()); await unitOfWork.SettingsRepository.AddOrUpdate(setting); await unitOfWork.SaveThrowAsync(); log.Debug("CanIpnsLastSequenceNumber updated in database to new value {0}.", setting.Value); } catch (Exception e) { log.Error("Unable to update CanIpnsLastSequenceNumber in the database to new value {0}, exception: {1}", canIpnsLastSequenceNumber, e.ToString()); } unitOfWork.ReleaseLock(UnitOfWork.SettingsLock); } } else if (cres.Message != "Shutdown") { log.Error("Failed to refresh profile server's IPNS record."); } log.Trace("(-)"); }
/// <summary> /// Calculates a signature of IPNS record. /// </summary> /// <param name="Record">IPNS record to calculate signature for.</param> /// <returns>Signature of the IPNS record.</returns> public byte[] CreateIpnsRecordSignature(CanIpnsEntry Record) { string validityTypeString = Record.ValidityType.ToString().ToUpperInvariant(); byte[] validityTypeBytes = Encoding.UTF8.GetBytes(validityTypeString); byte[] dataToSign = new byte[Record.Value.Length + Record.Validity.Length + validityTypeBytes.Length]; int offset = 0; Array.Copy(Record.Value.ToByteArray(), 0, dataToSign, offset, Record.Value.Length); offset += Record.Value.Length; Array.Copy(Record.Validity.ToByteArray(), 0, dataToSign, offset, Record.Validity.Length); offset += Record.Validity.Length; Array.Copy(validityTypeBytes, 0, dataToSign, offset, validityTypeBytes.Length); offset += validityTypeBytes.Length; byte[] res = Ed25519.Sign(dataToSign, Base.Configuration.Keys.ExpandedPrivateKey); return(res); }
/// <summary> /// Calculates a signature of IPNS record. /// </summary> /// <param name="Record">IPNS record to calculate signature for.</param> /// <returns>Signature of the IPNS record.</returns> public static byte[] CreateIpnsRecordSignature(CanIpnsEntry Record) { string validityTypeString = Record.ValidityType.ToString().ToUpperInvariant(); byte[] validityTypeBytes = Encoding.UTF8.GetBytes(validityTypeString); byte[] dataToSign = new byte[Record.Value.Length + Record.Validity.Length + validityTypeBytes.Length]; int offset = 0; Array.Copy(Record.Value.ToByteArray(), 0, dataToSign, offset, Record.Value.Length); offset += Record.Value.Length; Array.Copy(Record.Validity.ToByteArray(), 0, dataToSign, offset, Record.Validity.Length); offset += Record.Validity.Length; Array.Copy(validityTypeBytes, 0, dataToSign, offset, validityTypeBytes.Length); offset += validityTypeBytes.Length; ConfigBase config = (ConfigBase)Base.ComponentDictionary[ConfigBase.ComponentName]; byte[] res = Ed25519.Sign(dataToSign, ((KeysEd25519)config.Settings["Keys"]).ExpandedPrivateKey); return(res); }
/// <summary> /// Refreshes profile server's IPNS record in CAN. /// </summary> /// <param name="IpnsRecord">IPNS record to refresh.</param> /// <param name="PublicKey">Public key of the IPNS record owner.</param> /// <returns>Structure describing whether the function succeeded and response provided by CAN server.</returns> public async Task <CanRefreshIpnsResult> RefreshIpnsRecord(CanIpnsEntry IpnsRecord, byte[] PublicKey) { log.Trace("(PublicKey:'{0}')", PublicKey.ToHex()); string ipnsRecordEncoded = IpnsRecord.ToByteArray().ToBase64UrlPad(true); CanCryptoKey cryptoKey = new CanCryptoKey() { Type = CanCryptoKey.Types.KeyType.Ed25519, Data = ProtocolHelper.ByteArrayToByteString(PublicKey) }; string keyEncoded = Base58Encoding.Encoder.Encode(cryptoKey.ToByteArray()); log.Debug("Encoding public key: {0}", keyEncoded); NameValueCollection args = new NameValueCollection(); args.Add("arg", ipnsRecordEncoded); args.Add("key", keyEncoded); CanApiResult apiResult = await SendRequest("name/upload", args); CanRefreshIpnsResult res = CanRefreshIpnsResult.FromApiResult(apiResult); if (res.Success) { res.IsCanError = false; // Check that the ID, path and sequence number match what we expect. string canId = CanApi.PublicKeyToId(PublicKey).ToBase58(); if (res.Details.Peer == canId) { string path = Encoding.UTF8.GetString(IpnsRecord.Value.ToByteArray()); if (res.Details.NewPath == path) { if (res.Details.NewSeq == IpnsRecord.Sequence) { // All OK. } else { log.Warn("CAN sequence is {0}, received {1}.", IpnsRecord.Sequence, res.Details.NewSeq); res.Success = false; res.Message = "CAN path in response does not match expected value."; } } else { log.Warn("CAN path is '{0}', received '{1}'.", path, res.Details.NewPath); res.Success = false; res.Message = "CAN path in response does not match expected value."; } } else { log.Warn("CAN ID is '{0}', received '{1}'.", canId, res.Details.Peer); res.Success = false; res.Message = "CAN ID in response does not match expected value."; } } if (res.Success) { log.Trace("(-):*.Success={0}", res.Success); } else { log.Trace("(-):*.Success={0},*.IsCanError={1},*.Message='{2}'", res.Success, res.IsCanError, res.Message); } return(res); }
/// <summary> /// Implementation of the test itself. /// </summary> /// <returns>true if the test passes, false otherwise.</returns> public override async Task <bool> RunAsync() { IPAddress ServerIp = (IPAddress)ArgumentValues["Server IP"]; int PrimaryPort = (int)ArgumentValues["primary Port"]; log.Trace("(ServerIp:'{0}',PrimaryPort:{1})", ServerIp, PrimaryPort); bool res = false; Passed = false; ProtocolClient client = new ProtocolClient(); try { MessageBuilder mb = client.MessageBuilder; // Step 1 log.Trace("Step 1"); // Get port list. await client.ConnectAsync(ServerIp, PrimaryPort, false); Dictionary <ServerRoleType, uint> rolePorts = new Dictionary <ServerRoleType, uint>(); bool listPortsOk = await client.ListServerPorts(rolePorts); client.CloseConnection(); await client.ConnectAsync(ServerIp, (int)rolePorts[ServerRoleType.ClNonCustomer], true); bool hostingOk = await client.EstablishHostingAsync("Test"); client.CloseConnection(); await client.ConnectAsync(ServerIp, (int)rolePorts[ServerRoleType.ClCustomer], true); bool checkInOk = await client.CheckInAsync(); bool step1Ok = listPortsOk && hostingOk && checkInOk; log.Trace("Step 1: {0}", step1Ok ? "PASSED" : "FAILED"); // Step 2 log.Trace("Step 2"); string validityString = DateTime.UtcNow.AddMonths(1).ToString("yyyy-MM-dd'T'HH:mm:ss.fffK", DateTimeFormatInfo.InvariantInfo); CanIpnsEntry ipnsRecord = new CanIpnsEntry() { Value = ProtocolHelper.ByteArrayToByteString(Encoding.UTF8.GetBytes("/ipfs/QmaRvpLT4RgBDVY6cQKwqQGQNtbM31KSqh8TxvQgFoEUus")), ValidityType = CanIpnsEntry.Types.ValidityType.Eol, Validity = ProtocolHelper.ByteArrayToByteString(Encoding.UTF8.GetBytes(validityString)), Sequence = 1, Ttl = 6000000000, }; ipnsRecord.Signature = ProtocolHelper.ByteArrayToByteString(client.CreateIpnsRecordSignature(ipnsRecord)); Message requestMessage = mb.CreateCanPublishIpnsRecordRequest(ipnsRecord); await client.SendMessageAsync(requestMessage); Message responseMessage = await client.ReceiveMessageAsync(); bool idOk = responseMessage.Id == requestMessage.Id; bool statusOk = (responseMessage.Response.Status == Status.ErrorNotFound) || ((responseMessage.Response.Status == Status.ErrorInvalidValue) && (responseMessage.Response.Details == "record.value")); bool canPublishIpnsRecordOk = idOk && statusOk; // Step 2 Acceptance bool step2Ok = canPublishIpnsRecordOk; log.Trace("Step 2: {0}", step2Ok ? "PASSED" : "FAILED"); // Step 3 log.Trace("Step 3"); byte[] serverId = Crypto.Sha256(client.ServerKey); List <CanKeyValue> clientData = new List <CanKeyValue>() { new CanKeyValue() { Key = "key1", StringValue = "value 1" }, new CanKeyValue() { Key = "key2", Uint32Value = 2 }, new CanKeyValue() { Key = "key3", BoolValue = true }, new CanKeyValue() { Key = "key4", BinaryValue = ProtocolHelper.ByteArrayToByteString(new byte[] { 1, 2, 3 }) }, }; CanIdentityData identityData1 = new CanIdentityData() { HostingServerId = ProtocolHelper.ByteArrayToByteString(serverId) }; identityData1.KeyValueList.AddRange(clientData); requestMessage = mb.CreateCanStoreDataRequest(identityData1); await client.SendMessageAsync(requestMessage); responseMessage = await client.ReceiveMessageAsync(); idOk = responseMessage.Id == requestMessage.Id; statusOk = responseMessage.Response.Status == Status.Ok; bool canStoreDataOk = idOk && statusOk; byte[] objectHash1 = responseMessage.Response.ConversationResponse.CanStoreData.Hash.ToByteArray(); string objectPath1 = client.CreateIpfsPathFromHash(objectHash1); log.Trace("Object path 1 is '{0}'.", objectPath1); requestMessage = mb.CreateCanPublishIpnsRecordRequest(null); await client.SendMessageAsync(requestMessage); responseMessage = await client.ReceiveMessageAsync(); idOk = responseMessage.Id == requestMessage.Id; statusOk = responseMessage.Response.Status == Status.ErrorInvalidValue; bool detailsOk = responseMessage.Response.Details == "record"; canPublishIpnsRecordOk = idOk && statusOk && detailsOk; // Step 3 Acceptance bool step3Ok = canStoreDataOk && canPublishIpnsRecordOk; log.Trace("Step 3: {0}", step3Ok ? "PASSED" : "FAILED"); // Step 4 log.Trace("Step 4"); validityString = DateTime.UtcNow.AddMonths(1).ToString("yyyy-MM-dd'T'HH:mm:ss.fffK", DateTimeFormatInfo.InvariantInfo); ipnsRecord = new CanIpnsEntry() { Value = ProtocolHelper.ByteArrayToByteString(Encoding.UTF8.GetBytes("ipfabc")), ValidityType = CanIpnsEntry.Types.ValidityType.Eol, Validity = ProtocolHelper.ByteArrayToByteString(Encoding.UTF8.GetBytes(validityString)), Sequence = 1, Ttl = 6000000000, }; ipnsRecord.Signature = ProtocolHelper.ByteArrayToByteString(client.CreateIpnsRecordSignature(ipnsRecord)); requestMessage = mb.CreateCanPublishIpnsRecordRequest(ipnsRecord); await client.SendMessageAsync(requestMessage); responseMessage = await client.ReceiveMessageAsync(); idOk = responseMessage.Id == requestMessage.Id; statusOk = responseMessage.Response.Status == Status.ErrorInvalidValue; detailsOk = responseMessage.Response.Details == "record.value"; canPublishIpnsRecordOk = idOk && statusOk && detailsOk; // Step 4 Acceptance bool step4Ok = canPublishIpnsRecordOk; log.Trace("Step 4: {0}", step4Ok ? "PASSED" : "FAILED"); // Step 5 log.Trace("Step 5"); validityString = DateTime.UtcNow.AddMonths(1).ToString("yyyy-MM-dd'T'HH:mm:ss.fffK", DateTimeFormatInfo.InvariantInfo); ipnsRecord = new CanIpnsEntry() { Value = ProtocolHelper.ByteArrayToByteString(Encoding.UTF8.GetBytes(objectPath1)), ValidityType = CanIpnsEntry.Types.ValidityType.Eol, Validity = ProtocolHelper.ByteArrayToByteString(Encoding.UTF8.GetBytes(validityString)), Sequence = 1, Ttl = 6000000000, }; ipnsRecord.Signature = ProtocolHelper.ByteArrayToByteString(client.CreateIpnsRecordSignature(ipnsRecord)); requestMessage = mb.CreateCanPublishIpnsRecordRequest(ipnsRecord); await client.SendMessageAsync(requestMessage); responseMessage = await client.ReceiveMessageAsync(); idOk = responseMessage.Id == requestMessage.Id; statusOk = responseMessage.Response.Status == Status.Ok; canPublishIpnsRecordOk = idOk && statusOk; // Step 5 Acceptance bool step5Ok = canPublishIpnsRecordOk; log.Trace("Step 5: {0}", step5Ok ? "PASSED" : "FAILED"); // Step 6 log.Trace("Step 6"); validityString = DateTime.UtcNow.AddMonths(1).ToString("yyyy-MM-dd'T'HH:mm:ss.fffK", DateTimeFormatInfo.InvariantInfo); ipnsRecord = new CanIpnsEntry() { Value = ProtocolHelper.ByteArrayToByteString(Encoding.UTF8.GetBytes(objectPath1)), ValidityType = CanIpnsEntry.Types.ValidityType.Eol, Validity = ProtocolHelper.ByteArrayToByteString(Encoding.UTF8.GetBytes(validityString)), Sequence = 1, Ttl = 6000000000, }; ipnsRecord.Signature = ProtocolHelper.ByteArrayToByteString(client.CreateIpnsRecordSignature(ipnsRecord)); requestMessage = mb.CreateCanPublishIpnsRecordRequest(ipnsRecord); await client.SendMessageAsync(requestMessage); responseMessage = await client.ReceiveMessageAsync(); idOk = responseMessage.Id == requestMessage.Id; statusOk = responseMessage.Response.Status == Status.ErrorRejected; detailsOk = !string.IsNullOrEmpty(responseMessage.Response.Details); canPublishIpnsRecordOk = idOk && statusOk && detailsOk; // Step 6 Acceptance bool step6Ok = canPublishIpnsRecordOk; log.Trace("Step 6: {0}", step6Ok ? "PASSED" : "FAILED"); // Step 7 log.Trace("Step 7"); validityString = DateTime.UtcNow.AddMonths(1).ToString("yyyy-MM-dd'T'HH:mm:ss.fffK", DateTimeFormatInfo.InvariantInfo); ipnsRecord = new CanIpnsEntry() { Value = ProtocolHelper.ByteArrayToByteString(Encoding.UTF8.GetBytes(objectPath1)), ValidityType = CanIpnsEntry.Types.ValidityType.Eol, Validity = ProtocolHelper.ByteArrayToByteString(Encoding.UTF8.GetBytes(validityString)), Sequence = 2, Ttl = 6000000000, }; ipnsRecord.Signature = ProtocolHelper.ByteArrayToByteString(new byte[] { 0x40, 0x40, 0x40, 0x40, 0x40 }); requestMessage = mb.CreateCanPublishIpnsRecordRequest(ipnsRecord); await client.SendMessageAsync(requestMessage); responseMessage = await client.ReceiveMessageAsync(); idOk = responseMessage.Id == requestMessage.Id; statusOk = responseMessage.Response.Status == Status.ErrorRejected; detailsOk = !string.IsNullOrEmpty(responseMessage.Response.Details); canPublishIpnsRecordOk = idOk && statusOk && detailsOk; // Step 7 Acceptance bool step7Ok = canPublishIpnsRecordOk; log.Trace("Step 7: {0}", step7Ok ? "PASSED" : "FAILED"); // Step 8 log.Trace("Step 8"); requestMessage = mb.CreateCanStoreDataRequest(null); await client.SendMessageAsync(requestMessage); responseMessage = await client.ReceiveMessageAsync(); idOk = responseMessage.Id == requestMessage.Id; statusOk = responseMessage.Response.Status == Status.Ok; canStoreDataOk = idOk && statusOk; validityString = DateTime.UtcNow.AddMonths(1).ToString("yyyy-MM-dd'T'HH:mm:ss.fffK", DateTimeFormatInfo.InvariantInfo); ipnsRecord = new CanIpnsEntry() { Value = ProtocolHelper.ByteArrayToByteString(Encoding.UTF8.GetBytes(objectPath1)), ValidityType = CanIpnsEntry.Types.ValidityType.Eol, Validity = ProtocolHelper.ByteArrayToByteString(Encoding.UTF8.GetBytes(validityString)), Sequence = 3, Ttl = 6000000000, }; ipnsRecord.Signature = ProtocolHelper.ByteArrayToByteString(client.CreateIpnsRecordSignature(ipnsRecord)); requestMessage = mb.CreateCanPublishIpnsRecordRequest(ipnsRecord); await client.SendMessageAsync(requestMessage); responseMessage = await client.ReceiveMessageAsync(); idOk = responseMessage.Id == requestMessage.Id; statusOk = responseMessage.Response.Status == Status.ErrorNotFound; canPublishIpnsRecordOk = idOk && statusOk; // Step 8 Acceptance bool step8Ok = canStoreDataOk && canPublishIpnsRecordOk; log.Trace("Step 8: {0}", step8Ok ? "PASSED" : "FAILED"); Passed = step1Ok && step2Ok && step3Ok && step4Ok && step5Ok && step6Ok && step7Ok && step8Ok; res = true; } catch (Exception e) { log.Error("Exception occurred: {0}", e.ToString()); } client.Dispose(); log.Trace("(-):{0}", res); return(res); }
/// <summary> /// Implementation of the test itself. /// </summary> /// <returns>true if the test passes, false otherwise.</returns> public override async Task <bool> RunAsync() { IPAddress ServerIp = (IPAddress)ArgumentValues["Server IP"]; int PrimaryPort = (int)ArgumentValues["primary Port"]; int CanPort = (int)ArgumentValues["CAN Port"]; log.Trace("(ServerIp:'{0}',PrimaryPort:{1},CanPort:{2})", ServerIp, PrimaryPort, CanPort); bool res = false; Passed = false; ProtocolClient client = new ProtocolClient(); try { MessageBuilder mb = client.MessageBuilder; // Step 1 log.Trace("Step 1"); // Get port list. await client.ConnectAsync(ServerIp, PrimaryPort, false); Dictionary <ServerRoleType, uint> rolePorts = new Dictionary <ServerRoleType, uint>(); bool listPortsOk = await client.ListServerPorts(rolePorts); client.CloseConnection(); await client.ConnectAsync(ServerIp, (int)rolePorts[ServerRoleType.ClNonCustomer], true); bool hostingOk = await client.EstablishHostingAsync("Test"); client.CloseConnection(); await client.ConnectAsync(ServerIp, (int)rolePorts[ServerRoleType.ClCustomer], true); bool checkInOk = await client.CheckInAsync(); bool step1Ok = listPortsOk && hostingOk && checkInOk; log.Trace("Step 1: {0}", step1Ok ? "PASSED" : "FAILED"); // Step 2 log.Trace("Step 2"); byte[] serverId = Crypto.Sha256(client.ServerKey); List <CanKeyValue> clientData = new List <CanKeyValue>() { new CanKeyValue() { Key = "key1", StringValue = "value 1" }, new CanKeyValue() { Key = "key2", Uint32Value = 2 }, new CanKeyValue() { Key = "key3", BoolValue = true }, new CanKeyValue() { Key = "key4", BinaryValue = ProtocolHelper.ByteArrayToByteString(new byte[] { 1, 2, 3 }) }, }; CanIdentityData identityData1 = new CanIdentityData() { HostingServerId = ProtocolHelper.ByteArrayToByteString(serverId) }; identityData1.KeyValueList.AddRange(clientData); Message requestMessage = mb.CreateCanStoreDataRequest(identityData1); await client.SendMessageAsync(requestMessage); Message responseMessage = await client.ReceiveMessageAsync(); bool idOk = responseMessage.Id == requestMessage.Id; bool statusOk = responseMessage.Response.Status == Status.Ok; bool canStoreDataOk = idOk && statusOk; byte[] objectHash1 = responseMessage.Response.ConversationResponse.CanStoreData.Hash.ToByteArray(); string objectPath1 = client.CreateIpfsPathFromHash(objectHash1); log.Trace("Object path 1 is '{0}'.", objectPath1); string validityString = DateTime.UtcNow.AddMonths(1).ToString("yyyy-MM-dd'T'HH:mm:ss.fffK", DateTimeFormatInfo.InvariantInfo); CanIpnsEntry ipnsRecord = new CanIpnsEntry() { Value = ProtocolHelper.ByteArrayToByteString(Encoding.UTF8.GetBytes(objectPath1)), ValidityType = CanIpnsEntry.Types.ValidityType.Eol, Validity = ProtocolHelper.ByteArrayToByteString(Encoding.UTF8.GetBytes(validityString)), Sequence = 1, Ttl = 6000000000, }; ipnsRecord.Signature = ProtocolHelper.ByteArrayToByteString(client.CreateIpnsRecordSignature(ipnsRecord)); requestMessage = mb.CreateCanPublishIpnsRecordRequest(ipnsRecord); await client.SendMessageAsync(requestMessage); responseMessage = await client.ReceiveMessageAsync(); idOk = responseMessage.Id == requestMessage.Id; statusOk = responseMessage.Response.Status == Status.Ok; bool canPublishIpnsRecordOk = idOk && statusOk; // Step 2 Acceptance bool step2Ok = canStoreDataOk && canPublishIpnsRecordOk; log.Trace("Step 2: {0}", step2Ok ? "PASSED" : "FAILED"); // Step 3 log.Trace("Step 3"); IPEndPoint canEndPoint = new IPEndPoint(ServerIp, CanPort); byte[] clientCanId = client.CanPublicKeyToId(client.GetIdentityKeys().PublicKey); string ipnsPath = client.CreateIpnsPathFromHash(clientCanId); ProtocolClient.CanIpnsResolveResult canIpnsResolveResult = await client.CanIpnsResolve(canEndPoint, ipnsPath); string canObjectPath = canIpnsResolveResult.Path; bool objectPathOk = canObjectPath == objectPath1; bool resolveOk = canIpnsResolveResult.Success && objectPathOk; ProtocolClient.CanCatResult canCatResult = await client.CanGetObject(canEndPoint, canObjectPath); byte[] receivedData = canCatResult.Data; byte[] expectedData = identityData1.ToByteArray(); bool dataOk = StructuralComparisons.StructuralComparer.Compare(receivedData, expectedData) == 0; bool catOk = canCatResult.Success && dataOk; // Step 3 Acceptance bool step3Ok = resolveOk && catOk; log.Trace("Step 3: {0}", step3Ok ? "PASSED" : "FAILED"); // Step 4 log.Trace("Step 4"); ipnsRecord.Sequence = 2; ipnsRecord.Signature = ProtocolHelper.ByteArrayToByteString(client.CreateIpnsRecordSignature(ipnsRecord)); requestMessage = mb.CreateCanPublishIpnsRecordRequest(ipnsRecord); await client.SendMessageAsync(requestMessage); responseMessage = await client.ReceiveMessageAsync(); idOk = responseMessage.Id == requestMessage.Id; statusOk = responseMessage.Response.Status == Status.Ok; canPublishIpnsRecordOk = idOk && statusOk; canIpnsResolveResult = await client.CanIpnsResolve(canEndPoint, ipnsPath); canObjectPath = canIpnsResolveResult.Path; objectPathOk = canObjectPath == objectPath1; resolveOk = canIpnsResolveResult.Success && objectPathOk; // Step 4 Acceptance bool step4Ok = canPublishIpnsRecordOk && resolveOk; log.Trace("Step 4: {0}", step4Ok ? "PASSED" : "FAILED"); // Step 5 log.Trace("Step 5"); byte[] valX = new byte[50000]; for (int i = 0; i < valX.Length; i++) { valX[i] = 0x30; } clientData = new List <CanKeyValue>() { new CanKeyValue() { Key = "key1", StringValue = "value 1" }, new CanKeyValue() { Key = "key2", Uint32Value = 3 }, new CanKeyValue() { Key = "key3", BoolValue = false }, new CanKeyValue() { Key = "keyX", BinaryValue = ProtocolHelper.ByteArrayToByteString(valX) }, }; CanIdentityData identityData2 = new CanIdentityData() { HostingServerId = ProtocolHelper.ByteArrayToByteString(serverId) }; identityData2.KeyValueList.AddRange(clientData); requestMessage = mb.CreateCanStoreDataRequest(identityData2); await client.SendMessageAsync(requestMessage); responseMessage = await client.ReceiveMessageAsync(); idOk = responseMessage.Id == requestMessage.Id; statusOk = responseMessage.Response.Status == Status.Ok; canStoreDataOk = idOk && statusOk; byte[] objectHash2 = responseMessage.Response.ConversationResponse.CanStoreData.Hash.ToByteArray(); string objectPath2 = client.CreateIpfsPathFromHash(objectHash2); log.Trace("Object path 2 is '{0}'.", objectPath2); ipnsRecord.Sequence = 3; ipnsRecord.Value = ProtocolHelper.ByteArrayToByteString(Encoding.UTF8.GetBytes(objectPath2)); ipnsRecord.Signature = ProtocolHelper.ByteArrayToByteString(client.CreateIpnsRecordSignature(ipnsRecord)); requestMessage = mb.CreateCanPublishIpnsRecordRequest(ipnsRecord); await client.SendMessageAsync(requestMessage); responseMessage = await client.ReceiveMessageAsync(); idOk = responseMessage.Id == requestMessage.Id; statusOk = responseMessage.Response.Status == Status.Ok; canPublishIpnsRecordOk = idOk && statusOk; // Step 5 Acceptance bool step5Ok = canStoreDataOk && canPublishIpnsRecordOk; log.Trace("Step 5: {0}", step5Ok ? "PASSED" : "FAILED"); // Step 6 log.Trace("Step 6"); await Task.Delay(10000); canIpnsResolveResult = await client.CanIpnsResolve(canEndPoint, ipnsPath); canObjectPath = canIpnsResolveResult.Path; objectPathOk = canObjectPath == objectPath2; resolveOk = canIpnsResolveResult.Success && objectPathOk; canCatResult = await client.CanGetObject(canEndPoint, canObjectPath); receivedData = canCatResult.Data; expectedData = identityData2.ToByteArray(); dataOk = StructuralComparisons.StructuralComparer.Compare(receivedData, expectedData) == 0; catOk = canCatResult.Success && dataOk; // Step 6 Acceptance bool step6Ok = resolveOk && catOk; log.Trace("Step 6: {0}", step6Ok ? "PASSED" : "FAILED"); // Step 7 log.Trace("Step 7"); requestMessage = mb.CreateCanStoreDataRequest(null); await client.SendMessageAsync(requestMessage); responseMessage = await client.ReceiveMessageAsync(); idOk = responseMessage.Id == requestMessage.Id; statusOk = responseMessage.Response.Status == Status.Ok; canStoreDataOk = idOk && statusOk; ProtocolClient.CanDeleteResult canDeleteResult = await client.CanDeleteObject(canEndPoint, canObjectPath); bool pinsOk = (canDeleteResult.Pins == null) || (canDeleteResult.Pins.Length == 0); bool deleteOk = canDeleteResult.Success && pinsOk; // Step 7 Acceptance bool step7Ok = canStoreDataOk && deleteOk; log.Trace("Step 7: {0}", step7Ok ? "PASSED" : "FAILED"); // Step 8 log.Trace("Step 8"); canDeleteResult = await client.CanDeleteObject(canEndPoint, objectPath1); pinsOk = (canDeleteResult.Pins == null) || (canDeleteResult.Pins.Length == 0); deleteOk = canDeleteResult.Success && pinsOk; // Step 8 Acceptance bool step8Ok = deleteOk; log.Trace("Step 8: {0}", step8Ok ? "PASSED" : "FAILED"); Passed = step1Ok && step2Ok && step3Ok && step4Ok && step5Ok && step6Ok && step7Ok && step8Ok; res = true; } catch (Exception e) { log.Error("Exception occurred: {0}", e.ToString()); } client.Dispose(); log.Trace("(-):{0}", res); return(res); }