public function testPow() { $this->assertEquals(gmp_strval(gmp_pow($this->a, $this->a)), $this->math->pow($this->a, $this->a)); $this->assertEquals(gmp_strval(gmp_pow($this->b, $this->b)), $this->math->pow($this->b, $this->b)); $this->assertEquals(gmp_strval(gmp_pow($this->c, $this->c)), $this->math->pow($this->c, $this->c)); $this->assertEquals(1, $this->math->pow(1, 1)); }
public function testBaseConvertDigits() { $converter = new BaseConvertConverter(new Base62Symbols()); $this->assertSame(explode(':', '4:16:12:8:33:15:15:6:34:11:20:0:20:28:32:4:24:0:32:4:12:16:12:28:32'), $converter->convert(gmp_strval(gmp_pow(10, 38), 10), 10, 36)); $this->assertSame(str_split('100000000000', 1), $converter->convert('100000000000', 10, 10)); $this->assertSame(explode(':', '3:18:2:10:0:0:0:0:0'), $converter->convert('100000000000', 10, 20)); }
/** * Exponential expression / raise number into power * * @param string $base base to raise * @param string $exp exponent to use * @param string $use_function pow function to use, or false for auto-detect * * @return mixed string or float */ public static function pow($base, $exp, $use_function = '') { static $pow_function = null; if ($pow_function == null) { $pow_function = self::detectPow(); } if (!$use_function) { if ($exp < 0) { $use_function = 'pow'; } else { $use_function = $pow_function; } } if ($exp < 0 && $use_function != 'pow') { return false; } switch ($use_function) { case 'bcpow': // bcscale() needed for testing pow() with base values < 1 bcscale(10); $pow = bcpow($base, $exp); break; case 'gmp_pow': $pow = gmp_strval(gmp_pow($base, $exp)); break; case 'pow': $base = (double) $base; $exp = (int) $exp; $pow = pow($base, $exp); break; default: $pow = $use_function($base, $exp); } return $pow; }
/** * Return the modulus, also known as absolute value or magnitude of this number * = sqrt(r^2 + i^2); * * @return \Chippyash\Type\Number\Rational\GMPRationalType */ public function modulus() { if ($this->isReal()) { //sqrt(r^2 + 0^2) = sqrt(r^2) = abs(r) /** @noinspection PhpUndefinedMethodInspection */ return $this->value['real']->abs(); } //get r^2 and i^2 $sqrR = array('n' => gmp_pow($this->value['real']->numerator()->gmp(), 2), 'd' => gmp_pow($this->value['real']->denominator()->gmp(), 2)); $sqrI = array('n' => gmp_pow($this->value['imaginary']->numerator()->gmp(), 2), 'd' => gmp_pow($this->value['imaginary']->denominator()->gmp(), 2)); //r^2 + i^2 $den = $this->lcm($sqrR['d'], $sqrI['d']); $numRaw = gmp_strval(gmp_add(gmp_div_q(gmp_mul($sqrR['n'], $den), $sqrR['d']), gmp_div_q(gmp_mul($sqrI['n'], $den), $sqrI['d']))); $num = TypeFactory::createInt($numRaw); //sqrt(num/den) = sqrt(num)/sqrt(den) //now this a fudge - we ought to be able to get a proper square root using //factors etc but what we do instead is to do an approximation by converting //to intermediate rationals using as much precision as we can i.e. // rNum = GMPRationaType(sqrt(num)) // rDen = GMPRationalType(sqrt(den)) // mod = rN/1 * 1/rD $rNum = RationalTypeFactory::fromFloat(sqrt($num())); $rDen = RationalTypeFactory::fromFloat(sqrt(gmp_strval($den))); $modN = gmp_mul($rNum->numerator()->gmp(), $rDen->denominator()->gmp()); $modD = gmp_mul($rNum->denominator()->gmp(), $rDen->numerator()->gmp()); return RationalTypeFactory::create((int) gmp_strval($modN), (int) gmp_strval($modD)); }
/** * Exponential expression / raise number into power * * @param string $base base to raise * @param string $exp exponent to use * @param mixed $use_function pow function to use, or false for auto-detect * * @return mixed string or float */ function PMA_pow($base, $exp, $use_function = false) { static $pow_function = null; if (null == $pow_function) { $pow_function = PMA_detect_pow(); } if (!$use_function) { $use_function = $pow_function; } if ($exp < 0 && 'pow' != $use_function) { return false; } switch ($use_function) { case 'bcpow': // bcscale() needed for testing PMA_pow() with base values < 1 bcscale(10); $pow = bcpow($base, $exp); break; case 'gmp_pow': $pow = gmp_strval(gmp_pow($base, $exp)); break; case 'pow': $base = (double) $base; $exp = (int) $exp; $pow = pow($base, $exp); break; default: $pow = $use_function($base, $exp); } return $pow; }
function sumT($n) { if (gmp_intval($n) == 1) { return gmp_init(1); } return gmp_add(gmp_sub(gmp_pow($n, 2), gmp_pow(gmp_init(gmp_intval($n) - 1), 2)), sumT(gmp_init(gmp_intval($n) - 1))); //return gmp_mod(gmp_add(gmp_sub(gmp_mod(gmp_pow($n, 2), '1000000007'), gmp_mod(gmp_pow(gmp_init(gmp_intval($n)-1), 2), '1000000007')), sumT(gmp_init(gmp_intval($n)-1))), '1000000007'); }
private function makeId32($timestamp, $machine, $sequence) { $timestamp = gmp_mul((string) $timestamp, gmp_pow(2, 22)); $machine = gmp_mul((string) $machine, gmp_pow(2, 12)); $sequence = gmp_init((string) $sequence, 10); $value = gmp_or(gmp_or($timestamp, $machine), $sequence); return gmp_strval($value, 10); }
function gmp_shiftr($x, $n) { if ($x < 0) { return gmp_strval(gmp_com(gmp_div(gmp_com($x), gmp_pow(2, $n)))); } else { return gmp_strval(gmp_div($x, gmp_pow(2, $n))); } }
private function computeBaseNLength($number, $targetBase) { $digits = 0; while (gmp_cmp($number, gmp_pow($targetBase, $digits)) != -1) { $digits++; } return $digits ?: 1; }
public static function inc($X, $n) { $s = gmp_strval($X, 2); $s1 = (string) substr($s, 0, -$n); $s = gmp_add(gmp_init(substr($s, -$n), 2), 1); $s = gmp_mod($s, gmp_pow(2, $n)); $s2 = str_pad(gmp_strval($s, 2), $n, '0', STR_PAD_LEFT); return gmp_init($s1 . $s2, 2); }
protected function __construct() { $this->params['q'] = gmp_sub(gmp_pow(2, 255), 19); $this->params['l'] = gmp_add(gmp_pow(2, 252), '27742317777372353535851937790883648493'); $this->params['d'] = gmp_mul(-121665, $this->inv(121666)); $this->params['I'] = gmp_powm(2, gmp_div_q(gmp_sub($this->params['q'], 1), 4), $this->params['q']); $By = gmp_mul(4, $this->inv(5)); $Bx = $this->xrecover($By); $this->params['B'] = array($Bx, $By); }
/** * @dataProvider providerTestTAGLong */ public function testPutTAGLong($value) { $fPtr = fopen($this->vFile->url(), 'wb'); // 32-bit longs seem to be too long for pack() on 32-bit machines. Split into 4x16-bit instead. $quarters[0] = gmp_div(gmp_and($value, '0xFFFF000000000000'), gmp_pow(2, 48)); $quarters[1] = gmp_div(gmp_and($value, '0x0000FFFF00000000'), gmp_pow(2, 32)); $quarters[2] = gmp_div(gmp_and($value, '0x00000000FFFF0000'), gmp_pow(2, 16)); $quarters[3] = gmp_and($value, '0xFFFF'); $binary = pack('nnnn', gmp_intval($quarters[0]), gmp_intval($quarters[1]), gmp_intval($quarters[2]), gmp_intval($quarters[3])); $this->dataHandler->putTAGLong($fPtr, $value); $this->assertSame($binary, $this->vFile->getContent()); }
public function provideNumbase() { $symbols = '0123456789' . 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' . 'abcdefghijklmnopqrstuvwxyz'; $numbases = array(array(Numbase::createDefault()), array(Numbase::createDefault(new StringSymbols($symbols))), array(Numbase::createDefault(new ArraySymbols(str_split($symbols, 1))))); $numbers = array(array(gmp_strval(gmp_pow(10, 9), 10), 10, 1000000000, '10'), array(gmp_strval(gmp_pow(10, 1000), 10), 10, 100, '1' . str_pad('', 500, '0', STR_PAD_RIGHT)), array('10000000000000000000000', 10, 100, '100000000000'), array('15', 10, 16, 'F'), array('zz', 62, 10, '3843'), array('3843', 10, 62, 'zz'), array('-3843', 10, 62, '-zz'), array('100000', 10, 62, 'Q0u'), array('3843', 10, 16, 'F03'), array('65', 10, 2, '1000001'), array('1', 10, 10, '1'), array('0', 16, 2, '0'), array('64000', 10, 32000, '20')); $result = array(); foreach ($numbers as $number) { foreach ($numbases as $numbase) { $result[] = array_merge($numbase, $number); } } return $result; }
function number62_decode($string) { if (preg_match('#^[a-zA-Z0-9]+$#iu', $string) == 0) { return 0; } $out = 0; $length = mb_strlen($string); $array = array_flip(str_split("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")); for ($i = 0; $i < $length; $i++) { $out = gmp_add($out, gmp_mul($array[$string[$length - $i - 1]], gmp_pow(62, $i))); } $out = gmp_strval($out, 10); return $out; }
public function contains($x, $y) { $eq_zero = null; if (extension_loaded('gmp') && USE_EXT == 'GMP') { $eq_zero = gmp_cmp(gmp_Utils::gmp_mod2(gmp_sub(gmp_pow($y, 2), gmp_add(gmp_add(gmp_pow($x, 3), gmp_mul($this->a, $x)), $this->b)), $this->prime), 0); if ($eq_zero == 0) { return true; } else { return false; } } else { throw new ErrorException("Please install GMP"); } }
function recoverPubKey($r, $s, $e, $recoveryFlags, $G) { $isYEven = ($recoveryFlags & 1) != 0; $isSecondKey = ($recoveryFlags & 2) != 0; $curve = $G->getCurve(); $signature = new Signature($r, $s); // Precalculate (p + 1) / 4 where p is the field order static $p_over_four; // XXX just assuming only one curve/prime will be used if (!$p_over_four) { $p_over_four = gmp_div(gmp_add($curve->getPrime(), 1), 4); } // 1.1 Compute x if (!$isSecondKey) { $x = $r; } else { $x = gmp_add($r, $G->getOrder()); } // 1.3 Convert x to point $alpha = gmp_mod(gmp_add(gmp_add(gmp_pow($x, 3), gmp_mul($curve->getA(), $x)), $curve->getB()), $curve->getPrime()); $beta = NumberTheory::modular_exp($alpha, $p_over_four, $curve->getPrime()); // If beta is even, but y isn't or vice versa, then convert it, // otherwise we're done and y == beta. if (isBignumEven($beta) == $isYEven) { $y = gmp_sub($curve->getPrime(), $beta); } else { $y = $beta; } // 1.4 Check that nR is at infinity (implicitly done in construtor) $R = new Point($curve, $x, $y, $G->getOrder()); $point_negate = function ($p) { return new Point($p->curve, $p->x, gmp_neg($p->y), $p->order); }; // 1.6.1 Compute a candidate public key Q = r^-1 (sR - eG) $rInv = NumberTheory::inverse_mod($r, $G->getOrder()); $eGNeg = $point_negate(Point::mul($e, $G)); $Q = Point::mul($rInv, Point::add(Point::mul($s, $R), $eGNeg)); // 1.6.2 Test Q as a public key $Qk = new PublicKey($G, $Q); if ($Qk->verifies($e, $signature)) { return $Qk; } return false; }
/** * Exponential expression / raise number into power * * @uses function_exists() * @uses bcpow() * @uses gmp_pow() * @uses gmp_strval() * @uses pow() * @param number $base * @param number $exp * @param string pow function use, or false for auto-detect * @return mixed string or float */ function PMA_pow($base, $exp, $use_function = false) { static $pow_function = null; if (null == $pow_function) { if (function_exists('bcpow')) { // BCMath Arbitrary Precision Mathematics Function $pow_function = 'bcpow'; } elseif (function_exists('gmp_pow')) { // GMP Function $pow_function = 'gmp_pow'; } else { // PHP function $pow_function = 'pow'; } } if (! $use_function) { $use_function = $pow_function; } if ($exp < 0 && 'pow' != $use_function) { return false; } switch ($use_function) { case 'bcpow' : // bcscale() needed for testing PMA_pow() with base values < 1 bcscale(10); $pow = bcpow($base, $exp); break; case 'gmp_pow' : $pow = gmp_strval(gmp_pow($base, $exp)); break; case 'pow' : $base = (float) $base; $exp = (int) $exp; $pow = pow($base, $exp); break; default: $pow = $use_function($base, $exp); } return $pow; }
function deskripsi($chiper, $d, $n) { $time_start = microtime(true); //Pesan Enkripsi dipecah menjadi array dengan batasan "+" $hasildekrip = ''; $hasil = ''; $dekrip = explode(" ", $chiper); foreach ($dekrip as $nilai) { //Rumus Deskripsi ---> PlainTeks = <enkripsi>^<d>mod<n> $gm1 = gmp_pow($nilai, gmp_strval($d)); $gm2 = gmp_mod($gm1, $n); $gm3 = gmp_strval($gm2); $hasildekrip .= chr($gm3); } $time_end = microtime(true); // Waktu Eksekusi $time = $time_end - $time_start; $hasil = array($time, $hasildekrip); return $hasil; }
function base58_decode($string) { $table = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'; static $table_rev = null; if (is_null($table_rev)) { $table_rev = array(); for ($i = 0; $i < 58; ++$i) { $table_rev[$table[$i]] = $i; } } $l = strlen($string); $long_value = gmp_init('0'); for ($i = 0; $i < $l; ++$i) { $c = $string[$l - $i - 1]; $long_value = gmp_add($long_value, gmp_mul($table_rev[$c], gmp_pow(58, $i))); } // php is lacking binary output for gmp $res = pack('H*', gmp_strval($long_value, 16)); for ($nPad = 0; $string[$nPad] == $table[0]; ++$nPad) { } return str_repeat("", $nPad) . $res; }
/** * Calculate Wang hash for 64bit unsigned integer using GMP library * PHP only supports signed integers even with 64bit version * * See <code/nel/include/nel/misc/wang_hash.h> on https://bitbucket.org/ryzom/ryzomcore * * @param string $key * * @return string hash */ function wang_hash64($key) { // force $key to be base 10 $key = gmp_init($key, 10); //$key = (~$key) + ($key << 21); $key = gmp_add(gmp_com($key), gmp_mul($key, 1 << 21)); //$key = $key ^ ($key >> 24); $key = gmp_xor($key, gmp_div($key, 1 << 24)); //$key = $key * 265; $key = gmp_mul($key, 265); //$key = $key ^ ($key >> 14); $key = gmp_xor($key, gmp_div($key, 1 << 14)); //$key = $key * 21; $key = gmp_mul($key, 21); //$key = $key ^ ($key >> 28); $key = gmp_xor($key, gmp_div($key, 1 << 28)); //$key = $key + ($key << 31); $key = gmp_add($key, gmp_mul($key, gmp_pow(2, 31))); // limit to 64bit $key = gmp_and($key, "0xFFFFFFFFFFFFFFFF"); return gmp_strval($key, 10); }
/** * @param string $octets * * @throws InvalidArgumentException if the given octets represent a malformed base-128 value or the decoded value would exceed the the maximum integer length * * @return int */ public static function decode($octets) { $bitsPerOctet = 7; $value = gmp_init(0, 10); $i = 0; $leftShift = function ($number, $positions) { return gmp_mul($number, gmp_pow(2, $positions)); }; while (true) { if (!isset($octets[$i])) { throw new InvalidArgumentException(sprintf('Malformed base-128 encoded value (0x%s).', strtoupper(bin2hex($octets)) ?: '0')); } $octet = gmp_init(ord($octets[$i++]), 10); $l1 = $leftShift($value, $bitsPerOctet); $r1 = gmp_and($octet, 0x7f); $value = gmp_add($l1, $r1); if (0 === gmp_cmp(gmp_and($octet, 0x80), 0)) { break; } } return gmp_strval($value); }
/** * @param string $left_operand * @param string $right_operand * @return string */ public function pow($left_operand, $right_operand) { $result = gmp_pow($left_operand, $right_operand); return gmp_strval($result); }
public static function double(Point $p1) { $p = $p1->curve->prime; $a = $p1->curve->a; $inverse = gmp_invert(gmp_mul(2, $p1->y), $p); $three_x2 = gmp_mul(3, gmp_pow($p1->x, 2)); $l = gmp_mod(gmp_mul(gmp_add($three_x2, $a), $inverse), $p); $x3 = gmp_mod(gmp_sub(gmp_pow($l, 2), gmp_mul(2, $p1->x)), $p); $y3 = gmp_mod(gmp_sub(gmp_mul($l, gmp_sub($p1->x, $x3)), $p1->y), $p); if (gmp_cmp(0, $y3) > 0) { $y3 = gmp_add($p, $y3); } return new Point($p1->curve, $x3, $y3); }
function gmp_shiftr($x, $n) { return gmp_div($x, gmp_pow(2, $n)); }
/** * Logical Left Shift * * Shifts BigInteger's by $shift bits, effectively multiplying by 2**$shift. * * @param int $shift * @return Math_BigInteger * @access public * @internal The only version that yields any speed increases is the internal version. */ function bitwise_leftShift($shift) { $temp = new Math_BigInteger(); switch (MATH_BIGINTEGER_MODE) { case MATH_BIGINTEGER_MODE_GMP: static $two; if (!isset($two)) { $two = gmp_init('2'); } $temp->value = gmp_mul($this->value, gmp_pow($two, $shift)); break; case MATH_BIGINTEGER_MODE_BCMATH: $temp->value = bcmul($this->value, bcpow('2', $shift, 0), 0); break; default: // could just replace _rshift with this, but then all _lshift() calls would need to be rewritten // and I don't want to do that... $temp->value = $this->value; $temp->_lshift($shift); } return $this->_normalize($temp); }
/** * Raise one number to the power of the other, utilize Math extensions * * @param mixed a First operand * @param mixed b Second operand * @return mixed * @access private */ function _pow($a, $b) { switch (MATH_BASEX_MATHEXTENSION) { case 'bcmath': return bcpow($a, $b); case 'gmp': return gmp_strval(gmp_pow($a, $b)); case 'none': return pow($a, $b); } }
/** * Reformat incomplete IPv6 address to decimal for search! */ function reformatIPv6forSearch($ip) { //split network and subnet part $ip = explode("/", $ip); //if subnet is not provided we are looking for host! if (sizeof($ip) < 2) { $return['low'] = Transform2decimal($ip[0]); $return['high'] = Transform2decimal($ip[0]); } //if network part ends with :: we must search the complete provided subnet! $lastChars = substr($ip[0], -2); if ($lastChars == "::") { $return['low'] = Transform2decimal($ip[0]); //set highest IP address $subnet = substr($ip[0], 0, -2); $subnet = Transform2decimal($subnet); //calculate all possible hosts in subnet mask $maskHosts = gmp_strval(gmp_sub(gmp_pow(2, 128 - $ip[1]), 1)); $return['high'] = gmp_strval(gmp_add($return['low'], $maskHosts)); } return $return; }
protected function subtraction($A, $B, $radix) { $a = gmp_init($A, $radix); $b = gmp_init($B, $radix); // Prevent negative values if (gmp_cmp($a, $b) < 0) { $a = gmp_add($a, gmp_pow($radix, strlen($A))); } // Block-wise subtraction return $this->fixedLength(gmp_strval(gmp_sub($a, $b), $radix), strlen($A), '0'); }
public function import() { /*{{{*/ if (extension_loaded('xhprof')) { // xhprof slows things down xhprof_disable(); } if (!extension_loaded('gmp')) { throw new Exception('The blockchain importer requires the PHP GMP module to be installed and enabled'); } echo "\nTodo:\n\n* add Output_Key join table to support multisig, convert data, then re-import all multisig transactions\n* detect if PHP is 64-bit, if not, check if GMP is installed, otherwise us BCMath\n - ACTUALLY, just move to PHPSECLIB: http://phpseclib.sourceforge.net/math/intro.html \n* move RPC calls into separate class\n* move bitcoin specific utils into separate class\n* move conversion from satoshis to floats into view model\n* fix trailing decimal point on whole numbers in block and blockchain views\n\nMaybe:\n\n* move entities to model binder?\n"; sleep(1); // this can take a long time set_time_limit(0); $client = new \Zend\Json\Server\Client($this->bitcoindServerUrl); $client->getHttpClient()->setOptions(array('timeout' => 30)); $blockcount = $client->call('getblockcount'); // Get the last block in the DB $query = $this->objectManager->createQuery('SELECT b FROM Blockchain\\Entity\\Block b WHERE b.id = (SELECT MAX(bm.id) FROM Blockchain\\Entity\\Block bm)'); $result = $query->getResult(); if (count($result) == 1) { $blockEntity = $result[0]; $blockId = $blockEntity->getId(); $blockhash = $blockEntity->getBlockhash(); $blockNumber = $blockEntity->getBlockNumber(); $block = $this->getBlockFromServer($blockhash); // remove last block and all associated transactions in case it wasn't loaded full or there was no "nextblockhash" $connection = $this->objectManager->getConnection(); if ($connection->getDatabasePlatform()->getName() == 'mysql') { // The input and output tables have cyclical foreign keys, so rows can't be deleted $connection->query('SET FOREIGN_KEY_CHECKS=0'); } $this->objectManager->remove($blockEntity); $this->objectManager->flush(); if ($connection->getDatabasePlatform()->getName() == 'mysql') { $connection->query('SET FOREIGN_KEY_CHECKS=1'); } $coinbaseExp = floor($blockNumber / 210000); $gmp_coinbaseValue = gmp_div_q(gmp_init("5000000000"), gmp_pow(gmp_init("2"), $coinbaseExp)); } else { $blockNumber = 0; $blockhash = $client->call('getblockhash', array($blockNumber)); $gmp_coinbaseValue = gmp_init("5000000000"); } $batchSize = 25; $count = 0; // Start importing $lastTime = 0; $currTime = 0; $avgTime = 0; $blockCount = 0; while ($blockhash) { $currTime = microtime(true); if ($lastTime) { $diff = $currTime - $lastTime; // update average time between blocks $avgTime = ($avgTime * ($blockCount - 1) + $diff) / $blockCount; $blocksLeft = $blockcount - $blockNumber; $estimatedCompletion = $blocksLeft * $avgTime; echo sprintf("\n\nEstimated completion: %s (blocks left: %d, average block time: %s seconds\n", self::secondsToString($estimatedCompletion), $blocksLeft, number_format($avgTime, 2)); } if ($blockNumber % 210000 == 0) { // only calculate this when necessary instead of every loop $coinbaseExp = floor($blockNumber / 210000); $gmp_coinbaseValue = gmp_div_q(gmp_init("5000000000"), gmp_pow(gmp_init("2"), $coinbaseExp)); } echo "\nBlock {$blockNumber}, Transactions: "; $gmp_totalBlockValue = gmp_init("0"); $block = $this->getBlockFromServer($blockhash); $blockEntity = new \Blockchain\Entity\Block(); $blockEntity->setBlockNumber($blockNumber); $blockEntity->setBlockhash($block['hash']); $blockEntity->setSize($block['size']); $blockEntity->setHeight($block['height']); $blockEntity->setVersion($block['version']); $blockEntity->setMerkleroot($block['merkleroot']); $blockEntity->setTime(new \DateTime('@' . $block['time'])); $blockEntity->setNonce($block['nonce']); $blockEntity->setBits($block['bits']); $blockEntity->setDifficulty($block['difficulty']); if (isset($block['nextblockhash'])) { $blockEntity->setNextblockhash($block['nextblockhash']); } if (isset($block['previousblockhash'])) { $blockEntity->setPreviousblockhash($block['previousblockhash']); } $this->objectManager->persist($blockEntity); $count++; $gmp_offeredFees = gmp_init("0"); $gmp_takenFees = gmp_init("0"); // First block is unique if ($blockNumber > 0) { $seenTxids = array(); $seenAddresses = array(); $txCount = 0; foreach ($block['tx'] as $txid) { $txCount++; if ($txCount > 1) { echo ', '; } echo $txCount; // the JSON RPC client appears to have a memory leak, so isolate it inside a function $transaction = $this->getRawTransactionFromServer($txid); if (!$transaction) { die('failure retrieving transaction'); } if ($blockNumber == 91842 && $transaction['txid'] == 'd5d27987d2a3dfc724e359870c6644b40e497bdc0589a033220fe15429d88599') { // Special case where a transaction was duplicated in block 91812 and 91842 due to a bug in a mining client // ignore the second instance continue; } if ($blockNumber == 91880 && $transaction['txid'] == 'e3bf3d07d4b0375638d5f1db5255fe07ba2c4cb067cd81b84ee974b6585fb468') { // Special case where a transaction was duplicated in block 91722 and 91880 due to a bug in a mining client // ignore the second instance continue; } $transactionEntity = new \Blockchain\Entity\Transaction(); $transactionEntity->setTxid($transaction['txid']); $transactionEntity->setBlockhash($blockhash); $transactionEntity->setBlock($blockEntity); $transactionEntity->setVersion($transaction['version']); $transactionEntity->setLocktime($transaction['locktime']); $transactionEntity->setSize($transaction['size']); $this->objectManager->persist($transactionEntity); $count++; $gmp_totalInputValue = gmp_init("0"); foreach ($transaction['vin'] as $input) { $inputEntity = new \Blockchain\Entity\Input(); $inputEntity->setTxid($txid); $inputEntity->setSequence($input['sequence']); if (isset($input['coinbase'])) { $inputEntity->setCoinbase($input['coinbase']); $inputEntity->setValue(gmp_strval($gmp_coinbaseValue)); $gmp_totalInputValue = gmp_add($gmp_totalInputValue, $gmp_coinbaseValue); } else { if (isset($seenTxids[$input['txid']])) { // input of one transaction is referencing the output of another transaction in the same block. flush writes. $this->objectManager->flush(); // clear objects to free memory $this->objectManager->clear(); // reload associated entities $blockEntity = $this->objectManager->getRepository('Blockchain\\Entity\\Block')->findOneBy(array('blockhash' => $blockhash)); $transactionEntity = $this->objectManager->getRepository('Blockchain\\Entity\\Transaction')->findOneBy(array('txid' => $txid)); } $inputEntity->setRedeemedTxid($input['txid']); $inputEntity->setScriptSigAsm($input['scriptSig']['asm']); $inputEntity->setScriptSigHex($input['scriptSig']['hex']); $inputEntity->setVout($input['vout']); $redeemedOutputEntity = $this->objectManager->getRepository('Blockchain\\Entity\\Output')->findOneBy(array('txid' => $input['txid'], 'n' => $input['vout'])); if (!$redeemedOutputEntity) { die('could not find output'); } $nonstandard = false; $pubkey = null; $hash160 = null; $address = null; $keyEntity = null; if (preg_match('/(.+) (.+)/', $input['scriptSig']['asm'], $matches)) { // Standard Transaction to Bitcoin address (pay-to-pubkey-hash) // scriptPubKey: OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG // scriptSig: <sig> <pubKey> $signature = $matches[1]; $pubkey = $matches[2]; $hash160 = self::pubkeyToHash160($pubkey); $address = self::hash160ToAddress($hash160); } else { if ($redeemedOutputEntity->getType() == 'nonstandard') { $nonstandard = true; echo "...nonstandard output, scriptsig: " . $input['scriptSig']['asm'] . "..."; $redeemedOutputKeyEntity = $redeemedOutputEntity->getKey(); if ($redeemedOutputKeyEntity) { $pubkey = $redeemedOutputKeyEntity->getPubkey(); $hash160 = $redeemedOutputKeyEntity->getHash160(); $address = $redeemedOutputKeyEntity->getAddress(); } } else { if (preg_match('/([\\S]+)/', $input['scriptSig']['asm'])) { // Standard Generation Transaction (pay-to-pubkey) // scriptPubKey: <pubKey> OP_CHECKSIG // scriptSig: <sig> $redeemedOutputKeyEntity = $redeemedOutputEntity->getKey(); if ($redeemedOutputKeyEntity) { $pubkey = $redeemedOutputKeyEntity->getPubkey(); $hash160 = $redeemedOutputKeyEntity->getHash160(); $address = $redeemedOutputKeyEntity->getAddress(); } else { echo "\n\n" . $input['scriptSig']['asm'] . "\n"; die("\nStandard Generation without key\n"); } } else { die("strange scriptSig: " . $input['scriptSig']['asm'] . "\n"); } } } $keyEntity = $this->objectManager->getRepository('Blockchain\\Entity\\Key')->findOneBy(array('address' => $address)); if (!$keyEntity) { if ($address && !isset($seenAddresses[$address])) { $keyEntity = new \Blockchain\Entity\Key(); $keyEntity->setPubkey($pubkey); $keyEntity->setHash160($hash160); $keyEntity->setAddress($address); $keyEntity->setFirstblockhash($blockhash); $keyEntity->setFirstblock($blockEntity); $seenAddresses[$address] = array('pubkey' => $pubkey); } else { $this->objectManager->flush(); $keyEntity = $this->objectManager->getRepository('Blockchain\\Entity\\Key')->findOneBy(array('address' => $address)); } } if (!$keyEntity && !$nonstandard) { die("problem finding input key: {$address}\n"); } if ($keyEntity) { if ($pubkey && !$keyEntity->getPubkey()) { $keyEntity->setPubkey($pubkey); } $this->objectManager->persist($keyEntity); $inputEntity->setKey($keyEntity); } $inputEntity->setHash160($hash160); $inputEntity->setAddress($address); $gmp_inputValue = gmp_init($redeemedOutputEntity->getValue()); $inputEntity->setValue(gmp_strval($gmp_inputValue)); $inputEntity->setAddress($redeemedOutputEntity->getAddress()); $inputEntity->setRedeemedOutput($redeemedOutputEntity); $redeemedOutputEntity->setRedeemingInput($inputEntity); $this->objectManager->persist($redeemedOutputEntity); $gmp_totalInputValue = gmp_add($gmp_totalInputValue, gmp_init($inputEntity->getValue())); // echo 'txid: '.$txid.', input txid: '.$input['txid'].', vout: '.$input['vout'].", val: ".gmp_strval($gmp_inputValue)."\n"; // Need to figure out how to extract hash160, if it is of any value... // $inputEntity->setHash160(); } $inputEntity->setTransaction($transactionEntity); $this->objectManager->persist($inputEntity); $count++; } $gmp_totalBlockValue = gmp_add($gmp_totalBlockValue, $gmp_totalInputValue); $gmp_totalOutputValue = gmp_init("0"); foreach ($transaction['vout'] as $output) { $outputEntity = new \Blockchain\Entity\Output(); $outputEntity->setTxid($txid); $outputEntity->setN($output['n']); $gmp_outputValue = self::floatBTCToGmpSatoshis($output['value']); $outputEntity->setValue(gmp_strval($gmp_outputValue)); $gmp_totalOutputValue = gmp_add($gmp_totalOutputValue, $gmp_outputValue); $outputEntity->setScriptPubKeyAsm($output['scriptPubKey']['asm']); $outputEntity->setScriptPubKeyHex($output['scriptPubKey']['hex']); $pubkey = null; $hash160 = null; $address = null; if (preg_match('/OP_DUP OP_HASH160 ([\\S]+) OP_EQUALVERIFY OP_CHECKSIG/', $output['scriptPubKey']['asm'], $matches)) { $hash160 = $matches[1]; $address = self::hash160ToAddress($hash160); } else { if (preg_match('/^([\\S]+) OP_CHECKSIG$/', $output['scriptPubKey']['asm'], $matches)) { $pubkey = $matches[1]; $hash160 = self::pubkeyToHash160($pubkey); $address = self::hash160ToAddress($hash160); } } $keyEntity = null; if ($address) { $keyEntity = $this->objectManager->getRepository('Blockchain\\Entity\\Key')->findOneBy(array('address' => $address)); if (!$keyEntity) { if (!isset($seenAddresses[$address])) { $keyEntity = new \Blockchain\Entity\Key(); $keyEntity->setPubkey($pubkey); $keyEntity->setHash160($hash160); $keyEntity->setAddress($address); $keyEntity->setFirstblockhash($blockhash); $keyEntity->setFirstblock($blockEntity); $seenAddresses[$address] = array('pubkey' => $pubkey); } else { $this->objectManager->flush(); $keyEntity = $this->objectManager->getRepository('Blockchain\\Entity\\Key')->findOneBy(array('address' => $address)); } } if ($keyEntity) { if ($pubkey && !$keyEntity->getPubkey()) { $keyEntity->setPubkey($pubkey); } $this->objectManager->persist($keyEntity); $outputEntity->setKey($keyEntity); } if (!$keyEntity && $pubkey && !$seenAddresses[$address]['pubkey']) { die("Situation: address seen multiple times in transaction, and pubkey available\n"); } } if ($address && !$keyEntity) { die("Output key entity not generated: {$address}\n"); } $outputEntity->setHash160($hash160); if (isset($output['scriptPubKey']['reqSigs'])) { $outputEntity->setReqSigs($output['scriptPubKey']['reqSigs']); } $outputEntity->setType($output['scriptPubKey']['type']); if (count($output['scriptPubKey']['addresses']) > 1) { echo "\n\noutput with multiple addresses found:\n"; echo print_r($output, true); echo "\n"; } else { if (isset($output['scriptPubKey']['addresses'][0]) && $address != $output['scriptPubKey']['addresses'][0]) { echo $output['scriptPubKey']['asm'] . "\n"; die("inconsistent output addresses\n parsed: {$address}\n given: {$output['scriptPubKey']['addresses'][0]}\n"); } } $outputEntity->setAddress($output['scriptPubKey']['addresses'][0]); $outputEntity->setHash160($hash160); $outputEntity->setTransaction($transactionEntity); $this->objectManager->persist($outputEntity); $count++; } if (isset($input['coinbase'])) { $gmp_takenFees = gmp_sub($gmp_totalOutputValue, $gmp_coinbaseValue); } if (!isset($input['coinbase'])) { $gmp_fee = gmp_sub($gmp_totalInputValue, $gmp_totalOutputValue); $gmp_offeredFees = gmp_add($gmp_offeredFees, $gmp_fee); } else { $gmp_fee = gmp_init("0"); } $transactionEntity->setFee(gmp_strval($gmp_fee)); $transactionEntity->setTotalIn(gmp_strval($gmp_totalInputValue)); $transactionEntity->setTotalOut(gmp_strval($gmp_totalOutputValue)); $this->objectManager->persist($transactionEntity); $count++; $seenTxids[$txid] = true; if ($count % $batchSize == 0) { $this->objectManager->flush(); $this->objectManager->clear(); $blockEntity = $this->objectManager->getRepository('Blockchain\\Entity\\Block')->findOneBy(array('blockhash' => $blockhash)); } } } if (gmp_cmp($gmp_offeredFees, $gmp_takenFees) > 0) { echo "WARNING: Possible lost coins. Offered Fees: " . gmp_strval($gmp_offeredFees) . ", Taken Fees: " . gmp_strval($gmp_takenFees) . "\n"; } if (gmp_cmp($gmp_takenFees, $gmp_offeredFees) > 0) { die("ERROR. Impossible transaction: Offered Fees: " . gmp_strval($gmp_offeredFees) . ", Taken Fees: " . gmp_strval($gmp_takenFees) . "\n"); } $blockEntity->setOfferedFees(gmp_strval($gmp_offeredFees)); $blockEntity->setTakenFees(gmp_strval($gmp_takenFees)); $blockEntity->setTotalvalue(gmp_strval($gmp_totalBlockValue)); $gmp_lostValue = gmp_sub($gmp_offeredFees, $gmp_takenFees); $blockEntity->setLostvalue(gmp_strval($gmp_lostValue)); $this->objectManager->persist($blockEntity); $count++; if (isset($block['nextblockhash'])) { $nextblockhash = $block['nextblockhash']; } else { $nextblockhash = null; } $this->objectManager->flush(); $this->objectManager->clear(); $blockhash = $nextblockhash; $blockNumber++; $blockCount++; $lastTime = $currTime; } }
public static function double(Point $p1) { if (extension_loaded('gmp') && USE_EXT == 'GMP') { $p = $p1->curve->getPrime(); $a = $p1->curve->getA(); // $inverse = NumberTheory::inverse_mod(gmp_strval(gmp_mul(2, $p1->y)), $p); $inverse = gmp_strval(gmp_invert(gmp_strval(gmp_mul(2, $p1->y)), $p)); $three_x2 = gmp_mul(3, gmp_pow($p1->x, 2)); $l = gmp_strval(gmp_Utils::gmp_mod2(gmp_mul(gmp_add($three_x2, $a), $inverse), $p)); $x3 = gmp_strval(gmp_Utils::gmp_mod2(gmp_sub(gmp_pow($l, 2), gmp_mul(2, $p1->x)), $p)); $y3 = gmp_strval(gmp_Utils::gmp_mod2(gmp_sub(gmp_mul($l, gmp_sub($p1->x, $x3)), $p1->y), $p)); if (gmp_cmp(0, $y3) > 0) { $y3 = gmp_strval(gmp_add($p, $y3)); } $p3 = new Point($p1->curve, $x3, $y3); return $p3; } else { throw new ErrorException("Please install GMP"); } }