// validSiacoins checks that the siacoin inputs and outputs are valid in the // context of the current consensus set. func validSiacoins(tx *bolt.Tx, t types.Transaction) error { scoBucket := tx.Bucket(SiacoinOutputs) var inputSum types.Currency for _, sci := range t.SiacoinInputs { // Check that the input spends an existing output. scoBytes := scoBucket.Get(sci.ParentID[:]) if scoBytes == nil { return errMissingSiacoinOutput } // Check that the unlock conditions match the required unlock hash. var sco types.SiacoinOutput err := encoding.Unmarshal(scoBytes, &sco) if build.DEBUG && err != nil { panic(err) } if sci.UnlockConditions.UnlockHash() != sco.UnlockHash { return errWrongUnlockConditions } inputSum = inputSum.Add(sco.Value) } if inputSum.Cmp(t.SiacoinOutputSum()) != 0 { return errSiacoinInputOutputMismatch } return nil }
// validUnconfirmedSiacoins checks that all siacoin inputs and outputs are // valid in the context of the unconfirmed consensus set. func (tp *TransactionPool) validUnconfirmedSiacoins(t types.Transaction) (err error) { var inputSum types.Currency for _, sci := range t.SiacoinInputs { // All inputs must have corresponding outputs in the unconfirmed set. sco, exists := tp.siacoinOutputs[sci.ParentID] if !exists { return ErrUnrecognizedSiacoinInput } // The unlock conditions provided must match the unlock hash of the // corresponding output. if sci.UnlockConditions.UnlockHash() != sco.UnlockHash { return ErrBadUnlockConditions } inputSum = inputSum.Add(sco.Value) } // The sum of all inputs must equal the sum of all outputs. if inputSum.Cmp(t.SiacoinOutputSum()) != 0 { return ErrSiacoinOverspend } return }