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