In my opinion, you need to apply sym/endomorph to the candidate and not apply to splitKey or the result of addition
As you don't know the privKey when mining , it is not possible to calculate an offset to add in order to reduce to case 1.
May be I also missed something...
Well of course it’s possible! Are you sure you're a
jedidev?) Use Force, Luc!)
Oh, ok, explain, all simple.
I compared ver 1.12 vs 1.13 to understand how you added splitkey support.
You generate starting points from the seed, and add a splitkey to them. That is the whole problem.
With this implementation, it is necessary to apply symY/endomorph to the splitkey.
(what yourself do at the stage of indirect verification of the pair)
And you did not need to make changes to the code of cuda.
It’s convenient, a minimum of edits, everything works, yes. But not with appspot pool.
To make it compatible with the pool, you need to add a splitkey after applying symY/endomorph right before hash160.
It’s not very difficult there, but the performance will suffer, because the operations of adding points are added.
I have fixed a few functions for cpu -nosse only, a rough prototype demonstrating that this is possible.
Code is sloow, and problem not in sse. I think secp->AddDirect() is really tardy. I hope you find a quick solution.
C:\Users\User\source\repos\VanitySearch-1.15\x64\Release>VanitySearch -stop -t 4 -s "A Strong Password" -kp
Priv : L2JtWKgFrwzjyw4UQjaCMHu8Cq3e6yuq4Thdjd6H462XnTJz9ftE
Pub : 0280C3E351A2F47F1A09A20F130B922C2BE2009F4CB4892901559AE09ABB357389
C:\Users\User\source\repos\VanitySearch-1.15\x64\Release>VanitySearch -stop -t 4 -sp 0280C3E351A2F47F1A09A20F130B922C2BE2009F4CB4892901559AE09ABB357389 -nosse -o __keyinfo.txt 12345
VanitySearch v1.15
Difficulty: 4553521
Search: 12345 [Compressed, with public key]
Start Sat Aug 3 03:39:07 2019
Base Key: A6CDE51DC26E832F9C7AB673FF6B5F8F9D0C7F121E9A115CAC45B7884671F757
Number of CPU thread: 4
0.995 MK/s (GPU 0.000 MK/s) (2^20.92) [P 35.41%][50.00% in 00:00:01][0]
C:\Users\User\source\repos\VanitySearch-1.15\x64\Release>type __keyinfo.txt
Pub Addr: 12345zpQiMCPgjrCHcGwZ6kUsPpiid79MK
PartialPriv: KzN1kLMYrhZfRiWM8RR4dgReCHJeZmeMuPnqKS3KNj7HSe4SUTXA
C:\Users\User\source\repos\VanitySearch-1.15\x64\Release>VanitySearch -rp L2JtWKgFrwzjyw4UQjaCMHu8Cq3e6yuq4Thdjd6H462XnTJz9ftE __keyinfo.txt
Pub Addr: 12345zpQiMCPgjrCHcGwZ6kUsPpiid79MK
Priv (WIF): p2pkh:L5TC4zufJyHogQsVkTTx5hDRYVdnpBr98JknRunUaZfiBieQTxv8
Priv (HEX): 0xF5A25AAD2AA36613D8B58511DBE851C9EBE893141C00AC90823008B942A8E6ED
void VanitySearch::getCPUStartingKey(int thId,Int& key,Point& startP) {
if (rekey > 0) {
key.Rand(256);
} else {
key.Set(&startKey);
Int off((int64_t)thId);
off.ShiftL(64);
key.Add(&off);
}
Int km(&key);
km.Add((uint64_t)CPU_GRP_SIZE / 2);
startP = secp->ComputePublicKey(&km);
//if(startPubKeySpecified)
// startP = secp->AddDirect(startP,startPubKey);
}
void VanitySearch::checkAddresses(bool compressed, Int key, int i, Point p1) {
unsigned char h0[20];
Point pte1[1];
Point pte2[1];
Point ptmp;
// classic
if (startPubKeySpecified) {
ptmp = secp->AddDirect(p1, startPubKey);
}
else {
ptmp = p1;
}
secp->GetHash160(searchType,compressed, ptmp, h0);
prefix_t pr0 = *(prefix_t *)h0;
if (hasPattern || prefixes[pr0].items)
checkAddr(pr0, h0, key, i, 0, compressed);
// Endomorphism #1
pte1[0].x.ModMulK1(&p1.x, &beta);
pte1[0].y.Set(&p1.y);
if (startPubKeySpecified) {
ptmp = secp->AddDirect(pte1[0], startPubKey);
}
else {
ptmp = pte1[0];
}
secp->GetHash160(searchType, compressed, ptmp, h0);
pr0 = *(prefix_t *)h0;
if (hasPattern || prefixes[pr0].items)
checkAddr(pr0, h0, key, i, 1, compressed);
// Endomorphism #2
pte2[0].x.ModMulK1(&p1.x, &beta2);
pte2[0].y.Set(&p1.y);
if (startPubKeySpecified) {
ptmp = secp->AddDirect(pte2[0], startPubKey);
}
else {
ptmp = pte2[0];
}
secp->GetHash160(searchType, compressed, ptmp, h0);
pr0 = *(prefix_t *)h0;
if (hasPattern || prefixes[pr0].items)
checkAddr(pr0, h0, key, i, 2, compressed);
// Curve symetrie
// if (x,y) = k*G, then (x, -y) is -k*G
p1.y.ModNeg();
if (startPubKeySpecified) {
ptmp = secp->AddDirect(p1, startPubKey);
}
else {
ptmp = p1;
}
secp->GetHash160(searchType, compressed, ptmp, h0);
pr0 = *(prefix_t *)h0;
if (hasPattern || prefixes[pr0].items)
checkAddr(pr0, h0, key, -i, 0, compressed);
// Endomorphism #1
pte1[0].y.ModNeg();
if (startPubKeySpecified) {
ptmp = secp->AddDirect(pte1[0], startPubKey);
}
else {
ptmp = pte1[0];
}
secp->GetHash160(searchType, compressed, ptmp, h0);
pr0 = *(prefix_t *)h0;
if (hasPattern || prefixes[pr0].items)
checkAddr(pr0, h0, key, -i, 1, compressed);
// Endomorphism #2
pte2[0].y.ModNeg();
if (startPubKeySpecified) {
ptmp = secp->AddDirect(pte2[0], startPubKey);
}
else {
ptmp = pte2[0];
}
secp->GetHash160(searchType, compressed, ptmp, h0);
pr0 = *(prefix_t *)h0;
if (hasPattern || prefixes[pr0].items)
checkAddr(pr0, h0, key, -i, 2, compressed);
}
bool VanitySearch::checkPrivKey(string addr, Int &key, int32_t incr, int endomorphism, bool mode) {
Int k(&key);
Point sp = startPubKey;
if (incr < 0) {
k.Add((uint64_t)(-incr));
k.Neg();
k.Add(&secp->order);
//if (startPubKeySpecified) sp.y.ModNeg();
} else {
k.Add((uint64_t)incr);
}
// Endomorphisms
switch (endomorphism) {
case 1:
k.ModMulK1order(&lambda);
//if(startPubKeySpecified) sp.x.ModMulK1(&beta);
break;
case 2:
k.ModMulK1order(&lambda2);
//if (startPubKeySpecified) sp.x.ModMulK1(&beta2);
break;
}
// Check addresses
Point p = secp->ComputePublicKey(&k);
if (startPubKeySpecified) p = secp->AddDirect(p, sp);
string chkAddr = secp->GetAddress(searchType, mode, p);
if (chkAddr != addr) {
//Key may be the opposite one (negative zero or compressed key)
k.Neg();
k.Add(&secp->order);
p = secp->ComputePublicKey(&k);
if (startPubKeySpecified) {
//sp.y.ModNeg();
p = secp->AddDirect(p, sp);
}
string chkAddr = secp->GetAddress(searchType, mode, p);
if (chkAddr != addr) {
printf("\nWarning, wrong private key generated !\n");
printf(" Addr :%s\n", addr.c_str());
printf(" Check:%s\n", chkAddr.c_str());
printf(" Endo:%d incr:%d comp:%d\n", endomorphism, incr, mode);
return false;
}
}
output(addr, secp->GetPrivAddress(mode ,k), k.GetBase16());
return true;
}
void reconstructAdd(Secp256K1 *secp, string fileName, string outputFile, string privAddr) {
bool compressed;
int addrType;
Int lambda;
Int lambda2;
lambda.SetBase16("5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72");
lambda2.SetBase16("ac9c52b33fa3cf1f5ad9e3fd77ed9ba4a880b9fc8ec739c2e0cfc810b51283ce");
Int privKey = secp->DecodePrivateKey((char *)privAddr.c_str(),&compressed);
if(privKey.IsNegative())
exit(-1);
vector lines;
parseFile(fileName,lines);
for (int i = 0; i < (int)lines.size(); i+=2) {
string addr;
string partialPrivAddr;
if (lines[i].substr(0, 10) == "Pub Addr: ") {
addr = lines[i].substr(10);
switch (addr.data()[0]) {
case '1':
addrType = P2PKH; break;
case '3':
addrType = P2SH; break;
case 'b':
case 'B':
addrType = BECH32; break;
default:
printf("Invalid partialkey info file at line %d\n", i);
printf("%s Address format not supported\n", addr.c_str());
continue;
}
} else {
printf("Invalid partialkey info file at line %d (\"Pub Addr: \" expected)\n",i);
exit(-1);
}
if (lines[i+1].substr(0, 13) == "PartialPriv: ") {
partialPrivAddr = lines[i+1].substr(13);
} else {
printf("Invalid partialkey info file at line %d (\"PartialPriv: \" expected)\n", i);
exit(-1);
}
bool partialMode;
Int partialPrivKey = secp->DecodePrivateKey((char *)partialPrivAddr.c_str(), &partialMode);
if (privKey.IsNegative()) {
printf("Invalid partialkey info file at line %d\n", i);
exit(-1);
}
if (partialMode != compressed) {
printf("Warning, Invalid partialkey at line %d (Wrong compression mode, ignoring key)\n", i);
continue;
} else {
// Reconstruct the address
Int fullPriv;
Point p;
Int e;
string cAddr;
bool found = false;
Int save_partialPrivKey = partialPrivKey;
// No sym, no endo
e.Set(&privKey);
CHECK_ADDR();
// No sym, endo 1
e.Set(&privKey);
//e.ModMulK1order(&lambda);
partialPrivKey.Set(&save_partialPrivKey);
partialPrivKey.ModMulK1order(&lambda);
CHECK_ADDR();
// No sym, endo 2
e.Set(&privKey);
//e.ModMulK1order(&lambda2);
partialPrivKey.Set(&save_partialPrivKey);
partialPrivKey.ModMulK1order(&lambda2);
CHECK_ADDR();
// sym, no endo
e.Set(&privKey);
//e.Neg();
//e.Add(&secp->order);
partialPrivKey.Set(&save_partialPrivKey);
partialPrivKey.Neg();
partialPrivKey.Add(&secp->order);
CHECK_ADDR();
// sym, endo 1
e.Set(&privKey);
//e.ModMulK1order(&lambda);
//e.Neg();
//e.Add(&secp->order);
partialPrivKey.Set(&save_partialPrivKey);
partialPrivKey.ModMulK1order(&lambda);
partialPrivKey.Neg();
partialPrivKey.Add(&secp->order);
CHECK_ADDR();
// sym, endo 2
e.Set(&privKey);
//e.ModMulK1order(&lambda2);
//e.Neg();
//e.Add(&secp->order);
partialPrivKey.Set(&save_partialPrivKey);
partialPrivKey.ModMulK1order(&lambda2);
partialPrivKey.Neg();
partialPrivKey.Add(&secp->order);
CHECK_ADDR();
if (!found) {
printf("Unable to reconstruct final key from partialkey line %d\n Addr: %s\n PartKey: %s\n",
i, addr.c_str(),partialPrivAddr.c_str());
}
}
}
}