Elichai Turkel d3ede3a46f
Add new ErrMissingTxOut and ErrInvalidTransactionsInNewBlock errors (#972)
* Add new ErrMissingTxOut error

* Add tests for ruleError wrapping

* Update consensus to use new ErrMissingTxOut type where appropriate

* Add new ErrInvalidTransactionsInNewBlock error

* Add wrapping tests for ErrInvalidTransactionsInNewBlock

* Fix Review suggestions

* Fix broken serialization(add pointer redirection)
2020-10-29 16:59:00 +02:00

62 lines
2.0 KiB
Go

package transactionvalidator
import (
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/ruleerrors"
"github.com/kaspanet/kaspad/domain/consensus/utils/estimatedsize"
"github.com/kaspanet/kaspad/domain/consensus/utils/transactionhelper"
"github.com/kaspanet/kaspad/domain/consensus/utils/txscript"
)
const (
// MassPerTxByte is the number of grams that any byte
// adds to a transaction.
MassPerTxByte = 1
// MassPerScriptPubKeyByte is the number of grams that any
// scriptPubKey byte adds to a transaction.
MassPerScriptPubKeyByte = 10
// MassPerSigOp is the number of grams that any
// signature operation adds to a transaction.
MassPerSigOp = 10000
)
func (v *transactionValidator) transactionMassStandalonePart(tx *externalapi.DomainTransaction) uint64 {
size := estimatedsize.TransactionEstimatedSerializedSize(tx)
totalScriptPubKeySize := uint64(0)
for _, output := range tx.Outputs {
totalScriptPubKeySize += uint64(len(output.ScriptPublicKey))
}
return size*MassPerTxByte + totalScriptPubKeySize*MassPerScriptPubKeyByte
}
func (v *transactionValidator) transactionMass(tx *externalapi.DomainTransaction) (uint64, error) {
if transactionhelper.IsCoinBase(tx) {
return 0, nil
}
standaloneMass := v.transactionMassStandalonePart(tx)
sigOpsCount := uint64(0)
var missingOutpoints []externalapi.DomainOutpoint
for _, input := range tx.Inputs {
utxoEntry := input.UTXOEntry
if utxoEntry == nil {
missingOutpoints = append(missingOutpoints, input.PreviousOutpoint)
continue
}
// Count the precise number of signature operations in the
// referenced public key script.
sigScript := input.SignatureScript
isP2SH := txscript.IsPayToScriptHash(utxoEntry.ScriptPublicKey)
sigOpsCount += uint64(txscript.GetPreciseSigOpCount(sigScript, utxoEntry.ScriptPublicKey, isP2SH))
}
if len(missingOutpoints) > 0 {
return 0, ruleerrors.NewErrMissingTxOut(missingOutpoints)
}
return standaloneMass + sigOpsCount*MassPerSigOp, nil
}