mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-15 12:51:00 +02:00
Add OP_DETERMINISTICRANDOM
This commit is contained in:
parent
5a18be3769
commit
358a1bb494
5 changed files with 59 additions and 4 deletions
|
|
@ -1071,6 +1071,61 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case OP_DETERMINISTICRANDOM:
|
||||||
|
{
|
||||||
|
if (stack.size() < 3)
|
||||||
|
return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
|
||||||
|
|
||||||
|
valtype vchSeed = stacktop(-3);
|
||||||
|
CScriptNum bnMin(stacktop(-2), fRequireMinimal);
|
||||||
|
CScriptNum bnMax(stacktop(-1), fRequireMinimal);
|
||||||
|
|
||||||
|
if (bnMin > bnMax)
|
||||||
|
return set_error(serror, SCRIPT_ERR_UNKNOWN_ERROR);
|
||||||
|
|
||||||
|
if (bnMin == bnMax) {
|
||||||
|
popstack(stack);
|
||||||
|
popstack(stack);
|
||||||
|
popstack(stack);
|
||||||
|
stack.push_back(bnMin.getvch());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The range of the random source must be a multiple of the modulus
|
||||||
|
// to give every possible output value an equal possibility
|
||||||
|
uint64_t nMax = (bnMax-bnMin).getint();
|
||||||
|
uint64_t nRange = (std::numeric_limits<uint64_t>::max() / nMax) * nMax;
|
||||||
|
uint64_t nRand;
|
||||||
|
|
||||||
|
valtype vchHash(32, 0);
|
||||||
|
uint64_t nCounter = 0;
|
||||||
|
int nHashIndex = 3;
|
||||||
|
CSHA256 hasher;
|
||||||
|
hasher.Write(vchSeed.data(), vchSeed.size());
|
||||||
|
do {
|
||||||
|
if (nHashIndex >= 3) {
|
||||||
|
//TODO this isn't endian safe
|
||||||
|
CSHA256(hasher).Write((const unsigned char*)&nCounter, sizeof(nCounter)).Finalize(vchHash.data());
|
||||||
|
nHashIndex = 0;
|
||||||
|
nCounter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
nRand = 0;
|
||||||
|
for (size_t i=0; i<8; ++i)
|
||||||
|
nRand |= ((uint64_t)vchHash[(nHashIndex*8) + i]) << (8*i);
|
||||||
|
|
||||||
|
nHashIndex++;
|
||||||
|
} while (nRand > nRange);
|
||||||
|
CScriptNum result(nRand % nMax);
|
||||||
|
result += bnMin.getint();
|
||||||
|
|
||||||
|
popstack(stack);
|
||||||
|
popstack(stack);
|
||||||
|
popstack(stack);
|
||||||
|
stack.push_back(result.getvch());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return set_error(serror, SCRIPT_ERR_BAD_OPCODE);
|
return set_error(serror, SCRIPT_ERR_BAD_OPCODE);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -126,6 +126,7 @@ const char* GetOpName(opcodetype opcode)
|
||||||
case OP_CHECKSIGVERIFY : return "OP_CHECKSIGVERIFY";
|
case OP_CHECKSIGVERIFY : return "OP_CHECKSIGVERIFY";
|
||||||
case OP_CHECKMULTISIG : return "OP_CHECKMULTISIG";
|
case OP_CHECKMULTISIG : return "OP_CHECKMULTISIG";
|
||||||
case OP_CHECKMULTISIGVERIFY : return "OP_CHECKMULTISIGVERIFY";
|
case OP_CHECKMULTISIGVERIFY : return "OP_CHECKMULTISIGVERIFY";
|
||||||
|
case OP_DETERMINISTICRANDOM : return "OP_DETERMINISTICRANDOM";
|
||||||
|
|
||||||
// expansion
|
// expansion
|
||||||
case OP_NOP1 : return "OP_NOP1";
|
case OP_NOP1 : return "OP_NOP1";
|
||||||
|
|
|
||||||
|
|
@ -173,6 +173,7 @@ enum opcodetype
|
||||||
OP_CHECKSIGVERIFY = 0xad,
|
OP_CHECKSIGVERIFY = 0xad,
|
||||||
OP_CHECKMULTISIG = 0xae,
|
OP_CHECKMULTISIG = 0xae,
|
||||||
OP_CHECKMULTISIGVERIFY = 0xaf,
|
OP_CHECKMULTISIGVERIFY = 0xaf,
|
||||||
|
OP_DETERMINISTICRANDOM = 0xc0,
|
||||||
|
|
||||||
// expansion
|
// expansion
|
||||||
OP_NOP1 = 0xb0,
|
OP_NOP1 = 0xb0,
|
||||||
|
|
@ -192,7 +193,7 @@ enum opcodetype
|
||||||
};
|
};
|
||||||
|
|
||||||
// Maximum value that an opcode can be
|
// Maximum value that an opcode can be
|
||||||
static const unsigned int MAX_OPCODE = OP_NOP10;
|
static const unsigned int MAX_OPCODE = OP_DETERMINISTICRANDOM;
|
||||||
|
|
||||||
const char* GetOpName(opcodetype opcode);
|
const char* GetOpName(opcodetype opcode);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -258,7 +258,6 @@
|
||||||
["0", "IF 0xbd ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
|
["0", "IF 0xbd ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
|
||||||
["0", "IF 0xbe ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
|
["0", "IF 0xbe ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
|
||||||
["0", "IF 0xbf ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
|
["0", "IF 0xbf ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
|
||||||
["0", "IF 0xc0 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
|
|
||||||
["0", "IF 0xc1 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
|
["0", "IF 0xc1 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
|
||||||
["0", "IF 0xc2 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
|
["0", "IF 0xc2 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
|
||||||
["0", "IF 0xc3 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
|
["0", "IF 0xc3 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
|
||||||
|
|
@ -894,7 +893,6 @@
|
||||||
["1", "IF 0xbd ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
|
["1", "IF 0xbd ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
|
||||||
["1", "IF 0xbe ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
|
["1", "IF 0xbe ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
|
||||||
["1", "IF 0xbf ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
|
["1", "IF 0xbf ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
|
||||||
["1", "IF 0xc0 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
|
|
||||||
["1", "IF 0xc1 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
|
["1", "IF 0xc1 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
|
||||||
["1", "IF 0xc2 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
|
["1", "IF 0xc2 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
|
||||||
["1", "IF 0xc3 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
|
["1", "IF 0xc3 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
|
||||||
|
|
|
||||||
|
|
@ -1474,7 +1474,7 @@ BOOST_AUTO_TEST_CASE(script_HasValidOps)
|
||||||
BOOST_CHECK(script.HasValidOps());
|
BOOST_CHECK(script.HasValidOps());
|
||||||
script = ScriptFromHex("ff88ac"); // Script with OP_INVALIDOPCODE explicit
|
script = ScriptFromHex("ff88ac"); // Script with OP_INVALIDOPCODE explicit
|
||||||
BOOST_CHECK(!script.HasValidOps());
|
BOOST_CHECK(!script.HasValidOps());
|
||||||
script = ScriptFromHex("88acc0"); // Script with undefined opcode
|
script = ScriptFromHex("88acc1"); // Script with undefined opcode: one higher then MAX_OPCODE
|
||||||
BOOST_CHECK(!script.HasValidOps());
|
BOOST_CHECK(!script.HasValidOps());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue