public equation CombineAndReduce(equation othereq) { long topmultiplier = 0, bottommultiplier = 0; // This function considers "this" the top, and othereq the bottom. // It multiplies both equations by the first coefficient of the opposite equation, // and then subtracts the bottom from the top, eliminating the first coefficient from // the left side, and adding coefficients to the right. equation neweq = new equation(); othereq.KillFactors(); for (int i = 0; i < leftside.Count; i++) { coefficient topco = leftside[i]; coefficient bottomco = othereq.leftside[i]; if (i == 0) { topmultiplier = bottomco.multiplier; bottommultiplier = topco.multiplier; // avoid saving a coefficient because the multiplier and subtraction guarantee they cancel } else { neweq.leftside.Add(new coefficient(topco.multiplier * topmultiplier - bottomco.multiplier * bottommultiplier, topco.vindex)); } } for (int i = 0; i < 8; i++) { long multiplier = 0; foreach (coefficient r in rightside) { if (r.vindex == i) { multiplier += (r.multiplier * topmultiplier); } } foreach (coefficient r in othereq.rightside) { if (r.vindex == i) { multiplier -= (r.multiplier * bottommultiplier); } } if (multiplier != 0) { neweq.rightside.Add(new coefficient(multiplier, i)); } } neweq.KillFactors(); return(neweq); }
public equation CombineAndReduce(equation othereq) { long topmultiplier = 0, bottommultiplier = 0; // This function considers "this" the top, and othereq the bottom. // It multiplies both equations by the first coefficient of the opposite equation, // and then subtracts the bottom from the top, eliminating the first coefficient from // the left side, and adding coefficients to the right. equation neweq = new equation(); othereq.KillFactors(); for (int i = 0; i < leftside.Count; i++) { coefficient topco = leftside[i]; coefficient bottomco = othereq.leftside[i]; if (i == 0) { topmultiplier = bottomco.multiplier; bottommultiplier = topco.multiplier; // avoid saving a coefficient because the multiplier and subtraction guarantee they cancel } else { neweq.leftside.Add(new coefficient(topco.multiplier * topmultiplier - bottomco.multiplier * bottommultiplier, topco.vindex)); } } for (int i = 0; i < 8; i++) { long multiplier = 0; foreach (coefficient r in rightside) { if (r.vindex == i) multiplier += (r.multiplier * topmultiplier); } foreach (coefficient r in othereq.rightside) { if (r.vindex == i) multiplier -= (r.multiplier * bottommultiplier); } if (multiplier != 0) { neweq.rightside.Add(new coefficient(multiplier, i)); } } neweq.KillFactors(); return neweq; }
public void Decode() { ChecksumMatched = false; Decoded = false; KeyPair = null; if (PartsAccepted < PartsNeeded) { return; } BigInteger[] pc = new BigInteger[8]; for (int i = 0; i < decodedKeyParts.Count; i++) { byte[] g = decodedKeyParts[i]; pc[i] = new BigInteger(1, g, 4, 35); // If there is an overflow, then add it in. if ((g[2] & 0x80) == 0x80) { pc[i] = pc[i].Add(new BigInteger(((int)((g[2] & 0x60) >> 5)).ToString()).ShiftLeft(280)); Debug.WriteLine("overflow added"); } } List <equation> equations = new List <equation>(); // create equations for all the parts we need. for (int i = 0; i < PartsNeeded; i++) { byte[] got = decodedKeyParts[i]; // extract out part number int partnumber0 = (byte)((got[2] & 0x0e) >> 1); equations.Add(new equation(i, PartsNeeded, partnumber0)); } List <List <equation> > steps = new List <List <equation> >(); steps.Add(equations); // goal: get our equation set down such that there's only one coefficient on the left side. while (equations.Count > 1) { equations = solvesome(equations); steps.Add(equations); Debug.WriteLine("-----"); foreach (equation eq in equations) { Debug.WriteLine(eq.ToString()); } } BigInteger[] v = new BigInteger[8]; while (steps.Count > 0) { // pop off the last step List <equation> laststeps = steps[steps.Count - 1]; steps.RemoveAt(steps.Count - 1); equation laststep = laststeps[0]; Debug.WriteLine("-----"); Debug.WriteLine(laststep.ToString()); // solve for v long divisor = laststep.leftside[0].multiplier; laststep.divisor = laststep.leftside[0].multiplier; laststep.leftside[0].multiplier = 1; //foreach (coefficient c in laststep.rightside) c.divisor = divisor; //laststep.subtractor = laststep.subtractor.Divide(new BigInteger(divisor.ToString())); long idx = laststep.leftside[0].vindex; v[idx] = laststep.SolveRight(pc); Debug.WriteLine(String.Format("v({0})={1}", laststep.leftside[0].vindex, v[idx].ToString())); // go through all other steps and see that our solved value is incorporated into the equation. foreach (List <equation> eqbl in steps) { foreach (equation eqb in eqbl) { eqb.SolveLeft(v); } } } // xor the ones we need BigInteger xoraccum = BigInteger.Zero; for (int i = 0; i < PartsNeeded; i++) { xoraccum = xoraccum.Xor(v[i]); } ChecksumMatched = false; Decoded = true; byte[] keybytes = xoraccum.ToByteArrayUnsigned(); if (keybytes.Length > 32) { // if more than 32 bytes, decoding probably went wrong! truncate to 32 bytes, but force a checksum failure byte[] newkey = new byte[32]; for (int jj = 0; jj < 32; jj++) { newkey[jj] = keybytes[jj]; } keybytes = newkey; return; } else if (keybytes.Length < 32) { byte[] array32 = new byte[32]; Array.Copy(keybytes, 0, array32, 32 - keybytes.Length, keybytes.Length); keybytes = array32; } KeyPair = new KeyPair(keybytes); // Get the bitcoin address byte[] checksum = Util.ComputeSha256(BitcoinAddress); int mychecksum = ((checksum[0] & 1) << 8) + checksum[1]; if (mychecksum == expectedChecksum) { ChecksumMatched = true; } }