Enable txindex=1 as default #37
2 changed files with 50 additions and 56 deletions
|
@ -225,6 +225,55 @@ func isOpcodeConditional(opcode byte) bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// checkMinimalDataPush returns whether or not the provided opcode is the
|
||||||
|
// smallest possible way to represent the given data. For example, the value 15
|
||||||
|
// could be pushed with OP_DATA_1 15 (among other variations); however, OP_15 is
|
||||||
|
// a single opcode that represents the same value and is only a single byte
|
||||||
|
// versus two bytes.
|
||||||
|
func checkMinimalDataPush(op *opcode, data []byte) error {
|
||||||
|
opcodeVal := op.value
|
||||||
|
dataLen := len(data)
|
||||||
|
switch {
|
||||||
|
case dataLen == 0 && opcodeVal != OP_0:
|
||||||
|
str := fmt.Sprintf("zero length data push is encoded with opcode %s "+
|
||||||
|
"instead of OP_0", op.name)
|
||||||
|
return scriptError(ErrMinimalData, str)
|
||||||
|
case dataLen == 1 && data[0] >= 1 && data[0] <= 16:
|
||||||
|
if opcodeVal != OP_1+data[0]-1 {
|
||||||
|
// Should have used OP_1 .. OP_16
|
||||||
|
str := fmt.Sprintf("data push of the value %d encoded with opcode "+
|
||||||
|
"%s instead of OP_%d", data[0], op.name, data[0])
|
||||||
|
return scriptError(ErrMinimalData, str)
|
||||||
|
}
|
||||||
|
case dataLen == 1 && data[0] == 0x81:
|
||||||
|
if opcodeVal != OP_1NEGATE {
|
||||||
|
str := fmt.Sprintf("data push of the value -1 encoded with opcode "+
|
||||||
|
"%s instead of OP_1NEGATE", op.name)
|
||||||
|
return scriptError(ErrMinimalData, str)
|
||||||
|
}
|
||||||
|
case dataLen <= 75:
|
||||||
|
if int(opcodeVal) != dataLen {
|
||||||
|
// Should have used a direct push
|
||||||
|
str := fmt.Sprintf("data push of %d bytes encoded with opcode %s "+
|
||||||
|
"instead of OP_DATA_%d", dataLen, op.name, dataLen)
|
||||||
|
return scriptError(ErrMinimalData, str)
|
||||||
|
}
|
||||||
|
case dataLen <= 255:
|
||||||
|
if opcodeVal != OP_PUSHDATA1 {
|
||||||
|
str := fmt.Sprintf("data push of %d bytes encoded with opcode %s "+
|
||||||
|
"instead of OP_PUSHDATA1", dataLen, op.name)
|
||||||
|
return scriptError(ErrMinimalData, str)
|
||||||
|
}
|
||||||
|
case dataLen <= 65535:
|
||||||
|
if opcodeVal != OP_PUSHDATA2 {
|
||||||
|
str := fmt.Sprintf("data push of %d bytes encoded with opcode %s "+
|
||||||
|
"instead of OP_PUSHDATA2", dataLen, op.name)
|
||||||
|
return scriptError(ErrMinimalData, str)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// executeOpcode peforms execution on the passed opcode. It takes into account
|
// executeOpcode peforms execution on the passed opcode. It takes into account
|
||||||
// whether or not it is hidden by conditionals, but some rules still must be
|
// whether or not it is hidden by conditionals, but some rules still must be
|
||||||
// tested in this case.
|
// tested in this case.
|
||||||
|
@ -269,7 +318,7 @@ func (vm *Engine) executeOpcode(pop *parsedOpcode) error {
|
||||||
if vm.dstack.verifyMinimalData && vm.isBranchExecuting() &&
|
if vm.dstack.verifyMinimalData && vm.isBranchExecuting() &&
|
||||||
pop.opcode.value >= 0 && pop.opcode.value <= OP_PUSHDATA4 {
|
pop.opcode.value >= 0 && pop.opcode.value <= OP_PUSHDATA4 {
|
||||||
|
|
||||||
if err := pop.checkMinimalDataPush(); err != nil {
|
if err := checkMinimalDataPush(pop.opcode, pop.data); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -692,61 +692,6 @@ func (pop *parsedOpcode) checkParseableInScript(script []byte, scriptPos int) (i
|
||||||
return scriptPos, nil
|
return scriptPos, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// checkMinimalDataPush returns whether or not the current data push uses the
|
|
||||||
// smallest possible opcode to represent it. For example, the value 15 could
|
|
||||||
// be pushed with OP_DATA_1 15 (among other variations); however, OP_15 is a
|
|
||||||
// single opcode that represents the same value and is only a single byte versus
|
|
||||||
// two bytes.
|
|
||||||
func (pop *parsedOpcode) checkMinimalDataPush() error {
|
|
||||||
data := pop.data
|
|
||||||
dataLen := len(data)
|
|
||||||
opcode := pop.opcode.value
|
|
||||||
|
|
||||||
if dataLen == 0 && opcode != OP_0 {
|
|
||||||
str := fmt.Sprintf("zero length data push is encoded with "+
|
|
||||||
"opcode %s instead of OP_0", pop.opcode.name)
|
|
||||||
return scriptError(ErrMinimalData, str)
|
|
||||||
} else if dataLen == 1 && data[0] >= 1 && data[0] <= 16 {
|
|
||||||
if opcode != OP_1+data[0]-1 {
|
|
||||||
// Should have used OP_1 .. OP_16
|
|
||||||
str := fmt.Sprintf("data push of the value %d encoded "+
|
|
||||||
"with opcode %s instead of OP_%d", data[0],
|
|
||||||
pop.opcode.name, data[0])
|
|
||||||
return scriptError(ErrMinimalData, str)
|
|
||||||
}
|
|
||||||
} else if dataLen == 1 && data[0] == 0x81 {
|
|
||||||
if opcode != OP_1NEGATE {
|
|
||||||
str := fmt.Sprintf("data push of the value -1 encoded "+
|
|
||||||
"with opcode %s instead of OP_1NEGATE",
|
|
||||||
pop.opcode.name)
|
|
||||||
return scriptError(ErrMinimalData, str)
|
|
||||||
}
|
|
||||||
} else if dataLen <= 75 {
|
|
||||||
if int(opcode) != dataLen {
|
|
||||||
// Should have used a direct push
|
|
||||||
str := fmt.Sprintf("data push of %d bytes encoded "+
|
|
||||||
"with opcode %s instead of OP_DATA_%d", dataLen,
|
|
||||||
pop.opcode.name, dataLen)
|
|
||||||
return scriptError(ErrMinimalData, str)
|
|
||||||
}
|
|
||||||
} else if dataLen <= 255 {
|
|
||||||
if opcode != OP_PUSHDATA1 {
|
|
||||||
str := fmt.Sprintf("data push of %d bytes encoded "+
|
|
||||||
"with opcode %s instead of OP_PUSHDATA1",
|
|
||||||
dataLen, pop.opcode.name)
|
|
||||||
return scriptError(ErrMinimalData, str)
|
|
||||||
}
|
|
||||||
} else if dataLen <= 65535 {
|
|
||||||
if opcode != OP_PUSHDATA2 {
|
|
||||||
str := fmt.Sprintf("data push of %d bytes encoded "+
|
|
||||||
"with opcode %s instead of OP_PUSHDATA2",
|
|
||||||
dataLen, pop.opcode.name)
|
|
||||||
return scriptError(ErrMinimalData, str)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// disasmOpcode writes a human-readable disassembly of the provided opcode and
|
// disasmOpcode writes a human-readable disassembly of the provided opcode and
|
||||||
// data into the provided buffer. The compact flag indicates the disassembly
|
// data into the provided buffer. The compact flag indicates the disassembly
|
||||||
// should print a more compact representation of data-carrying and small integer
|
// should print a more compact representation of data-carrying and small integer
|
||||||
|
|
Loading…
Reference in a new issue