/// <summary> /// Creates a new object based on a result from CAN API including validation checks. /// </summary> /// <param name="ApiResult">CAN API result object to copy values from.</param> /// <returns>Structure describing result of CAN IPNS refresh operation.</returns> public static CanRefreshIpnsResult FromApiResult(CanApiResult ApiResult) { log.Trace("()"); CanRefreshIpnsResult res = new CanRefreshIpnsResult(ApiResult); if (res.Success) { bool error = false; try { CanRefreshIpnsResponse response = JsonConvert.DeserializeObject <CanRefreshIpnsResponse>(res.DataStr); res.Details = response; } catch (Exception e) { log.Error("Exception occurred: {0}", e.ToString()); error = true; } if (error) { res.Success = false; res.Message = "Invalid CAN response."; res.IsCanError = false; } } log.Trace("(-)"); return(res); }
/// <summary> /// Refreshes porofile server's IPNS record. /// </summary> public async Task IpnsRecordRefresh() { log.Trace("()"); Base.Configuration.CanIpnsLastSequenceNumber++; canIpnsRecord = CreateIpnsRecord(canContactInformationHash, Base.Configuration.CanIpnsLastSequenceNumber); CanRefreshIpnsResult cres = await canApi.RefreshIpnsRecord(canIpnsRecord, Base.Configuration.Keys.PublicKey); if (cres.Success) { using (UnitOfWork unitOfWork = new UnitOfWork()) { await unitOfWork.AcquireLockAsync(UnitOfWork.SettingsLock); try { Setting setting = new Setting("CanIpnsLastSequenceNumber", Base.Configuration.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}", Base.Configuration.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> /// 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); }