Example #1
0
// Check if Tx is standard.
func (t *Tx) IsStandard(blockHeight uint32, blockTime uint32) error {
	if t.Version > numbers.TxCurrentVersion || t.Version < 1 {
		return errBadVersion
	}
	if !t.IsFinal(blockHeight, blockTime) {
		return errNotFinal
	}
	// Uses ">=" to follow the Satoshi client
	if t.ByteSize() >= numbers.MaxStandardTxSize {
		return errStdSizeLimit
	}
	for _, txin := range t.TxIns {
		s := script.Script(txin.SigScript)
		if len(s) > numbers.MaxSigScriptSize {
			return errSigScriptSizeLimit
		}
		if !s.IsPushOnly() {
			return errSigScriptNotPushOnly
		}
		if !s.PushesCanonical() {
			return errNonCanonicalPush
		}
	}
	dataOut := 0
	for _, txout := range t.TxOuts {
		sType := script.Script(txout.PKScript).PKScriptType()
		if sType == script.PKS_NonStandard {
			return errNonStandardPKScript
		} else if sType == script.PKS_NullData {
			dataOut++
		} else if txout.IsDust() {
			return errDustTxOut
		}
	}
	if dataOut > 1 {
		return errMoreThanOneReturn
	}
	return nil
}
Example #2
0
// Check inputs and the "script" of pay-to-script-hash
func (t *Tx) InputsStandard(utxos UTXOs) bool {
	if t.IsCoinBase() {
		return true
	}
	for _, txi := range t.TxIns {
		txo := utxos.GetTxOut(&txi.PreviousOutput)
		pkScript := script.Script(txo.PKScript)
		ttype := pkScript.PKScriptType()
		ok, argCount := pkScript.SigArgsExpected(ttype)
		if !ok {
			return false
		}
		err, result := script.RunSigScript(txi.SigScript)
		if err != nil {
			return false
		}
		if ttype == script.PKS_ScriptHash {
			if len(result) == 0 {
				return false
			}
			pkScript := script.Script(result[len(result)-1])
			ttype := pkScript.PKScriptType()
			if ttype == script.PKS_ScriptHash {
				return false // Recursive P2SH
			}
			ok, count := pkScript.SigArgsExpected(ttype)
			if !ok {
				return false
			}
			argCount += count
		}
		if len(result) != argCount {
			return false
		}
	}
	return true
}
Example #3
0
func encodeTxo(txo *catma.TxOut) ([]byte, error) {
	s := script.Script(txo.PKScript)
	if s.IsTypePubKeyHash() {
		ret := make([]byte, 20+1+8)
		ret[0] = byte(script.PKS_PubKeyHash)
		binary.LittleEndian.PutUint64(ret[1:], uint64(txo.Value))
		copy(ret[9:], txo.PKScript[3:23])
		return ret, nil
	} else if s.IsTypeScriptHash() {
		ret := make([]byte, 20+1+8)
		ret[0] = byte(script.PKS_ScriptHash)
		binary.LittleEndian.PutUint64(ret[1:], uint64(txo.Value))
		copy(ret[9:], txo.PKScript[2:22])
		return ret, nil
	} else {
		ret := make([]byte, len(txo.PKScript)+1+8)
		ret[0] = 0
		binary.LittleEndian.PutUint64(ret[len(txo.PKScript)+1:], uint64(txo.Value))
		copy(ret[9:], txo.PKScript)
		return ret, nil
	}
}