|
|
<?php
|
|
|
|
|
|
class block
|
|
|
{
|
|
|
public $hash = null;
|
|
|
public $height = null;
|
|
|
public $name = null;
|
|
|
public $desc = null;
|
|
|
|
|
|
function __construct($ahash, $aheight, $aname = null, $adesc = null)
|
|
|
{
|
|
|
$this->hash = $ahash;
|
|
|
$this->height = $aheight;
|
|
|
$this->name = $aname;
|
|
|
$this->desc = $adesc;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
class blockchain
|
|
|
{
|
|
|
private static $url_info = 'https://blockchain.info/';
|
|
|
private static $offline_block = OFFLINE_PATH.'/offline_block.zip';
|
|
|
/*
|
|
|
* Liste de blocks spéciaux dans l'histoire du Bitcoin
|
|
|
*
|
|
|
* 'GENESIS' - Premier block de la blochain
|
|
|
* 'THE_ANSWER' - Block 42 (pour le fun)
|
|
|
* 'HAL_FINLEY' - Hal Finley has mined this block
|
|
|
* 'FIRST_TX' - First exchange between Satoshi and Hal Finley
|
|
|
* 'LUCIFER' - Block 666 (pour le fun)
|
|
|
* 'LEET' - Block 1337 (pour le fun)
|
|
|
* 'FISRT_USD_TX' - Martti Malmi change 5000 BTC for 5,02 $
|
|
|
* 'PIZZA' - Block 57035 : le block du pizza day, 22 05 2010
|
|
|
* 'HALVING_1' - First halving, block 2100000, 28 11 2012
|
|
|
* 'HALVING_2' - Second halving, block 420000, 09 07 2017
|
|
|
* 'BIP_91_LOCK' - Block 477120 : Verouillage du BIP 91, 23/07/2017
|
|
|
* 'BCC' - Block 478558 : Bitcoin Cash Fork 01/08/2017
|
|
|
* 'SEGWIT_LOCK' - Block 479808 SEGWIT est verrouillé 09 08 2017
|
|
|
* 'SEGWIT' - Block 481823 SEGWIT est activé 24 08 2017
|
|
|
* 'HALVING_3' - Third Hhalving, block 630000, 11 05 2020
|
|
|
* 'DORMEUR' - Block 631058 Une adresse datant de 2009 dépense ses 50 BTC de reward
|
|
|
* TX : cb1440c787d8a46977886405a34da89939e1b04907f567bf182ef27ce53a8d71
|
|
|
* 'SALVADOR' - BTC monnaie légale au Salvaldor 07 09 2021
|
|
|
* ____JUMP______ : Lorsque le cours atteint certains palier (à la hausse ou à la baisse)
|
|
|
* WHALE____ : Lorsqu'une baleine remonte respirer (grosse TX)
|
|
|
* GOLGOTH____ : Lorsque le GOLGOTH pousse fort ... (grosse TX)
|
|
|
*/
|
|
|
private static $special_blocks = null;
|
|
|
|
|
|
// ----
|
|
|
// -- Des fonctions outils
|
|
|
// -- Parce que depuis PHP.7.0.33-10, file_get_contents ne focnitonne plus en HTTPS
|
|
|
// ----
|
|
|
private static function get_curl_data($url)
|
|
|
{
|
|
|
$ch = curl_init();
|
|
|
$timeout = 5;
|
|
|
curl_setopt($ch,CURLOPT_URL,$url);
|
|
|
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
|
|
|
curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,$timeout);
|
|
|
$data = curl_exec($ch);
|
|
|
curl_close($ch);
|
|
|
return $data;
|
|
|
}
|
|
|
|
|
|
private static function get_data($url, $with_curl = true)
|
|
|
{
|
|
|
if (!$with_curl)
|
|
|
return file_get_contents($url);
|
|
|
|
|
|
return self::get_curl_data($url);
|
|
|
}
|
|
|
|
|
|
//
|
|
|
// Init special blocks array ...
|
|
|
//
|
|
|
public static function init_v1()
|
|
|
{
|
|
|
self::$special_blocks = array ();
|
|
|
|
|
|
self::$special_blocks[] = new block(
|
|
|
'00000000000000000001e6d99b42a2fe649591e7b97b1d4327e2bc3ade53d6d7',
|
|
|
772923,
|
|
|
'BERNIQUE'
|
|
|
);
|
|
|
|
|
|
self::$special_blocks[] = new block(
|
|
|
'00000000000000000001f5beb60d9ca47adf18db5136b558379ed533fc9f6c85',
|
|
|
753335,
|
|
|
'ELISABETH_2_HAS_DIED'
|
|
|
);
|
|
|
|
|
|
self::$special_blocks[] = new block(
|
|
|
'000000000000000000065676a19a2dfba0171b592d52f5ea7db54d45bb386400',
|
|
|
724697,
|
|
|
'UKRAINE'
|
|
|
);
|
|
|
|
|
|
self::$special_blocks[] = new block(
|
|
|
'000000000000000000031ec514b89bdac2c4786bbcc3a1a0acd1206f82181901',
|
|
|
718720,
|
|
|
'POITIERS'
|
|
|
);
|
|
|
|
|
|
self::$special_blocks[] = new block(
|
|
|
'00000000000000000000e55da58b378880e797f9f3e96811d3e64a2f801eed9a',
|
|
|
700700,
|
|
|
'BAB_BRUXELLES'
|
|
|
);
|
|
|
|
|
|
self::$special_blocks[] = new block(
|
|
|
'00000000000000000000bfade5b2979c3d47c6dd6a1e8ddf53380e8c3d736ce0',
|
|
|
699382,
|
|
|
'SALVADOR'
|
|
|
);
|
|
|
|
|
|
self::$special_blocks[] = new block(
|
|
|
'0000000000000000000b7b8574bc6fd285825ec2dbcbeca149121fc05b0c828c',
|
|
|
666666,
|
|
|
'MORNING_STAR'
|
|
|
);
|
|
|
|
|
|
self::$special_blocks[] = new block(
|
|
|
'000000000000000000070daa5861fe1e7064ef8007825431229c6c1cab2c766f',
|
|
|
654364,
|
|
|
'WHALE20201026'
|
|
|
);
|
|
|
|
|
|
self::$special_blocks[] = new block(
|
|
|
'00000000000000000005c0f74e8b00c3961d6dfbf32936edeaa300015949f3c4',
|
|
|
632676,
|
|
|
'2020JUMP10000'
|
|
|
);
|
|
|
|
|
|
self::$special_blocks[] = new block(
|
|
|
'00000000000000000000f811e171eee52157e9a95963140e62fa83610f23ea7e',
|
|
|
631058,
|
|
|
'DORMEUR'
|
|
|
);
|
|
|
|
|
|
self::$special_blocks[] = new block(
|
|
|
'000000000000000000024bead8df69990852c202db0e0097c1a12ea637d7e96d',
|
|
|
630000,
|
|
|
'HALVING_3'
|
|
|
);
|
|
|
|
|
|
self::$special_blocks[] = new block(
|
|
|
'0000000000000000001186079bbf9a5d945231236135af7a766bd34d814e7319',
|
|
|
628710,
|
|
|
'RIP_STEEVE'
|
|
|
);
|
|
|
|
|
|
self::$special_blocks[] = new block(
|
|
|
'000000000000000000099457d2aeb2b7fc8ad8adb1490814cb674dc5767ae9b9',
|
|
|
622453,
|
|
|
'COVID19'
|
|
|
);
|
|
|
|
|
|
self::$special_blocks[] = new block(
|
|
|
'00000000000000000001a3c68111789a6c2cc76f1209d1dae63b05460053eb2b',
|
|
|
619165,
|
|
|
'EQUILIBRE202002'
|
|
|
);
|
|
|
|
|
|
self::$special_blocks[] = new block(
|
|
|
'0000000000000000000f2306f08e8f34872a24dfaad3423801a91ee1626e9ea4',
|
|
|
618986,
|
|
|
'SOPHIA202002'
|
|
|
);
|
|
|
|
|
|
self::$special_blocks[] = new block(
|
|
|
'0000000000000000001085a869441fa2aa77f149a887af0ce59846ef51da6e4c',
|
|
|
616193,
|
|
|
'EQUILIBRE'
|
|
|
);
|
|
|
|
|
|
self::$special_blocks[] = new block(
|
|
|
'0000000000000000000b05f877e6e49b380f4f78b3cfb605b67439f825dba197',
|
|
|
613470,
|
|
|
'2020JUMP9000'
|
|
|
);
|
|
|
|
|
|
self::$special_blocks[] = new block(
|
|
|
'00000000000000000009e8fb4ac719a362c1c4e3df439740069ee58e2a713258',
|
|
|
612149,
|
|
|
'DEMISSION20200110'
|
|
|
);
|
|
|
|
|
|
self::$special_blocks[] = new block(
|
|
|
'000000000000000000051f84a7a1d0f5b2ddaf5682cbec5f7acb2bf5fa339725',
|
|
|
593879,
|
|
|
'GOLGOTH201909'
|
|
|
);
|
|
|
|
|
|
// 94 500 BTC, soit environ 1 milliards de dollars, 700 dollars de fees ...
|
|
|
self::$special_blocks[] = new block(
|
|
|
'00000000000000000014fcb29e6e3b0ead3bd2e307d7f619a935f1d5323e9013',
|
|
|
593468,
|
|
|
'WHALE201909'
|
|
|
);
|
|
|
|
|
|
self::$special_blocks[] = new block(
|
|
|
'0000000000000000000f9f2dadfb8f312572183272802cbfcc4ff95b4ee6777d',
|
|
|
545911,
|
|
|
'WHALE201810'
|
|
|
);
|
|
|
|
|
|
self::$special_blocks[] = new block(
|
|
|
'00000000000000000021e800c1e8df51b22c1588e5a624bea17e9faa34b2dc4a',
|
|
|
528249,
|
|
|
'BLOCK21E800'
|
|
|
);
|
|
|
|
|
|
self::$special_blocks[] = new block(
|
|
|
'0000000000000000000fe6d521a187a5523d5cef6f6c178923ff82ffe5a0f372',
|
|
|
506734,
|
|
|
'HURRICANE_1'
|
|
|
);
|
|
|
|
|
|
self::$special_blocks[] = new block(
|
|
|
'0000000000000000004b27f9ee7ba33d6f048f684aaeb0eea4befd80f1701126',
|
|
|
501726,
|
|
|
'NO_REWARD'
|
|
|
);
|
|
|
|
|
|
self::$special_blocks[] = new block(
|
|
|
'000000000000000000cbeff0b533f8e1189cf09dfbebf57a8ebe349362811b80',
|
|
|
481823,
|
|
|
'SEGWIT'
|
|
|
);
|
|
|
|
|
|
self::$special_blocks[] = new block(
|
|
|
'0000000000000000012e6060980c6475a9a8e62a1bf44b76c5d51f707d54522c',
|
|
|
479808,
|
|
|
'SEGWIT_LOCK'
|
|
|
);
|
|
|
|
|
|
self::$special_blocks[] = new block(
|
|
|
'00000000000000000019f112ec0a9982926f1258cdcc558dd7c3b7e5dc7fa148',
|
|
|
478559,
|
|
|
'BCC'
|
|
|
);
|
|
|
|
|
|
self::$special_blocks[] = new block(
|
|
|
'0000000000000000015411ca4b35f7b48ecab015b14de5627b647e262ba0ec40',
|
|
|
477120,
|
|
|
'BIP_91_LOCK'
|
|
|
);
|
|
|
|
|
|
self::$special_blocks[] = new block(
|
|
|
'000000000000000002cce816c0ab2c5c269cb081896b7dcb34b8422d6b74ffa1',
|
|
|
420000,
|
|
|
'HALVING_2'
|
|
|
);
|
|
|
|
|
|
self::$special_blocks[] = new block(
|
|
|
'0000000000000001bc7156dd1183c87859b326affa3a5cdd157e809537f0b284',
|
|
|
270953,
|
|
|
'WHALE201311'
|
|
|
);
|
|
|
|
|
|
self::$special_blocks[] = new block(
|
|
|
'000000000000048b95347e83192f69cf0366076336c639f9b7228e9ba171342e',
|
|
|
210000,
|
|
|
'HALVING_1'
|
|
|
);
|
|
|
|
|
|
self::$special_blocks[] = new block(
|
|
|
'000000000000041c718cd2fa4270ab80c917bb94caa79c84b417b7924a867a68',
|
|
|
196883,
|
|
|
'JOHN_CONWAY'
|
|
|
);
|
|
|
|
|
|
self::$special_blocks[] = new block(
|
|
|
'00000000152340ca42227603908689183edc47355204e7aca59383b0aaac1fd8',
|
|
|
57043,
|
|
|
'PIZZA'
|
|
|
);
|
|
|
|
|
|
self::$special_blocks[] = new block(
|
|
|
'00000000132fbe8314fc571c0be60b31ccd461c9ee85f42bde8c6d160a9dacc0',
|
|
|
24835,
|
|
|
'FIRST_USD_TX'
|
|
|
);
|
|
|
|
|
|
self::$special_blocks[] = new block(
|
|
|
'000000000a73e64735a2b75c97ea674950a9018da1420d01328a918c9ff9852c',
|
|
|
5637,
|
|
|
'TOPISTO'
|
|
|
);
|
|
|
|
|
|
self::$special_blocks[] = new block(
|
|
|
'00000000a70ba4a405c67310757606dd955cf1a3a8e5c042335d78394ea6cb67',
|
|
|
3654,
|
|
|
'DORMEUR_ORIGINE'
|
|
|
);
|
|
|
|
|
|
self::$special_blocks[] = new block(
|
|
|
'000000008bf44a528a09d203203a6a97c165cf53a92ecc27aed0b49b86a19564',
|
|
|
1337,
|
|
|
'LEET'
|
|
|
);
|
|
|
|
|
|
self::$special_blocks[] = new block(
|
|
|
'00000000fc5b3c76f27f810ee775e480ae7fd604fd196b2d8da4257fcd39f4f9',
|
|
|
666,
|
|
|
'LUCIFER'
|
|
|
);
|
|
|
|
|
|
self::$special_blocks[] = new block(
|
|
|
'00000000d1145790a8694403d4063f323d499e655c83426834d4ce2f8dd4a2ee',
|
|
|
170,
|
|
|
'FIRST_TX'
|
|
|
);
|
|
|
|
|
|
self::$special_blocks[] = new block(
|
|
|
'00000000a2886c95400fd3b263b9920af80b118b28fee5d2a162a18e4d9d8b2f',
|
|
|
78,
|
|
|
'HAL_FINLEY'
|
|
|
);
|
|
|
|
|
|
self::$special_blocks[] = new block(
|
|
|
'00000000314e90489514c787d615cea50003af2023796ccdd085b6bcc1fa28f5',
|
|
|
42,
|
|
|
'THE_ANSWER'
|
|
|
);
|
|
|
|
|
|
self::$special_blocks[] = new block(
|
|
|
'000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f',
|
|
|
0,
|
|
|
'GENESIS'
|
|
|
);
|
|
|
}
|
|
|
public static function init_v2()
|
|
|
{
|
|
|
$path = APP_PATH.'/blockchain/data/blocks.json';
|
|
|
$jsonString = file_get_contents($path);
|
|
|
self::$special_blocks = json_decode($jsonString, true);
|
|
|
}
|
|
|
public static function init(){
|
|
|
self::init_v2();
|
|
|
}
|
|
|
|
|
|
|
|
|
// ---
|
|
|
// --- Retourne le JSON du tableau des blocs speciaux
|
|
|
// ---
|
|
|
public static function getSpecialBlocksJSON()
|
|
|
{
|
|
|
return json_encode(self::$special_blocks);
|
|
|
}
|
|
|
|
|
|
// ---
|
|
|
// --- Retourne le nom d'un block à partir de son hash
|
|
|
// --- si ce n'est pas un block special, on renvoie le hash
|
|
|
// ---
|
|
|
public static function hash2SpecialName($block_hash)
|
|
|
{
|
|
|
foreach(self::$special_blocks as $value)
|
|
|
if ($block_hash == $value->hash) return $value->name;
|
|
|
|
|
|
return $block_hash;
|
|
|
}
|
|
|
|
|
|
// ---
|
|
|
// --- Accès aux blocks spéciaux
|
|
|
// --- On en rajoute un : le LAST block
|
|
|
// --- En fait toute valeur ne faisant pas partie des blocks connus
|
|
|
// ---
|
|
|
public static function getSpecialBlock($nom_du_block)
|
|
|
{
|
|
|
$block_hash = '';
|
|
|
|
|
|
foreach(self::$special_blocks as $value)
|
|
|
{
|
|
|
if ($nom_du_block == $value->name)
|
|
|
{
|
|
|
$block_hash = $value->hash;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (file_exists(self::$offline_block)) $block_hash = 'offline';
|
|
|
|
|
|
if ($block_hash == '') $block_hash = self::getLastBlockHash();
|
|
|
|
|
|
return self::getBlockWithHash($block_hash);
|
|
|
}
|
|
|
|
|
|
// ---
|
|
|
// --- Accès au dernier block en cache ...
|
|
|
// ---
|
|
|
public static function getLastCacheBlockHash()
|
|
|
{
|
|
|
// on commence par le cache d'images
|
|
|
$myarray = glob(DATA_PATH.'/hasard/*.png');
|
|
|
if (isset($myarray[0]))
|
|
|
{
|
|
|
usort( $myarray, function( $a, $b ) { return filemtime($b) - filemtime($a); } );
|
|
|
return substr(basename($myarray[0],'.png'),0,strlen(self::$special_blocks[0]->hash));
|
|
|
}
|
|
|
|
|
|
// S'il n'y a rien dans le cache d'images
|
|
|
$filename=DATA_PATH.'/finished_block_list.txt';
|
|
|
|
|
|
if (file_exists($filename))
|
|
|
{
|
|
|
$handle = fopen($filename, "r");
|
|
|
if ($handle)
|
|
|
{
|
|
|
while (($buffer = fgets($handle, 4096)) !== false) {
|
|
|
$valeurs = explode(" ",$buffer);
|
|
|
if ($valeurs[0] == 'LAST') return $valeurs[1];
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
// ---
|
|
|
// --- Accès au dernier block
|
|
|
// ---
|
|
|
public static function getLastBlockHash()
|
|
|
{
|
|
|
if (file_exists(self::$offline_block)) return 'offline';
|
|
|
|
|
|
$filename=self::$url_info.'/latestblock';
|
|
|
$message=self::get_data($filename);
|
|
|
if ($message === FALSE) return FALSE;
|
|
|
$the_block = json_decode($message);
|
|
|
return $the_block->hash;
|
|
|
}
|
|
|
|
|
|
// ---
|
|
|
// --- Accès à partir du hash
|
|
|
// ---
|
|
|
public static function getBlockWithHash($block_hash)
|
|
|
{
|
|
|
// Si on est offline, peut importe le hash passé
|
|
|
if (!file_exists(self::$offline_block))
|
|
|
{
|
|
|
if (!file_exists(DATA_PATH."/json/$block_hash.zip"))
|
|
|
{
|
|
|
$filename=self::$url_info.'/rawblock/'.$block_hash;
|
|
|
$message=self::get_data($filename);
|
|
|
if ( $message === FALSE ) return FALSE;
|
|
|
$the_block = json_decode($message);
|
|
|
return self::saveBlockInTmpDir($the_block);
|
|
|
}
|
|
|
touch(DATA_PATH."/json/$block_hash.zip");
|
|
|
}
|
|
|
return self::zip2Block($block_hash);
|
|
|
}
|
|
|
|
|
|
// ---
|
|
|
// --- Gestion du cache
|
|
|
// ---
|
|
|
private static function saveBlockInTmpDir($the_block)
|
|
|
{
|
|
|
if (file_exists(DATA_PATH.'/json/'.$the_block->hash.'.zip')) return $the_block;
|
|
|
|
|
|
// Blockchain.info renvoie des nonces négatifs
|
|
|
// Je repasse par la forme binaire pour retrouver
|
|
|
// une valeur positive
|
|
|
$the_block->nonce_binary_str = decbin($the_block->nonce);
|
|
|
if (strlen($the_block->nonce_binary_str) > 32) $the_block->nonce_binary_str = substr($the_block->nonce_binary_str,-32,32);
|
|
|
$the_block->topisto_nonce_blockchain_info = $the_block->nonce;
|
|
|
$the_block->nonce = bindec($the_block->nonce_binary_str);
|
|
|
|
|
|
if (!isset($the_block->topisto_inputs))
|
|
|
{
|
|
|
$the_block->topisto_inputs = 0;
|
|
|
$the_block->topisto_outputs = 0;
|
|
|
$the_block->topisto_fees = 0;
|
|
|
$the_block->topisto_reward = 0;
|
|
|
|
|
|
foreach($the_block->tx as $transaction)
|
|
|
{
|
|
|
$tx_inputs = 0;
|
|
|
$tx_outputs = 0;
|
|
|
|
|
|
if (isset($transaction->inputs))
|
|
|
foreach($transaction->inputs as $input)
|
|
|
if (isset($input->prev_out->value))
|
|
|
$tx_inputs += $input->prev_out->value;
|
|
|
|
|
|
if (isset($transaction->out))
|
|
|
foreach($transaction->out as $output)
|
|
|
if (isset($output->value))
|
|
|
$tx_outputs += $output->value;
|
|
|
|
|
|
$tx_fees = abs($tx_inputs - $tx_outputs);
|
|
|
$the_block->topisto_inputs += $tx_inputs;
|
|
|
|
|
|
if ($tx_inputs == 0)
|
|
|
{
|
|
|
$the_block->topisto_reward += $tx_outputs;
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
$the_block->topisto_outputs += $tx_outputs;
|
|
|
$the_block->topisto_fees += $tx_fees;
|
|
|
}
|
|
|
// On retire les frais de la récompense
|
|
|
$the_block->topisto_reward -= $the_block->topisto_fees;
|
|
|
|
|
|
self::block2zip($the_block);
|
|
|
}
|
|
|
|
|
|
return $the_block;
|
|
|
}
|
|
|
|
|
|
private static function block2zip($the_block)
|
|
|
{
|
|
|
$zip = new ZipArchive();
|
|
|
if($zip->open(DATA_PATH.'/json/'.$the_block->hash.'.zip', ZipArchive::CREATE) === true)
|
|
|
{
|
|
|
$zip->addFromString($the_block->hash.'.json', json_encode($the_block));
|
|
|
$zip->close();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private static function zip2Block($the_block_hash)
|
|
|
{
|
|
|
$local_hash = $the_block_hash;
|
|
|
$zipBlock = DATA_PATH."/json/$the_block_hash.zip";
|
|
|
if (file_exists(self::$offline_block))
|
|
|
{
|
|
|
$local_hash = 'offline';
|
|
|
$zipBlock = self::$offline_block;
|
|
|
}
|
|
|
|
|
|
$zip = new ZipArchive;
|
|
|
|
|
|
if ($zip->open($zipBlock) === TRUE) {
|
|
|
$the_block = json_decode($zip->getFromName("$local_hash.json"));
|
|
|
$zip->close();
|
|
|
return $the_block;
|
|
|
}
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
public static function DrawBlockHeaderFooter($the_block, $vImage, $hauteur, $couleur = -1)
|
|
|
{
|
|
|
$color_tab = [
|
|
|
[
|
|
|
[19,15,64],
|
|
|
[255,255,255]
|
|
|
],
|
|
|
[
|
|
|
[106,176,76],
|
|
|
[0,0,0]
|
|
|
],
|
|
|
[
|
|
|
[106,176,76],
|
|
|
[255,255,255]
|
|
|
],
|
|
|
[
|
|
|
[240,147,43],
|
|
|
[0,0,0]
|
|
|
],
|
|
|
[
|
|
|
[34,166,179],
|
|
|
[0,0,0]
|
|
|
],
|
|
|
[
|
|
|
[240,147,43],
|
|
|
[255,255,255]
|
|
|
],
|
|
|
// pour splinelineblack
|
|
|
[
|
|
|
[17,61,86],
|
|
|
[255,255,255]
|
|
|
],
|
|
|
[
|
|
|
[17,61,86],
|
|
|
[255,134,63]
|
|
|
],
|
|
|
[
|
|
|
[234,220,207],
|
|
|
[127,106,85]
|
|
|
],
|
|
|
[
|
|
|
[48,51,107],
|
|
|
[255,255,255]
|
|
|
],
|
|
|
[
|
|
|
[246, 229, 141],
|
|
|
[235,77,75]
|
|
|
],
|
|
|
[
|
|
|
[40, 40, 40],
|
|
|
[158,227,253]
|
|
|
],
|
|
|
[
|
|
|
[255, 255, 255],
|
|
|
[0, 0, 0]
|
|
|
],
|
|
|
[
|
|
|
[0, 0, 0],
|
|
|
[255, 255, 255]
|
|
|
],
|
|
|
[
|
|
|
[255, 255, 255],
|
|
|
[255, 0, 0]
|
|
|
]
|
|
|
];
|
|
|
|
|
|
$color = $couleur;
|
|
|
if (($color == -1) || ($color > (count($color_tab)-1))) $color = $the_block->nonce % count($color_tab);
|
|
|
|
|
|
// Rajout des HASHES
|
|
|
$white = imagecolorallocate($vImage, 254, 254, 254);
|
|
|
$fond = imagecolorallocate($vImage, 255, 255, 255);
|
|
|
$black = imagecolorallocate($vImage, 0, 0, 0);
|
|
|
$w = imagesx($vImage);
|
|
|
$h = imagesy($vImage);
|
|
|
|
|
|
// On rend le blanc transparent
|
|
|
imagecolortransparent($vImage, $white);
|
|
|
|
|
|
// On place un fond transparent sur toute l'image
|
|
|
imagefilledrectangle($vImage, 0, 0, $w, $h, $white);
|
|
|
// Puis un fond sur la zone de dessin...
|
|
|
imagefilledrectangle($vImage, 0, $hauteur, $w, $h-$hauteur, $fond);
|
|
|
|
|
|
$len = strlen($the_block->hash);
|
|
|
$ratio_w = ($w - 10) / $len;
|
|
|
$ratio_h = $hauteur / 32; // car hexadécimal
|
|
|
|
|
|
// Récupérer les hashes dans 2 tableaux
|
|
|
$tableau1 = str_split($the_block->hash);
|
|
|
$tableau2 = str_split($the_block->prev_block);
|
|
|
|
|
|
// Convertir les tableaux en liste de points
|
|
|
$points1 = [];
|
|
|
$points2 = [];
|
|
|
|
|
|
$points1[] = 0;
|
|
|
$points1[] = $hauteur - 1;
|
|
|
|
|
|
$points2[] = 0;
|
|
|
$points2[] = $hauteur - 1;
|
|
|
|
|
|
for($i=0;$i<$len;$i++)
|
|
|
{
|
|
|
// Le HASH
|
|
|
$coin_x1 = $ratio_w * $i;
|
|
|
$coin_x2 = $ratio_w * ($i + 1);
|
|
|
$coin_y1 = $hauteur;
|
|
|
$coin_y2 = 5 + hexdec($tableau1[$i])*$ratio_h;
|
|
|
|
|
|
$points1[] = $coin_x1;
|
|
|
$points1[] = $coin_y2;
|
|
|
$points1[] = $coin_x2;
|
|
|
$points1[] = $coin_y2;
|
|
|
|
|
|
// Le PREV HASH
|
|
|
$coin_x1 = $ratio_w * $i;
|
|
|
$coin_x2 = $ratio_w * ($i + 1);
|
|
|
$coin_y1 = $hauteur;
|
|
|
$coin_y2 = 25 - hexdec($tableau2[$i])*$ratio_h;
|
|
|
|
|
|
$points2[] = $coin_x1;
|
|
|
$points2[] = $coin_y2;
|
|
|
$points2[] = $coin_x2;
|
|
|
$points2[] = $coin_y2;
|
|
|
}
|
|
|
|
|
|
// Rajouter une barre au HASH
|
|
|
$coin_x1 = $ratio_w * $i;
|
|
|
$coin_x2 = $ratio_w * ($i + 1);
|
|
|
$coin_y1 = $hauteur;
|
|
|
$coin_y2 = 5;
|
|
|
|
|
|
$points1[] = $coin_x1;
|
|
|
$points1[] = $coin_y2;
|
|
|
$points1[] = $coin_x2;
|
|
|
$points1[] = $coin_y2;
|
|
|
|
|
|
// Rajouter une barre au PREV HASH
|
|
|
$coin_x1 = $ratio_w * $i;
|
|
|
$coin_x2 = $ratio_w * ($i + 1);
|
|
|
$coin_y1 = $hauteur;
|
|
|
$coin_y2 = 25;
|
|
|
|
|
|
$points2[] = $coin_x1;
|
|
|
$points2[] = $coin_y2;
|
|
|
$points2[] = $coin_x2;
|
|
|
$points2[] = $coin_y2;
|
|
|
|
|
|
// Rajouter un coin
|
|
|
$points1[] = $w;
|
|
|
$points1[] = $hauteur - 1;
|
|
|
|
|
|
$points2[] = $w;
|
|
|
$points2[] = $hauteur - 1;
|
|
|
|
|
|
// Inverser le PREV HASH
|
|
|
for($i=0;$i<count($points2);$i+=2)
|
|
|
{
|
|
|
$points2[$i+1] = $h - $points2[$i+1];
|
|
|
if ($points2[$i+1] >= $h) $points2[$i+1] = $h - 1;
|
|
|
}
|
|
|
|
|
|
// Dessiner le HASH
|
|
|
imagefilledpolygon($vImage, $points1, (count($points1)/2), $fond);
|
|
|
imagepolygon($vImage, $points1, (count($points1)/2), $black);
|
|
|
|
|
|
// Dessiner le PREV HASH
|
|
|
imagefilledpolygon($vImage, $points2, (count($points2)/2), $fond);
|
|
|
imagepolygon($vImage, $points2, (count($points2)/2), $black);
|
|
|
|
|
|
// Rajout des textes
|
|
|
$the_name = blockchain::hash2SpecialName($the_block->hash);
|
|
|
if ($the_name == $the_block->hash) $the_name = date('Ymd H:i:s', $the_block->time);
|
|
|
|
|
|
putenv('GDFONTPATH='.RESS_PATH.'/fonts/');
|
|
|
$font = 'DS-DIGIB.TTF';
|
|
|
|
|
|
$the_texte = "Height : ".$the_block->height;
|
|
|
imagettftext($vImage,18, 0, 5, $hauteur-5, $black, $font, $the_texte);
|
|
|
$the_texte = "Inputs : ".$the_block->topisto_inputs;
|
|
|
if (count($the_block->tx)==1) $the_texte = "Reward : ".$the_block->topisto_reward;
|
|
|
imagettftext($vImage, 15, 0, 25, ($h - $hauteur)+18, $black, $font, $the_texte);
|
|
|
|
|
|
$bbox = imagettfbbox(14, 0, $font, $the_name);
|
|
|
imagettftext($vImage, 14, 0, ($w-3)-($bbox[2]-$bbox[0]), ($hauteur-5), $black, $font, $the_name);
|
|
|
|
|
|
$draw = imagecolorallocate($vImage, $color_tab[$color][1][0], $color_tab[$color][1][1], $color_tab[$color][1][2]);
|
|
|
$fond = imagecolorallocate($vImage, $color_tab[$color][0][0], $color_tab[$color][0][1], $color_tab[$color][0][2]);
|
|
|
|
|
|
return [$white, $fond, $draw, $font, $color_tab[$color][1], $color_tab[$color][0]];
|
|
|
}
|
|
|
|
|
|
public static function getTransactionData($the_block, $type=1)
|
|
|
{
|
|
|
// Cela a déjà été calculé
|
|
|
if (isset($the_block->data[$type])) return $the_block->data[$type];
|
|
|
|
|
|
$data = [];
|
|
|
foreach($the_block->tx as $transaction)
|
|
|
{
|
|
|
$total_outputs = 0;
|
|
|
$total_inputs = 0;
|
|
|
$value = 0;
|
|
|
|
|
|
if (isset($transaction->out))
|
|
|
foreach($transaction->out as $output)
|
|
|
if (isset($output->value))
|
|
|
$total_outputs += $output->value;
|
|
|
|
|
|
if (isset($transaction->inputs))
|
|
|
foreach($transaction->inputs as $input)
|
|
|
if (isset($input->prev_out->value))
|
|
|
$total_inputs += $input->prev_out->value;
|
|
|
|
|
|
switch($type)
|
|
|
{
|
|
|
// OUTPUTS
|
|
|
case 1:
|
|
|
if ($total_inputs != 0)
|
|
|
$data[] = ["hash" => $transaction->hash, "value" => $total_outputs];
|
|
|
break;
|
|
|
|
|
|
// INPUTS
|
|
|
case 2:
|
|
|
$data[] = ["hash" => $transaction->hash, "value" => $total_inputs];
|
|
|
break;
|
|
|
|
|
|
// FEES
|
|
|
case 3:
|
|
|
if ($total_inputs != 0)
|
|
|
$data[] = ["hash" => $transaction->hash, "value" => ($total_outputs-$total_inputs)];
|
|
|
break;
|
|
|
|
|
|
// REWARD
|
|
|
case 4:
|
|
|
if ($total_inputs == 0)
|
|
|
$data[] = ["hash" => $transaction->hash, "value" => $total_outputs];
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
if (!isset($the_block->data)) $the_block->data = [];
|
|
|
$the_block->data[$type] = $data;
|
|
|
return $data;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
blockchain::init();
|
|
|
|
|
|
?>
|