diff --git a/blockchain/validate.go b/blockchain/validate.go index 56ea9be2a..e5cb9f29e 100644 --- a/blockchain/validate.go +++ b/blockchain/validate.go @@ -55,7 +55,7 @@ const ( // MinTransactionSize is the minimum transaction size allowed on the // network after the magneticanomaly hardfork - MinTransactionSize = 100 + MinTransactionSize = 65 // BlockMaxBytesMaxSigChecksRatio is the ratio between the maximum allowable // block size and the maximum allowable * SigChecks (executed signature check diff --git a/chaincfg/params.go b/chaincfg/params.go index 94f1e788e..8bed97879 100644 --- a/chaincfg/params.go +++ b/chaincfg/params.go @@ -138,7 +138,7 @@ type Params struct { BIP0065Height int32 BIP0066Height int32 - // Only testnet4 uses CSV activation by height. All the others use the + // Only testnet4 and chipnet uses CSV activation by height. All the others use the // deployment schedule. If this value is set to anything other than zero // then it will activate at this height. CSVHeight int32 @@ -154,6 +154,8 @@ type Params struct { AxionActivationHeight int32 // Nov 15, 2020 hardfork CosmicInflationActivationTime uint64 // May 15, 2022 hardfork + VMLimitsAndBigIntUpgradeActivationTime uint64 + // CoinbaseMaturity is the number of blocks required before newly mined // coins (coinbase transactions) can be spent. CoinbaseMaturity uint16 @@ -262,7 +264,7 @@ var MainNetParams = Params{ Name: "mainnet", Net: wire.MainNet, DefaultPort: "8333", - DNSSeeds: []DNSSeed{ + DNSSeeds: []DNSSeed{ // TODO change this to proper dns seed {"seed.bchd.cash", true}, {"btccash-seeder.bitcoinunlimited.info", true}, {"seed.bch.loping.net", true}, @@ -288,6 +290,8 @@ var MainNetParams = Params{ CosmicInflationActivationTime: 1652616000, + VMLimitsAndBigIntUpgradeActivationTime: 1747310400, + CoinbaseMaturity: 100, SubsidyReductionInterval: 210000, TargetTimespan: time.Hour * 24 * 14, // 14 days @@ -623,6 +627,96 @@ var TestNet3Params = Params{ SlpAddressPrefix: "slptest", } +var ChipNetParams = Params{ + Name: "chipnet", + Net: wire.ChipNet, + DefaultPort: "48333", + DNSSeeds: []DNSSeed{ + {"chipnet.bitjson.com", true}, + }, + + // Chain parameters + GenesisBlock: &testNet4GenesisBlock, // Same value as testnet4 + GenesisHash: &testNet4GenesisHash, // Same value as testnet4 + PowLimit: testNet3PowLimit, // Same value as testnet3 + PowLimitBits: 0x1d00ffff, + BIP0034Height: 2, + BIP0065Height: 3, + BIP0066Height: 4, + CSVHeight: 5, + + UahfForkHeight: 5, + DaaForkHeight: 3000, + MagneticAnonomalyForkHeight: 3999, + GreatWallForkHeight: 0, + GravitonForkHeight: 4999, + PhononForkHeight: 0, + AxionActivationHeight: 16844, + + CosmicInflationActivationTime: 1637694000, + + VMLimitsAndBigIntUpgradeActivationTime: 1731672000, + + CoinbaseMaturity: 100, + SubsidyReductionInterval: 210000, + TargetTimespan: time.Hour * 24 * 14, // 14 days + TargetTimePerBlock: time.Minute * 10, // 10 minutes + RetargetAdjustmentFactor: 4, // 25% less, 400% more + ReduceMinDifficulty: true, + NoDifficultyAdjustment: false, + MinDiffReductionTime: time.Minute * 20, // TargetTimePerBlock * 2 + AsertDifficultyHalflife: 3600, // 1 hour + AsertDifficultyAnchorHeight: 16844, + AsertDifficultyAnchorParentTimestamp: 1605451779, + AsertDifficultyAnchorBits: 0x1d00ffff, + GenerateSupported: false, + + // Checkpoints ordered from oldest to newest. + Checkpoints: []Checkpoint{}, + + // Consensus rule change deployments. + // + // The miner confirmation window is defined as: + // target proof of work timespan / target proof of work spacing + RuleChangeActivationThreshold: 1512, // 75% of MinerConfirmationWindow + MinerConfirmationWindow: 2016, + Deployments: [DefinedDeployments]ConsensusDeployment{ + DeploymentTestDummy: { + BitNumber: 28, + StartTime: 1199145601, // January 1, 2008 UTC + ExpireTime: 1230767999, // December 31, 2008 UTC + }, + DeploymentCSV: { + BitNumber: 0, + StartTime: 1456790400, // March 1st, 2016 + ExpireTime: 1493596800, // May 1st, 2017 + }, + }, + + // Mempool parameters + RelayNonStdTxs: false, + + // The prefix for the cashaddress + CashAddressPrefix: "bchtest", // always bchtest for testnet + + // Address encoding magics + LegacyPubKeyHashAddrID: 0x6f, // starts with m or n + LegacyScriptHashAddrID: 0xc4, // starts with 2 + PrivateKeyID: 0xef, // starts with 9 (uncompressed) or c (compressed) + + // BIP32 hierarchical deterministic extended key magics + HDPrivateKeyID: [4]byte{0x04, 0x35, 0x83, 0x94}, // starts with tprv + HDPublicKeyID: [4]byte{0x04, 0x35, 0x87, 0xcf}, // starts with tpub + + // BIP44 coin type used in the hierarchical deterministic path for + // address generation. + HDCoinType: 1, // all coins use 1 + + // slp indexer parameters + SlpIndexStartHeight: 0, + SlpAddressPrefix: "slptest", +} + // TestNet4Params defines the network parameters for the test Bitcoin network // (version 4). Not to be confused with the regression test network, this // network is sometimes simply called "testnet". diff --git a/config.go b/config.go index 6f178e7e3..e61a8e9a2 100644 --- a/config.go +++ b/config.go @@ -156,6 +156,7 @@ type config struct { TorIsolation bool `long:"torisolation" description:"Enable Tor stream isolation by randomizing user credentials for each connection."` TestNet3 bool `long:"testnet" description:"Use the test network"` TestNet4 bool `long:"testnet4" description:"Use the test 4 network"` + ChipNet bool `long:"chipnet" description:"Use the chip network"` RegressionTest bool `long:"regtest" description:"Use the regression test network"` RegressionTestAnyHost bool `long:"regtestanyhost" description:"In regression test mode, allow connections from any host, not just localhost"` RegressionTestNoReset bool `long:"regtestnoreset" description:"In regression test mode, don't reset the network db on node restart"` @@ -595,6 +596,10 @@ func loadConfig() (*config, []string, error) { numNets++ activeNetParams = &testNet4Params } + if cfg.ChipNet { + numNets++ + activeNetParams = &chipNetParams + } if cfg.RegressionTest { numNets++ activeNetParams = ®ressionNetParams @@ -606,7 +611,7 @@ func loadConfig() (*config, []string, error) { cfg.DisableDNSSeed = true } if numNets > 1 { - str := "%s: The testnet, regtest, segnet, and simnet params " + + str := "%s: The testnet, chipnet, regtest, segnet, and simnet params " + "can't be used together -- choose one of the four" err := fmt.Errorf(str, funcName) fmt.Fprintln(os.Stderr, err) diff --git a/params.go b/params.go index b60748b31..ff89d213f 100644 --- a/params.go +++ b/params.go @@ -61,6 +61,15 @@ var testNet4Params = params{ gRRPPort: "18335", } +// chipNetParams contains parameters specific to the chip network +// (wire.ChipNet). NOTE: The RPC port is intentionally different than the +// reference implementation - see the mainNetParams comment for details. +var chipNetParams = params{ + Params: &chaincfg.ChipNetParams, + rpcPort: "18334", + gRRPPort: "18335", +} + // simNetParams contains parameters specific to the simulation test network // (wire.SimNet). var simNetParams = params{ diff --git a/txscript/engine.go b/txscript/engine.go index ec213f15a..9c842e8f9 100644 --- a/txscript/engine.go +++ b/txscript/engine.go @@ -127,6 +127,9 @@ const ( // ScriptVerifyNativeIntrospection enables the suite of native introspection // opcodes. ScriptVerifyNativeIntrospection + + // ScriptIncreasedVMLimits enables the upgrade '25 vm limits + ScriptIncreasedVMLimits ) // HasFlag returns whether the ScriptFlags has the passed flag set. @@ -158,6 +161,7 @@ type Engine struct { txIdx int condStack []int numOps int + opCost int flags ScriptFlags sigCache *SigCache hashCache *TxSigHashes @@ -204,11 +208,15 @@ func (vm *Engine) executeOpcode(pop *parsedOpcode) error { // Note that this includes OP_RESERVED which counts as a push operation. if pop.opcode.value > OP_16 { - vm.numOps++ - if vm.numOps > MaxOpsPerScript { - str := fmt.Sprintf("exceeded max operation limit of %d", - MaxOpsPerScript) - return scriptError(ErrTooManyOperations, str) + if vm.hasFlag(ScriptIncreasedVMLimits) { + vm.opCost += 100 + } else { + vm.numOps++ + if vm.numOps > MaxOpsPerScript { + str := fmt.Sprintf("exceeded max operation limit of %d", + MaxOpsPerScript) + return scriptError(ErrTooManyOperations, str) + } } } else if len(pop.data) > MaxScriptElementSize { @@ -407,6 +415,7 @@ func (vm *Engine) Step() (done bool, err error) { _ = vm.astack.DropN(vm.astack.Depth()) vm.numOps = 0 // number of ops is per script. + vm.opCost = 0 vm.scriptOff = 0 if vm.scriptIdx == 0 && vm.bip16 { vm.scriptIdx++ @@ -833,6 +842,7 @@ func (vm *Engine) Clone() *Engine { scriptOff: vm.scriptOff, scriptIdx: vm.scriptIdx, numOps: vm.numOps, + opCost: vm.opCost, lastCodeSep: vm.lastCodeSep, tx: vm.tx, bip16: vm.bip16, diff --git a/txscript/opcode.go b/txscript/opcode.go index 6daf31252..3dd5ad1d1 100644 --- a/txscript/opcode.go +++ b/txscript/opcode.go @@ -36,266 +36,266 @@ type opcode struct { // in bitcoin core and in most if not all other references and software related // to handling BCH scripts. const ( - OP_0 = 0x00 // 0 - OP_FALSE = 0x00 // 0 - AKA OP_0 - OP_DATA_1 = 0x01 // 1 - OP_DATA_2 = 0x02 // 2 - OP_DATA_3 = 0x03 // 3 - OP_DATA_4 = 0x04 // 4 - OP_DATA_5 = 0x05 // 5 - OP_DATA_6 = 0x06 // 6 - OP_DATA_7 = 0x07 // 7 - OP_DATA_8 = 0x08 // 8 - OP_DATA_9 = 0x09 // 9 - OP_DATA_10 = 0x0a // 10 - OP_DATA_11 = 0x0b // 11 - OP_DATA_12 = 0x0c // 12 - OP_DATA_13 = 0x0d // 13 - OP_DATA_14 = 0x0e // 14 - OP_DATA_15 = 0x0f // 15 - OP_DATA_16 = 0x10 // 16 - OP_DATA_17 = 0x11 // 17 - OP_DATA_18 = 0x12 // 18 - OP_DATA_19 = 0x13 // 19 - OP_DATA_20 = 0x14 // 20 - OP_DATA_21 = 0x15 // 21 - OP_DATA_22 = 0x16 // 22 - OP_DATA_23 = 0x17 // 23 - OP_DATA_24 = 0x18 // 24 - OP_DATA_25 = 0x19 // 25 - OP_DATA_26 = 0x1a // 26 - OP_DATA_27 = 0x1b // 27 - OP_DATA_28 = 0x1c // 28 - OP_DATA_29 = 0x1d // 29 - OP_DATA_30 = 0x1e // 30 - OP_DATA_31 = 0x1f // 31 - OP_DATA_32 = 0x20 // 32 - OP_DATA_33 = 0x21 // 33 - OP_DATA_34 = 0x22 // 34 - OP_DATA_35 = 0x23 // 35 - OP_DATA_36 = 0x24 // 36 - OP_DATA_37 = 0x25 // 37 - OP_DATA_38 = 0x26 // 38 - OP_DATA_39 = 0x27 // 39 - OP_DATA_40 = 0x28 // 40 - OP_DATA_41 = 0x29 // 41 - OP_DATA_42 = 0x2a // 42 - OP_DATA_43 = 0x2b // 43 - OP_DATA_44 = 0x2c // 44 - OP_DATA_45 = 0x2d // 45 - OP_DATA_46 = 0x2e // 46 - OP_DATA_47 = 0x2f // 47 - OP_DATA_48 = 0x30 // 48 - OP_DATA_49 = 0x31 // 49 - OP_DATA_50 = 0x32 // 50 - OP_DATA_51 = 0x33 // 51 - OP_DATA_52 = 0x34 // 52 - OP_DATA_53 = 0x35 // 53 - OP_DATA_54 = 0x36 // 54 - OP_DATA_55 = 0x37 // 55 - OP_DATA_56 = 0x38 // 56 - OP_DATA_57 = 0x39 // 57 - OP_DATA_58 = 0x3a // 58 - OP_DATA_59 = 0x3b // 59 - OP_DATA_60 = 0x3c // 60 - OP_DATA_61 = 0x3d // 61 - OP_DATA_62 = 0x3e // 62 - OP_DATA_63 = 0x3f // 63 - OP_DATA_64 = 0x40 // 64 - OP_DATA_65 = 0x41 // 65 - OP_DATA_66 = 0x42 // 66 - OP_DATA_67 = 0x43 // 67 - OP_DATA_68 = 0x44 // 68 - OP_DATA_69 = 0x45 // 69 - OP_DATA_70 = 0x46 // 70 - OP_DATA_71 = 0x47 // 71 - OP_DATA_72 = 0x48 // 72 - OP_DATA_73 = 0x49 // 73 - OP_DATA_74 = 0x4a // 74 - OP_DATA_75 = 0x4b // 75 - OP_PUSHDATA1 = 0x4c // 76 - OP_PUSHDATA2 = 0x4d // 77 - OP_PUSHDATA4 = 0x4e // 78 - OP_1NEGATE = 0x4f // 79 - OP_RESERVED = 0x50 // 80 - OP_1 = 0x51 // 81 - AKA OP_TRUE - OP_TRUE = 0x51 // 81 - OP_2 = 0x52 // 82 - OP_3 = 0x53 // 83 - OP_4 = 0x54 // 84 - OP_5 = 0x55 // 85 - OP_6 = 0x56 // 86 - OP_7 = 0x57 // 87 - OP_8 = 0x58 // 88 - OP_9 = 0x59 // 89 - OP_10 = 0x5a // 90 - OP_11 = 0x5b // 91 - OP_12 = 0x5c // 92 - OP_13 = 0x5d // 93 - OP_14 = 0x5e // 94 - OP_15 = 0x5f // 95 - OP_16 = 0x60 // 96 - OP_NOP = 0x61 // 97 - OP_VER = 0x62 // 98 - OP_IF = 0x63 // 99 - OP_NOTIF = 0x64 // 100 - OP_VERIF = 0x65 // 101 - OP_VERNOTIF = 0x66 // 102 - OP_ELSE = 0x67 // 103 - OP_ENDIF = 0x68 // 104 - OP_VERIFY = 0x69 // 105 - OP_RETURN = 0x6a // 106 - OP_TOALTSTACK = 0x6b // 107 - OP_FROMALTSTACK = 0x6c // 108 - OP_2DROP = 0x6d // 109 - OP_2DUP = 0x6e // 110 - OP_3DUP = 0x6f // 111 - OP_2OVER = 0x70 // 112 - OP_2ROT = 0x71 // 113 - OP_2SWAP = 0x72 // 114 - OP_IFDUP = 0x73 // 115 - OP_DEPTH = 0x74 // 116 - OP_DROP = 0x75 // 117 - OP_DUP = 0x76 // 118 - OP_NIP = 0x77 // 119 - OP_OVER = 0x78 // 120 - OP_PICK = 0x79 // 121 - OP_ROLL = 0x7a // 122 - OP_ROT = 0x7b // 123 - OP_SWAP = 0x7c // 124 - OP_TUCK = 0x7d // 125 - OP_CAT = 0x7e // 126 - OP_SPLIT = 0x7f // 127 - OP_NUM2BIN = 0x80 // 128 - OP_BIN2NUM = 0x81 // 129 - OP_SIZE = 0x82 // 130 - OP_INVERT = 0x83 // 131 - OP_AND = 0x84 // 132 - OP_OR = 0x85 // 133 - OP_XOR = 0x86 // 134 - OP_EQUAL = 0x87 // 135 - OP_EQUALVERIFY = 0x88 // 136 - OP_RESERVED1 = 0x89 // 137 - OP_RESERVED2 = 0x8a // 138 - OP_1ADD = 0x8b // 139 - OP_1SUB = 0x8c // 140 - OP_2MUL = 0x8d // 141 - OP_2DIV = 0x8e // 142 - OP_NEGATE = 0x8f // 143 - OP_ABS = 0x90 // 144 - OP_NOT = 0x91 // 145 - OP_0NOTEQUAL = 0x92 // 146 - OP_ADD = 0x93 // 147 - OP_SUB = 0x94 // 148 - OP_MUL = 0x95 // 149 - OP_DIV = 0x96 // 150 - OP_MOD = 0x97 // 151 - OP_LSHIFT = 0x98 // 152 - OP_RSHIFT = 0x99 // 153 - OP_BOOLAND = 0x9a // 154 - OP_BOOLOR = 0x9b // 155 - OP_NUMEQUAL = 0x9c // 156 - OP_NUMEQUALVERIFY = 0x9d // 157 - OP_NUMNOTEQUAL = 0x9e // 158 - OP_LESSTHAN = 0x9f // 159 - OP_GREATERTHAN = 0xa0 // 160 - OP_LESSTHANOREQUAL = 0xa1 // 161 - OP_GREATERTHANOREQUAL = 0xa2 // 162 - OP_MIN = 0xa3 // 163 - OP_MAX = 0xa4 // 164 - OP_WITHIN = 0xa5 // 165 - OP_RIPEMD160 = 0xa6 // 166 - OP_SHA1 = 0xa7 // 167 - OP_SHA256 = 0xa8 // 168 - OP_HASH160 = 0xa9 // 169 - OP_HASH256 = 0xaa // 170 - OP_CODESEPARATOR = 0xab // 171 - OP_CHECKSIG = 0xac // 172 - OP_CHECKSIGVERIFY = 0xad // 173 - OP_CHECKMULTISIG = 0xae // 174 - OP_CHECKMULTISIGVERIFY = 0xaf // 175 - OP_NOP1 = 0xb0 // 176 - OP_NOP2 = 0xb1 // 177 - OP_CHECKLOCKTIMEVERIFY = 0xb1 // 177 - AKA OP_NOP2 - OP_NOP3 = 0xb2 // 178 - OP_CHECKSEQUENCEVERIFY = 0xb2 // 178 - AKA OP_NOP3 - OP_NOP4 = 0xb3 // 179 - OP_NOP5 = 0xb4 // 180 - OP_NOP6 = 0xb5 // 181 - OP_NOP7 = 0xb6 // 182 - OP_NOP8 = 0xb7 // 183 - OP_NOP9 = 0xb8 // 184 - OP_NOP10 = 0xb9 // 185 - OP_CHECKDATASIG = 0xba // 186 - OP_CHECKDATASIGVERIFY = 0xbb // 187 - OP_REVERSEBYTES = 0xbc // 188 - OP_UNKNOWN189 = 0xbd // 189 - OP_UNKNOWN190 = 0xbe // 190 - OP_UNKNOWN191 = 0xbf // 191 - OP_INPUTINDEX = 0xc0 // 192 - OP_ACTIVEBYTECODE = 0xc1 // 193 - OP_TXVERSION = 0xc2 // 194 - OP_TXINPUTCOUNT = 0xc3 // 195 - OP_TXOUTPUTCOUNT = 0xc4 // 196 - OP_TXLOCKTIME = 0xc5 // 197 - OP_UTXOVALUE = 0xc6 // 198 - OP_UTXOBYTECODE = 0xc7 // 199 - OP_OUTPOINTTXHASH = 0xc8 // 200 - OP_OUTPOINTINDEX = 0xc9 // 201 - OP_INPUTBYTECODE = 0xca // 202 - OP_INPUTSEQUENCENUMBER = 0xcb // 203 - OP_OUTPUTVALUE = 0xcc // 204 - OP_OUTPUTBYTECODE = 0xcd // 205 - OP_UNKNOWN206 = 0xce // 206 - OP_UNKNOWN207 = 0xcf // 207 - OP_UNKNOWN208 = 0xd0 // 208 - OP_UNKNOWN209 = 0xd1 // 209 - OP_UNKNOWN210 = 0xd2 // 210 - OP_UNKNOWN211 = 0xd3 // 211 - OP_UNKNOWN212 = 0xd4 // 212 - OP_UNKNOWN213 = 0xd5 // 213 - OP_UNKNOWN214 = 0xd6 // 214 - OP_UNKNOWN215 = 0xd7 // 215 - OP_UNKNOWN216 = 0xd8 // 216 - OP_UNKNOWN217 = 0xd9 // 217 - OP_UNKNOWN218 = 0xda // 218 - OP_UNKNOWN219 = 0xdb // 219 - OP_UNKNOWN220 = 0xdc // 220 - OP_UNKNOWN221 = 0xdd // 221 - OP_UNKNOWN222 = 0xde // 222 - OP_UNKNOWN223 = 0xdf // 223 - OP_UNKNOWN224 = 0xe0 // 224 - OP_UNKNOWN225 = 0xe1 // 225 - OP_UNKNOWN226 = 0xe2 // 226 - OP_UNKNOWN227 = 0xe3 // 227 - OP_UNKNOWN228 = 0xe4 // 228 - OP_UNKNOWN229 = 0xe5 // 229 - OP_UNKNOWN230 = 0xe6 // 230 - OP_UNKNOWN231 = 0xe7 // 231 - OP_UNKNOWN232 = 0xe8 // 232 - OP_UNKNOWN233 = 0xe9 // 233 - OP_UNKNOWN234 = 0xea // 234 - OP_UNKNOWN235 = 0xeb // 235 - OP_UNKNOWN236 = 0xec // 236 - OP_UNKNOWN237 = 0xed // 237 - OP_UNKNOWN238 = 0xee // 238 - OP_UNKNOWN239 = 0xef // 239 - OP_UNKNOWN240 = 0xf0 // 240 - OP_UNKNOWN241 = 0xf1 // 241 - OP_UNKNOWN242 = 0xf2 // 242 - OP_UNKNOWN243 = 0xf3 // 243 - OP_UNKNOWN244 = 0xf4 // 244 - OP_UNKNOWN245 = 0xf5 // 245 - OP_UNKNOWN246 = 0xf6 // 246 - OP_UNKNOWN247 = 0xf7 // 247 - OP_UNKNOWN248 = 0xf8 // 248 - OP_UNKNOWN249 = 0xf9 // 249 - OP_SMALLINTEGER = 0xfa // 250 - bitcoin core internal - OP_PUBKEYS = 0xfb // 251 - bitcoin core internal - OP_UNKNOWN252 = 0xfc // 252 - OP_PUBKEYHASH = 0xfd // 253 - bitcoin core internal - OP_PUBKEY = 0xfe // 254 - bitcoin core internal - OP_INVALIDOPCODE = 0xff // 255 - bitcoin core internal + OP_0 = 0x00 // 0 + OP_FALSE = 0x00 // 0 - AKA OP_0 + OP_DATA_1 = 0x01 // 1 + OP_DATA_2 = 0x02 // 2 + OP_DATA_3 = 0x03 // 3 + OP_DATA_4 = 0x04 // 4 + OP_DATA_5 = 0x05 // 5 + OP_DATA_6 = 0x06 // 6 + OP_DATA_7 = 0x07 // 7 + OP_DATA_8 = 0x08 // 8 + OP_DATA_9 = 0x09 // 9 + OP_DATA_10 = 0x0a // 10 + OP_DATA_11 = 0x0b // 11 + OP_DATA_12 = 0x0c // 12 + OP_DATA_13 = 0x0d // 13 + OP_DATA_14 = 0x0e // 14 + OP_DATA_15 = 0x0f // 15 + OP_DATA_16 = 0x10 // 16 + OP_DATA_17 = 0x11 // 17 + OP_DATA_18 = 0x12 // 18 + OP_DATA_19 = 0x13 // 19 + OP_DATA_20 = 0x14 // 20 + OP_DATA_21 = 0x15 // 21 + OP_DATA_22 = 0x16 // 22 + OP_DATA_23 = 0x17 // 23 + OP_DATA_24 = 0x18 // 24 + OP_DATA_25 = 0x19 // 25 + OP_DATA_26 = 0x1a // 26 + OP_DATA_27 = 0x1b // 27 + OP_DATA_28 = 0x1c // 28 + OP_DATA_29 = 0x1d // 29 + OP_DATA_30 = 0x1e // 30 + OP_DATA_31 = 0x1f // 31 + OP_DATA_32 = 0x20 // 32 + OP_DATA_33 = 0x21 // 33 + OP_DATA_34 = 0x22 // 34 + OP_DATA_35 = 0x23 // 35 + OP_DATA_36 = 0x24 // 36 + OP_DATA_37 = 0x25 // 37 + OP_DATA_38 = 0x26 // 38 + OP_DATA_39 = 0x27 // 39 + OP_DATA_40 = 0x28 // 40 + OP_DATA_41 = 0x29 // 41 + OP_DATA_42 = 0x2a // 42 + OP_DATA_43 = 0x2b // 43 + OP_DATA_44 = 0x2c // 44 + OP_DATA_45 = 0x2d // 45 + OP_DATA_46 = 0x2e // 46 + OP_DATA_47 = 0x2f // 47 + OP_DATA_48 = 0x30 // 48 + OP_DATA_49 = 0x31 // 49 + OP_DATA_50 = 0x32 // 50 + OP_DATA_51 = 0x33 // 51 + OP_DATA_52 = 0x34 // 52 + OP_DATA_53 = 0x35 // 53 + OP_DATA_54 = 0x36 // 54 + OP_DATA_55 = 0x37 // 55 + OP_DATA_56 = 0x38 // 56 + OP_DATA_57 = 0x39 // 57 + OP_DATA_58 = 0x3a // 58 + OP_DATA_59 = 0x3b // 59 + OP_DATA_60 = 0x3c // 60 + OP_DATA_61 = 0x3d // 61 + OP_DATA_62 = 0x3e // 62 + OP_DATA_63 = 0x3f // 63 + OP_DATA_64 = 0x40 // 64 + OP_DATA_65 = 0x41 // 65 + OP_DATA_66 = 0x42 // 66 + OP_DATA_67 = 0x43 // 67 + OP_DATA_68 = 0x44 // 68 + OP_DATA_69 = 0x45 // 69 + OP_DATA_70 = 0x46 // 70 + OP_DATA_71 = 0x47 // 71 + OP_DATA_72 = 0x48 // 72 + OP_DATA_73 = 0x49 // 73 + OP_DATA_74 = 0x4a // 74 + OP_DATA_75 = 0x4b // 75 + OP_PUSHDATA1 = 0x4c // 76 + OP_PUSHDATA2 = 0x4d // 77 + OP_PUSHDATA4 = 0x4e // 78 + OP_1NEGATE = 0x4f // 79 + OP_RESERVED = 0x50 // 80 + OP_1 = 0x51 // 81 - AKA OP_TRUE + OP_TRUE = 0x51 // 81 + OP_2 = 0x52 // 82 + OP_3 = 0x53 // 83 + OP_4 = 0x54 // 84 + OP_5 = 0x55 // 85 + OP_6 = 0x56 // 86 + OP_7 = 0x57 // 87 + OP_8 = 0x58 // 88 + OP_9 = 0x59 // 89 + OP_10 = 0x5a // 90 + OP_11 = 0x5b // 91 + OP_12 = 0x5c // 92 + OP_13 = 0x5d // 93 + OP_14 = 0x5e // 94 + OP_15 = 0x5f // 95 + OP_16 = 0x60 // 96 + OP_NOP = 0x61 // 97 + OP_VER = 0x62 // 98 + OP_IF = 0x63 // 99 + OP_NOTIF = 0x64 // 100 + OP_VERIF = 0x65 // 101 + OP_VERNOTIF = 0x66 // 102 + OP_ELSE = 0x67 // 103 + OP_ENDIF = 0x68 // 104 + OP_VERIFY = 0x69 // 105 + OP_RETURN = 0x6a // 106 + OP_TOALTSTACK = 0x6b // 107 + OP_FROMALTSTACK = 0x6c // 108 + OP_2DROP = 0x6d // 109 + OP_2DUP = 0x6e // 110 + OP_3DUP = 0x6f // 111 + OP_2OVER = 0x70 // 112 + OP_2ROT = 0x71 // 113 + OP_2SWAP = 0x72 // 114 + OP_IFDUP = 0x73 // 115 + OP_DEPTH = 0x74 // 116 + OP_DROP = 0x75 // 117 + OP_DUP = 0x76 // 118 + OP_NIP = 0x77 // 119 + OP_OVER = 0x78 // 120 + OP_PICK = 0x79 // 121 + OP_ROLL = 0x7a // 122 + OP_ROT = 0x7b // 123 + OP_SWAP = 0x7c // 124 + OP_TUCK = 0x7d // 125 + OP_CAT = 0x7e // 126 + OP_SPLIT = 0x7f // 127 + OP_NUM2BIN = 0x80 // 128 + OP_BIN2NUM = 0x81 // 129 + OP_SIZE = 0x82 // 130 + OP_INVERT = 0x83 // 131 + OP_AND = 0x84 // 132 + OP_OR = 0x85 // 133 + OP_XOR = 0x86 // 134 + OP_EQUAL = 0x87 // 135 + OP_EQUALVERIFY = 0x88 // 136 + OP_RESERVED1 = 0x89 // 137 + OP_RESERVED2 = 0x8a // 138 + OP_1ADD = 0x8b // 139 + OP_1SUB = 0x8c // 140 + OP_2MUL = 0x8d // 141 + OP_2DIV = 0x8e // 142 + OP_NEGATE = 0x8f // 143 + OP_ABS = 0x90 // 144 + OP_NOT = 0x91 // 145 + OP_0NOTEQUAL = 0x92 // 146 + OP_ADD = 0x93 // 147 + OP_SUB = 0x94 // 148 + OP_MUL = 0x95 // 149 + OP_DIV = 0x96 // 150 + OP_MOD = 0x97 // 151 + OP_LSHIFT = 0x98 // 152 + OP_RSHIFT = 0x99 // 153 + OP_BOOLAND = 0x9a // 154 + OP_BOOLOR = 0x9b // 155 + OP_NUMEQUAL = 0x9c // 156 + OP_NUMEQUALVERIFY = 0x9d // 157 + OP_NUMNOTEQUAL = 0x9e // 158 + OP_LESSTHAN = 0x9f // 159 + OP_GREATERTHAN = 0xa0 // 160 + OP_LESSTHANOREQUAL = 0xa1 // 161 + OP_GREATERTHANOREQUAL = 0xa2 // 162 + OP_MIN = 0xa3 // 163 + OP_MAX = 0xa4 // 164 + OP_WITHIN = 0xa5 // 165 + OP_RIPEMD160 = 0xa6 // 166 + OP_SHA1 = 0xa7 // 167 + OP_SHA256 = 0xa8 // 168 + OP_HASH160 = 0xa9 // 169 + OP_HASH256 = 0xaa // 170 + OP_CODESEPARATOR = 0xab // 171 + OP_CHECKSIG = 0xac // 172 + OP_CHECKSIGVERIFY = 0xad // 173 + OP_CHECKMULTISIG = 0xae // 174 + OP_CHECKMULTISIGVERIFY = 0xaf // 175 + OP_NOP1 = 0xb0 // 176 + OP_NOP2 = 0xb1 // 177 + OP_CHECKLOCKTIMEVERIFY = 0xb1 // 177 - AKA OP_NOP2 + OP_NOP3 = 0xb2 // 178 + OP_CHECKSEQUENCEVERIFY = 0xb2 // 178 - AKA OP_NOP3 + OP_NOP4 = 0xb3 // 179 + OP_NOP5 = 0xb4 // 180 + OP_NOP6 = 0xb5 // 181 + OP_NOP7 = 0xb6 // 182 + OP_NOP8 = 0xb7 // 183 + OP_NOP9 = 0xb8 // 184 + OP_NOP10 = 0xb9 // 185 + OP_CHECKDATASIG = 0xba // 186 + OP_CHECKDATASIGVERIFY = 0xbb // 187 + OP_REVERSEBYTES = 0xbc // 188 + OP_UNKNOWN189 = 0xbd // 189 + OP_UNKNOWN190 = 0xbe // 190 + OP_UNKNOWN191 = 0xbf // 191 + OP_INPUTINDEX = 0xc0 // 192 + OP_ACTIVEBYTECODE = 0xc1 // 193 + OP_TXVERSION = 0xc2 // 194 + OP_TXINPUTCOUNT = 0xc3 // 195 + OP_TXOUTPUTCOUNT = 0xc4 // 196 + OP_TXLOCKTIME = 0xc5 // 197 + OP_UTXOVALUE = 0xc6 // 198 + OP_UTXOBYTECODE = 0xc7 // 199 + OP_OUTPOINTTXHASH = 0xc8 // 200 + OP_OUTPOINTINDEX = 0xc9 // 201 + OP_INPUTBYTECODE = 0xca // 202 + OP_INPUTSEQUENCENUMBER = 0xcb // 203 + OP_OUTPUTVALUE = 0xcc // 204 + OP_OUTPUTBYTECODE = 0xcd // 205 + OP_UTXOTOKENCATEGORY = 0xce // 206 + OP_UTXOTOKENCOMMITMENT = 0xcf // 207 + OP_UTXOTOKENAMOUNT = 0xd0 // 208 + OP_OUTPUTTOKENCATEGORY = 0xd1 // 209 + OP_OUTPUTTOKENCOMMITMENT = 0xd2 // 210 + OP_OUTPUTTOKENAMOUNT = 0xd3 // 211 + OP_UNKNOWN212 = 0xd4 // 212 + OP_UNKNOWN213 = 0xd5 // 213 + OP_UNKNOWN214 = 0xd6 // 214 + OP_UNKNOWN215 = 0xd7 // 215 + OP_UNKNOWN216 = 0xd8 // 216 + OP_UNKNOWN217 = 0xd9 // 217 + OP_UNKNOWN218 = 0xda // 218 + OP_UNKNOWN219 = 0xdb // 219 + OP_UNKNOWN220 = 0xdc // 220 + OP_UNKNOWN221 = 0xdd // 221 + OP_UNKNOWN222 = 0xde // 222 + OP_UNKNOWN223 = 0xdf // 223 + OP_UNKNOWN224 = 0xe0 // 224 + OP_UNKNOWN225 = 0xe1 // 225 + OP_UNKNOWN226 = 0xe2 // 226 + OP_UNKNOWN227 = 0xe3 // 227 + OP_UNKNOWN228 = 0xe4 // 228 + OP_UNKNOWN229 = 0xe5 // 229 + OP_UNKNOWN230 = 0xe6 // 230 + OP_UNKNOWN231 = 0xe7 // 231 + OP_UNKNOWN232 = 0xe8 // 232 + OP_UNKNOWN233 = 0xe9 // 233 + OP_UNKNOWN234 = 0xea // 234 + OP_UNKNOWN235 = 0xeb // 235 + OP_UNKNOWN236 = 0xec // 236 + OP_UNKNOWN237 = 0xed // 237 + OP_UNKNOWN238 = 0xee // 238 + OP_UNKNOWN239 = 0xef // 239 + OP_UNKNOWN240 = 0xf0 // 240 + OP_UNKNOWN241 = 0xf1 // 241 + OP_UNKNOWN242 = 0xf2 // 242 + OP_UNKNOWN243 = 0xf3 // 243 + OP_UNKNOWN244 = 0xf4 // 244 + OP_UNKNOWN245 = 0xf5 // 245 + OP_UNKNOWN246 = 0xf6 // 246 + OP_UNKNOWN247 = 0xf7 // 247 + OP_UNKNOWN248 = 0xf8 // 248 + OP_UNKNOWN249 = 0xf9 // 249 + OP_SMALLINTEGER = 0xfa // 250 - bitcoin core internal + OP_PUBKEYS = 0xfb // 251 - bitcoin core internal + OP_UNKNOWN252 = 0xfc // 252 + OP_PUBKEYHASH = 0xfd // 253 - bitcoin core internal + OP_PUBKEY = 0xfe // 254 - bitcoin core internal + OP_INVALIDOPCODE = 0xff // 255 - bitcoin core internal ) // Conditional execution constants. @@ -530,16 +530,18 @@ var opcodeArray = [256]opcode{ OP_NOP9: {OP_NOP9, "OP_NOP9", 1, opcodeNop}, OP_NOP10: {OP_NOP10, "OP_NOP10", 1, opcodeNop}, + // CashTokens opcodes. + OP_UTXOTOKENCATEGORY: {OP_UTXOTOKENCATEGORY, "OP_UTXOTOKENCATEGORY", 1, opcodeDummy}, + OP_UTXOTOKENCOMMITMENT: {OP_UTXOTOKENCOMMITMENT, "OP_UTXOTOKENCOMMITMENT", 1, opcodeDummy}, + OP_UTXOTOKENAMOUNT: {OP_UTXOTOKENAMOUNT, "OP_UTXOTOKENAMOUNT", 1, opcodeDummy}, + OP_OUTPUTTOKENCATEGORY: {OP_OUTPUTTOKENCATEGORY, "OP_OUTPUTTOKENCATEGORY", 1, opcodeDummy}, + OP_OUTPUTTOKENCOMMITMENT: {OP_OUTPUTTOKENCOMMITMENT, "OP_OUTPUTTOKENCOMMITMENT", 1, opcodeDummy}, + OP_OUTPUTTOKENAMOUNT: {OP_OUTPUTTOKENAMOUNT, "OP_OUTPUTTOKENAMOUNT", 1, opcodeDummy}, + // Undefined opcodes. OP_UNKNOWN189: {OP_UNKNOWN189, "OP_UNKNOWN189", 1, opcodeInvalid}, OP_UNKNOWN190: {OP_UNKNOWN190, "OP_UNKNOWN190", 1, opcodeInvalid}, OP_UNKNOWN191: {OP_UNKNOWN191, "OP_UNKNOWN191", 1, opcodeInvalid}, - OP_UNKNOWN206: {OP_UNKNOWN206, "OP_UNKNOWN206", 1, opcodeInvalid}, - OP_UNKNOWN207: {OP_UNKNOWN207, "OP_UNKNOWN207", 1, opcodeInvalid}, - OP_UNKNOWN208: {OP_UNKNOWN208, "OP_UNKNOWN208", 1, opcodeInvalid}, - OP_UNKNOWN209: {OP_UNKNOWN209, "OP_UNKNOWN209", 1, opcodeInvalid}, - OP_UNKNOWN210: {OP_UNKNOWN210, "OP_UNKNOWN210", 1, opcodeInvalid}, - OP_UNKNOWN211: {OP_UNKNOWN211, "OP_UNKNOWN211", 1, opcodeInvalid}, OP_UNKNOWN212: {OP_UNKNOWN212, "OP_UNKNOWN212", 1, opcodeInvalid}, OP_UNKNOWN213: {OP_UNKNOWN213, "OP_UNKNOWN213", 1, opcodeInvalid}, OP_UNKNOWN214: {OP_UNKNOWN214, "OP_UNKNOWN214", 1, opcodeInvalid}, @@ -855,6 +857,11 @@ func opcodeInvalid(op *parsedOpcode, vm *Engine) error { return scriptError(ErrReservedOpcode, str) } +// opcodeDummy is a common handler for all dummy opcodes. +func opcodeDummy(op *parsedOpcode, vm *Engine) error { + return nil +} + // opcodeFalse pushes an empty array to the data stack to represent false. Note // that 0, when encoded as a number according to the numeric encoding consensus // rules, is an empty array. @@ -1374,6 +1381,9 @@ func opcodeRoll(op *parsedOpcode, vm *Engine) error { if err != nil { return err } + if vm.hasFlag(ScriptIncreasedVMLimits) { + vm.opCost += int(vm.dstack.Depth()) + } return vm.dstack.RollN(val.Int32()) } @@ -1597,6 +1607,12 @@ func opcodeAnd(op *parsedOpcode, vm *Engine) error { c[i] = a[i] & b[i] } vm.dstack.PushByteArray(c) + + if vm.hasFlag(ScriptIncreasedVMLimits) { + //vm.opCost += result.size() TODO VMLIMITS + vm.opCost += len(c) + } + return nil } @@ -1620,6 +1636,12 @@ func opcodeOr(op *parsedOpcode, vm *Engine) error { c[i] = a[i] | b[i] } vm.dstack.PushByteArray(c) + + if vm.hasFlag(ScriptIncreasedVMLimits) { + //vm.opCost += result.size() TODO VMLIMITS + vm.opCost += len(c) + } + return nil } @@ -1643,6 +1665,12 @@ func opcodeXor(op *parsedOpcode, vm *Engine) error { c[i] = a[i] ^ b[i] } vm.dstack.PushByteArray(c) + + if vm.hasFlag(ScriptIncreasedVMLimits) { + //vm.opCost += result.size() TODO VMLIMITS + vm.opCost += len(c) + } + return nil } @@ -1690,6 +1718,11 @@ func opcode1Add(op *parsedOpcode, vm *Engine) error { } vm.dstack.PushInt(m + 1) + + if vm.hasFlag(ScriptIncreasedVMLimits) { + vm.opCost += len((m + 1).Bytes()) + } + return nil } @@ -1704,6 +1737,10 @@ func opcode1Sub(op *parsedOpcode, vm *Engine) error { } vm.dstack.PushInt(m - 1) + if vm.hasFlag(ScriptIncreasedVMLimits) { + vm.opCost += len((m - 1).Bytes()) + } + return nil } @@ -1718,6 +1755,11 @@ func opcodeNegate(op *parsedOpcode, vm *Engine) error { } vm.dstack.PushInt(-m) + + if vm.hasFlag(ScriptIncreasedVMLimits) { + vm.opCost += len((-m).Bytes()) + } + return nil } @@ -1735,6 +1777,11 @@ func opcodeAbs(op *parsedOpcode, vm *Engine) error { m = -m } vm.dstack.PushInt(m) + + if vm.hasFlag(ScriptIncreasedVMLimits) { + vm.opCost += len((m).Bytes()) + } + return nil } @@ -1758,8 +1805,17 @@ func opcodeNot(op *parsedOpcode, vm *Engine) error { if m == 0 { vm.dstack.PushInt(scriptNum(1)) + + if vm.hasFlag(ScriptIncreasedVMLimits) { + vm.opCost += len((scriptNum(1)).Bytes()) + } + } else { vm.dstack.PushInt(scriptNum(0)) + + if vm.hasFlag(ScriptIncreasedVMLimits) { + vm.opCost += len((scriptNum(0)).Bytes()) + } } return nil } @@ -1780,6 +1836,11 @@ func opcode0NotEqual(op *parsedOpcode, vm *Engine) error { m = 1 } vm.dstack.PushInt(m) + + if vm.hasFlag(ScriptIncreasedVMLimits) { + vm.opCost += len(m.Bytes()) + } + return nil } @@ -1804,6 +1865,11 @@ func opcodeAdd(op *parsedOpcode, vm *Engine) error { } if (c > v0) == (v1 > 0) { vm.dstack.PushInt(c) + + if vm.hasFlag(ScriptIncreasedVMLimits) { + vm.opCost += len(c.Bytes()) + } + return nil } return scriptError(ErrIntegerOverflow, "integer overflow") @@ -1831,6 +1897,11 @@ func opcodeSub(op *parsedOpcode, vm *Engine) error { } if (c < v1) == (v0 > 0) { vm.dstack.PushInt(c) + + if vm.hasFlag(ScriptIncreasedVMLimits) { + vm.opCost += len(c.Bytes()) + } + return nil } return scriptError(ErrIntegerOverflow, "integer overflow") @@ -1857,6 +1928,11 @@ func opcodeMul(op *parsedOpcode, vm *Engine) error { if a == 0 || b == 0 { vm.dstack.PushInt(0) + + if vm.hasFlag(ScriptIncreasedVMLimits) { + vm.opCost += len(scriptNum(0).Bytes()) + } + return nil } c := a * b @@ -1866,6 +1942,11 @@ func opcodeMul(op *parsedOpcode, vm *Engine) error { if (c < 0) == ((a < 0) != (b < 0)) { if c/b == a { vm.dstack.PushInt(c) + + if vm.hasFlag(ScriptIncreasedVMLimits) { + vm.opCost += len(c.Bytes()) + } + return nil } } @@ -1891,6 +1972,11 @@ func opcodeDiv(op *parsedOpcode, vm *Engine) error { return scriptError(ErrNumberTooSmall, "divide by zero") } vm.dstack.PushInt(a / b) + + if vm.hasFlag(ScriptIncreasedVMLimits) { + vm.opCost += len((a / b).Bytes()) + } + return nil } @@ -1913,6 +1999,11 @@ func opcodeMod(op *parsedOpcode, vm *Engine) error { return scriptError(ErrNumberTooSmall, "mod by zero") } vm.dstack.PushInt(a % b) + + if vm.hasFlag(ScriptIncreasedVMLimits) { + vm.opCost += len((a % b).Bytes()) + } + return nil } @@ -1936,8 +2027,14 @@ func opcodeBoolAnd(op *parsedOpcode, vm *Engine) error { if v0 != 0 && v1 != 0 { vm.dstack.PushInt(scriptNum(1)) + if vm.hasFlag(ScriptIncreasedVMLimits) { + vm.opCost += len(scriptNum(1).Bytes()) + } } else { vm.dstack.PushInt(scriptNum(0)) + if vm.hasFlag(ScriptIncreasedVMLimits) { + vm.opCost += len(scriptNum(0).Bytes()) + } } return nil @@ -1963,8 +2060,14 @@ func opcodeBoolOr(op *parsedOpcode, vm *Engine) error { if v0 != 0 || v1 != 0 { vm.dstack.PushInt(scriptNum(1)) + if vm.hasFlag(ScriptIncreasedVMLimits) { + vm.opCost += len(scriptNum(1).Bytes()) + } } else { vm.dstack.PushInt(scriptNum(0)) + if vm.hasFlag(ScriptIncreasedVMLimits) { + vm.opCost += len(scriptNum(0).Bytes()) + } } return nil @@ -1988,8 +2091,14 @@ func opcodeNumEqual(op *parsedOpcode, vm *Engine) error { if v0 == v1 { vm.dstack.PushInt(scriptNum(1)) + if vm.hasFlag(ScriptIncreasedVMLimits) { + vm.opCost += len(scriptNum(1).Bytes()) + } } else { vm.dstack.PushInt(scriptNum(0)) + if vm.hasFlag(ScriptIncreasedVMLimits) { + vm.opCost += len(scriptNum(0).Bytes()) + } } return nil @@ -2029,8 +2138,14 @@ func opcodeNumNotEqual(op *parsedOpcode, vm *Engine) error { if v0 != v1 { vm.dstack.PushInt(scriptNum(1)) + if vm.hasFlag(ScriptIncreasedVMLimits) { + vm.opCost += len(scriptNum(1).Bytes()) + } } else { vm.dstack.PushInt(scriptNum(0)) + if vm.hasFlag(ScriptIncreasedVMLimits) { + vm.opCost += len(scriptNum(0).Bytes()) + } } return nil @@ -2054,8 +2169,14 @@ func opcodeLessThan(op *parsedOpcode, vm *Engine) error { if v1 < v0 { vm.dstack.PushInt(scriptNum(1)) + if vm.hasFlag(ScriptIncreasedVMLimits) { + vm.opCost += len(scriptNum(1).Bytes()) + } } else { vm.dstack.PushInt(scriptNum(0)) + if vm.hasFlag(ScriptIncreasedVMLimits) { + vm.opCost += len(scriptNum(0).Bytes()) + } } return nil @@ -2079,8 +2200,14 @@ func opcodeGreaterThan(op *parsedOpcode, vm *Engine) error { if v1 > v0 { vm.dstack.PushInt(scriptNum(1)) + if vm.hasFlag(ScriptIncreasedVMLimits) { + vm.opCost += len(scriptNum(1).Bytes()) + } } else { vm.dstack.PushInt(scriptNum(0)) + if vm.hasFlag(ScriptIncreasedVMLimits) { + vm.opCost += len(scriptNum(0).Bytes()) + } } return nil } @@ -2103,8 +2230,14 @@ func opcodeLessThanOrEqual(op *parsedOpcode, vm *Engine) error { if v1 <= v0 { vm.dstack.PushInt(scriptNum(1)) + if vm.hasFlag(ScriptIncreasedVMLimits) { + vm.opCost += len(scriptNum(1).Bytes()) + } } else { vm.dstack.PushInt(scriptNum(0)) + if vm.hasFlag(ScriptIncreasedVMLimits) { + vm.opCost += len(scriptNum(0).Bytes()) + } } return nil } @@ -2127,8 +2260,14 @@ func opcodeGreaterThanOrEqual(op *parsedOpcode, vm *Engine) error { if v1 >= v0 { vm.dstack.PushInt(scriptNum(1)) + if vm.hasFlag(ScriptIncreasedVMLimits) { + vm.opCost += len(scriptNum(1).Bytes()) + } } else { vm.dstack.PushInt(scriptNum(0)) + if vm.hasFlag(ScriptIncreasedVMLimits) { + vm.opCost += len(scriptNum(0).Bytes()) + } } return nil @@ -2151,8 +2290,14 @@ func opcodeMin(op *parsedOpcode, vm *Engine) error { if v1 < v0 { vm.dstack.PushInt(v1) + if vm.hasFlag(ScriptIncreasedVMLimits) { + vm.opCost += len(v1.Bytes()) + } } else { vm.dstack.PushInt(v0) + if vm.hasFlag(ScriptIncreasedVMLimits) { + vm.opCost += len(v0.Bytes()) + } } return nil @@ -2175,8 +2320,14 @@ func opcodeMax(op *parsedOpcode, vm *Engine) error { if v1 > v0 { vm.dstack.PushInt(v1) + if vm.hasFlag(ScriptIncreasedVMLimits) { + vm.opCost += len(v1.Bytes()) + } } else { vm.dstack.PushInt(v0) + if vm.hasFlag(ScriptIncreasedVMLimits) { + vm.opCost += len(v0.Bytes()) + } } return nil @@ -2211,6 +2362,11 @@ func opcodeWithin(op *parsedOpcode, vm *Engine) error { } else { vm.dstack.PushInt(scriptNum(0)) } + + if vm.hasFlag(ScriptIncreasedVMLimits) { + vm.opCost += len((maxVal + minVal + x).Bytes()) + } + return nil } @@ -2486,7 +2642,11 @@ func opcodeCheckMultiSig(op *parsedOpcode, vm *Engine) error { numPubKeys, MaxPubKeysPerMultiSig) return scriptError(ErrInvalidPubKeyCount, str) } - vm.numOps += numPubKeys + + if !vm.hasFlag(ScriptIncreasedVMLimits) { + vm.numOps += numPubKeys + } + if vm.numOps > MaxOpsPerScript { str := fmt.Sprintf("exceeded max operation limit of %d", MaxOpsPerScript) diff --git a/txscript/script.go b/txscript/script.go index 8e57d0bf7..bf81596e7 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -41,9 +41,9 @@ const ( // These are the constants specified for maximums in individual scripts. const ( - MaxOpsPerScript = 201 // Max number of non-push operations. - MaxPubKeysPerMultiSig = 20 // Multisig can't have more sigs than this. - MaxScriptElementSize = 520 // Max bytes pushable to the stack. + MaxOpsPerScript = 201 // Max number of non-push operations. + MaxPubKeysPerMultiSig = 20 // Multisig can't have more sigs than this. + MaxScriptElementSize = 10000 // Max bytes pushable to the stack. ) // isSmallInt returns whether or not the opcode is considered a small integer, @@ -261,7 +261,7 @@ func DisasmString(buf []byte) (string, error) { return disbuf.String(), err } -// removeOpcode will remove any opcode matching ``opcode'' from the opcode +// removeOpcode will remove any opcode matching “opcode” from the opcode // stream in pkscript func removeOpcode(pkscript []parsedOpcode, opcode byte) []parsedOpcode { retScript := make([]parsedOpcode, 0, len(pkscript)) diff --git a/wire/protocol.go b/wire/protocol.go index a5455563f..a326f61f5 100644 --- a/wire/protocol.go +++ b/wire/protocol.go @@ -188,6 +188,9 @@ const ( // TestNet4 represents the test network (version 4). TestNet4 BitcoinNet = 0xafdab7e2 + // ChipNet represents the chip network. + ChipNet BitcoinNet = 0xafdab7e2 + // SimNet represents the simulation test network. SimNet BitcoinNet = 0x12141c16 )