Полезные ссылки (Администрирование Linux)

Полезные ссылки. Установка, администрирование Linux/CentOS, Apache, PHP, Git:

===
Перепечатка материалов блога разрешается с обязательной ссылкой на blog.coolsoftware.ru

OddEven Game (Smart Contract)

Для изучения смарт-контрактов и возможностей написания приложений с их использованием, написал простенькую игру: "Чет-Нечет" (Odd-Even).

Тут: http://oddeven.coolsoftware.ru/web3/

Update. Игра больше недоступна. Исходники, если будет время, опубликую на github.

Правила

В игре участвуют двое: “банкир” и игрок. За банкира играет сервис на PHP.
Банкир загадывает число, и записывает в смарт-контракт хэш от него. Затем игрок вводит свое число, которое отправляется в смарт-контракт. Потом “банкир” сообщает смарт-контракту загаданное им число (которое должно совпасть с хэшем). В конце определяется победитель: если игрок и банкир оба загадали четное число, или оба загадали нечетное число (иными словами: игрок угадал, загадал ли банкир четное число или нечетное), то выиграл игрок. Иначе выиграл банкир.

Смарт-контракт опубликован в тестовой сети rinkeby: https://rinkeby.etherscan.io/address/0x7a21ff65b1c509c2236aeaad47e1c938e6dd921c

Для игры игроку нужно установить MetaMask (https://metamask.io/) и завести аккаунт в сети rinkeby. Получить (бесплатно) ETH в этой тестовой сети можно тут: https://www.rinkeby.io/#faucet

===
Перепечатка материалов блога разрешается с обязательной ссылкой на blog.coolsoftware.ru

Ethereum и PHP

Полезные ссылки:

API client lib for communication with geth (go-ethereum) node
https://github.com/petrhejna/geth-jsonrpc-php-client

PHP interface to Ethereum JSON-RPC API
https://github.com/digitaldonkey/ethereum-php

A php interface for interacting with the Ethereum blockchain and ecosystem
https://github.com/sc0Vu/web3.php

Устанавливаются библиотеки с пом. композера, брать его тут: https://getcomposer.org/

Подключается установленная с пом. композера либа так:

<?php require_once __DIR__ . ‘/vendor/autoload.php’; ?>

===
Перепечатка материалов блога разрешается с обязательной ссылкой на blog.coolsoftware.ru

Связь GUI (web) и смарт-контракта.

Видео-туториал тут: https://www.youtube.com/watch?v=hcTPjpPvas8

Парочка замечаний:

1. Устанавливать надо версию web3 0.20.6 (в версии 0.20.7 можем получить ошибку: Access to XMLHttpRequest at ‘http://localhost:8545/' from origin ‘null’ has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: The value of the ‘Access-Control-Allow-Origin’ header in the response must not be the wildcard ‘*‘ when the request’s credentials mode is ‘include’. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.)

2. Чтобы установился dist\web3.min.js нужно при установке добавлять ключ –verbose.

Резюмируя: npm install web3@0.20.6 –save –verbose

===
Перепечатка материалов блога разрешается с обязательной ссылкой на blog.coolsoftware.ru

Первый Smart Contract

Годное введение здесь: Build Your First Ethereum Smart Contract with Solidity

Пара замечаний:

1. Для подсоединения к запущенной ноде надо использовать:

    geth attach ipc:\\.\pipe\geth.ipc

Если же просто выполнить geth attach, то получим ошибку: Unable to attach to remote geth: no known transport for URL scheme “c” (это верно для версии geth 1.8.23).

2. Mist лучше устанавливать 0.9.3, а не 0.11.1. В последнем при попытке вызвать методы созданного смарт контракта выводится ошибка: Couldn’t estimate gas, resorting to default parameters. Transaction is likely cheaper than the estimate. И в дальнейшем состояние “counter” контракта из примера не изменяется (остается всегда 5). В версии Mist 0.9.3 все OK.

Upd. Под Win10 Mist 0.11.1 работает OK. Правда, после установки Mist изругался: “Checksum mismatch in downloaded node. Please install the Geth node version 1.8.23 manually”. Пришлось переустанавливать geth. Причем, устанавливать надо 64-битную версию. Иначе при попытке запустить майнер можно получить ошибку: “Fatal Error:Not enough storage is available”

Полезные ссылки:

Go-Ethereum Management APIs: https://github.com/ethereum/go-ethereum/wiki/Management-APIs
Solidity 0.5.3 documentation: https://solidity.readthedocs.io/en/v0.5.3/contracts.html

===
Перепечатка материалов блога разрешается с обязательной ссылкой на blog.coolsoftware.ru

[Delphi XE2] MD4/MD5 Bug on x64

В библиотеке Indy, которая поставляется с  Delphi XE2 под 64-битной платформой, имеется баг в вычислении MD4/MD5 (компоненты TIdHashMessageDigest4, TIdHashMessageDigest5 соответственно).

Вот код для вычисления MD5:

var
md5indy: TIdHashMessageDigest5;
sMD5: String;
begin
md5indy := TIdHashMessageDigest5.Create;
sMD5 := md5indy.HashStringAsHex('123456');
md5indy.Free;
end;

Под Win32 результат будет: ‘e10adc3949ba59abbe56e057f20f883e’ (правильно)
Под Win64 результат будет: ‘6e692400e5c684b74314252e341b92c7’ (ошибка)

Этот баг был исправлен в более поздних версиях версиях Indy/Delphi (не скажу точно, в какой именно, в Delphi 10.2 Tokyo его нет).

Баг в asm-функциях ROL и ROR в модуле IdGlobalProtocols. Вот как они выглядят в XE2:


// Arg1=EAX, Arg2=DL
function ROL(const AVal: LongWord; AShift: Byte): LongWord; assembler;
asm
mov cl, dl
rol eax, cl
end;
function ROR(const AVal: LongWord; AShift: Byte): LongWord; assembler;
asm
mov cl, dl
ror eax, cl
end;
{$ENDIF}

А вот так это выглядит в Delpgi 10.2 Tokyo:

// 32-bit: Arg1=EAX, Arg2=DL
// 64-bit: Arg1=ECX, Arg2=DL
function ROL(const AVal: UInt32; AShift: Byte): UInt32; assembler;
asm
{$IFDEF CPU64}
mov eax, ecx
{$ENDIF}
mov cl, dl
rol eax, cl
end;
function ROR(const AVal: UInt32; AShift: Byte): UInt32; assembler;
asm
{$IFDEF CPU64}
mov eax, ecx
{$ENDIF}
mov cl, dl
ror eax, cl
end;

Чтобы можно было генерировать MD4/MD5 в XE2 под Win64 без установки новой версии Indy, я сделал модуль IdHashMessageDigestEx с “исправленными” классами TIdHashMessageDigest4Ex и TIdHashMessageDigest5Ex, которыми следует пользоваться вместо TIdHashMessageDigest4 и TIdHashMessageDigest5 соответственно. Замечу, что в XE2 не работает макрос CPU64 (как в более поздних версиях Delphi), а работает CPUX64.

unit IdHashMessageDigestEx;
interface
uses
IdFIPS, IdHashMessageDigest;
type
{$IFDEF VER230} //XE2
TIdHashMessageDigest4Ex = class(TIdHashMessageDigest4)
protected
procedure MDCoder; override;
end;
TIdHashMessageDigest5Ex = class(TIdHashMessageDigest4Ex)
protected
procedure MDCoder; override;
function InitHash : TIdHashIntCtx; override;
public
class function IsIntfAvailable : Boolean; override;
end;
{$ELSE}
TIdHashMessageDigest4Ex = TIdHashMessageDigest4;
TIdHashMessageDigest5Ex = TIdHashMessageDigest5;
{$ENDIF}
implementation
{$IFDEF VER230} //XE2
{$IFDEF NO_NATIVE_ASM)} //XE2
uses IdGlobalProtocols;
{$ELSE}
// 32-bit: Arg1=EAX, Arg2=DL
// 64-bit: Arg1=ECX, Arg2=DL
function ROL(const AVal: LongWord; AShift: LongWord): LongWord; assembler;
asm
{$IFDEF CPUX64}
mov eax, ecx
{$ENDIF}
mov cl, dl
rol eax, cl
end;
{$ENDIF}
{ TIdHashMessageDigest4Ex }
{$Q-} // Arithmetic operations performed modulo $100000000
procedure TIdHashMessageDigest4Ex.MDCoder;
var
A, B, C, D, i : LongWord;
buff : T16x4LongWordRecord; // 64-byte buffer
begin
A := FState[0];
B := FState[1];
C := FState[2];
D := FState[3];
for i := 0 to 15 do
begin
buff[i] := FCBuffer[i*4+0] +
(FCBuffer[i*4+1] shl 8) +
(FCBuffer[i*4+2] shl 16) +
(FCBuffer[i*4+3] shl 24);
end;
// Round 1
{ Note:
(x and y) or ( (not x) and z)
is equivalent to
(((z xor y) and x) xor z)
-HHellstrцm }
for i := 0 to 3 do
begin
A := ROL((((D xor C) and B) xor D) + A + buff[i*4+0], 3);
D := ROL((((C xor B) and A) xor C) + D + buff[i*4+1], 7);
C := ROL((((B xor A) and D) xor B) + C + buff[i*4+2], 11);
B := ROL((((A xor D) and C) xor A) + B + buff[i*4+3], 19);
end;
// Round 2
{ Note:
(x and y) or (x and z) or (y and z)
is equivalent to
((x and y) or (z and (x or y)))
-HHellstrцm }
for i := 0 to 3 do
begin
A := ROL(((B and C) or (D and (B or C))) + A + buff[0*4+i] + $5A827999, 3);
D := ROL(((A and B) or (C and (A or B))) + D + buff[1*4+i] + $5A827999, 5);
C := ROL(((D and A) or (B and (D or A))) + C + buff[2*4+i] + $5A827999, 9);
B := ROL(((C and D) or (A and (C or D))) + B + buff[3*4+i] + $5A827999, 13);
end;
// Round 3
A := ROL((B xor C xor D) + A + buff[ 0] + $6ED9EBA1, 3);
D := ROL((A xor B xor C) + D + buff[ 8] + $6ED9EBA1, 9);
C := ROL((D xor A xor B) + C + buff[ 4] + $6ED9EBA1, 11);
B := ROL((C xor D xor A) + B + buff[12] + $6ED9EBA1, 15);
A := ROL((B xor C xor D) + A + buff[ 2] + $6ED9EBA1, 3);
D := ROL((A xor B xor C) + D + buff[10] + $6ED9EBA1, 9);
C := ROL((D xor A xor B) + C + buff[ 6] + $6ED9EBA1, 11);
B := ROL((C xor D xor A) + B + buff[14] + $6ED9EBA1, 15);
A := ROL((B xor C xor D) + A + buff[ 1] + $6ED9EBA1, 3);
D := ROL((A xor B xor C) + D + buff[ 9] + $6ED9EBA1, 9);
C := ROL((D xor A xor B) + C + buff[ 5] + $6ED9EBA1, 11);
B := ROL((C xor D xor A) + B + buff[13] + $6ED9EBA1, 15);
A := ROL((B xor C xor D) + A + buff[ 3] + $6ED9EBA1, 3);
D := ROL((A xor B xor C) + D + buff[11] + $6ED9EBA1, 9);
C := ROL((D xor A xor B) + C + buff[ 7] + $6ED9EBA1, 11);
B := ROL((C xor D xor A) + B + buff[15] + $6ED9EBA1, 15);
Inc(FState[0], A);
Inc(FState[1], B);
Inc(FState[2], C);
Inc(FState[3], D);
end;
{$Q+}
{ TIdHashMessageDigest5Ex }
const
MD5_SINE : array[1..64] of LongWord = (
{ Round 1. }
$d76aa478, $e8c7b756, $242070db, $c1bdceee, $f57c0faf, $4787c62a,
$a8304613, $fd469501, $698098d8, $8b44f7af, $ffff5bb1, $895cd7be,
$6b901122, $fd987193, $a679438e, $49b40821,
{ Round 2. }
$f61e2562, $c040b340, $265e5a51, $e9b6c7aa, $d62f105d, $02441453,
$d8a1e681, $e7d3fbc8, $21e1cde6, $c33707d6, $f4d50d87, $455a14ed,
$a9e3e905, $fcefa3f8, $676f02d9, $8d2a4c8a,
{ Round 3. }
$fffa3942, $8771f681, $6d9d6122, $fde5380c, $a4beea44, $4bdecfa9,
$f6bb4b60, $bebfbc70, $289b7ec6, $eaa127fa, $d4ef3085, $04881d05,
$d9d4d039, $e6db99e5, $1fa27cf8, $c4ac5665,
{ Round 4. }
$f4292244, $432aff97, $ab9423a7, $fc93a039, $655b59c3, $8f0ccc92,
$ffeff47d, $85845dd1, $6fa87e4f, $fe2ce6e0, $a3014314, $4e0811a1,
$f7537e82, $bd3af235, $2ad7d2bb, $eb86d391
);
{$Q-} // Arithmetic operations performed modulo $100000000
function TIdHashMessageDigest5Ex.InitHash: TIdHashIntCtx;
begin
Result := GetMD5HashInst;
end;
class function TIdHashMessageDigest5Ex.IsIntfAvailable: Boolean;
begin
Result := IsHashingIntfAvail and IsMD5HashIntfAvail ;
end;
procedure TIdHashMessageDigest5Ex.MDCoder;
var
A, B, C, D : LongWord;
i: Integer;
x : T16x4LongWordRecord; // 64-byte buffer
begin
A := FState[0];
B := FState[1];
C := FState[2];
D := FState[3];
for i := 0 to 15 do
begin
x[i] := FCBuffer[i*4+0] +
(FCBuffer[i*4+1] shl 8) +
(FCBuffer[i*4+2] shl 16) +
(FCBuffer[i*4+3] shl 24);
end;
{ Round 1 }
{ Note:
(x and y) or ( (not x) and z)
is equivalent to
(((z xor y) and x) xor z)
-HHellstrцm }
A := ROL(A + (((D xor C) and B) xor D) + x[ 0] + MD5_SINE[ 1], 7) + B;
D := ROL(D + (((C xor B) and A) xor C) + x[ 1] + MD5_SINE[ 2], 12) + A;
C := ROL(C + (((B xor A) and D) xor B) + x[ 2] + MD5_SINE[ 3], 17) + D;
B := ROL(B + (((A xor D) and C) xor A) + x[ 3] + MD5_SINE[ 4], 22) + C;
A := ROL(A + (((D xor C) and B) xor D) + x[ 4] + MD5_SINE[ 5], 7) + B;
D := ROL(D + (((C xor B) and A) xor C) + x[ 5] + MD5_SINE[ 6], 12) + A;
C := ROL(C + (((B xor A) and D) xor B) + x[ 6] + MD5_SINE[ 7], 17) + D;
B := ROL(B + (((A xor D) and C) xor A) + x[ 7] + MD5_SINE[ 8], 22) + C;
A := ROL(A + (((D xor C) and B) xor D) + x[ 8] + MD5_SINE[ 9], 7) + B;
D := ROL(D + (((C xor B) and A) xor C) + x[ 9] + MD5_SINE[10], 12) + A;
C := ROL(C + (((B xor A) and D) xor B) + x[10] + MD5_SINE[11], 17) + D;
B := ROL(B + (((A xor D) and C) xor A) + x[11] + MD5_SINE[12], 22) + C;
A := ROL(A + (((D xor C) and B) xor D) + x[12] + MD5_SINE[13], 7) + B;
D := ROL(D + (((C xor B) and A) xor C) + x[13] + MD5_SINE[14], 12) + A;
C := ROL(C + (((B xor A) and D) xor B) + x[14] + MD5_SINE[15], 17) + D;
B := ROL(B + (((A xor D) and C) xor A) + x[15] + MD5_SINE[16], 22) + C;
{ Round 2 }
{ Note:
(x and z) or (y and (not z) )
is equivalent to
(((y xor x) and z) xor y)
-HHellstrцm }
A := ROL(A + (C xor (D and (B xor C))) + x[ 1] + MD5_SINE[17], 5) + B;
D := ROL(D + (B xor (C and (A xor B))) + x[ 6] + MD5_SINE[18], 9) + A;
C := ROL(C + (A xor (B and (D xor A))) + x[11] + MD5_SINE[19], 14) + D;
B := ROL(B + (D xor (A and (C xor D))) + x[ 0] + MD5_SINE[20], 20) + C;
A := ROL(A + (C xor (D and (B xor C))) + x[ 5] + MD5_SINE[21], 5) + B;
D := ROL(D + (B xor (C and (A xor B))) + x[10] + MD5_SINE[22], 9) + A;
C := ROL(C + (A xor (B and (D xor A))) + x[15] + MD5_SINE[23], 14) + D;
B := ROL(B + (D xor (A and (C xor D))) + x[ 4] + MD5_SINE[24], 20) + C;
A := ROL(A + (C xor (D and (B xor C))) + x[ 9] + MD5_SINE[25], 5) + B;
D := ROL(D + (B xor (C and (A xor B))) + x[14] + MD5_SINE[26], 9) + A;
C := ROL(C + (A xor (B and (D xor A))) + x[ 3] + MD5_SINE[27], 14) + D;
B := ROL(B + (D xor (A and (C xor D))) + x[ 8] + MD5_SINE[28], 20) + C;
A := ROL(A + (C xor (D and (B xor C))) + x[13] + MD5_SINE[29], 5) + B;
D := ROL(D + (B xor (C and (A xor B))) + x[ 2] + MD5_SINE[30], 9) + A;
C := ROL(C + (A xor (B and (D xor A))) + x[ 7] + MD5_SINE[31], 14) + D;
B := ROL(B + (D xor (A and (C xor D))) + x[12] + MD5_SINE[32], 20) + C;
{ Round 3. }
A := ROL(A + (B xor C xor D) + x[ 5] + MD5_SINE[33], 4) + B;
D := ROL(D + (A xor B xor C) + x[ 8] + MD5_SINE[34], 11) + A;
C := ROL(C + (D xor A xor B) + x[11] + MD5_SINE[35], 16) + D;
B := ROL(B + (C xor D xor A) + x[14] + MD5_SINE[36], 23) + C;
A := ROL(A + (B xor C xor D) + x[ 1] + MD5_SINE[37], 4) + B;
D := ROL(D + (A xor B xor C) + x[ 4] + MD5_SINE[38], 11) + A;
C := ROL(C + (D xor A xor B) + x[ 7] + MD5_SINE[39], 16) + D;
B := ROL(B + (C xor D xor A) + x[10] + MD5_SINE[40], 23) + C;
A := ROL(A + (B xor C xor D) + x[13] + MD5_SINE[41], 4) + B;
D := ROL(D + (A xor B xor C) + x[ 0] + MD5_SINE[42], 11) + A;
C := ROL(C + (D xor A xor B) + x[ 3] + MD5_SINE[43], 16) + D;
B := ROL(B + (C xor D xor A) + x[ 6] + MD5_SINE[44], 23) + C;
A := ROL(A + (B xor C xor D) + x[ 9] + MD5_SINE[45], 4) + B;
D := ROL(D + (A xor B xor C) + x[12] + MD5_SINE[46], 11) + A;
C := ROL(C + (D xor A xor B) + x[15] + MD5_SINE[47], 16) + D;
B := ROL(B + (C xor D xor A) + x[ 2] + MD5_SINE[48], 23) + C;
{ Round 4. }
A := ROL(A + ((B or not D) xor C) + x[ 0] + MD5_SINE[49], 6) + B;
D := ROL(D + ((A or not C) xor B) + x[ 7] + MD5_SINE[50], 10) + A;
C := ROL(C + ((D or not B) xor A) + x[14] + MD5_SINE[51], 15) + D;
B := ROL(B + ((C or not A) xor D) + x[ 5] + MD5_SINE[52], 21) + C;
A := ROL(A + ((B or not D) xor C) + x[12] + MD5_SINE[53], 6) + B;
D := ROL(D + ((A or not C) xor B) + x[ 3] + MD5_SINE[54], 10) + A;
C := ROL(C + ((D or not B) xor A) + x[10] + MD5_SINE[55], 15) + D;
B := ROL(B + ((C or not A) xor D) + x[ 1] + MD5_SINE[56], 21) + C;
A := ROL(A + ((B or not D) xor C) + x[ 8] + MD5_SINE[57], 6) + B;
D := ROL(D + ((A or not C) xor B) + x[15] + MD5_SINE[58], 10) + A;
C := ROL(C + ((D or not B) xor A) + x[ 6] + MD5_SINE[59], 15) + D;
B := ROL(B + ((C or not A) xor D) + x[13] + MD5_SINE[60], 21) + C;
A := ROL(A + ((B or not D) xor C) + x[ 4] + MD5_SINE[61], 6) + B;
D := ROL(D + ((A or not C) xor B) + x[11] + MD5_SINE[62], 10) + A;
C := ROL(C + ((D or not B) xor A) + x[ 2] + MD5_SINE[63], 15) + D;
B := ROL(B + ((C or not A) xor D) + x[ 9] + MD5_SINE[64], 21) + C;
Inc(FState[0], A);
Inc(FState[1], B);
Inc(FState[2], C);
Inc(FState[3], D);
end;
{$Q+}
{$ENDIF}
end.

===

Перепечатка материалов блога разрешается с обязательной ссылкой на blog.coolsoftware.ru

AHCI

Wiki: “Advanced Host Controller Interface (AHCI) — механизм, используемый для подключения накопителей информации по протоколу Serial ATA, позволяющий пользоваться расширенными функциями, такими, как встроенная очерёдность команд (NCQ) и горячая замена.”

Как включить:

Windows 7

1. В реестре в разделе HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\msachi установить значение параметра “Start” (REG_DWORD) равным 0 (по-умолчанию Start=3).

2. В реестре в разделе HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\iaStorV установить значение параметра “Start” (REG_DWORD) равным 0 (по-умолчанию Start=3).

3. В BIOS включить режим AHCI вместо IDE.

Windows 10

1. В реестре в разделе HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\iaStorV установить значение параметра “Start” (REG_DWORD) равным 0.

2. В реестре в разделе HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\iaStorAV\StartOverride установить значение параметра “0” равным 0 (по-умолчанию значение этого параметра равно 3).

3. В реестре в разделе HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\storachi\StartOverride установить значение параметра “0” равным 0 (по-умолчанию значение этого параметра равно 3).

4. В BIOS включить режим AHCI вместо IDE.

CentOS 7

1. Выполнить:

sudo modprobe ahci
sudo cp /boot/initramfs-`uname -r`.img /boot/initramfs-`uname -r`.img.bak
sudo mkinitrd -f --with=ahci /boot/initramfs-`uname -r`.img `uname -r`

2. В BIOS включить режим AHCI вместо IDE.

===
Перепечатка материалов блога разрешается с обязательной ссылкой на blog.coolsoftware.ru