public async Task <IActionResult> JoinFederationAsync([FromBody] JoinFederationRequestModel request, CancellationToken cancellationToken = default) { Guard.NotNull(request, nameof(request)); // Checks that the request is valid. if (!this.ModelState.IsValid) { this.logger.LogTrace("(-)[MODEL_STATE_INVALID]"); return(ModelStateErrors.BuildErrorResponse(this.ModelState)); } try { PubKey minerPubKey = await(this.federationManager as CollateralFederationManager).JoinFederationAsync(request, cancellationToken); var model = new JoinFederationResponseModel { MinerPublicKey = minerPubKey.ToHex() }; this.logger.LogTrace("(-):'{0}'", model); return(this.Json(model)); } catch (Exception e) { this.logger.LogError("Exception occurred: {0}", e.ToString()); this.logger.LogTrace("(-)[ERROR]"); return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString())); } }
public async Task <IActionResult> JoinFederationAsync([FromBody] JoinFederationRequestModel request, CancellationToken cancellationToken = default) { Guard.NotNull(request, nameof(request)); // Checks that the request is valid. if (!this.ModelState.IsValid) { this.logger.LogTrace("(-)[MODEL_STATE_INVALID]"); return(ModelStateErrors.BuildErrorResponse(this.ModelState)); } if (!(this.network.Consensus.Options as PoAConsensusOptions).AutoKickIdleMembers) { return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, "Error", "This feature is currently disabled.")); } try { PubKey minerPubKey = await this.joinFederationRequestService.JoinFederationAsync(request, cancellationToken); var model = new JoinFederationResponseModel { MinerPublicKey = minerPubKey.ToHex() }; this.logger.LogTrace("(-):'{0}'", model); return(this.Json(model)); } catch (Exception e) { this.logger.LogError("Exception occurred: {0}", e.ToString()); this.logger.LogTrace("(-)[ERROR]"); return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString())); } }
public async Task <PubKey> JoinFederationAsync(JoinFederationRequestModel request, CancellationToken cancellationToken) { // Get the address pub key hash. var address = BitcoinAddress.Create(request.CollateralAddress, this.counterChainSettings.CounterChainNetwork); KeyId addressKey = PayToPubkeyHashTemplate.Instance.ExtractScriptPubKeyParameters(address.ScriptPubKey); // Get mining key. var keyTool = new KeyTool(this.settings.DataFolder); Key minerKey = keyTool.LoadPrivateKey(); if (minerKey == null) { throw new Exception($"The private key file ({KeyTool.KeyFileDefaultName}) has not been configured."); } var expectedCollateralAmount = CollateralFederationMember.GetCollateralAmountForPubKey(this.network, minerKey.PubKey); Money collateralAmount = new Money(expectedCollateralAmount, MoneyUnit.BTC); var joinRequest = new JoinFederationRequest(minerKey.PubKey, collateralAmount, addressKey); // Populate the RemovalEventId. var collateralFederationMember = new CollateralFederationMember(minerKey.PubKey, false, joinRequest.CollateralAmount, request.CollateralAddress); byte[] federationMemberBytes = (this.network.Consensus.ConsensusFactory as CollateralPoAConsensusFactory).SerializeFederationMember(collateralFederationMember); var votingManager = this.fullNode.NodeService <VotingManager>(); Poll poll = votingManager.GetFinishedPolls().FirstOrDefault(x => x.IsExecuted && x.VotingData.Key == VoteKey.KickFederationMember && x.VotingData.Data.SequenceEqual(federationMemberBytes)); joinRequest.RemovalEventId = (poll == null) ? Guid.Empty : new Guid(poll.PollExecutedBlockData.Hash.ToBytes().TakeLast(16).ToArray()); // Get the signature by calling the counter-chain "signmessage" API. var signMessageRequest = new SignMessageRequest() { Message = joinRequest.SignatureMessage, WalletName = request.CollateralWalletName, Password = request.CollateralWalletPassword, ExternalAddress = request.CollateralAddress }; var walletClient = new WalletClient(this.loggerFactory, this.httpClientFactory, $"http://{this.counterChainSettings.CounterChainApiHost}", this.counterChainSettings.CounterChainApiPort); string signature = await walletClient.SignMessageAsync(signMessageRequest, cancellationToken); if (signature == null) { throw new Exception("Operation was cancelled during call to counter-chain to sign the collateral address."); } joinRequest.AddSignature(signature); var walletTransactionHandler = this.fullNode.NodeService <IWalletTransactionHandler>(); var encoder = new JoinFederationRequestEncoder(this.loggerFactory); Transaction trx = JoinFederationRequestBuilder.BuildTransaction(walletTransactionHandler, this.network, joinRequest, encoder, request.WalletName, request.WalletAccount, request.WalletPassword); var walletService = this.fullNode.NodeService <IWalletService>(); await walletService.SendTransaction(new SendTransactionRequest(trx.ToHex()), cancellationToken); return(minerKey.PubKey); }
private async Task <bool> CallJoinFederationRequestAsync() { Console.Clear(); Console.WriteLine($"The relevant masternode registration wallets has now been setup and verified."); Console.WriteLine($"Press any key to continue (this will deduct the registation fee from your Cirrus wallet)"); Console.ReadKey(); string collateralWallet; string collateralPassword; string collateralAddress; string cirrusWalletName; string cirrusWalletPassword; do { Console.WriteLine($"[Strax] Please enter the collateral wallet name:"); collateralWallet = Console.ReadLine(); Console.WriteLine($"[Strax] Please enter the collateral wallet password:"******"[Strax] Please enter the collateral address in which the collateral amount of {CollateralRequirement} {this.mainchainNetwork.CoinTicker} is held:"); collateralAddress = Console.ReadLine(); Console.WriteLine($"[Cirrus] Please enter the wallet name which holds the registration fee of {FeeRequirement} {this.sidechainNetwork.CoinTicker}:"); cirrusWalletName = Console.ReadLine(); Console.WriteLine($"[Cirrus] Please enter the above wallet's password:"******"ERROR: Please ensure that you enter the relevant details correctly."); } while (true); var request = new JoinFederationRequestModel() { CollateralAddress = collateralAddress, CollateralWalletName = collateralWallet, CollateralWalletPassword = collateralPassword, WalletAccount = "account 0", WalletName = cirrusWalletName, WalletPassword = cirrusWalletPassword }; try { await $"http://localhost:{this.sidechainNetwork.DefaultAPIPort}/api".AppendPathSegment("collateral/joinfederation").PostJsonAsync(request); Console.WriteLine($"SUCCESS: The masternode request has now been submitted to the network,please press any key to view its progress."); return(true); } catch (Exception ex) { Console.WriteLine($"ERROR: An exception occurred trying to registre your masternode: {ex}"); return(false); } }