Пример #1
0
        public void TestRpcImportPubkeyIsSuccessful()
        {
            using (NodeBuilder builder = NodeBuilder.Create(this))
            {
                CoreNode node  = builder.CreateStratisPowNode(new BitcoinRegTest()).AlwaysFlushBlocks().WithWallet().Start();
                CoreNode node2 = builder.CreateStratisPowNode(new BitcoinRegTest()).WithReadyBlockchainData(ReadyBlockchain.BitcoinRegTest10Miner).Start();

                TestHelper.ConnectAndSync(node, node2);

                UnspentOutputReference tx = node2.FullNode.WalletManager().GetUnspentTransactionsInWallet("mywallet", 0, Features.Wallet.Wallet.NormalAccounts).First();

                RPCClient rpc = node.CreateRPCClient();

                PubKey pubKey  = PayToPubkeyTemplate.Instance.ExtractScriptPubKeyParameters(tx.Address.Pubkey);
                PubKey pubKey2 = new Key().PubKey;

                uint256 blockHash = rpc.GenerateToAddress(1, pubKey2.GetAddress(rpc.Network)).First();
                Block   block     = rpc.GetBlock(blockHash);
                uint256 tx2       = block.Transactions.First().GetHash();

                Assert.Throws <RPCException>(() => rpc.SendCommand(RPCOperations.gettransaction, tx.Transaction.Id.ToString(), true));
                Assert.Throws <RPCException>(() => rpc.SendCommand(RPCOperations.gettransaction, tx2.ToString(), true));;

                // Test that adding the same pubkey twice doesn't throw.
                rpc.ImportPubKey(pubKey.ToHex());
                rpc.ImportPubKey(pubKey.ToHex());

                // Add a second pubkey and ensure it doesn't throw.
                rpc.ImportPubKey(pubKey2.ToHex());

                // Add an arbitrary pubkey and ensure it doesn't throw.
                rpc.ImportPubKey(new Key().PubKey.ToHex());

                TestBase.WaitLoop(() => node.FullNode.WalletManager().WalletTipHeight == node2.FullNode.WalletManager().WalletTipHeight);

                TestBase.WaitLoop(() =>
                {
                    try
                    {
                        // Check if gettransaction can now find the transactions in the watch only account.
                        RPCResponse walletTx  = rpc.SendCommand(RPCOperations.gettransaction, tx.Transaction.Id.ToString(), true);
                        RPCResponse walletTx2 = rpc.SendCommand(RPCOperations.gettransaction, tx2.ToString(), true);

                        return(walletTx != null && walletTx2 != null);
                    }
                    catch (RPCException)
                    {
                        return(false);
                    }
                });

                // Check that when include_watchonly is not set, the watched addresses' transactions cannot be located in the normal wallet accounts.
                Assert.Throws <RPCException>(() => rpc.SendCommand(RPCOperations.gettransaction, tx.Transaction.Id.ToString(), false));
                Assert.Throws <RPCException>(() => rpc.SendCommand(RPCOperations.gettransaction, tx2.ToString(), false));
            }
        }
Пример #2
0
        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()));
            }
        }
Пример #3
0
        public void GetBalance()
        {
            ssbalance = 0;
            string privateKeyStr = PrivateKey;
            //string privateKeyStr = "cUvazeu9ucqD4trygt8xMEQKZfR3SZ5BdiAWb3eEwbQ48iPwYKSB";
            BitcoinSecret  privateKey = new BitcoinSecret(privateKeyStr);
            Network        network    = privateKey.Network;
            PubKey         pubKey     = privateKey.PubKey;
            string         pubKeyStr  = pubKey.ToHex();
            KeyId          pkhash     = pubKey.Hash;
            string         pkhashStr  = pkhash.ToString();
            BitcoinAddress addres     = pkhash.GetAddress(network);
            string         address    = addres.ToString();
            string         networkStr = bsvConfiguration_class.testNetwork;
            string         uri        = bsvConfiguration_class.RestApiUri;
            //读取未消费的交易输出utxo
            Task <RestApiUtxo_class[]> utxo = Task <RestApiUtxo_class[]> .Run(() =>
            {
                RestApiUtxo_class[] untxo = RestApi_class.getUtxosByAnAddress(uri, networkStr, address);
                return(untxo);
            });

            utxo.Wait();
            int n = utxo.Result.Length;

            for (int i = 0; i < n; i++)
            {
                ssbalance += utxo.Result[i].Value;
            }
            //Console.WriteLine(ssbalance);

            label3.Text  = "账户余额:";
            label3.Text += ssbalance;
            label3.Text += " sat";
        }
        private void AddFederationMember(byte[] pubKeyBytes)
        {
            var key = new PubKey(pubKeyBytes);

            this.logger.LogInformation("Adding new fed member: '{0}'.", key.ToHex());
            this.federationManager.AddFederationMember(key);
        }
        private void RemoveFederationMember(byte[] pubKeyBytes)
        {
            var key = new PubKey(pubKeyBytes);

            this.logger.LogInformation("Kicking fed member: '{0}'.", key.ToHex());
            this.federationManager.RemoveFederationMember(key);
        }
Пример #6
0
        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()));
            }
        }
Пример #7
0
 private void label4_Click(object sender, EventArgs e)//查询地址
 {
     if (flagadr == 0)
     {
         string         privateKeyStr = PrivateKey;
         BitcoinSecret  privateKey    = new BitcoinSecret(privateKeyStr);
         Network        network       = privateKey.Network;
         PubKey         pubKey        = privateKey.PubKey;
         string         pubKeyStr     = pubKey.ToHex();
         KeyId          pkhash        = pubKey.Hash;
         string         pkhashStr     = pkhash.ToString();
         BitcoinAddress addres        = pkhash.GetAddress(network);
         string         address       = addres.ToString();
         textBox1.Visible = true;
         textBox1.Text    = address;
         flagadr          = 2;
     }
     else if (flagadr == 1)
     {
         textBox1.Visible = true;
         flagadr          = 2;
     }
     else
     {
         textBox1.Visible = false;
         flagadr          = 1;
     }
 }
Пример #8
0
 /// <summary>
 ///  Describe public key
 /// </summary>
 /// <param name="publicKey"></param>
 /// <returns></returns>
 public static ScanTxoutPubkey PublicKey(PubKey publicKey)
 {
     if (publicKey == null)
     {
         throw new ArgumentNullException(nameof(publicKey));
     }
     return(new ScanTxoutPubkey($"{publicKey.ToHex()}"));
 }
Пример #9
0
        public void TestRpcListUnspentForWatchOnlyIsSuccessful()
        {
            using (NodeBuilder builder = NodeBuilder.Create(this))
            {
                CoreNode node  = builder.CreateStratisPowNode(new BitcoinRegTest()).AlwaysFlushBlocks().WithWallet().Start();
                CoreNode node2 = builder.CreateStratisPowNode(new BitcoinRegTest()).WithReadyBlockchainData(ReadyBlockchain.BitcoinRegTest10Miner).Start();

                TestHelper.ConnectAndSync(node, node2);

                UnspentOutputReference tx = node2.FullNode.WalletManager().GetUnspentTransactionsInWallet("mywallet", 0, Features.Wallet.Wallet.NormalAccounts).First();

                RPCClient rpc = node.CreateRPCClient();

                PubKey pubKey = PayToPubkeyTemplate.Instance.ExtractScriptPubKeyParameters(tx.Address.Pubkey);

                Assert.Throws <RPCException>(() => rpc.SendCommand(RPCOperations.gettransaction, tx.Transaction.Id.ToString(), true));

                rpc.ImportPubKey(pubKey.ToHex());

                // ListUnspent will not regard the outputs as spendable if they are not sufficiently mature.
                rpc.Generate((int)node.FullNode.Network.Consensus.CoinbaseMaturity);

                TestBase.WaitLoop(() => node.FullNode.WalletManager().WalletTipHeight == node2.FullNode.WalletManager().WalletTipHeight);

                TestBase.WaitLoop(() =>
                {
                    try
                    {
                        // Wait until gettransaction can find the transaction in the watch only account.
                        RPCResponse walletTx = rpc.SendCommand(RPCOperations.gettransaction, tx.Transaction.Id.ToString(), true);

                        return(walletTx != null);
                    }
                    catch (RPCException)
                    {
                        return(false);
                    }
                });

                UnspentCoin[] unspent = rpc.ListUnspent(1, 9999999);

                bool found = false;

                foreach (UnspentCoin coin in unspent)
                {
                    if (coin.OutPoint == tx.ToOutPoint())
                    {
                        found = true;
                    }

                    Assert.Equal(coin.Account, Features.Wallet.Wallet.WatchOnlyAccountName);
                }

                Assert.True(found);
            }
        }
Пример #10
0
        public void RemoveFederationMember(PubKey pubKey)
        {
            lock (this.locker)
            {
                this.federationMembers.Remove(pubKey);

                this.SaveFederationKeys(this.federationMembers);

                this.logger.LogInformation("Federation member '{0}' was removed!", pubKey.ToHex());
            }
        }
Пример #11
0
 public WhatIsPublicKey(PubKey pubkey, Network network)
 {
     Hex         = pubkey.ToHex();
     Address     = new WhatIsAddress(pubkey.GetAddress(network));
     P2SHAddress = new WhatIsAddress(pubkey.ScriptPubKey.GetScriptAddress(network))
     {
         RedeemScript = new WhatIsScript(pubkey.ScriptPubKey, network)
     };
     ScriptPubKey = new WhatIsScript(pubkey.ScriptPubKey, network);
     IsCompressed = pubkey.IsCompressed;
 }
Пример #12
0
        public void ListSecrets(NetworkCredential credentials, string host, Network net)
        {
            RPCClient client = new RPCClient("usuaraw:SupEr3421aw", new Uri("127.0.0.1"), net);
            IEnumerable <BitcoinSecret> secrets = client.ListSecrets();

            foreach (BitcoinSecret secret in secrets)
            {
                PubKey pub = secret.PubKey;
                Console.WriteLine("key: " + secret.PrivateKey.GetWif(net));
                Console.WriteLine("secret: " + secret);
                Console.WriteLine("pub: " + pub.ToHex());
                Console.WriteLine("addr: " + pub.GetAddress(net));
            }
        }
Пример #13
0
        public void RemoveFederationMember(PubKey pubKey)
        {
            lock (this.locker)
            {
                this.federationMembers.Remove(pubKey);

                this.SaveFederationKeys(this.federationMembers);
                this.SetIsFederationMember();

                this.logger.LogInformation("Federation member '{0}' was removed!", pubKey.ToHex());
            }

            this.signals.Publish(new FedMemberKicked(pubKey));
        }
Пример #14
0
        private int FindPubKey(ExtPubKey xpubKey, PubKey pubKey)
        {
            var receive = xpubKey.Derive(0);

            for (int i = 0; i < 100; i++)
            {
                if (receive.Derive((uint)i).PubKey.ToHex() == pubKey.ToHex())
                {
                    return(i);
                }
            }

            throw new ArgumentException("Pubkey not found");
        }
Пример #15
0
        public void AddFederationMember(PubKey pubKey)
        {
            lock (this.locker)
            {
                if (this.federationMembers.Contains(pubKey))
                {
                    this.logger.LogTrace("(-)[ALREADY_EXISTS]");
                    return;
                }

                this.federationMembers.Add(pubKey);

                this.SaveFederationKeys(this.federationMembers);

                this.logger.LogInformation("Federation member '{0}' was added!", pubKey.ToHex());
            }
        }
Пример #16
0
        /// <summary>
        /// Verify the Neblio message signed by some Neblio Private Key.
        /// This function uses the Public Key instead of the Address for the verification
        /// </summary>
        /// <param name="message">input original message</param>
        /// <param name="signature">signature made by some Neblio address</param>
        /// <param name="address">Neblio address</param>
        /// <returns></returns>
        public static async Task <(bool, string)> VerifyMessage(string message, string signature, PubKey pubkey, bool messageIsAlreadyHash = false)
        {
            //if (string.IsNullOrEmpty(message) || string.IsNullOrEmpty(signature) || string.IsNullOrEmpty(address))
            if (string.IsNullOrEmpty(message) || string.IsNullOrEmpty(signature) || pubkey == null)
            {
                return(false, "Input parameters cannot be empty or null.");
            }

            try
            {
                //var add = BitcoinAddress.Create(address, NeblioTransactionHelpers.Network);
                //var vadd = (add as IPubkeyHashUsable);
                var split = signature.Split('@');
                if (split.Length > 1)
                {
                    var sg         = Convert.FromBase64String(split[1]);
                    var recoveryId = Convert.ToInt32(split[0]);

                    var sgs = new CompactSignature(recoveryId, sg);
                    Console.WriteLine("Signature loaded.");
                    PubKey recoveredPubKey = null;
                    if (!messageIsAlreadyHash)
                    {
                        uint256 hash = NBitcoin.Crypto.Hashes.DoubleSHA256(Encoding.UTF8.GetBytes(message));
                        recoveredPubKey = PubKey.RecoverCompact(hash, sgs);
                    }
                    else
                    {
                        recoveredPubKey = PubKey.RecoverCompact(uint256.Parse(message), sgs);
                    }

                    if (recoveredPubKey.ToHex() == pubkey.ToHex())
                    {
                        return(true, "Verified.");
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception in verification. " + ex.Message);
                return(false, "Wrong input. Cannot verify the message signature." + ex.Message);
            }
            return(false, "Not verified.");
        }
Пример #17
0
        private static void Main(string[] args)
        {
            string wif        = "KxyJg5ZCk6SFsorqiR7Bb6heDDmss4PX76VtyM5qTEyn83Bgt1tD";
            Key    privateKey = Key.Parse(wif);

            Console.WriteLine("0. private_key:\r\n" + privateKey.ToBytes().ToHex());

            PubKey publicKey = privateKey.PubKey;

            Console.WriteLine("00. public_key_uncompressed:\r\n" + publicKey.ToHex());

            string output = HashUtils.CreateBitcoinAddressVerbose(publicKey.Compress(true).ToBytes());

            Console.WriteLine(output);

            string check = HashUtils.WifToBitcoinAddress(wif);

            Console.WriteLine("Check:\r\n" + check);
        }
Пример #18
0
        private async Task VoteAndMineBlockAsync(PubKey key, bool add, CoreNode node)
        {
            var model = new HexPubKeyModel()
            {
                PubKeyHex = key.ToHex()
            };

            if (add)
            {
                node.FullNode.NodeService <FederationVotingController>().VoteAddFedMember(model);
            }
            else
            {
                node.FullNode.NodeService <FederationVotingController>().VoteKickFedMember(model);
            }

            await node.MineBlocksAsync(1);

            CoreNodePoAExtensions.WaitTillSynced(this.node1, this.node2, this.node3);
        }
        /// <summary>Checks that whomever mined this block is participating in any pending polls to vote-in new federation members.</summary>
        public override Task RunAsync(RuleContext context)
        {
            // "AddFederationMember" polls, that were started at or before this height, that are still pending, which this node has voted in favor of.
            List <Poll> pendingPolls = this.ruleEngine.VotingManager.GetPendingPolls()
                                       .Where(p => p.VotingData.Key == VoteKey.AddFederationMember &&
                                              p.PollStartBlockData != null &&
                                              p.PollStartBlockData.Height <= context.ValidationContext.ChainedHeaderToValidate.Height &&
                                              p.PubKeysHexVotedInFavor.Any(pk => pk == this.federationManager.CurrentFederationKey.PubKey.ToHex())).ToList();

            // Exit if there aren't any.
            if (!pendingPolls.Any())
            {
                return(Task.CompletedTask);
            }

            // Ignore any polls that the miner has already voted on.
            PubKey blockMiner = this.federationHistory.GetFederationMemberForBlock(context.ValidationContext.ChainedHeaderToValidate).PubKey;

            pendingPolls = pendingPolls.Where(p => !p.PubKeysHexVotedInFavor.Any(pk => pk == blockMiner.ToHex())).ToList();

            // Exit if there is nothing remaining.
            if (!pendingPolls.Any())
            {
                return(Task.CompletedTask);
            }

            // Verify that the miner is including all the missing votes now.
            Transaction coinbase = context.ValidationContext.BlockToValidate.Transactions[0];

            byte[] votingDataBytes = this.votingDataEncoder.ExtractRawVotingData(coinbase);

            if (votingDataBytes == null)
            {
                PoAConsensusErrors.BlockMissingVotes.Throw();
            }

            // If any remaining polls are not found in the voting data list then throw a consenus error.
            List <VotingData> votingDataList = this.votingDataEncoder.Decode(votingDataBytes);

            if (pendingPolls.Any(p => !votingDataList.Any(data => data == p.VotingData)))
            {
                PoAConsensusErrors.BlockMissingVotes.Throw();
            }

            return(Task.CompletedTask);
        }
Пример #20
0
        public void key_test1()
        {
            BitcoinSecret bsecret1  = this.networkMain.CreateBitcoinSecret(strSecret1);
            BitcoinSecret bsecret2  = this.networkMain.CreateBitcoinSecret(strSecret2);
            BitcoinSecret bsecret1C = this.networkMain.CreateBitcoinSecret(strSecret1C);
            BitcoinSecret bsecret2C = this.networkMain.CreateBitcoinSecret(strSecret2C);

            Assert.Throws <FormatException>(() => this.networkMain.CreateBitcoinSecret(strAddressBad));

            Key key1 = bsecret1.PrivateKey;

            Assert.True(key1.IsCompressed == false);
            Assert.True(bsecret1.Copy(true).PrivateKey.IsCompressed == true);
            Assert.True(bsecret1.Copy(true).Copy(false).IsCompressed == false);
            Assert.True(bsecret1.Copy(true).Copy(false).ToString() == bsecret1.ToString());
            Key key2 = bsecret2.PrivateKey;

            Assert.True(key2.IsCompressed == false);
            Key key1C = bsecret1C.PrivateKey;

            Assert.True(key1C.IsCompressed == true);
            Key key2C = bsecret2C.PrivateKey;

            Assert.True(key1C.IsCompressed == true);

            PubKey pubkey1  = key1.PubKey;
            PubKey pubkey2  = key2.PubKey;
            PubKey pubkey1C = key1C.PubKey;
            PubKey pubkey2C = key2C.PubKey;

            Assert.True(this.addr1.Hash == pubkey1.Hash);
            Assert.True(this.addr2.Hash == pubkey2.Hash);
            Assert.True(this.addr1C.Hash == pubkey1C.Hash);
            Assert.True(this.addr2C.Hash == pubkey2C.Hash);



            for (int n = 0; n < 16; n++)
            {
                string strMsg = String.Format("Very secret message {0}: 11", n);
                if (n == 10)
                {
                    //Test one long message
                    strMsg = String.Join(",", Enumerable.Range(0, 2000).Select(i => i.ToString()).ToArray());
                }
                uint256 hashMsg = Hashes.Hash256(TestUtils.ToBytes(strMsg));

                // normal signatures

                ECDSASignature sign1 = null, sign2 = null, sign1C = null, sign2C = null;
                var            tasks = new List <Task>();
                tasks.Add(Task.Run(() => sign1  = key1.Sign(hashMsg)));
                tasks.Add(Task.Run(() => sign2  = key2.Sign(hashMsg)));
                tasks.Add(Task.Run(() => sign1C = key1C.Sign(hashMsg)));
                tasks.Add(Task.Run(() => sign2C = key2C.Sign(hashMsg)));
                Task.WaitAll(tasks.ToArray());
                tasks.Clear();

                tasks.Add(Task.Run(() => Assert.True(pubkey1.Verify(hashMsg, sign1))));
                tasks.Add(Task.Run(() => Assert.True(pubkey2.Verify(hashMsg, sign2))));
                tasks.Add(Task.Run(() => Assert.True(pubkey1C.Verify(hashMsg, sign1C))));
                tasks.Add(Task.Run(() => Assert.True(pubkey2C.Verify(hashMsg, sign2C))));
                Task.WaitAll(tasks.ToArray());
                tasks.Clear();

                tasks.Add(Task.Run(() => Assert.True(pubkey1.Verify(hashMsg, sign1))));
                tasks.Add(Task.Run(() => Assert.True(!pubkey1.Verify(hashMsg, sign2))));
                tasks.Add(Task.Run(() => Assert.True(pubkey1.Verify(hashMsg, sign1C))));
                tasks.Add(Task.Run(() => Assert.True(!pubkey1.Verify(hashMsg, sign2C))));

                tasks.Add(Task.Run(() => Assert.True(!pubkey2.Verify(hashMsg, sign1))));
                tasks.Add(Task.Run(() => Assert.True(pubkey2.Verify(hashMsg, sign2))));
                tasks.Add(Task.Run(() => Assert.True(!pubkey2.Verify(hashMsg, sign1C))));
                tasks.Add(Task.Run(() => Assert.True(pubkey2.Verify(hashMsg, sign2C))));

                tasks.Add(Task.Run(() => Assert.True(pubkey1C.Verify(hashMsg, sign1))));
                tasks.Add(Task.Run(() => Assert.True(!pubkey1C.Verify(hashMsg, sign2))));
                tasks.Add(Task.Run(() => Assert.True(pubkey1C.Verify(hashMsg, sign1C))));
                tasks.Add(Task.Run(() => Assert.True(!pubkey1C.Verify(hashMsg, sign2C))));

                tasks.Add(Task.Run(() => Assert.True(!pubkey2C.Verify(hashMsg, sign1))));
                tasks.Add(Task.Run(() => Assert.True(pubkey2C.Verify(hashMsg, sign2))));
                tasks.Add(Task.Run(() => Assert.True(!pubkey2C.Verify(hashMsg, sign1C))));
                tasks.Add(Task.Run(() => Assert.True(pubkey2C.Verify(hashMsg, sign2C))));

                Task.WaitAll(tasks.ToArray());
                tasks.Clear();

                // compact signatures (with key recovery)

                byte[] csign1 = null, csign2 = null, csign1C = null, csign2C = null;

                tasks.Add(Task.Run(() => csign1  = key1.SignCompact(hashMsg)));
                tasks.Add(Task.Run(() => csign2  = key2.SignCompact(hashMsg)));
                tasks.Add(Task.Run(() => csign1C = key1C.SignCompact(hashMsg)));
                tasks.Add(Task.Run(() => csign2C = key2C.SignCompact(hashMsg)));
                Task.WaitAll(tasks.ToArray());
                tasks.Clear();

                PubKey rkey1 = null, rkey2 = null, rkey1C = null, rkey2C = null;
                tasks.Add(Task.Run(() => rkey1  = PubKey.RecoverCompact(hashMsg, csign1)));
                tasks.Add(Task.Run(() => rkey2  = PubKey.RecoverCompact(hashMsg, csign2)));
                tasks.Add(Task.Run(() => rkey1C = PubKey.RecoverCompact(hashMsg, csign1C)));
                tasks.Add(Task.Run(() => rkey2C = PubKey.RecoverCompact(hashMsg, csign2C)));
                Task.WaitAll(tasks.ToArray());
                tasks.Clear();

                Assert.True(rkey1.ToHex() == pubkey1.ToHex());
                Assert.True(rkey2.ToHex() == pubkey2.ToHex());
                Assert.True(rkey1C.ToHex() == pubkey1C.ToHex());
                Assert.True(rkey2C.ToHex() == pubkey2C.ToHex());
            }
        }
        public override async Task RunAsync(RuleContext context)
        {
            ChainedHeader chainedHeader = context.ValidationContext.ChainedHeaderToValidate;

            var header = chainedHeader.Header as PoABlockHeader;

            List <IFederationMember> federation = this.federationHistory.GetFederationForBlock(chainedHeader);

            PubKey pubKey = this.federationHistory.GetFederationMemberForBlock(context.ValidationContext.ChainedHeaderToValidate, federation)?.PubKey;

            if (pubKey == null || !this.validator.VerifySignature(pubKey, header))
            {
                ChainedHeader currentHeader = context.ValidationContext.ChainedHeaderToValidate;

                // If we're evaluating a batch of received headers it's possible that we're so far beyond the current tip
                // that we have not yet processed all the votes that may determine the federation make-up.
                bool mightBeInsufficient = currentHeader.Height - this.chainState.ConsensusTip.Height > this.maxReorg;
                if (mightBeInsufficient)
                {
                    // Mark header as insufficient to avoid banning the peer that presented it.
                    // When we advance consensus we will be able to validate it.
                    context.ValidationContext.InsufficientHeaderInformation = true;
                }

                this.Logger.LogDebug("(-)[INVALID_SIGNATURE]");
                PoAConsensusErrors.InvalidHeaderSignature.Throw();
            }

            // Look at the last round of blocks to find the previous time that the miner mined.
            uint roundTime    = this.slotsManager.GetRoundLengthSeconds(federation.Count);
            int  blockCounter = 0;

            for (ChainedHeader prevHeader = chainedHeader.Previous; prevHeader.Previous != null; prevHeader = prevHeader.Previous)
            {
                blockCounter += 1;

                if ((header.Time - prevHeader.Header.Time) >= roundTime)
                {
                    break;
                }

                // If the miner is found again within the same round then throw a consensus error.
                if (this.federationHistory.GetFederationMemberForBlock(prevHeader)?.PubKey != pubKey)
                {
                    continue;
                }

                // Mining slots shift when the federation changes.
                // Only raise an error if the federation did not change.
                uint newRoundTime = this.slotsManager.GetRoundLengthSeconds(this.federationHistory.GetFederationForBlock(prevHeader).Count);
                if (newRoundTime != roundTime)
                {
                    break;
                }

                // Exempt this one block that somehow got included in the chain where the miner managed to mine too early.
                if (prevHeader.HashBlock == uint256.Parse("7d67ea42010f03971edd6ba5e1b644d09c9fd0191ca8d312255c12d23f7cd147"))
                {
                    break;
                }

                this.Logger.LogWarning($"Block {prevHeader.HashBlock} was mined by the same miner '{pubKey.ToHex()}' as {blockCounter} blocks ({header.Time - prevHeader.Header.Time})s ago and there was no federation change.");
            }
        }
        /// <inheritdoc/>
        public void AddVote(string requestId, BigInteger transactionId, PubKey pubKey)
        {
            lock (this.lockObject)
            {
                if (!this.receivedVotes.TryGetValue(requestId, out HashSet <PubKey> voted))
                {
                    voted = new HashSet <PubKey>();
                }

                // Ignore the vote if the pubkey has already submitted a vote.
                if (voted.Contains(pubKey))
                {
                    return;
                }

                this.logger.Info("Pubkey {0} adding vote for request {1}, transactionId {2}.", pubKey.ToHex(), requestId, transactionId);

                voted.Add(pubKey);

                if (!this.activeVotes.TryGetValue(requestId, out Dictionary <BigInteger, int> transactionIdVotes))
                {
                    transactionIdVotes = new Dictionary <BigInteger, int>();
                }

                if (!transactionIdVotes.ContainsKey(transactionId))
                {
                    transactionIdVotes[transactionId] = 1;
                }
                else
                {
                    transactionIdVotes[transactionId]++;
                }

                this.activeVotes[requestId]   = transactionIdVotes;
                this.receivedVotes[requestId] = voted;
            }
        }
        public List <Teammate> GetWithPubKey(PubKey pubKey)
        {
            string pubKeyHex = pubKey.ToHex();

            return(_context.Teammate.Where(x => x.PublicKey == pubKeyHex).ToList());
        }
Пример #24
0
        public override void Run(RuleContext context)
        {
            var header = context.ValidationContext.ChainedHeaderToValidate.Header as PoABlockHeader;

            PubKey pubKey = this.slotsManager.GetFederationMemberForBlock(context.ValidationContext.ChainedHeaderToValidate, this.votingManager).PubKey;

            if (!this.validator.VerifySignature(pubKey, header))
            {
                if (this.votingEnabled)
                {
                    ChainedHeader currentHeader = context.ValidationContext.ChainedHeaderToValidate;

                    // If we're evaluating a batch of received headers it's possible that we're so far beyond the current tip
                    // that we have not yet processed all the votes that may determine the federation make-up.
                    bool mightBeInsufficient = currentHeader.Height - this.chainState.ConsensusTip.Height > this.maxReorg;
                    if (mightBeInsufficient)
                    {
                        // Mark header as insufficient to avoid banning the peer that presented it.
                        // When we advance consensus we will be able to validate it.
                        context.ValidationContext.InsufficientHeaderInformation = true;
                    }
                }

                try
                {
                    // Gather all past and present mining public keys.
                    IEnumerable <PubKey> genesisFederation = ((PoAConsensusOptions)this.network.Consensus.Options).GenesisFederationMembers.Select(m => m.PubKey);
                    var knownKeys = new HashSet <PubKey>(genesisFederation);
                    foreach (Poll poll in this.votingManager.GetFinishedPolls().Where(x => ((x.VotingData.Key == VoteKey.AddFederationMember) || (x.VotingData.Key == VoteKey.KickFederationMember))))
                    {
                        IFederationMember federationMember = ((PoAConsensusFactory)(this.network.Consensus.ConsensusFactory)).DeserializeFederationMember(poll.VotingData.Data);
                        knownKeys.Add(federationMember.PubKey);
                    }

                    // Try to provide the public key that signed the block.
                    var signature = ECDSASignature.FromDER(header.BlockSignature.Signature);
                    for (int recId = 0; recId < 4; recId++)
                    {
                        PubKey pubKeyForSig = PubKey.RecoverFromSignature(recId, signature, header.GetHash(), true);
                        if (pubKeyForSig == null)
                        {
                            this.Logger.LogDebug($"Could not match candidate keys to any known key.");
                            break;
                        }

                        this.Logger.LogDebug($"Attempting to match candidate key '{ pubKeyForSig.ToHex() }' to known keys.");

                        if (!knownKeys.Any(pk => pk == pubKeyForSig))
                        {
                            continue;
                        }

                        IEnumerable <PubKey> modifiedFederation = this.votingManager?.GetModifiedFederation(context.ValidationContext.ChainedHeaderToValidate).Select(m => m.PubKey) ?? genesisFederation;

                        this.Logger.LogDebug($"Block is signed by '{0}' but expected '{1}' from: {2}.", pubKeyForSig.ToHex(), pubKey, string.Join(" ", modifiedFederation.Select(pk => pk.ToHex())));

                        break;
                    }
                    ;
                }
                catch (Exception) { }

                this.Logger.LogTrace("(-)[INVALID_SIGNATURE]");
                PoAConsensusErrors.InvalidHeaderSignature.Throw();
            }
        }
Пример #25
0
        public override async Task RunAsync(RuleContext context)
        {
            // Only start validating at the last checkpoint block.
            if (context.ValidationContext.ChainedHeaderToValidate.Height < (this.lastCheckPoint?.Height ?? 0))
            {
                return;
            }

            ChainedHeader chainedHeader = context.ValidationContext.ChainedHeaderToValidate;

            // If we're evaluating a batch of received headers it's possible that we're so far beyond the current tip
            // that we have not yet processed all the votes that may determine the federation make-up.
            if (!this.federationHistory.CanGetFederationForBlock(chainedHeader))
            {
                // Mark header as insufficient to avoid banning the peer that presented it.
                // When we advance consensus we will be able to validate it.
                context.ValidationContext.InsufficientHeaderInformation = true;

                this.Logger.LogWarning("The polls repository is too far behind to reliably determine the federation members.");
                this.Logger.LogDebug("(-)[INVALID_SIGNATURE]");
                PoAConsensusErrors.InvalidHeaderSignature.Throw();
            }

            var header = chainedHeader.Header as PoABlockHeader;

            PubKey pubKey = this.federationHistory.GetFederationMemberForBlock(chainedHeader)?.PubKey;

            if (pubKey == null || !this.validator.VerifySignature(pubKey, header))
            {
                this.Logger.LogWarning("The block signature could not be matched with a current federation member.");
                this.Logger.LogDebug("(-)[INVALID_SIGNATURE]");
                PoAConsensusErrors.InvalidHeaderSignature.Throw();
            }

            // Look at the last round of blocks to find the previous time that the miner mined.
            var roundTime    = this.slotsManager.GetRoundLength(this.federationHistory.GetFederationForBlock(chainedHeader).Count);
            int blockCounter = 0;

            for (ChainedHeader prevHeader = chainedHeader.Previous; prevHeader.Previous != null; prevHeader = prevHeader.Previous)
            {
                blockCounter += 1;

                if ((header.BlockTime - prevHeader.Header.BlockTime) >= roundTime)
                {
                    break;
                }

                // If the miner is found again within the same round then throw a consensus error.
                if (this.federationHistory.GetFederationMemberForBlock(prevHeader)?.PubKey != pubKey)
                {
                    continue;
                }

                // Mining slots shift when the federation changes.
                // Only raise an error if the federation did not change.
                if (this.slotsManager.GetRoundLength(this.federationHistory.GetFederationForBlock(prevHeader).Count) != roundTime)
                {
                    break;
                }

                if (this.slotsManager.GetRoundLength(this.federationHistory.GetFederationForBlock(prevHeader.Previous).Count) != roundTime)
                {
                    break;
                }

                this.Logger.LogDebug("Block {0} was mined by the same miner '{1}' as {2} blocks ({3})s ago and there was no federation change.", prevHeader.HashBlock, pubKey.ToHex(), blockCounter, header.Time - prevHeader.Header.Time);
                this.Logger.LogTrace("(-)[TIME_TOO_EARLY]");
                ConsensusErrors.BlockTimestampTooEarly.Throw();
            }
        }
Пример #26
0
        /// <summary>Checks that whomever mined this block is participating in any pending polls to vote-in new federation members.</summary>
        public override Task RunAsync(RuleContext context)
        {
            // Determine the members that this node is currently in favor of adding.
            List <Poll>          pendingPolls = this.ruleEngine.VotingManager.GetPendingPolls();
            var                  encoder      = new JoinFederationRequestEncoder(this.loggerFactory);
            IEnumerable <PubKey> newMembers   = pendingPolls
                                                .Where(p => p.VotingData.Key == VoteKey.AddFederationMember &&
                                                       (p.PollStartBlockData == null || p.PollStartBlockData.Height <= context.ValidationContext.ChainedHeaderToValidate.Height) &&
                                                       p.PubKeysHexVotedInFavor.Any(pk => pk == this.federationManager.CurrentFederationKey.PubKey.ToHex()))
                                                .Select(p => ((CollateralFederationMember)this.consensusFactory.DeserializeFederationMember(p.VotingData.Data)).PubKey);

            if (!newMembers.Any())
            {
                return(Task.CompletedTask);
            }

            // Determine who mined the block.
            PubKey blockMiner = this.slotsManager.GetFederationMemberForBlock(context.ValidationContext.ChainedHeaderToValidate, this.votingManager).PubKey;

            // Check that the miner is in favor of adding the same member(s).
            Dictionary <string, bool> checkList = newMembers.ToDictionary(x => x.ToHex(), x => false);

            foreach (CollateralFederationMember member in pendingPolls
                     .Where(p => p.VotingData.Key == VoteKey.AddFederationMember && p.PubKeysHexVotedInFavor.Any(pk => pk == blockMiner.ToHex()))
                     .Select(p => (CollateralFederationMember)this.consensusFactory.DeserializeFederationMember(p.VotingData.Data)))
            {
                checkList[member.PubKey.ToHex()] = true;
            }

            if (!checkList.Any(c => !c.Value))
            {
                return(Task.CompletedTask);
            }

            // Otherwise check that the miner is including those votes now.
            Transaction coinbase = context.ValidationContext.BlockToValidate.Transactions[0];

            byte[] votingDataBytes = this.votingDataEncoder.ExtractRawVotingData(coinbase);
            if (votingDataBytes != null)
            {
                List <VotingData> votingDataList = this.votingDataEncoder.Decode(votingDataBytes);
                foreach (VotingData votingData in votingDataList)
                {
                    var member = (CollateralFederationMember)this.consensusFactory.DeserializeFederationMember(votingData.Data);

                    var expectedCollateralAmount = CollateralFederationMember.GetCollateralAmountForPubKey((PoANetwork)this.network, member.PubKey);

                    // Check collateral amount.
                    if (member.CollateralAmount.ToDecimal(MoneyUnit.BTC) != expectedCollateralAmount)
                    {
                        this.logger.LogTrace("(-)[INVALID_COLLATERAL_REQUIREMENT]");
                        PoAConsensusErrors.InvalidCollateralRequirement.Throw();
                    }

                    // Can't be a multisig member.
                    if (member.IsMultisigMember)
                    {
                        this.logger.LogTrace("(-)[INVALID_MULTISIG_VOTING]");
                        PoAConsensusErrors.VotingRequestInvalidMultisig.Throw();
                    }

                    checkList[member.PubKey.ToHex()] = true;
                }
            }

            // If any outstanding votes have not been included throw a consensus error.
            if (checkList.Any(c => !c.Value))
            {
                PoAConsensusErrors.BlockMissingVotes.Throw();
            }

            return(Task.CompletedTask);
        }
        /// <inheritdoc/>
        public void AddVote(string requestId, BigInteger transactionId, PubKey pubKey)
        {
            lock (this.lockObject)
            {
                // If the request has not yet been voted on, create a voting list.
                if (!this.receivedVotes.TryGetValue(requestId, out HashSet <PubKey> voted))
                {
                    voted = new HashSet <PubKey>();
                }

                // Check if the pubkey node has voted for this request.
                if (!voted.Contains(pubKey))
                {
                    this.logger.LogDebug("Adding vote for request '{0}' (transactionId '{1}') from pubkey {2}.", requestId, transactionId, pubKey.ToHex());

                    voted.Add(pubKey);

                    // If the set of active votes does not contain the request, create a new list.
                    if (!this.transactionIdVotes.TryGetValue(requestId, out Dictionary <BigInteger, int> transactionIdVotesForRequestId))
                    {
                        transactionIdVotesForRequestId = new Dictionary <BigInteger, int>();
                    }

                    if (!transactionIdVotesForRequestId.ContainsKey(transactionId))
                    {
                        transactionIdVotesForRequestId[transactionId] = 1;
                    }
                    else
                    {
                        transactionIdVotesForRequestId[transactionId]++;
                    }

                    this.transactionIdVotes[requestId] = transactionIdVotesForRequestId;
                    this.receivedVotes[requestId]      = voted;
                }
            }
        }
Пример #28
0
        private void GatherMiningStatistics()
        {
            var log = new StringBuilder();

            log.AppendLine(">> Miner");
            log.AppendLine();

            if (!this.federationManager.IsFederationMember)
            {
                log.AppendLine("Mining information is not available for non federation members.");
                log.AppendLine("It is possible that your node was kicked from the federation due to inactivity.");
                log.AppendLine();

                this.miningStatisticsLog = log.ToString();

                return;
            }

            if (this.ibdState.IsInitialBlockDownload())
            {
                log.AppendLine("Mining information is not available whilst the node is syncing.");
                log.AppendLine("The node will mine once it reaches the network's height.");
                log.AppendLine();

                this.miningStatisticsLog = log.ToString();

                return;
            }

            ChainedHeader tip           = this.consensusManager.Tip;
            ChainedHeader currentHeader = tip;

            int pubKeyTakeCharacters = 5;
            int hitCount             = 0;

            List <IFederationMember> modifiedFederation = this.federationHistory.GetFederationForBlock(currentHeader);

            int maxDepth = modifiedFederation.Count;

            // TODO: Make this a command line option.
            bool includeHeight = false;

            log.AppendLine($"Mining information for the last { maxDepth } blocks.");
            if (includeHeight)
            {
                log.AppendLine("Note 'MISS' indicates a slot where a miner didn't produce a block.");
            }
            else
            {
                log.AppendLine("Note that '<' and '>' surrounds a slot where a miner didn't produce a block.");
            }

            uint currentSlotTime = (uint)this.dateTimeProvider.GetAdjustedTimeAsUnixTimestamp();

            currentSlotTime -= currentSlotTime % this.network.ConsensusOptions.TargetSpacingSeconds;

            // Determine the public key of the current slot.
            string pubKeyRepresentation;

            // Iterate mining slots.
            for (int i = 0; i < maxDepth; i++, currentSlotTime -= this.network.ConsensusOptions.TargetSpacingSeconds)
            {
                // Find the chained header for this slot.
                while (currentHeader.Header.Time > currentSlotTime)
                {
                    currentHeader = currentHeader.Previous;
                }

                // Mined in this slot?
                bool minedInThisSlot = currentHeader.Header.Time == currentSlotTime;

                PubKey pubKey = (minedInThisSlot ?
                                 this.federationHistory.GetFederationMemberForBlock(currentHeader) :
                                 DetermineExpectedMinerForTimestamp(currentSlotTime)).PubKey;


                if (pubKey == this.federationManager.CurrentFederationKey?.PubKey)
                {
                    pubKeyRepresentation = "█████";
                    this.miningStatistics.ProducedBlockInLastRound = minedInThisSlot;
                }
                else
                {
                    pubKeyRepresentation = pubKey.ToHex().Substring(0, pubKeyTakeCharacters);
                }

                if (includeHeight)
                {
                    string strHeight = minedInThisSlot ? currentHeader.Height.ToString().PadLeft(7) : "---MISS";
                    log.Append($"{strHeight}:{ pubKeyRepresentation } ");
                }
                else
                {
                    log.Append(minedInThisSlot ? $"[{pubKeyRepresentation}] " : $"<{pubKeyRepresentation}> ");
                }

                if (minedInThisSlot)
                {
                    hitCount++;
                }

                if (((i + 1) % (includeHeight ? 10 : 20)) == 0)
                {
                    log.AppendLine();
                }
            }

            this.miningStatistics.MinerHits = hitCount;

            log.Append("...");
            log.AppendLine();
            log.AppendLine($"Miner hits".PadRight(LoggingConfiguration.ColumnLength) + $": {hitCount} of {maxDepth}({(((float)hitCount / (float)maxDepth)).ToString("P2")})");
            log.AppendLine($"Miner idle time".PadRight(LoggingConfiguration.ColumnLength) + $": { TimeSpan.FromSeconds(this.network.ConsensusOptions.TargetSpacingSeconds * (maxDepth - hitCount)).ToString(@"hh\:mm\:ss")}");
            log.AppendLine();

            this.miningStatisticsLog = log.ToString();
        }
Пример #29
0
        private void ProcessBlock(DBreeze.Transactions.Transaction transaction, ChainedHeaderBlock chBlock)
        {
            long flagFall = DateTime.Now.Ticks;

            try
            {
                lock (this.locker)
                {
                    bool pollsRepositoryModified = false;

                    foreach (Poll poll in this.GetPendingPolls().Where(p => PollsRepository.IsPollExpiredAt(p, chBlock.ChainedHeader, this.network as PoANetwork)).ToList())
                    {
                        this.logger.LogDebug("Expiring poll '{0}'.", poll);

                        // Flag the poll as expired. The "PollVotedInFavorBlockData" will always be null at this point due to the "GetPendingPolls" filter above.
                        // The value of the hash is not significant but we set it to a non-zero value to prevent the field from being de-serialized as null.
                        poll.IsExpired = true;
                        this.polls.OnPendingStatusChanged(poll);
                        this.PollsRepository.UpdatePoll(transaction, poll);
                        pollsRepositoryModified = true;
                    }

                    foreach (Poll poll in this.GetApprovedPolls())
                    {
                        if (poll.IsExpired || chBlock.ChainedHeader.Height != (poll.PollVotedInFavorBlockData.Height + this.network.Consensus.MaxReorgLength))
                        {
                            continue;
                        }

                        this.logger.LogDebug("Applying poll '{0}'.", poll);
                        this.pollResultExecutor.ApplyChange(poll.VotingData);

                        poll.PollExecutedBlockData = new HashHeightPair(chBlock.ChainedHeader);
                        this.PollsRepository.UpdatePoll(transaction, poll);

                        pollsRepositoryModified = true;
                    }

                    if (this.federationManager.GetMultisigMinersApplicabilityHeight() == chBlock.ChainedHeader.Height)
                    {
                        this.federationManager.UpdateMultisigMiners(true);
                    }

                    byte[] rawVotingData = this.votingDataEncoder.ExtractRawVotingData(chBlock.Block.Transactions[0]);

                    if (rawVotingData == null)
                    {
                        this.PollsRepository.SaveCurrentTip(pollsRepositoryModified ? transaction : null, chBlock.ChainedHeader);
                        return;
                    }

                    IFederationMember member = this.federationHistory.GetFederationMemberForBlock(chBlock.ChainedHeader);
                    if (member == null)
                    {
                        this.logger.LogError("The block was mined by a non-federation-member!");
                        this.logger.LogTrace("(-)[ALIEN_BLOCK]");

                        this.PollsRepository.SaveCurrentTip(pollsRepositoryModified ? transaction : null, chBlock.ChainedHeader);
                        return;
                    }

                    PubKey fedMemberKey = member.PubKey;

                    string fedMemberKeyHex = fedMemberKey.ToHex();

                    List <VotingData> votingDataList = this.votingDataEncoder.Decode(rawVotingData);

                    this.logger.LogDebug("Applying {0} voting data items included in a block by '{1}'.", votingDataList.Count, fedMemberKeyHex);

                    lock (this.locker)
                    {
                        foreach (VotingData data in votingDataList)
                        {
                            if (this.federationManager.CurrentFederationKey?.PubKey.ToHex() == fedMemberKeyHex)
                            {
                                // Any votes found in the block is no longer scheduled.
                                // This avoids clinging to votes scheduled during IBD.
                                if (this.scheduledVotingData.Any(v => v == data))
                                {
                                    this.scheduledVotingData.Remove(data);
                                }
                            }

                            if (this.IsVotingOnMultisigMember(data))
                            {
                                continue;
                            }

                            Poll poll = this.polls.GetPendingPollByVotingData(data);

                            if (poll == null)
                            {
                                // Ensures that highestPollId can't be changed before the poll is committed.
                                this.PollsRepository.Synchronous(() =>
                                {
                                    poll = new Poll()
                                    {
                                        Id = this.PollsRepository.GetHighestPollId() + 1,
                                        PollVotedInFavorBlockData = null,
                                        PollExecutedBlockData     = null,
                                        PollStartBlockData        = new HashHeightPair(chBlock.ChainedHeader),
                                        VotingData             = data,
                                        PubKeysHexVotedInFavor = new List <Vote>()
                                        {
                                            new Vote()
                                            {
                                                PubKey = fedMemberKeyHex, Height = chBlock.ChainedHeader.Height
                                            }
                                        }
                                    };

                                    this.polls.Add(poll);

                                    this.PollsRepository.AddPolls(transaction, poll);
                                    pollsRepositoryModified = true;

                                    this.logger.LogDebug("New poll was created: '{0}'.", poll);
                                });
                            }
                            else if (!poll.PubKeysHexVotedInFavor.Any(v => v.PubKey == fedMemberKeyHex))
                            {
                                poll.PubKeysHexVotedInFavor.Add(new Vote()
                                {
                                    PubKey = fedMemberKeyHex, Height = chBlock.ChainedHeader.Height
                                });
                                this.PollsRepository.UpdatePoll(transaction, poll);
                                pollsRepositoryModified = true;

                                this.logger.LogDebug("Voted on existing poll: '{0}'.", poll);
                            }
                            else
                            {
                                this.logger.LogDebug("Fed member '{0}' already voted for this poll. Ignoring his vote. Poll: '{1}'.", fedMemberKeyHex, poll);
                            }

                            List <IFederationMember> modifiedFederation = this.federationManager.GetFederationMembers();

                            var fedMembersHex = new ConcurrentHashSet <string>(modifiedFederation.Select(x => x.PubKey.ToHex()));

                            // Member that were about to be kicked when voting started don't participate.
                            if (this.idleFederationMembersKicker != null)
                            {
                                ChainedHeader chainedHeader = chBlock.ChainedHeader.GetAncestor(poll.PollStartBlockData.Height);

                                if (chainedHeader?.Header == null)
                                {
                                    chainedHeader = this.chainIndexer.GetHeader(poll.PollStartBlockData.Hash);
                                    if (chainedHeader == null)
                                    {
                                        this.logger.LogWarning("Couldn't retrieve header for block at height-hash: {0}-{1}.", poll.PollStartBlockData.Height, poll.PollStartBlockData.Hash?.ToString());

                                        Guard.NotNull(chainedHeader, nameof(chainedHeader));
                                        Guard.NotNull(chainedHeader.Header, nameof(chainedHeader.Header));
                                    }
                                }

                                foreach (IFederationMember miner in modifiedFederation)
                                {
                                    if (this.idleFederationMembersKicker.ShouldMemberBeKicked(miner, chainedHeader, chBlock.ChainedHeader, out _))
                                    {
                                        fedMembersHex.TryRemove(miner.PubKey.ToHex());
                                    }
                                }
                            }

                            // It is possible that there is a vote from a federation member that was deleted from the federation.
                            // Do not count votes from entities that are not active fed members.
                            int validVotesCount = poll.PubKeysHexVotedInFavor.Count(x => fedMembersHex.Contains(x.PubKey));

                            int requiredVotesCount = (fedMembersHex.Count / 2) + 1;

                            this.logger.LogDebug("Fed members count: {0}, valid votes count: {1}, required votes count: {2}.", fedMembersHex.Count, validVotesCount, requiredVotesCount);

                            if (validVotesCount < requiredVotesCount)
                            {
                                continue;
                            }

                            poll.PollVotedInFavorBlockData = new HashHeightPair(chBlock.ChainedHeader);
                            this.polls.OnPendingStatusChanged(poll);

                            this.PollsRepository.UpdatePoll(transaction, poll);
                            pollsRepositoryModified = true;
                        }
                    }

                    this.PollsRepository.SaveCurrentTip(pollsRepositoryModified ? transaction : null, chBlock.ChainedHeader);
                }
            }
            catch (Exception ex)
            {
                this.logger.LogError(ex, ex.ToString());
                throw;
            }
            finally
            {
                long timeConsumed = DateTime.Now.Ticks - flagFall;

                this.blocksProcessed++;
                this.blocksProcessingTime += timeConsumed;
            }
        }
Пример #30
0
        public void key_test1()
        {
            BitcoinSecret bsecret1  = Network.Main.CreateBitcoinSecret(strSecret1);
            BitcoinSecret bsecret2  = Network.Main.CreateBitcoinSecret(strSecret2);
            BitcoinSecret bsecret1C = Network.Main.CreateBitcoinSecret(strSecret1C);
            BitcoinSecret bsecret2C = Network.Main.CreateBitcoinSecret(strSecret2C);

            Assert.Throws <FormatException>(() => Network.Main.CreateBitcoinSecret(strAddressBad));

            Key key1 = bsecret1.PrivateKey;

            Assert.True(key1.IsCompressed == false);
            Assert.True(bsecret1.Copy(true).PrivateKey.IsCompressed == true);
            Assert.True(bsecret1.Copy(true).Copy(false).IsCompressed == false);
            Assert.True(bsecret1.Copy(true).Copy(false).ToString() == bsecret1.ToString());
            Key key2 = bsecret2.PrivateKey;

            Assert.True(key2.IsCompressed == false);
            Key key1C = bsecret1C.PrivateKey;

            Assert.True(key1C.IsCompressed == true);
            Key key2C = bsecret2C.PrivateKey;

            Assert.True(key1C.IsCompressed == true);

            PubKey pubkey1  = key1.PubKey;
            PubKey pubkey2  = key2.PubKey;
            PubKey pubkey1C = key1C.PubKey;
            PubKey pubkey2C = key2C.PubKey;

            Assert.True(addr1.Hash == pubkey1.Hash);
            Assert.True(addr2.Hash == pubkey2.Hash);
            Assert.True(addr1C.Hash == pubkey1C.Hash);
            Assert.True(addr2C.Hash == pubkey2C.Hash);


            for (int n = 0; n < 16; n++)
            {
                string strMsg = String.Format("Very secret message {0}: 11", n);
                if (n == 10)
                {
                    //Test one long message
                    strMsg = String.Join(",", Enumerable.Range(0, 2000).Select(i => i.ToString()).ToArray());
                }
                uint256 hashMsg = Hashes.DoubleSHA256(TestUtils.ToBytes(strMsg));

                // normal signatures

                ECDSASignature sign1 = null, sign2 = null, sign1C = null, sign2C = null;
                List <Task>    tasks = new List <Task>();
                sign1  = key1.Sign(hashMsg);
                sign2  = key2.Sign(hashMsg);
                sign1C = key1C.Sign(hashMsg);
                sign2C = key2C.Sign(hashMsg);

                for (int i = 0; i < 30; i++)
                {
                    Assert.True(pubkey1.Verify(hashMsg, sign1));
                    Assert.True(pubkey2.Verify(hashMsg, sign2));
                    Assert.True(pubkey1C.Verify(hashMsg, sign1C));
                    Assert.True(pubkey2C.Verify(hashMsg, sign2C));

                    Assert.True(pubkey1.Verify(hashMsg, sign1));
                    Assert.True(!pubkey1.Verify(hashMsg, sign2));
                    Assert.True(pubkey1.Verify(hashMsg, sign1C));
                    Assert.True(!pubkey1.Verify(hashMsg, sign2C));

                    Assert.True(!pubkey2.Verify(hashMsg, sign1));
                    Assert.True(pubkey2.Verify(hashMsg, sign2));
                    Assert.True(!pubkey2.Verify(hashMsg, sign1C));
                    Assert.True(pubkey2.Verify(hashMsg, sign2C));

                    Assert.True(pubkey1C.Verify(hashMsg, sign1));
                    Assert.True(!pubkey1C.Verify(hashMsg, sign2));
                    Assert.True(pubkey1C.Verify(hashMsg, sign1C));
                    Assert.True(!pubkey1C.Verify(hashMsg, sign2C));

                    Assert.True(!pubkey2C.Verify(hashMsg, sign1));
                    Assert.True(pubkey2C.Verify(hashMsg, sign2));
                    Assert.True(!pubkey2C.Verify(hashMsg, sign1C));
                    Assert.True(pubkey2C.Verify(hashMsg, sign2C));
                }
                // compact signatures (with key recovery)

                byte[] csign1 = null, csign2 = null, csign1C = null, csign2C = null;

                csign1  = key1.SignCompact(hashMsg);
                csign2  = key2.SignCompact(hashMsg);
                csign1C = key1C.SignCompact(hashMsg);
                csign2C = key2C.SignCompact(hashMsg);

                PubKey rkey1 = null, rkey2 = null, rkey1C = null, rkey2C = null;
                rkey1  = PubKey.RecoverCompact(hashMsg, csign1);
                rkey2  = PubKey.RecoverCompact(hashMsg, csign2);
                rkey1C = PubKey.RecoverCompact(hashMsg, csign1C);
                rkey2C = PubKey.RecoverCompact(hashMsg, csign2C);

                Assert.True(rkey1.ToHex() == pubkey1.ToHex());
                Assert.True(rkey2.ToHex() == pubkey2.ToHex());
                Assert.True(rkey1C.ToHex() == pubkey1C.ToHex());
                Assert.True(rkey2C.ToHex() == pubkey2C.ToHex());

                Assert.True(sign1.IsLowR && sign1.ToDER().Length <= 70);
                Assert.True(sign2.IsLowR && sign2.ToDER().Length <= 70);
                Assert.True(sign1C.IsLowR && sign1C.ToDER().Length <= 70);
                Assert.True(sign2C.IsLowR && sign2C.ToDER().Length <= 70);
            }
        }