diff --git a/mempool.go b/mempool.go
index 2f36eb97..ab1748a3 100644
--- a/mempool.go
+++ b/mempool.go
@@ -60,10 +60,10 @@ const (
 	// prosperity.  3*80 + 3*65 + 65 = 500
 	maxStandardSigScriptSize = 500
 
-	// maxStandardMultiSigs is the maximum number of signatures
-	// allowed in a multi-signature transaction output script for it to be
+	// maxStandardMultiSigKeys is the maximum number of public keys allowed
+	// in a multi-signature transaction output script for it to be
 	// considered standard.
-	maxStandardMultiSigs = 3
+	maxStandardMultiSigKeys = 3
 
 	// minTxRelayFee is the minimum fee in satoshi that is required for a
 	// transaction to be treated as free for relay purposes.  It is also
@@ -157,22 +157,42 @@ func isDust(txOut *btcwire.TxOut) bool {
 // checkPkScriptStandard performs a series of checks on a transaction ouput
 // script (public key script) to ensure it is a "standard" public key script.
 // A standard public key script is one that is a recognized form, and for
-// multi-signature scripts, only contains from 1 to 3 signatures.
-func checkPkScriptStandard(pkScript []byte) error {
-	scriptClass := btcscript.GetScriptClass(pkScript)
+// multi-signature scripts, only contains from 1 to maxStandardMultiSigKeys
+// public keys.
+func checkPkScriptStandard(pkScript []byte, scriptClass btcscript.ScriptClass) error {
 	switch scriptClass {
 	case btcscript.MultiSigTy:
-		// TODO(davec): Need to get the actual number of signatures.
-		numSigs := 1
+		numPubKeys, numSigs, err := btcscript.CalcMultiSigStats(pkScript)
+		if err != nil {
+			return err
+		}
+
+		// A standard multi-signature public key script must contain
+		// from 1 to maxStandardMultiSigKeys public keys.
+		if numPubKeys < 1 {
+			str := fmt.Sprintf("multi-signature script with no " +
+				"pubkeys")
+			return TxRuleError(str)
+		}
+		if numPubKeys > maxStandardMultiSigKeys {
+			str := fmt.Sprintf("multi-signature script with %d "+
+				"public keys which is more than the allowed "+
+				"max of %d", numPubKeys, maxStandardMultiSigKeys)
+			return TxRuleError(str)
+		}
+
+		// A standard multi-signature public key script must have at
+		// least 1 signature and no more signatures than available
+		// public keys.
 		if numSigs < 1 {
 			str := fmt.Sprintf("multi-signature script with no " +
 				"signatures")
 			return TxRuleError(str)
 		}
-		if numSigs > maxStandardMultiSigs {
+		if numSigs > numPubKeys {
 			str := fmt.Sprintf("multi-signature script with %d "+
-				"signatures which is more than the allowed max "+
-				"of %d", numSigs, maxStandardMultiSigs)
+				"signatures which is more than the available "+
+				"%d public keys", numSigs, numPubKeys)
 			return TxRuleError(str)
 		}
 
@@ -243,13 +263,20 @@ func checkTransactionStandard(tx *btcutil.Tx, height int64) error {
 
 	// None of the output public key scripts can be a non-standard script or
 	// be "dust".
+	numNullDataOutputs := 0
 	for i, txOut := range msgTx.TxOut {
-		err := checkPkScriptStandard(txOut.PkScript)
+		scriptClass := btcscript.GetScriptClass(txOut.PkScript)
+		err := checkPkScriptStandard(txOut.PkScript, scriptClass)
 		if err != nil {
 			str := fmt.Sprintf("transaction output %d: %v", i, err)
 			return TxRuleError(str)
 		}
 
+		// Accumulate the number of outputs which only carry data.
+		if scriptClass == btcscript.NullDataTy {
+			numNullDataOutputs++
+		}
+
 		if isDust(txOut) {
 			str := fmt.Sprintf("transaction output %d: payment "+
 				"of %d is dust", i, txOut.Value)
@@ -257,17 +284,62 @@ func checkTransactionStandard(tx *btcutil.Tx, height int64) error {
 		}
 	}
 
+	// A standard transaction must not have more than one output script that
+	// only carries data.
+	if numNullDataOutputs > 1 {
+		return TxRuleError("more than one transaction output is a " +
+			"nulldata script")
+	}
+
 	return nil
 }
 
 // checkInputsStandard performs a series of checks on a transaction's inputs
 // to ensure they are "standard".  A standard transaction input is one that
-// that consumes the same number of outputs from the stack as the output script
-// pushes.  This help prevent resource exhaustion attacks by "creative" use of
-// scripts that are super expensive to process like OP_DUP OP_CHECKSIG OP_DROP
-// repeated a large number of times followed by a final OP_TRUE.
-func checkInputsStandard(tx *btcutil.Tx) error {
-	// TODO(davec): Implement
+// that consumes the expected number of elements from the stack and that number
+// is the same as the output script pushes.  This help prevent resource
+// exhaustion attacks by "creative" use of scripts that are super expensive to
+// process like OP_DUP OP_CHECKSIG OP_DROP repeated a large number of times
+// followed by a final OP_TRUE.
+func checkInputsStandard(tx *btcutil.Tx, txStore btcchain.TxStore) error {
+	// NOTE: The reference implementation also does a coinbase check here,
+	// but coinbases have already been rejected prior to calling this
+	// function so no need to recheck.
+
+	for i, txIn := range tx.MsgTx().TxIn {
+		// It is safe to elide existence and index checks here since
+		// they have already been checked prior to calling this
+		// function.
+		prevOut := txIn.PreviousOutpoint
+		originTx := txStore[prevOut.Hash].Tx.MsgTx()
+		originPkScript := originTx.TxOut[prevOut.Index].PkScript
+
+		// Calculate stats for the script pair.
+		scriptInfo, err := btcscript.CalcScriptInfo(txIn.SignatureScript,
+			originPkScript, true)
+		if err != nil {
+			return err
+		}
+
+		// A negative value for expected inputs indicates the script is
+		// non-standard in some way.
+		if scriptInfo.ExpectedInputs < 0 {
+			str := fmt.Sprintf("transaction input #%d expects %d "+
+				"inputs", i, scriptInfo.ExpectedInputs)
+			return TxRuleError(str)
+		}
+
+		// The script pair is non-standard if the number of available
+		// inputs does not match the number of expected inputs.
+		if scriptInfo.NumInputs != scriptInfo.ExpectedInputs {
+			str := fmt.Sprintf("transaction input #%d expects %d "+
+				"inputs, but referenced output script only "+
+				"provides %d", i, scriptInfo.ExpectedInputs,
+				scriptInfo.NumInputs)
+			return TxRuleError(str)
+		}
+	}
+
 	return nil
 }
 
@@ -710,7 +782,7 @@ func (mp *txMemPool) maybeAcceptTransaction(tx *btcutil.Tx, isOrphan *bool) erro
 	// Don't allow transactions with non-standard inputs on the main
 	// network.
 	if activeNetParams.btcnet == btcwire.MainNet {
-		err := checkInputsStandard(tx)
+		err := checkInputsStandard(tx, txStore)
 		if err != nil {
 			str := fmt.Sprintf("transaction %v has a non-standard "+
 				"input: %v", txHash, err)
@@ -732,8 +804,8 @@ func (mp *txMemPool) maybeAcceptTransaction(tx *btcutil.Tx, isOrphan *bool) erro
 	}
 
 	// TODO(davec): Rate-limit 'free' transactions.  That is to say
-	// transactions which are less than the minimum relay fee and are there
-	// considered free.
+	// transactions which are less than the minimum relay fee and are
+	// therefore considered free.
 
 	// Verify crypto signatures for each input and reject the transaction if
 	// any don't verify.