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

     1  package btc
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/binary"
     6  	"encoding/hex"
     7  	"errors"
     8  	"fmt"
     9  	"math/big"
    10  	"strconv"
    11  	"strings"
    12  )
    13  
    14  func RawToStack(sig []byte) []byte {
    15  	if len(sig) == 1 {
    16  		if sig[0] == 0x81 {
    17  			return []byte{OP_1NEGATE}
    18  		}
    19  		if sig[0] == 0x80 || sig[0] == 0x00 {
    20  			return []byte{OP_0}
    21  		}
    22  		if sig[0] <= 16 {
    23  			return []byte{OP_1 - 1 + sig[0]}
    24  		}
    25  	}
    26  	bb := new(bytes.Buffer)
    27  	if len(sig) < OP_PUSHDATA1 {
    28  		bb.Write([]byte{byte(len(sig))})
    29  	} else if len(sig) <= 0xff {
    30  		bb.Write([]byte{OP_PUSHDATA1})
    31  		bb.Write([]byte{byte(len(sig))})
    32  	} else if len(sig) <= 0xffff {
    33  		bb.Write([]byte{OP_PUSHDATA2})
    34  		binary.Write(bb, binary.LittleEndian, uint16(len(sig)))
    35  	} else {
    36  		bb.Write([]byte{OP_PUSHDATA4})
    37  		binary.Write(bb, binary.LittleEndian, uint32(len(sig)))
    38  	}
    39  	bb.Write(sig)
    40  	return bb.Bytes()
    41  }
    42  
    43  func int2scr(v int64) []byte {
    44  	if v == -1 || v >= 1 && v <= 16 {
    45  		return []byte{byte(v + OP_1 - 1)}
    46  	}
    47  
    48  	neg := v < 0
    49  	if neg {
    50  		v = -v
    51  	}
    52  	bn := big.NewInt(v)
    53  	bts := bn.Bytes()
    54  	if (bts[0] & 0x80) != 0 {
    55  		if neg {
    56  			bts = append([]byte{0x80}, bts...)
    57  		} else {
    58  			bts = append([]byte{0x00}, bts...)
    59  		}
    60  	} else if neg {
    61  		bts[0] |= 0x80
    62  	}
    63  
    64  	sig := make([]byte, len(bts))
    65  	for i := range bts {
    66  		sig[len(bts)-i-1] = bts[i]
    67  	}
    68  
    69  	return RawToStack(sig)
    70  }
    71  
    72  func DecodeScript(pk string) (out []byte, e error) {
    73  	xx := strings.Split(pk, " ")
    74  	for i := range xx {
    75  		v, er := strconv.ParseInt(xx[i], 10, 64)
    76  		if er == nil {
    77  			switch {
    78  			case v == -1:
    79  				out = append(out, 0x4f)
    80  			case v == 0:
    81  				out = append(out, 0x0)
    82  			case v > 0 && v <= 16:
    83  				out = append(out, 0x50+byte(v))
    84  			default:
    85  				out = append(out, int2scr(v)...)
    86  			}
    87  		} else if len(xx[i]) > 2 && xx[i][:2] == "0x" {
    88  			d, _ := hex.DecodeString(xx[i][2:])
    89  			out = append(out, d...)
    90  		} else {
    91  			if len(xx[i]) >= 2 && xx[i][0] == '\'' && xx[i][len(xx[i])-1] == '\'' {
    92  				out = append(out, RawToStack([]byte(xx[i][1:len(xx[i])-1]))...)
    93  			} else {
    94  				if len(xx[i]) > 3 && xx[i][:3] == "OP_" {
    95  					xx[i] = xx[i][3:]
    96  				}
    97  				switch xx[i] {
    98  				case "RESERVED":
    99  					out = append(out, 0x50)
   100  				case "NOP":
   101  					out = append(out, 0x61)
   102  				case "VER":
   103  					out = append(out, 0x62)
   104  				case "IF":
   105  					out = append(out, 0x63)
   106  				case "NOTIF":
   107  					out = append(out, 0x64)
   108  				case "VERIF":
   109  					out = append(out, 0x65)
   110  				case "VERNOTIF":
   111  					out = append(out, 0x66)
   112  				case "ELSE":
   113  					out = append(out, 0x67)
   114  				case "ENDIF":
   115  					out = append(out, 0x68)
   116  				case "VERIFY":
   117  					out = append(out, 0x69)
   118  				case "RETURN":
   119  					out = append(out, 0x6a)
   120  				case "TOALTSTACK":
   121  					out = append(out, 0x6b)
   122  				case "FROMALTSTACK":
   123  					out = append(out, 0x6c)
   124  				case "2DROP":
   125  					out = append(out, 0x6d)
   126  				case "2DUP":
   127  					out = append(out, 0x6e)
   128  				case "3DUP":
   129  					out = append(out, 0x6f)
   130  				case "2OVER":
   131  					out = append(out, 0x70)
   132  				case "2ROT":
   133  					out = append(out, 0x71)
   134  				case "2SWAP":
   135  					out = append(out, 0x72)
   136  				case "IFDUP":
   137  					out = append(out, 0x73)
   138  				case "DEPTH":
   139  					out = append(out, 0x74)
   140  				case "DROP":
   141  					out = append(out, 0x75)
   142  				case "DUP":
   143  					out = append(out, 0x76)
   144  				case "NIP":
   145  					out = append(out, 0x77)
   146  				case "OVER":
   147  					out = append(out, 0x78)
   148  				case "PICK":
   149  					out = append(out, 0x79)
   150  				case "ROLL":
   151  					out = append(out, 0x7a)
   152  				case "ROT":
   153  					out = append(out, 0x7b)
   154  				case "SWAP":
   155  					out = append(out, 0x7c)
   156  				case "TUCK":
   157  					out = append(out, 0x7d)
   158  				case "CAT":
   159  					out = append(out, 0x7e)
   160  				case "SUBSTR":
   161  					out = append(out, 0x7f)
   162  				case "LEFT":
   163  					out = append(out, 0x80)
   164  				case "RIGHT":
   165  					out = append(out, 0x81)
   166  				case "SIZE":
   167  					out = append(out, 0x82)
   168  				case "INVERT":
   169  					out = append(out, 0x83)
   170  				case "AND":
   171  					out = append(out, 0x84)
   172  				case "OR":
   173  					out = append(out, 0x85)
   174  				case "XOR":
   175  					out = append(out, 0x86)
   176  				case "EQUAL":
   177  					out = append(out, 0x87)
   178  				case "EQUALVERIFY":
   179  					out = append(out, 0x88)
   180  				case "RESERVED1":
   181  					out = append(out, 0x89)
   182  				case "RESERVED2":
   183  					out = append(out, 0x8a)
   184  				case "1ADD":
   185  					out = append(out, 0x8b)
   186  				case "1SUB":
   187  					out = append(out, 0x8c)
   188  				case "2MUL":
   189  					out = append(out, 0x8d)
   190  				case "2DIV":
   191  					out = append(out, 0x8e)
   192  				case "NEGATE":
   193  					out = append(out, 0x8f)
   194  				case "ABS":
   195  					out = append(out, 0x90)
   196  				case "NOT":
   197  					out = append(out, 0x91)
   198  				case "0NOTEQUAL":
   199  					out = append(out, 0x92)
   200  				case "ADD":
   201  					out = append(out, 0x93)
   202  				case "SUB":
   203  					out = append(out, 0x94)
   204  				case "MUL":
   205  					out = append(out, 0x95)
   206  				case "DIV":
   207  					out = append(out, 0x96)
   208  				case "MOD":
   209  					out = append(out, 0x97)
   210  				case "LSHIFT":
   211  					out = append(out, 0x98)
   212  				case "RSHIFT":
   213  					out = append(out, 0x99)
   214  				case "BOOLAND":
   215  					out = append(out, 0x9a)
   216  				case "BOOLOR":
   217  					out = append(out, 0x9b)
   218  				case "NUMEQUAL":
   219  					out = append(out, 0x9c)
   220  				case "NUMEQUALVERIFY":
   221  					out = append(out, 0x9d)
   222  				case "NUMNOTEQUAL":
   223  					out = append(out, 0x9e)
   224  				case "LESSTHAN":
   225  					out = append(out, 0x9f)
   226  				case "GREATERTHAN":
   227  					out = append(out, 0xa0)
   228  				case "LESSTHANOREQUAL":
   229  					out = append(out, 0xa1)
   230  				case "GREATERTHANOREQUAL":
   231  					out = append(out, 0xa2)
   232  				case "MIN":
   233  					out = append(out, 0xa3)
   234  				case "MAX":
   235  					out = append(out, 0xa4)
   236  				case "WITHIN":
   237  					out = append(out, 0xa5)
   238  				case "RIPEMD160":
   239  					out = append(out, 0xa6)
   240  				case "SHA1":
   241  					out = append(out, 0xa7)
   242  				case "SHA256":
   243  					out = append(out, 0xa8)
   244  				case "HASH160":
   245  					out = append(out, 0xa9)
   246  				case "HASH256":
   247  					out = append(out, 0xaa)
   248  				case "CODESEPARATOR":
   249  					out = append(out, 0xab)
   250  				case "CHECKSIG":
   251  					out = append(out, 0xac)
   252  				case "CHECKSIGVERIFY":
   253  					out = append(out, 0xad)
   254  				case "CHECKMULTISIG":
   255  					out = append(out, 0xae)
   256  				case "CHECKMULTISIGVERIFY":
   257  					out = append(out, 0xaf)
   258  				case "NOP1":
   259  					out = append(out, 0xb0)
   260  				case "NOP2":
   261  					out = append(out, 0xb1)
   262  				case "CHECKLOCKTIMEVERIFY":
   263  					out = append(out, 0xb1)
   264  				case "NOP3":
   265  					out = append(out, 0xb2)
   266  				case "CHECKSEQUENCEVERIFY":
   267  					out = append(out, 0xb2)
   268  				case "NOP4":
   269  					out = append(out, 0xb3)
   270  				case "NOP5":
   271  					out = append(out, 0xb4)
   272  				case "NOP6":
   273  					out = append(out, 0xb5)
   274  				case "NOP7":
   275  					out = append(out, 0xb6)
   276  				case "NOP8":
   277  					out = append(out, 0xb7)
   278  				case "NOP9":
   279  					out = append(out, 0xb8)
   280  				case "NOP10":
   281  					out = append(out, 0xb9)
   282  				case "CHECKSIGADD":
   283  					out = append(out, 0xba)
   284  				case "":
   285  					out = append(out, []byte{}...)
   286  				default:
   287  					dat, _ := hex.DecodeString(xx[i])
   288  					if dat == nil {
   289  						return nil, errors.New("Syntax error: " + xx[i])
   290  					}
   291  					out = append(out, RawToStack(dat)...)
   292  				}
   293  			}
   294  		}
   295  	}
   296  	return
   297  }
   298  
   299  func ScriptToText(p []byte) (out []string, e error) {
   300  	var opcnt, idx int
   301  	for idx < len(p) {
   302  		opcode, vchPushValue, n, er := GetOpcode(p[idx:])
   303  
   304  		if er != nil {
   305  			e = errors.New("ScriptToText: " + er.Error())
   306  			println("C", idx, hex.EncodeToString(p))
   307  			return
   308  		}
   309  		idx += n
   310  
   311  		if vchPushValue != nil && len(vchPushValue) > MAX_SCRIPT_ELEMENT_SIZE {
   312  			e = errors.New(fmt.Sprint("ScriptToText: vchPushValue too long ", len(vchPushValue)))
   313  			return
   314  		}
   315  
   316  		if opcode > 0x60 {
   317  			opcnt++
   318  			if opcnt > 201 {
   319  				e = errors.New("ScriptToText: evalScript has too many opcodes")
   320  				return
   321  			}
   322  		}
   323  
   324  		if opcode == 0x7e /*OP_CAT*/ ||
   325  			opcode == 0x7f /*OP_SUBSTR*/ ||
   326  			opcode == 0x80 /*OP_LEFT*/ ||
   327  			opcode == 0x81 /*OP_RIGHT*/ ||
   328  			opcode == 0x83 /*OP_INVERT*/ ||
   329  			opcode == 0x84 /*OP_AND*/ ||
   330  			opcode == 0x85 /*OP_OR*/ ||
   331  			opcode == 0x86 /*OP_XOR*/ ||
   332  			opcode == 0x8d /*OP_2MUL*/ ||
   333  			opcode == 0x8e /*OP_2DIV*/ ||
   334  			opcode == 0x95 /*OP_MUL*/ ||
   335  			opcode == 0x96 /*OP_DIV*/ ||
   336  			opcode == 0x97 /*OP_MOD*/ ||
   337  			opcode == 0x98 /*OP_LSHIFT*/ ||
   338  			opcode == 0x99 /*OP_RSHIFT*/ {
   339  			e = errors.New(fmt.Sprint("ScriptToText: Unsupported opcode ", opcode))
   340  			return
   341  		}
   342  
   343  		var sel string
   344  		if 0 <= opcode && opcode <= OP_PUSHDATA4 {
   345  			if len(vchPushValue) == 0 {
   346  				sel = "OP_FALSE"
   347  			} else {
   348  				sel = hex.EncodeToString(vchPushValue)
   349  			}
   350  		} else {
   351  			switch {
   352  			case opcode == 0x4f:
   353  				sel = "1NEGATE"
   354  			case opcode >= 0x50 && opcode <= 0x60:
   355  				sel = fmt.Sprint(opcode - 0x50)
   356  			case opcode == 0x61:
   357  				sel = "NOP"
   358  			case opcode == 0x63:
   359  				sel = "IF"
   360  			case opcode == 0x64:
   361  				sel = "NOTIF"
   362  			case opcode == 0x67:
   363  				sel = "ELSE"
   364  			case opcode == 0x68:
   365  				sel = "ENDIF"
   366  			case opcode == 0x69:
   367  				sel = "VERIFY"
   368  			case opcode == 0x6a:
   369  				sel = "RETURN"
   370  			case opcode == 0x74:
   371  				sel = "DEPTH"
   372  			case opcode == 0x75:
   373  				sel = "DROP"
   374  			case opcode == 0x76:
   375  				sel = "DUP"
   376  			case opcode == 0x87:
   377  				sel = "EQUAL"
   378  			case opcode == 0x88:
   379  				sel = "EQUALVERIFY"
   380  			case opcode == 0xa9:
   381  				sel = "HASH160"
   382  			case opcode == 0xac:
   383  				sel = "CHECKSIG"
   384  			case opcode == 0xad:
   385  				sel = "CHECKSIGVERIFY"
   386  			case opcode == 0xae:
   387  				sel = "CHECKMULTISIG"
   388  			case opcode == 0xb2:
   389  				sel = "CHECKSEQUENCEVERIFY"
   390  			default:
   391  				sel = fmt.Sprintf("0x%02X", opcode)
   392  			}
   393  			sel = "OP_" + sel
   394  		}
   395  		out = append(out, sel)
   396  	}
   397  	return
   398  }