//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 }
// 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 }