mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-14 12:43:40 +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;
|
||||
|
||||
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:
|
||||
return set_error(serror, SCRIPT_ERR_BAD_OPCODE);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue