package bsv
import "strconv"
type Opcode struct {
Num int
}
var opcodeMap = map[string]int{
"OP_FALSE": 0, "OP_0": 0,
"OP_PUSHDATA1": 76, "OP_PUSHDATA2": 77, "OP_PUSHDATA4": 78,
"OP_1NEGATE": 79, "OP_RESERVED": 80, "OP_TRUE": 81, "OP_1": 81,
"OP_2": 82, "OP_3": 83, "OP_4": 84, "OP_5": 85, "OP_6": 86,
"OP_7": 87, "OP_8": 88, "OP_9": 89, "OP_10": 90, "OP_11": 91,
"OP_12": 92, "OP_13": 93, "OP_14": 94, "OP_15": 95, "OP_16": 96,
"OP_NOP": 97, "OP_VER": 98, "OP_IF": 99, "OP_NOTIF": 100,
"OP_VERIF": 101, "OP_VERNOTIF": 102, "OP_ELSE": 103, "OP_ENDIF": 104,
"OP_VERIFY": 105, "OP_RETURN": 106,
"OP_TOALTSTACK": 107, "OP_FROMALTSTACK": 108, "OP_2DROP": 109,
"OP_2DUP": 110, "OP_3DUP": 111, "OP_2OVER": 112, "OP_2ROT": 113,
"OP_2SWAP": 114, "OP_IFDUP": 115, "OP_DEPTH": 116, "OP_DROP": 117,
"OP_DUP": 118, "OP_NIP": 119, "OP_OVER": 120, "OP_PICK": 121,
"OP_ROLL": 122, "OP_ROT": 123, "OP_SWAP": 124, "OP_TUCK": 125,
"OP_CAT": 126, "OP_SPLIT": 127, "OP_NUM2BIN": 128, "OP_BIN2NUM": 129,
"OP_SIZE": 130,
"OP_INVERT": 131, "OP_AND": 132, "OP_OR": 133, "OP_XOR": 134,
"OP_EQUAL": 135, "OP_EQUALVERIFY": 136, "OP_RESERVED1": 137, "OP_RESERVED2": 138,
"OP_1ADD": 139, "OP_1SUB": 140, "OP_2MUL": 141, "OP_2DIV": 142,
"OP_NEGATE": 143, "OP_ABS": 144, "OP_NOT": 145, "OP_0NOTEQUAL": 146,
"OP_ADD": 147, "OP_SUB": 148, "OP_MUL": 149, "OP_DIV": 150, "OP_MOD": 151,
"OP_LSHIFT": 152, "OP_RSHIFT": 153,
"OP_BOOLAND": 154, "OP_BOOLOR": 155, "OP_NUMEQUAL": 156,
"OP_NUMEQUALVERIFY": 157, "OP_NUMNOTEQUAL": 158, "OP_LESSTHAN": 159,
"OP_GREATERTHAN": 160, "OP_LESSTHANOREQUAL": 161, "OP_GREATERTHANOREQUAL": 162,
"OP_MIN": 163, "OP_MAX": 164,
"OP_WITHIN": 165,
"OP_RIPEMD160": 166, "OP_SHA1": 167, "OP_SHA256": 168, "OP_HASH160": 169,
"OP_HASH256": 170, "OP_CODESEPARATOR": 171, "OP_CHECKSIG": 172,
"OP_CHECKSIGVERIFY": 173, "OP_CHECKMULTISIG": 174, "OP_CHECKMULTISIGVERIFY": 175,
"OP_CHECKLOCKTIMEVERIFY": 177, "OP_CHECKSEQUENCEVERIFY": 178,
"OP_NOP1": 176, "OP_NOP2": 177, "OP_NOP3": 178, "OP_NOP4": 179,
"OP_NOP5": 180, "OP_NOP6": 181, "OP_NOP7": 182, "OP_NOP8": 183,
"OP_NOP9": 184, "OP_NOP10": 185,
"OP_PUBKEYHASH": 253, "OP_PUBKEY": 254, "OP_INVALIDOPCODE": 255,
}
var opcodeReverseMap = map[int]string{}
func init() {
for k, v := range opcodeMap {
opcodeReverseMap[v] = k
}
opcodeReverseMap[0] = "OP_0"
opcodeReverseMap[81] = "OP_1"
}
func NewOpcode(num interface{}) (*Opcode, error) {
switch v := num.(type) {
case int:
return &Opcode{Num: v}, nil
case string:
val, ok := opcodeMap[v]
if !ok {
return nil, newError("InvalidOpcode", "Invalid opcodestr: %s", v)
}
return &Opcode{Num: val}, nil
default:
return nil, newError("InvalidOpcode", "Unrecognized num type for Opcode")
}
}
func OpcodeFromBuffer(buf []byte) (*Opcode, error) {
if len(buf) != 1 {
return nil, newError("InvalidOpcode", "opcode buffer must be 1 byte")
}
return &Opcode{Num: int(buf[0])}, nil
}
func OpcodeFromNumber(num int) *Opcode { return &Opcode{Num: num} }
func OpcodeFromString(str string) (*Opcode, error) { return NewOpcode(str) }
func (o *Opcode) ToHex() string { return strconv.FormatInt(int64(o.Num), 16) }
func (o *Opcode) ToBuffer() []byte { return []byte{byte(o.Num)} }
func (o *Opcode) ToNumber() int { return o.Num }
func (o *Opcode) ToString() (string, error) {
str, ok := opcodeReverseMap[o.Num]
if !ok {
return "", newError("InvalidOpcode", "Opcode does not have a string representation")
}
return str, nil
}
func (o *Opcode) ToSafeString() string {
if str, ok := opcodeReverseMap[o.Num]; ok {
return str
}
return o.ToHex()
}
func SmallInt(n int) (*Opcode, error) {
if n < 0 || n > 16 {
return nil, newError("InvalidArgument", "Invalid Argument: n must be between 0 and 16")
}
if n == 0 {
return NewOpcode("OP_0")
}
return &Opcode{Num: opcodeMap["OP_1"] + n - 1}, nil
}
func IsSmallIntOp(opcode int) bool {
return opcode == opcodeMap["OP_0"] || (opcode >= opcodeMap["OP_1"] && opcode <= opcodeMap["OP_16"])
}