lto/api

LTO Network 客户端

v0.3.0 2021-01-11 04:30 UTC

README

LTO github readme

PHP 的 LTO Network 客户端

PHP Scrutinizer Code Quality Code Coverage Packagist Stable Version Packagist License

签名和地址对于(私有)事件链和公共链都适用。

安装

composer require lto/api

账户

创建

从种子创建账户

$seedText = "manage manual recall harvest series desert melt police rose hollow moral pledge kitten position add";

$factory = new LTO\AccountFactory('T'); // 'T' for testnet, 'L' for mainnet
$account = $factory->seed($seedText);

从签名密钥创建账户

$secretKey = 'wJ4WH8dD88fSkNdFQRjaAhjFUZzZhV5yiDLDwNUnp6bYwRXrvWV8MJhQ9HL9uqMDG1n7XpTGZx7PafqaayQV8Rp';

$factory = new LTO\AccountFactory('T'); // 'T' for testnet, 'L' for mainnet
$account = $factory->create($secretKey);

从完整信息创建账户

$accountInfo = [
  'address' => '3PLSsSDUn3kZdGe8qWEDak9y8oAjLVecXV1',
  'sign' => [
    'secretkey' => 'wJ4WH8dD88fSkNdFQRjaAhjFUZzZhV5yiDLDwNUnp6bYwRXrvWV8MJhQ9HL9uqMDG1n7XpTGZx7PafqaayQV8Rp',
    'publickey' => 'FkU1XyfrCftc4pQKXCrrDyRLSnifX1SMvmx1CYiiyB3Y'
  ],
  'encrypt' => [
    'secretkey' => 'BnjFJJarge15FiqcxrB7Mzt68nseBXXR4LQ54qFBsWJN',
    'publickey' => 'BVv1ZuE3gKFa6krwWJQwEmrLYUESuUabNCXgYTmCoBt6'
  ]
];

$factory = new LTO\AccountFactory('T'); // 'T' for testnet, 'L' for mainnet
$account = $factory->create($accountInfo);

指定的属性将进行验证。省略的属性将在可能的情况下生成。

签名(ED25519)

签名消息

$signature = $account->sign('hello world'); // Base58 encoded signature

验证签名

if (!$account->verify($signature, 'hello world')) {
    throw new RuntimeException('invalid signature');
}

加密(X25519)

为另一个账户加密消息

$message = 'hello world';

$recipientPublicKey = "HBqhfdFASRQ5eBBpu2y6c6KKi1az6bMx8v1JxX4iW1Q8"; // base58 encoded X25519 public key
$recipient = $factory->createPublic(null, $recipientPublicKey);

$cyphertext = $account->encryptFor($recipient, $message); // Raw binary, not encoded

您可以使用 $account->encryptFor($account, $message); 为自己加密消息。

解密来自另一个账户的消息

$senderPublicKey = "HBqhfdFASRQ5eBBpu2y6c6KKi1az6bMx8v1JxX4iW1Q8"; // base58 encoded X25519 public key
$sender = $factory->createPublic(null, $senderPublicKey);

$message = $account->decryptFrom($sender, $cyphertext);

您可以使用 $account->decryptFrom($account, $message); 解密来自自己的消息。

公共层

use LTO\Transaction\Transfer;
use LTO\PublicNode;

$node = new PublicNode('https://nodes.lto.network');

$amount = 1000.0; // Amount of LTO to transfer
$recipient = "3Jo1JCrBvnWCg37VDxMXAjYhsS9rRDLBSze";

$transferTx = (new Transfer($amount, $recipient))
    ->signWith($account)
    ->broadcastTo($node);

私有层

事件链

创建新的事件链

$chain = $account->createEventChain(); // Creates an empty event chain with a valid id and last hash

注意:您需要添加一个身份作为链上的第一个事件。这不是自动完成的。

创建并签名事件并将其添加到现有事件链

$body = [
  '$schema' => "http://specs.example.com/message#",
  'content' => "Hello world!"
];

$chainId = "JEKNVnkbo3jqSHT8tfiAKK4tQTFK7jbx8t18wEEnygya";
$chainLastHash = "3yMApqCuCjXDWPrbjfR5mjCPTHqFG8Pux1TxQrEM35jj";

$chain = new LTO\EventChain($chainId, $chainLastHash);

$chain->add(new Event($body))->signWith($account);

您需要链 ID 和最后一个事件的哈希来使用现有链。

HTTP 身份验证

签名 HTTP 消息的描述在 IETF 草案 draft-cavage-http-signatures-10 中。

可以使用 HTTP Authentication library 来签名和验证 PSR-7 请求

此库可以与 HTTP 身份验证库一起使用。`keyId` 应该是 base58 编码的公钥。

对于 `POST` 和 `PUT` 请求,建议创建 HTTP Digest(《RFC 3230`)。这是一个体哈希,间接地将体包含在签名中。请参阅《HTTP Digest library`>。

创建 HTTP 身份验证服务

use Jasny\HttpSignature\HttpSignature;

$secretKey = 'wJ4WH8dD88fSkNdFQRjaAhjFUZzZhV5yiDLDwNUnp6bYwRXrvWV8MJhQ9HL9uqMDG1n7XpTGZx7PafqaayQV8Rp';

$factory = new LTO\AccountFactory('T'); // 'T' for testnet, 'L' for mainnet
$ourAccount = $factory->create($secretKey);

$service = new HttpSignature(
    ['ed25519', 'ed25519-sha256'],
    new SignCallback($ourAccount),
    new VerifyCallback($accountFactory)
);

服务器中间件

创建服务器中间件以验证传入请求。

可以使用 LTO\Account\ServerMiddleware 为包含 `signature_key_id` 属性的服务器请求设置 account 属性。

use Jasny\HttpDigest\HttpDigest;
use Jasny\HttpDigest\ServerMiddleware as DigestMiddleware;
use Jasny\HttpDigest\Negitiation\DigestNegotiator;
use Jasny\HttpSignature\HttpSignature;
use Jasny\HttpSignature\ServerMiddleware as SignatureMiddleware;
use LTO\Account\ServerMiddleware as AccountMiddleware;
use Relay\RelayBuilder;

$factory = new LTO\AccountFactory('T'); // 'T' for testnet, 'L' for mainnet
$ourAccount = $factory->create($secretKey);

$digestService = HttpDigest(new DigestNegotiator(), ["SHA-256"]);

$signatureService = new HttpSignature(
    ['ed25519', 'ed25519-sha256'],
    function() { throw new \LogicException('sign not supported'); },
    new VerifyCallback($accountFactory)
);

$relayBuilder = new RelayBuilder($resolver);
$relay = $relayBuilder->newInstance([
    (new DigestMiddleware($digestService))->asDoublePass(),
    (new SignatureMiddleware($signatureService))->asDoublePass(),
    (new AccountMiddleware($factory))->asDoublePass(),
]);

服务器中间件实现了 PSR-15 MiddlewareInterface 以支持单次传递,并返回双次传递的回调,通过 asDoublePass() 方法。

客户端中间件

创建客户端中间件以签名传出请求。

use GuzzleHttp\HandlerStack;
use GuzzleHttp\Client;
use Jasny\HttpDigest\HttpDigest;
use Jasny\HttpDigest\ClientMiddleware as DigestMiddleware;
use Jasny\HttpDigest\Negitiation\DigestNegotiator;
use Jasny\HttpSignature\HttpSignature;
use Jasny\HttpSignature\ClientMiddleware as SignatureMiddleware;

$secretKey = 'wJ4WH8dD88fSkNdFQRjaAhjFUZzZhV5yiDLDwNUnp6bYwRXrvWV8MJhQ9HL9uqMDG1n7XpTGZx7PafqaayQV8Rp';

$factory = new LTO\AccountFactory('T'); // 'T' for testnet, 'L' for mainnet
$ourAccount = $factory->create($secretKey);

$digestService = HttpDigest(new DigestNegotiator(), ["SHA-256"]);

$signatureService = new HttpSignature(
    ['ed25519', 'ed25519-sha256'],
    new SignCallback($ourAccount),
    function() { throw new \LogicException('verify not supported'); }
);

$signatureMiddleware = new SignatureMiddleware(
    $service->withAlgorithm('ed25519-sha256'),
    $ourAccount->getPublicKey()
);

$stack = new HandlerStack();
$stack->push((new DigestMiddleware($digestService))->forGuzzle());
$stack->push($signatureMiddleware->forGuzzle());

$client = new Client(['handler' => $stack]);

命令行脚本

从种子生成账户

stdin 获取种子以生成账户信息。

$ vendor/bin/lto-seed <<< "manage manual recall harvest series desert melt police rose hollow moral pledge kitten position add"

address: 3JmCa4jLVv7Yn2XkCnBUGsa7WNFVEMxAfWe
sign:
  secretkey: 4zsR9xoFpxfnNwLcY4hdRUarwf5xWtLj6FpKGDFBgscPxecPj2qgRNx4kJsFCpe9YDxBRNoeBWTh2SDAdwTySomS
  publickey: GjSacB6a5DFNEHjDSmn724QsrRStKYzkahPH67wyrhAY
encrypt:
  secretkey: 4q7HKMbwbLcG58iFV3pz4vkRnPTwbrY9Q5JrwnwLEZCC
  publickey: 6fDod1xcVj4Zezwyy3tdPGHkuDyMq8bDHQouyp5BjXsX

默认情况下生成主网(L)地址。通过将 T 作为参数传递来创建测试网地址。

$ vendor/bin/lto-seed T <<< "manage manual recall harvest series desert melt police rose hollow moral pledge kitten position add"

账户信息

从密钥(密钥)显示账户信息。密钥应该是 base58 编码的。

$ vendor/bin/lto-account 4zsR9xoFpxfnNwLcY4hdRUarwf5xWtLj6FpKGDFBgscPxecPj2qgRNx4kJsFCpe9YDxBRNoeBWTh2SDAdwTySomS

address: 3JmCa4jLVv7Yn2XkCnBUGsa7WNFVEMxAfWe
sign:
  secretkey: 4zsR9xoFpxfnNwLcY4hdRUarwf5xWtLj6FpKGDFBgscPxecPj2qgRNx4kJsFCpe9YDxBRNoeBWTh2SDAdwTySomS
  publickey: GjSacB6a5DFNEHjDSmn724QsrRStKYzkahPH67wyrhAY
encrypt:
  secretkey: 4q7HKMbwbLcG58iFV3pz4vkRnPTwbrY9Q5JrwnwLEZCC
  publickey: 6fDod1xcVj4Zezwyy3tdPGHkuDyMq8bDHQouyp5BjXsX

默认情况下生成主网(L)地址。通过将 T 作为第三个参数传递来创建测试网地址。

$ vendor/bin/lto-seed 4zsR9xoFpxfnNwLcY4hdRUarwf5xWtLj6FpKGDFBgscPxecPj2qgRNx4kJsFCpe9YDxBRNoeBWTh2SDAdwTySomS T

签名消息

签名消息(从 stdin)。密钥应该是 base58 编码的。输出签名和哈希(base58 编码)。

$ cat message.json | vendor/bin/lto-sign 4zsR9xoFpxfnNwLcY4hdRUarwf5xWtLj6FpKGDFBgscPxecPj2qgRNx4kJsFCpe9YDxBRNoeBWTh2SDAdwTySomS

signature: 5i9gBaHwg9UFPuwU63LBdBR29yZdRDstWM9z7oo8GzevWhBdAAWwCSRUQbPLaCT3nFgjbQuuWxVQckzCd3CoFig4
hash:      42TEXg1vFAbcJ65y7qdYG9iCPvYfy3NDdVLd75akX2P5