github.com/piotrnar/gocoin@v0.0.0-20240512203912-faa0448c5e96/lib/script/misc.go (about)

     1  package script
     2  
     3  import (
     4  	"encoding/hex"
     5  	"fmt"
     6  
     7  	"github.com/piotrnar/gocoin/lib/btc"
     8  	"github.com/piotrnar/gocoin/lib/secp256k1"
     9  )
    10  
    11  func IsP2KH(scr []byte) bool {
    12  	return len(scr) == 25 && scr[0] == 0x76 && scr[1] == 0xa9 &&
    13  		scr[2] == 0x14 && scr[23] == 0x88 && scr[24] == 0xac
    14  }
    15  
    16  func IsP2SH(scr []byte) bool {
    17  	return len(scr) == 23 && scr[0] == 0xa9 && scr[1] == 0x14 && scr[22] == 0x87
    18  }
    19  
    20  func IsP2WPKH(scr []byte) bool {
    21  	return len(scr) == 22 && scr[0] == 0 && scr[1] == 20
    22  }
    23  
    24  func IsP2WSH(scr []byte) bool {
    25  	return len(scr) == 34 && scr[0] == 0 && scr[1] == 32
    26  }
    27  
    28  func IsP2TAP(scr []byte) bool {
    29  	return len(scr) == 34 && scr[0] == btc.OP_1 && scr[1] == 32
    30  }
    31  
    32  func IsP2PK(scr []byte) (bool, []byte) {
    33  	if len(scr) == 35 && scr[0] == 33 && scr[34] == 0xac && (scr[1] == 0x02 || scr[1] == 0x03) {
    34  		return true, scr[1:34]
    35  	}
    36  	if len(scr) == 67 && scr[0] == 65 && scr[66] == 0xac && scr[1] == 0x04 {
    37  		var pk secp256k1.XY
    38  		if pk.ParsePubkey(scr[1:66]) && pk.IsValid() {
    39  			return true, scr[1:66]
    40  		}
    41  		//println("invalid uncompressed pubkey")
    42  	}
    43  	return false, nil
    44  }
    45  
    46  func IsUnspendable(scr []byte) bool {
    47  	if len(scr) > 0 && scr[0] == 0x6a {
    48  		return true
    49  	}
    50  	if len(scr) > MAX_SCRIPT_SIZE {
    51  		return true
    52  	}
    53  	if len(scr) == 67 && scr[0] == 65 && scr[66] == 0xac && scr[1] == 0x04 {
    54  		var pk secp256k1.XY
    55  		if !pk.ParsePubkey(scr[1:66]) || !pk.IsValid() {
    56  			return true // pay to public key script with invalid (uncompressed) key
    57  		}
    58  	}
    59  	return false
    60  }
    61  
    62  func IsValidSignatureEncoding(sig []byte) bool {
    63  	// Minimum and maximum size constraints.
    64  	if len(sig) < 9 {
    65  		return false
    66  	}
    67  	if len(sig) > 73 {
    68  		return false
    69  	}
    70  
    71  	// A signature is of type 0x30 (compound).
    72  	if sig[0] != 0x30 {
    73  		return false
    74  	}
    75  
    76  	// Make sure the length covers the entire signature.
    77  	if int(sig[1]) != len(sig)-3 {
    78  		return false
    79  	}
    80  
    81  	// Extract the length of the R element.
    82  	lenR := uint(sig[3])
    83  
    84  	// Make sure the length of the S element is still inside the signature.
    85  	if 5+lenR >= uint(len(sig)) {
    86  		return false
    87  	}
    88  
    89  	// Extract the length of the S element.
    90  	lenS := uint(sig[5+lenR])
    91  
    92  	// Verify that the length of the signature matches the sum of the length
    93  	// of the elements.
    94  	if lenR+lenS+7 != uint(len(sig)) {
    95  		return false
    96  	}
    97  
    98  	// Check whether the R element is an integer.
    99  	if sig[2] != 0x02 {
   100  		return false
   101  	}
   102  
   103  	// Zero-length integers are not allowed for R.
   104  	if lenR == 0 {
   105  		return false
   106  	}
   107  
   108  	// Negative numbers are not allowed for R.
   109  	if (sig[4] & 0x80) != 0 {
   110  		return false
   111  	}
   112  
   113  	// Null bytes at the start of R are not allowed, unless R would
   114  	// otherwise be interpreted as a negative number.
   115  	if lenR > 1 && sig[4] == 0x00 && (sig[5]&0x80) == 0 {
   116  		return false
   117  	}
   118  
   119  	// Check whether the S element is an integer.
   120  	if sig[lenR+4] != 0x02 {
   121  		return false
   122  	}
   123  
   124  	// Zero-length integers are not allowed for S.
   125  	if lenS == 0 {
   126  		return false
   127  	}
   128  
   129  	// Negative numbers are not allowed for S.
   130  	if (sig[lenR+6] & 0x80) != 0 {
   131  		return false
   132  	}
   133  
   134  	// Null bytes at the start of S are not allowed, unless S would otherwise be
   135  	// interpreted as a negative number.
   136  	if lenS > 1 && (sig[lenR+6] == 0x00) && (sig[lenR+7]&0x80) == 0 {
   137  		return false
   138  	}
   139  
   140  	return true
   141  }
   142  
   143  func IsDefinedHashtypeSignature(sig []byte) bool {
   144  	if len(sig) == 0 {
   145  		return false
   146  	}
   147  	htype := sig[len(sig)-1] & (btc.SIGHASH_ANYONECANPAY ^ 0xff)
   148  	if htype < btc.SIGHASH_ALL || htype > btc.SIGHASH_SINGLE {
   149  		return false
   150  	}
   151  	return true
   152  }
   153  
   154  func IsLowS(sig []byte) bool {
   155  	if !IsValidSignatureEncoding(sig) {
   156  		return false
   157  	}
   158  
   159  	ss, e := btc.NewSignature(sig)
   160  	if e != nil {
   161  		return false
   162  	}
   163  
   164  	return ss.IsLowS()
   165  }
   166  
   167  func CheckSignatureEncoding(sig []byte, flags uint32) bool {
   168  	if len(sig) == 0 {
   169  		return true
   170  	}
   171  	if (flags&(VER_DERSIG|VER_STRICTENC)) != 0 && !IsValidSignatureEncoding(sig) {
   172  		return false
   173  	} else if (flags&VER_LOW_S) != 0 && !IsLowS(sig) {
   174  		return false
   175  	} else if (flags&VER_STRICTENC) != 0 && !IsDefinedHashtypeSignature(sig) {
   176  		return false
   177  	}
   178  	return true
   179  }
   180  
   181  func IsCompressedOrUncompressedPubKey(pk []byte) bool {
   182  	if len(pk) < 33 {
   183  		return false
   184  	}
   185  	if pk[0] == 0x04 {
   186  		if len(pk) != 65 {
   187  			return false
   188  		}
   189  	} else if pk[0] == 0x02 || pk[0] == 0x03 {
   190  		if len(pk) != 33 {
   191  			return false
   192  		}
   193  	} else {
   194  		return false
   195  	}
   196  	return true
   197  }
   198  
   199  func IsCompressedPubKey(pk []byte) bool {
   200  	if len(pk) != 33 {
   201  		return false
   202  	}
   203  	if pk[0] == 0x02 || pk[0] == 0x03 {
   204  		return true
   205  	}
   206  	return false
   207  }
   208  
   209  func CheckPubKeyEncoding(pk []byte, flags uint32, sigversion int) bool {
   210  	if (flags&VER_STRICTENC) != 0 && !IsCompressedOrUncompressedPubKey(pk) {
   211  		return false
   212  	}
   213  	// Only compressed keys are accepted in segwit
   214  	if (flags&VER_WITNESS_PUBKEY) != 0 && sigversion == SIGVERSION_WITNESS_V0 && !IsCompressedPubKey(pk) {
   215  		return false
   216  	}
   217  	return true
   218  }
   219  
   220  // https://bitcointalk.org/index.php?topic=1240385.0
   221  func checkMinimalPush(d []byte, opcode int) bool {
   222  	if DBG_SCR {
   223  		fmt.Printf("checkMinimalPush %02x %s\n", opcode, hex.EncodeToString(d))
   224  	}
   225  	if len(d) == 0 {
   226  		// Could have used OP_0.
   227  		if DBG_SCR {
   228  			fmt.Println("Could have used OP_0.")
   229  		}
   230  		return opcode == 0x00
   231  	} else if len(d) == 1 && d[0] >= 1 && d[0] <= 16 {
   232  		// Could have used OP_1 .. OP_16.
   233  		if DBG_SCR {
   234  			fmt.Println("Could have used OP_1 .. OP_16.", 0x01+int(d[0]-1), 0x01, int(d[0]-1))
   235  		}
   236  		return opcode == 0x51+int(d[0])-1
   237  	} else if len(d) == 1 && d[0] == 0x81 {
   238  		// Could have used OP_1NEGATE.
   239  		if DBG_SCR {
   240  			fmt.Println("Could have used OP_1NEGATE.")
   241  		}
   242  		return opcode == 0x4f
   243  	} else if len(d) <= 75 {
   244  		// Could have used a direct push (opcode indicating number of bytes pushed + those bytes).
   245  		if DBG_SCR {
   246  			fmt.Println("Could have used a direct push (opcode indicating number of bytes pushed + those bytes).")
   247  		}
   248  		return opcode == len(d)
   249  	} else if len(d) <= 255 {
   250  		// Could have used OP_PUSHDATA.
   251  		if DBG_SCR {
   252  			fmt.Println("Could have used OP_PUSHDATA.")
   253  		}
   254  		return opcode == 0x4c
   255  	} else if len(d) <= 65535 {
   256  		// Could have used OP_PUSHDATA2.
   257  		if DBG_SCR {
   258  			fmt.Println("Could have used OP_PUSHDATA2.")
   259  		}
   260  		return opcode == 0x4d
   261  	}
   262  	fmt.Println("All checks passed")
   263  	return true
   264  }
   265  
   266  func CheckSequence(tx *btc.Tx, inp int, seq int64) bool {
   267  	if tx.Version < 2 {
   268  		return false
   269  	}
   270  
   271  	toseq := int64(tx.TxIn[inp].Sequence)
   272  
   273  	if (toseq & SEQUENCE_LOCKTIME_DISABLE_FLAG) != 0 {
   274  		return false
   275  	}
   276  
   277  	// Mask off any bits that do not have consensus-enforced meaning
   278  	// before doing the integer comparisons
   279  	const nLockTimeMask = SEQUENCE_LOCKTIME_TYPE_FLAG | SEQUENCE_LOCKTIME_MASK
   280  	txToSequenceMasked := toseq & nLockTimeMask
   281  	nSequenceMasked := seq & nLockTimeMask
   282  
   283  	if !((txToSequenceMasked < SEQUENCE_LOCKTIME_TYPE_FLAG && nSequenceMasked < SEQUENCE_LOCKTIME_TYPE_FLAG) ||
   284  		(txToSequenceMasked >= SEQUENCE_LOCKTIME_TYPE_FLAG && nSequenceMasked >= SEQUENCE_LOCKTIME_TYPE_FLAG)) {
   285  		return false
   286  	}
   287  
   288  	// Now that we know we're comparing apples-to-apples, the
   289  	// comparison is a simple numeric one.
   290  	if nSequenceMasked > txToSequenceMasked {
   291  		return false
   292  	}
   293  
   294  	return true
   295  }
   296  
   297  func CompressScript(scr []byte) (out []byte) {
   298  	if IsP2KH(scr) {
   299  		out = make([]byte, 21)
   300  		//out[0] = 0x00
   301  		copy(out[1:], scr[3:23])
   302  		return
   303  	}
   304  	if IsP2SH(scr) {
   305  		out = make([]byte, 21)
   306  		out[0] = 0x01
   307  		copy(out[1:], scr[2:22])
   308  		return
   309  	}
   310  
   311  	if ok, pk := IsP2PK(scr); ok {
   312  		out = make([]byte, 33)
   313  		copy(out[1:], pk[1:33])
   314  		out[0] = pk[0]
   315  		if pk[0] == 0x04 {
   316  			out[0] |= pk[64] & 0x01
   317  		}
   318  	}
   319  	return
   320  }
   321  
   322  func DecompressScript(data []byte) (script []byte) {
   323  	switch data[0] {
   324  	case 0x00:
   325  		script = make([]byte, 25)
   326  		script[0] = 0x76
   327  		script[1] = 0xa9
   328  		script[2] = 20
   329  		copy(script[3:23], data[1:21])
   330  		script[23] = 0x88
   331  		script[24] = 0xac
   332  
   333  	case 0x01:
   334  		script = make([]byte, 23)
   335  		script[0] = 0xa9
   336  		script[1] = 20
   337  		copy(script[2:22], data[1:])
   338  		script[22] = 0x87
   339  
   340  	case 0x02, 0x03:
   341  		script = make([]byte, 35)
   342  		script[0] = 33
   343  		copy(script[1:34], data)
   344  		script[34] = 0xac
   345  
   346  	case 0x04, 0x05:
   347  		var vch [33]byte
   348  		var pk secp256k1.XY
   349  		vch[0] = data[0] - 2
   350  		copy(vch[1:], data[1:])
   351  		pk.ParsePubkey(vch[:])
   352  		script = make([]byte, 67)
   353  		script[0] = 65
   354  		pk.GetPublicKey(script[1:66])
   355  		script[66] = 0xac
   356  	}
   357  	return
   358  }