Пример #1
0
        private IFederationMember GetFederationMemberForBlockInternal(ChainedHeader chainedHeader, List <IFederationMember> federation)
        {
            if (chainedHeader.Height == 0)
            {
                return(federation.Last());
            }

            // Try to provide the public key that signed the block.
            try
            {
                var header = chainedHeader.Header as PoABlockHeader;

                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)
                    {
                        break;
                    }

                    IFederationMember federationMember = federation.FirstOrDefault(m => m.PubKey == pubKeyForSig);
                    if (federationMember != null)
                    {
                        this.minersByBlockHash[chainedHeader.HashBlock] = federationMember;
                        return(federationMember);
                    }
                }
            }
            catch (Exception)
            {
            }

            return(null);
        }
Пример #2
0
        public void can_always_recover_pubkey_from_signature_when_stopping_at_null()
        {
            var rand = new Random();

            for (int i = 0; i < 1000; i++)
            {
                var      key   = new Key();
                PosBlock block = new PosBlock(new BlockHeader()
                {
                    Time = (uint)rand.Next()
                });
                ECDSASignature signature = key.Sign(block.GetHash());
                block.BlockSignature = new BlockSignature {
                    Signature = signature.ToDER()
                };
                Assert.True(key.PubKey.Verify(block.GetHash(), new ECDSASignature(block.BlockSignature.Signature)));
                signature = ECDSASignature.FromDER(block.BlockSignature.Signature);
                bool match = false;
                for (int recId = 0; !match; recId++)
                {
                    PubKey pubKeyForSig = PubKey.RecoverFromSignature(recId, signature, block.GetHash(), true);
                    if (pubKeyForSig == null)
                    {
                        break;
                    }

                    match = pubKeyForSig == key.PubKey;
                }
                Assert.True(match);
            }
        }
Пример #3
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();
            }
        }