Ejemplo n.º 1
0
//verify block signature
func (bc *BlockChain) VerifyBlockSignature(block Block) error {
	//set signature
	hash := block.Head.Hash()                            //block hash
	pubkey, err := cipher.PubKeyFromSig(block.Sig, hash) //recovered pubkey for sig
	if err != nil {
		return errors.New("Pubkey recovery failed")
	}
	if bc.Genesis().Head.PrevHash != PubKeyHash(pubkey) {
		return errors.New("NewBlock, signature is not for pubkey for genesis")
	}
	err = cipher.VerifySignedHash(block.Sig, hash)
	if err != nil {
		return errors.New("Signature verification failed for hash")
	}
	return nil
}
Ejemplo n.º 2
0
// Verify attempts to determine if the transaction is well formed
// Verify cannot check transaction signatures, it needs the address from unspents
// Verify cannot check if outputs being spent exist
// Verify cannot check if the transaction would create or destroy coins
// or if the inputs have the required coin base
func (self *Transaction) Verify() error {

	h := self.HashInner()
	if h != self.InnerHash {
		return errors.New("Invalid header hash")
	}

	if len(self.In) == 0 {
		return errors.New("No inputs")
	}
	if len(self.Out) == 0 {
		return errors.New("No outputs")
	}

	// Check signature index fields
	if len(self.Sigs) != len(self.In) {
		return errors.New("Invalid number of signatures")
	}
	if len(self.Sigs) >= math.MaxUint16 {
		return errors.New("Too many signatures and inputs")
	}

	// Check duplicate inputs
	uxOuts := make(map[cipher.SHA256]int, len(self.In))
	for i, _ := range self.In {
		uxOuts[self.In[i]] = 1
	}
	if len(uxOuts) != len(self.In) {
		return errors.New("Duplicate spend")
	}

	if self.Type != 0 {
		return errors.New("transaction type invalid")
	}
	if self.Length != uint32(self.Size()) {
		return errors.New("transaction size prefix invalid")
	}

	// Check for duplicate potential outputs
	outputs := make(map[cipher.SHA256]int, len(self.Out))
	uxb := UxBody{
		SrcTransaction: self.Hash(),
	}
	for _, to := range self.Out {
		uxb.Coins = to.Coins
		uxb.Hours = to.Hours
		uxb.Address = to.Address
		outputs[uxb.Hash()] = 1
	}
	if len(outputs) != len(self.Out) {
		return errors.New("Duplicate output in transaction")
	}

	// Validate signature
	for i, sig := range self.Sigs {
		hash := cipher.AddSHA256(self.InnerHash, self.In[i])
		if err := cipher.VerifySignedHash(sig, hash); err != nil {
			return err
		}
	}

	// Artificial restriction to prevent spam
	// Must spend only multiples of 1e6
	for _, txo := range self.Out {
		if txo.Coins == 0 {
			return errors.New("Zero coin output")
		}
		if txo.Coins%1e6 != 0 {
			return errors.New("Transaction outputs must be multiple of 1e6 " +
				"base units")
		}
	}

	return nil
}