Example #1
0
// Verify that +2/3 of the set had signed the given signBytes
func (valSet *ValidatorSet) VerifyValidation(chainID string,
	hash []byte, parts PartSetHeader, height int, v *Validation) error {
	if valSet.Size() != len(v.Precommits) {
		return fmt.Errorf("Invalid validation -- wrong set size: %v vs %v", valSet.Size(), len(v.Precommits))
	}
	if height != v.Height() {
		return fmt.Errorf("Invalid validation -- wrong height: %v vs %v", height, v.Height())
	}

	talliedVotingPower := int64(0)
	round := v.Round()

	for idx, precommit := range v.Precommits {
		// may be nil if validator skipped.
		if precommit == nil {
			continue
		}
		if precommit.Height != height {
			return fmt.Errorf("Invalid validation -- wrong height: %v vs %v", height, precommit.Height)
		}
		if precommit.Round != round {
			return fmt.Errorf("Invalid validation -- wrong round: %v vs %v", round, precommit.Round)
		}
		if precommit.Type != VoteTypePrecommit {
			return fmt.Errorf("Invalid validation -- not precommit @ index %v", idx)
		}
		_, val := valSet.GetByIndex(idx)
		// Validate signature
		precommitSignBytes := account.SignBytes(chainID, precommit)
		if !val.PubKey.VerifyBytes(precommitSignBytes, precommit.Signature) {
			return fmt.Errorf("Invalid validation -- invalid signature: %v", precommit)
		}
		if !bytes.Equal(precommit.BlockHash, hash) {
			continue // Not an error, but doesn't count
		}
		if !parts.Equals(precommit.BlockPartsHeader) {
			continue // Not an error, but doesn't count
		}
		// Good precommit!
		talliedVotingPower += val.VotingPower
	}

	if talliedVotingPower > valSet.TotalVotingPower()*2/3 {
		return nil
	} else {
		return fmt.Errorf("Invalid validation -- insufficient voting power: got %v, needed %v",
			talliedVotingPower, (valSet.TotalVotingPower()*2/3 + 1))
	}
}
Example #2
0
func (voteSet *VoteSet) addVote(val *Validator, valIndex int, vote *Vote) (bool, int, error) {

	// Make sure the step matches. (or that vote is commit && round < voteSet.round)
	if (vote.Height != voteSet.height) ||
		(vote.Round != voteSet.round) ||
		(vote.Type != voteSet.type_) {
		return false, 0, ErrVoteUnexpectedStep
	}

	// Check signature.
	if !val.PubKey.VerifyBytes(acm.SignBytes(config.GetString("chain_id"), vote), vote.Signature) {
		// Bad signature.
		return false, 0, ErrVoteInvalidSignature
	}

	// If vote already exists, return false.
	if existingVote := voteSet.votes[valIndex]; existingVote != nil {
		if bytes.Equal(existingVote.BlockHash, vote.BlockHash) {
			return false, valIndex, nil
		} else {
			return false, valIndex, &ErrVoteConflictingSignature{
				VoteA: existingVote,
				VoteB: vote,
			}
		}
	}

	// Add vote.
	voteSet.votes[valIndex] = vote
	voteSet.votesBitArray.SetIndex(valIndex, true)
	blockKey := string(vote.BlockHash) + string(wire.BinaryBytes(vote.BlockPartsHeader))
	totalBlockHashVotes := voteSet.votesByBlock[blockKey] + val.VotingPower
	voteSet.votesByBlock[blockKey] = totalBlockHashVotes
	voteSet.totalVotes += val.VotingPower

	// If we just nudged it up to two thirds majority, add it.
	if totalBlockHashVotes > voteSet.valSet.TotalVotingPower()*2/3 &&
		(totalBlockHashVotes-val.VotingPower) <= voteSet.valSet.TotalVotingPower()*2/3 {
		voteSet.maj23Hash = vote.BlockHash
		voteSet.maj23PartsHeader = vote.BlockPartsHeader
		voteSet.maj23Exists = true
	}

	return true, valIndex, nil
}
Example #3
0
func (privVal *PrivValidator) SignRebondTx(chainID string, rebondTx *RebondTx) error {
	privVal.mtx.Lock()
	defer privVal.mtx.Unlock()
	if privVal.LastHeight < rebondTx.Height {

		// Persist height/round/step
		// Prevent doing anything else for this rebondTx.Height.
		privVal.LastHeight = rebondTx.Height
		privVal.LastRound = math.MaxInt32 // MaxInt64 overflows on 32bit architectures.
		privVal.LastStep = math.MaxInt8
		privVal.save()

		// Sign
		rebondTx.Signature = privVal.PrivKey.Sign(acm.SignBytes(chainID, rebondTx)).(acm.SignatureEd25519)
		return nil
	} else {
		return errors.New(fmt.Sprintf("Attempt of duplicate signing of rebondTx: Height %v", rebondTx.Height))
	}
}
Example #4
0
func (privVal *PrivValidator) SignProposal(chainID string, proposal *Proposal) error {
	privVal.mtx.Lock()
	defer privVal.mtx.Unlock()
	if privVal.LastHeight < proposal.Height ||
		privVal.LastHeight == proposal.Height && privVal.LastRound < proposal.Round ||
		privVal.LastHeight == 0 && privVal.LastRound == 0 && privVal.LastStep == stepNone {

		// Persist height/round/step
		privVal.LastHeight = proposal.Height
		privVal.LastRound = proposal.Round
		privVal.LastStep = stepPropose
		privVal.save()

		// Sign
		proposal.Signature = privVal.PrivKey.Sign(acm.SignBytes(chainID, proposal)).(acm.SignatureEd25519)
		return nil
	} else {
		return errors.New(fmt.Sprintf("Attempt of duplicate signing of proposal: Height %v, Round %v", proposal.Height, proposal.Round))
	}
}
Example #5
0
// tx has either one input or we default to the first one (ie for send/bond)
// TODO: better support for multisig and bonding
func signTx(signAddr, chainID string, tx_ types.Tx) ([]byte, types.Tx, error) {
	signBytes := fmt.Sprintf("%X", account.SignBytes(chainID, tx_))
	var inputAddr []byte
	var sigED account.SignatureEd25519
	switch tx := tx_.(type) {
	case *types.SendTx:
		inputAddr = tx.Inputs[0].Address
		defer func(s *account.SignatureEd25519) { tx.Inputs[0].Signature = *s }(&sigED)
	case *types.NameTx:
		inputAddr = tx.Input.Address
		defer func(s *account.SignatureEd25519) { tx.Input.Signature = *s }(&sigED)
	case *types.CallTx:
		inputAddr = tx.Input.Address
		defer func(s *account.SignatureEd25519) { tx.Input.Signature = *s }(&sigED)
	case *types.PermissionsTx:
		inputAddr = tx.Input.Address
		defer func(s *account.SignatureEd25519) { tx.Input.Signature = *s }(&sigED)
	case *types.BondTx:
		inputAddr = tx.Inputs[0].Address
		defer func(s *account.SignatureEd25519) {
			tx.Signature = *s
			tx.Inputs[0].Signature = *s
		}(&sigED)
	case *types.UnbondTx:
		inputAddr = tx.Address
		defer func(s *account.SignatureEd25519) { tx.Signature = *s }(&sigED)
	case *types.RebondTx:
		inputAddr = tx.Address
		defer func(s *account.SignatureEd25519) { tx.Signature = *s }(&sigED)
	}
	addrHex := fmt.Sprintf("%X", inputAddr)
	sig, err := Sign(signBytes, addrHex, signAddr)
	if err != nil {
		return nil, nil, err
	}
	sigED = account.SignatureEd25519(sig)
	logger.Debugf("SIG: %X\n", sig)
	return inputAddr, tx_, nil
}
Example #6
0
func (privVal *PrivValidator) SignVoteUnsafe(chainID string, vote *Vote) {
	vote.Signature = privVal.PrivKey.Sign(acm.SignBytes(chainID, vote)).(acm.SignatureEd25519)
}
Example #7
0
// This should match the leaf hashes of Block.Data.Hash()'s SimpleMerkleTree.
func TxID(chainID string, tx Tx) []byte {
	signBytes := acm.SignBytes(chainID, tx)
	return wire.BinaryRipemd160(signBytes)
}