casper_network 1.0.2 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +221 -78
- data/lib/casper_network.rb +7 -4
- data/lib/crypto/asymmetric_key.rb +19 -18
- data/lib/crypto/ed25519.rb +114 -0
- data/lib/crypto/ed25519_key.rb +111 -10
- data/lib/crypto/keys.rb +1 -2
- data/lib/crypto/keys_util.rb +20 -0
- data/lib/entity/deploy.rb +154 -1
- data/lib/entity/deploy_executable.rb +50 -7
- data/lib/entity/deploy_executable_item_internal.rb +1 -1
- data/lib/entity/deploy_header.rb +17 -0
- data/lib/entity/deploy_named_argument.rb +61 -2
- data/lib/entity/module_bytes.rb +9 -2
- data/lib/include.rb +2 -0
- data/lib/serialization/cl_value_serializer.rb +69 -12
- data/lib/serialization/deploy_serializer.rb +129 -15
- data/lib/types/cl_option.rb +9 -1
- data/lib/types/cl_public_key.rb +2 -0
- data/lib/types/cl_value.rb +8 -0
- data/lib/utils/byte_utils.rb +28 -0
- data/lib/utils/helpers.rb +10 -0
- data/lib/version.rb +1 -1
- data/spec/cl_value_serializer_spec.rb +15 -1
- data/spec/deploy_executable_spec.rb +90 -0
- data/spec/testnet_spec.rb +5 -3
- metadata +7 -24
- data/lib/crypto/00_asymmetric_key.rb +0 -95
- data/lib/crypto/01_ed25519.rb +0 -67
- data/lib/crypto/key_pair.rb +0 -40
- data/lib/crypto/secp256k1_key.rb +0 -0
- data/lib/crypto/test_ed25519_key.rb +0 -44
- data/lib/entity/executable_deploy_item.rb +0 -11
- data/lib/serialization/test.rb +0 -431
- data/lib/types/cl_account_hash.rb +0 -24
- data/lib/types/cl_account_hash_type.rb +0 -22
- data/lib/utils/utils.rb +0 -2
- data/spec/a_spec.rb +0 -697
- data/spec/cl_public_spec.rb +0 -169
- data/spec/crypto_spec.rb +0 -42
- data/spec/deploy_executable_serializer_spec.rb +0 -0
- data/spec/deploy_serializer_test_spec.rb +0 -225
- data/spec/string_spec.rb +0 -68
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b46d9a498eaea47808ae5b3bf9455f8858692215494aac8f2816e0a6493b8ad8
|
4
|
+
data.tar.gz: cfd0376e3a0349028674273347d27506699ee1cacc573dbaf62d870accc5f3ca
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 49bf35f83b681f3f023ad263d8cfa5c9f259235cfb01a226e8ae89197463d6b99dec6a73414c5ca9d0812c9002bd78fa1d9ea5812421d0178bc87199352cf14f
|
7
|
+
data.tar.gz: 94b5d574ed064525b0b0e4265652935595ec2337a6602d1bbee4a83f27c083ccd1fa26c8b045355294acb6435b01c19fd3ece4dfffa5a93aaef1a88cc1dc1564
|
data/README.md
CHANGED
@@ -70,7 +70,20 @@ yardoc lib/**/*.rb lib/*.rb - README.md LICENSE CONTRIBUTING.md SECURITY.md
|
|
70
70
|
yardoc --help
|
71
71
|
```
|
72
72
|
|
73
|
-
## Documentation
|
73
|
+
## Documentation
|
74
|
+
|
75
|
+
The SDK documentation can be found [here](https://www.rubydoc.info/gems/casper_network/1.1.2) in detail.
|
76
|
+
|
77
|
+
### Serialization
|
78
|
+
Casper provides a custom implementation to serialize data structures used by the Casper node to their byte representation.
|
79
|
+
More information on this custom implementation can be found [here](https://caspernetwork.readthedocs.io/en/latest/implementation/serialization-standard.html).
|
80
|
+
|
81
|
+
* [Serialization](https://github.com/saitgulmez/casper-ruby-sdk/blob/main/docs/serialization.md#serialization)
|
82
|
+
* [Examples](https://github.com/saitgulmez/casper-ruby-sdk/blob/main/docs/serialization.md#examples)
|
83
|
+
|
84
|
+
### Key Management
|
85
|
+
* [CLPublicKey](https://github.com/saitgulmez/casper-ruby-sdk/blob/main/docs/keys.md#public-keys)
|
86
|
+
|
74
87
|
### Casper-Ruby-Sdk RPC
|
75
88
|
* [info_get_peers](https://github.com/saitgulmez/casper-ruby-sdk/blob/main/docs/rpc.md#info_get_peers)
|
76
89
|
* [chain_get_StateRootHash](https://github.com/saitgulmez/casper-ruby-sdk/blob/main/docs/rpc.md#get-state_root_hash)
|
@@ -333,91 +346,221 @@ stake_amount = delegator.get_staked_amount # => 27871095039894
|
|
333
346
|
```
|
334
347
|
|
335
348
|
|
336
|
-
###
|
349
|
+
### Example
|
350
|
+
```bash
|
351
|
+
# example.rb
|
352
|
+
# how to execute example.rb
|
353
|
+
$ ruby example.rb
|
354
|
+
```
|
355
|
+
|
337
356
|
```ruby
|
357
|
+
# example.rb
|
338
358
|
require 'casper_network'
|
359
|
+
# Class-Object Level
|
360
|
+
# Casper::CasperClient
|
361
|
+
node_ip_address = "5.9.23.55" # IP is taken from "testnet"
|
362
|
+
client = Casper::CasperClient.new(node_ip_address)
|
363
|
+
|
364
|
+
#********** info_get_peers *********************************#
|
365
|
+
|
366
|
+
# Uncomment following lines to see the outputs
|
367
|
+
# puts client.info_get_peers
|
368
|
+
# puts client.info_get_peers[0].get_node_id
|
369
|
+
# puts client.info_get_peers[0].get_address
|
370
|
+
|
371
|
+
|
372
|
+
#********** chain_get_StateRootHash *********************************#
|
373
|
+
# Uncomment following line to see the outputs
|
374
|
+
# puts client.chain_get_StateRootHash
|
339
375
|
|
340
|
-
# In order to interact with casper network we should give a valid ip address to the constructor
|
341
376
|
|
342
|
-
|
343
|
-
|
344
|
-
|
377
|
+
#********** info_get_deploy(deploy_hash) *********************************#
|
378
|
+
deploy_hash = "0806cc477a5282574bc5302d7598cd33a09875704c5fef9264d984535c945e31"
|
379
|
+
deploy = client.info_get_deploy(deploy_hash)
|
380
|
+
# Uncomment following lines to see the outputs
|
381
|
+
# puts deploy
|
382
|
+
# hash = Casper::Entity::DeployHash.new(deploy.get_hash)
|
383
|
+
# puts hash
|
384
|
+
# header = Casper::Entity::DeployHeader.new(deploy.get_header)
|
385
|
+
# puts header
|
386
|
+
# payment = deploy.get_payment
|
387
|
+
# puts payment
|
388
|
+
# session = deploy.get_session
|
389
|
+
# puts session
|
390
|
+
|
391
|
+
# approvals = []
|
392
|
+
# num_of_approvals = deploy.get_approvals.size
|
393
|
+
# num_of_approvals.times do |i|
|
394
|
+
# approvals.push(Casper::Entity::DeployApproval.new(deploy.get_approvals[i]))
|
395
|
+
# end
|
396
|
+
# puts approvals[0].get_signer
|
397
|
+
# puts hash, header, payment, session, approvals
|
398
|
+
|
399
|
+
#********** info_get_status *********************************#
|
400
|
+
node_status = client.info_get_status
|
401
|
+
# Uncomment following lines to see the outputs
|
402
|
+
# puts node_status
|
403
|
+
# puts node_status.get_api_version
|
404
|
+
# puts node_status.get_chainspec_name
|
405
|
+
# puts node_status.get_starting_state_root_hash
|
406
|
+
# puts node_status.get_peers
|
407
|
+
# puts node_status.get_last_added_block_info
|
408
|
+
# puts node_status.get_our_public_signing_key
|
409
|
+
# puts node_status.get_round_length
|
410
|
+
# puts node_status.get_next_upgrade
|
411
|
+
# puts node_status.get_build_version
|
412
|
+
# puts node_status.get_uptime
|
413
|
+
|
414
|
+
#********** chain_get_block_transfers(block_hash = "") *********************************#
|
345
415
|
# block_Hash taken from Testnet
|
346
|
-
block_hash = "
|
347
|
-
|
348
|
-
|
349
|
-
|
416
|
+
block_hash = "ff2ad232c3efc22a385fce44df844fc696e904ce8ba78599a576aa68c76889c4"
|
417
|
+
transfers = client.chain_get_block_transfers(block_hash)
|
418
|
+
# Uncomment following lines to see the outputs
|
419
|
+
# puts transfers
|
420
|
+
# transfers.each do |transfer|
|
421
|
+
# puts transfer.get_deploy_hash
|
422
|
+
# puts transfer.get_from
|
423
|
+
# puts transfer.get_to
|
424
|
+
# puts transfer.get_source
|
425
|
+
# puts transfer.get_target
|
426
|
+
# puts transfer.get_amount
|
427
|
+
# puts transfer.get_gas
|
428
|
+
# puts transfer.get_id
|
429
|
+
# end
|
430
|
+
|
431
|
+
|
432
|
+
|
433
|
+
#********** chain_get_block(block_hash) *********************************#
|
434
|
+
block_hash = "ff2ad232c3efc22a385fce44df844fc696e904ce8ba78599a576aa68c76889c4"
|
435
|
+
block = client.chain_get_block(block_hash)
|
436
|
+
# Uncomment following lines to see the outputs
|
437
|
+
# puts block
|
438
|
+
# To retrieve BlockHeader object
|
439
|
+
# block_header = block.get_header
|
440
|
+
# puts block_header
|
441
|
+
# To access and print members of the block_header object (block_header is an instance of BlockHeader )
|
442
|
+
# puts block_header.get_parent_hash
|
443
|
+
# puts block_header.get_state_root_hash
|
444
|
+
# puts block_header.get_body_hash
|
445
|
+
# puts block_header.get_random_bit
|
446
|
+
# puts block_header.get_accumulated_seed
|
447
|
+
# puts block_header.get_era_end
|
448
|
+
# puts block_header.get_timestamp
|
449
|
+
# puts block_header.get_era_id
|
450
|
+
# puts block_header.get_height
|
451
|
+
# puts block_header.get_protocol_version
|
452
|
+
|
453
|
+
# To retrieve BlockBody object
|
454
|
+
# block_body = block.get_body
|
455
|
+
# To access and print members of the block_body object (block_body is an instance of BlockBody )
|
456
|
+
# puts block_body
|
457
|
+
# puts block_body.get_proposer
|
458
|
+
# puts block_body.get_deploy_hashes
|
459
|
+
# puts block_body.get_transfer_hashes
|
460
|
+
|
461
|
+
# To retrieve an array of BlockProof objects
|
462
|
+
# proofs = block.get_proofs
|
463
|
+
# To access and print members of the block_proof objects (block_proof is an instance of BlockProof )
|
464
|
+
# puts proofs
|
465
|
+
# To access and print each proof object and its members
|
466
|
+
# i = 0
|
467
|
+
# proofs.each do |proof|
|
468
|
+
# puts "proofs[#{i}]: #{proof}"
|
469
|
+
# puts "public_key: " + proof.get_public_key
|
470
|
+
# puts "signature: " + proof.get_signature
|
471
|
+
# i += 1
|
472
|
+
# end
|
473
|
+
|
474
|
+
|
475
|
+
|
476
|
+
#********** chain_get_eraInfo_by_SwitchBlock(block_hash) *********************************#
|
477
|
+
block_hash = "d2077716e5b8796723c5720237239720f54e6ada54e3357f2c4896f2a51a6d8f"
|
478
|
+
era_summary = client.chain_get_eraInfo_by_SwitchBlock(block_hash)
|
479
|
+
# Uncomment following lines to see the outputs
|
480
|
+
# puts era_summary
|
481
|
+
# puts era_summary.get_block_hash
|
482
|
+
# puts era_summary.get_era_id
|
483
|
+
# puts era_summary.get_stored_value
|
484
|
+
# puts era_summary.get_stored_value.get_stored_value
|
485
|
+
# puts era_summary.get_state_root_hash
|
486
|
+
# puts era_summary.get_merkle_proof
|
487
|
+
# era_summary.map { |k, v| puts "#{k}" }
|
488
|
+
#
|
489
|
+
|
490
|
+
|
491
|
+
|
492
|
+
#********** state_get_item(state_root_hash, key, path) *********************************#
|
493
|
+
node_ip_address = "65.108.78.120" # => Taken from Mainnet
|
494
|
+
client = Casper::CasperClient.new(node_ip_address)
|
495
|
+
# Retrieve the stored_value object which is an instance of StoredValue
|
496
|
+
# Uncomment following lines to see the outputs
|
497
|
+
stored_value = client.state_get_item("647C28545316E913969B032Cf506d5D242e0F857061E70Fb3DF55980611ace86", "bid-24b6D5Aabb8F0AC17D272763A405E9CECa9166B75B745Cf200695E172857c2dD", [])
|
498
|
+
# puts stored_value # => #<Casper::Entity::StoredValue:0x0000000003767a48>
|
499
|
+
# puts stored_value.get_key # => Bid
|
500
|
+
# puts stored_value.get_bid # => Retrieve and print Bid object related data
|
501
|
+
# # or
|
502
|
+
# puts stored_value.get_stored_value # => Retrieve and print Bid object related data
|
503
|
+
|
504
|
+
|
505
|
+
|
506
|
+
|
507
|
+
#********** state_get_dictionary_item(state_root_hash, item_key, uref) *********************************#
|
508
|
+
node_ip_address = "65.108.78.120" # => Taken from Mainnet
|
509
|
+
client = Casper::CasperClient.new(node_ip_address)
|
510
|
+
state_root_hash = "7b605ad991c949832fd966495afc3f97a2b8122a1a6afc2610b545a8c07e3456"
|
350
511
|
item_key = "f870e3cadfde21d7d7686fdf3d1a8413838274d363ca7b27ae71fc9125eb6743"
|
351
|
-
uref = "uref-
|
352
|
-
|
512
|
+
uref = "uref-0d689e987db7ee5be246282c3a7badf0411e34baeeab8e9d73c1223ae4ad02e5-007"
|
513
|
+
# # Retrieve folowing data from the network and convert it into its proper CLValue
|
514
|
+
# # {"CLValue"=>{"cl_type"=>"String", "bytes"=>"1a00000068747470733a2f2f636173706572636f6d6d756e6974792e696f", "parsed"=>"https://caspercommunity.io"}}
|
515
|
+
|
516
|
+
# Uncomment following lines to see the outputs
|
517
|
+
# stored_value = client.state_get_dictionary_item(state_root_hash, item_key, uref)
|
518
|
+
# puts stored_value # => #<CLString:0x0000000002b3c8e0>
|
519
|
+
# puts stored_value.get_cl_type # => String
|
520
|
+
# puts stored_value.get_value # => https://caspercommunity.io
|
521
|
+
# puts CLValueBytesParsers::CLStringBytesParser.to_bytes(stored_value.get_value) # => 1a00000068747470733a2f2f636173706572636f6d6d756e6974792e696f
|
522
|
+
|
523
|
+
|
524
|
+
|
525
|
+
#********** state_get_balance(state_root_hash, balance_uref) *********************************#
|
526
|
+
node_ip_address = "65.108.78.120" # => Taken from Mainnet
|
527
|
+
client = Casper::CasperClient.new(node_ip_address)
|
528
|
+
state_root_hash = "610e932aef10d3e1fa04940c79a4a2789ee79c17046f1a9b45a2919f3600f3d5"
|
529
|
+
uref = "uref-7de5e973b7d70bc2b328814411f2009aafd8dba901cfc2c588ba65088dcd22bb-007"
|
353
530
|
|
531
|
+
# Uncomment following lines to see the outputs
|
532
|
+
# balance = client.state_get_balance(state_root_hash, uref)
|
533
|
+
# puts balance # => 29269647684075 (current balance 9/24/2022)
|
354
534
|
|
355
|
-
|
356
|
-
|
357
|
-
# IP is taken from "Mainnet"
|
358
|
-
# node_ip_address = "65.108.78.12"
|
535
|
+
|
536
|
+
#********** state_get_AuctionInfo *********************************#
|
359
537
|
# block_Hash taken from MainNet
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
# state_root_hash = "7b605ad991c949832fd966495afc3f97a2b8122a1a6afc2610b545a8c07e3456"
|
364
|
-
# item_key = "f870e3cadfde21d7d7686fdf3d1a8413838274d363ca7b27ae71fc9125eb6743"
|
365
|
-
# uref = "uref-0d689e987db7ee5be246282c3a7badf0411e34baeeab8e9d73c1223ae4ad02e5-007"
|
366
|
-
# switch_block_hash = "4696285db1ca6572f425cada612257f85a58a6a4034c09846afe360ba40e5df0"
|
367
|
-
|
368
|
-
if (IPAddress.valid? node_ip_address)
|
369
|
-
client = Casper::CasperClient.new(node_ip_address)
|
370
|
-
peers = client.info_get_peers.sample(5)
|
371
|
-
puts "node_id and address of five randomly selected 5 peers:"
|
372
|
-
puts peers
|
373
|
-
|
374
|
-
# Store ip addresses of these peers into an array
|
375
|
-
ips = []
|
376
|
-
peers.select do |item|
|
377
|
-
ip = item["address"]
|
378
|
-
ips << ip[0, ip.index(':')]
|
379
|
-
end
|
380
|
-
|
381
|
-
clients = []
|
382
|
-
puts "Randomly selected 5 peers ip addresses:"
|
383
|
-
ips.each do |ip_address|
|
384
|
-
# Create a client object for each iteration
|
385
|
-
puts ip_address
|
386
|
-
client = CasperClient.new(ip_address)
|
387
|
-
clients.push(client)
|
388
|
-
end
|
389
|
-
|
390
|
-
|
391
|
-
clients.each do |client|
|
392
|
-
puts client.info_get_peers
|
393
|
-
puts client.chain_get_StateRootHash(block_hash)
|
394
|
-
puts client.chain_get_StateRootHash
|
395
|
-
puts client.info_get_deploy(deploy_hash)
|
396
|
-
puts client.info_get_status
|
397
|
-
puts client.chain_get_block_transfers(block_hash)
|
398
|
-
puts client.chain_get_block_transfers
|
399
|
-
puts client.chain_get_block(block_hash)
|
400
|
-
puts client.chain_get_eraInfo_by_SwitchBlock(switch_block_hash)
|
401
|
-
puts client.state_get_item("647C28545316E913969B032Cf506d5D242e0F857061E70Fb3DF55980611ace86", "bid-24b6D5Aabb8F0AC17D272763A405E9CECa9166B75B745Cf200695E172857c2dD", [])
|
402
|
-
puts client.state_get_dictionary_item(state_root_hash, item_key, uref)
|
403
|
-
state_root_hash = "610e932aef10d3e1fa04940c79a4a2789ee79c17046f1a9b45a2919f3600f3d5"
|
404
|
-
uref = "uref-7de5e973b7d70bc2b328814411f2009aafd8dba901cfc2c588ba65088dcd22bb-007"
|
405
|
-
puts client.state_get_balance(state_root_hash, uref)
|
406
|
-
puts client.state_get_AuctionInfo
|
407
|
-
|
408
|
-
end
|
409
|
-
else
|
410
|
-
puts "Invalid IP address"
|
411
|
-
end
|
412
|
-
```
|
413
|
-
- [Testnet](https://testnet.cspr.live/tools/peers), [Mainnet](https://cspr.live/tools/peers)
|
414
|
-
- [doc](https://www.rubydoc.info/gems/casper_network/0.2.1)
|
538
|
+
block_hash = "5fdbdf3fa70d37821aa2d1752743e9653befc15e65e40c2655e1ce93a807260f"
|
539
|
+
node_ip_address = "65.108.78.120" # => Taken from Mainnet
|
540
|
+
client = Casper::CasperClient.new(node_ip_address)
|
415
541
|
|
542
|
+
# Uncomment following lines to see the outputs
|
543
|
+
# auction = client.state_get_AuctionInfo
|
544
|
+
# Retrieve and print an instance of AuctionState entity
|
545
|
+
# puts auction # => #<Casper::Entity::AuctionState:0x0000000003306bc0>
|
546
|
+
# Retrieve and print state root hash as a String value
|
547
|
+
# puts auction.get_state_root_hash # => "6448b55f1dd7c9ad337f4fd4c77586d7ae30da146e0b340932aba7e7efa9cbcb"
|
548
|
+
# Retrieve and print block height as an Integer value
|
549
|
+
# puts auction.get_block_height # => 1128800
|
550
|
+
# Retrieve and print an array of instances of EraValidor entity
|
551
|
+
# puts auction.get_era_validators # => [#<Casper::Entity::EraValidator:0x0000000002b69980>, #<Casper::Entity::EraValidator:0x0000000002b68940>]
|
552
|
+
# Retrieve and print an array of instances of Bid entity
|
553
|
+
# puts auction.get_bids # => [#<Casper::Entity::Bid:0x000000000430bcf0>, #<Casper::Entity::Bid:0x000000000430b6d8>....]
|
416
554
|
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
555
|
+
# Retrieve and print an instance of BidInfo, which is also the member of bid object
|
556
|
+
# bids = auction.get_bids
|
557
|
+
# bid = bids[0] # => #<Casper::Entity::Bid:0x0000000003773dc0>
|
558
|
+
# bid_info = bid.get_bid_info # => #<Casper::Entity::BidInfo:0x00000000042cffc0>
|
559
|
+
# Retrieve and print an array of delegator objects, which are instance of Delegator entity
|
560
|
+
# delegators = bid_info.get_delegators
|
561
|
+
# puts delegators # => [#<Casper::Entity::Delegator:0x000000000396c550>, #<Casper::Entity::Delegator:0x000000000396c500>.....]
|
562
|
+
# How to access members of one of the above delegator instances
|
563
|
+
# For instance, access to stake amount at first delegator
|
564
|
+
# delegator = delegators[0]
|
565
|
+
# stake_amount = delegator.get_staked_amount # => 27871095039894
|
566
|
+
```
|
data/lib/casper_network.rb
CHANGED
@@ -15,6 +15,8 @@ require_relative './serialization/deploy_serializer.rb'
|
|
15
15
|
# Dir["./serialization/*.rb"].each {|file| require file }
|
16
16
|
# Dir["./types/*.rb"].each {|file| require file }
|
17
17
|
require_relative './include.rb'
|
18
|
+
require_relative './crypto/ed25519_key.rb'
|
19
|
+
require_relative './crypto/asymmetric_key.rb'
|
18
20
|
module Casper
|
19
21
|
# Interacting with the network
|
20
22
|
class CasperClient
|
@@ -281,7 +283,7 @@ module Casper
|
|
281
283
|
state_root_hash = @auction_state[:state_root_hash]
|
282
284
|
block_height = @auction_state[:block_height]
|
283
285
|
era_validators = @auction_state[:era_validators]
|
284
|
-
|
286
|
+
|
285
287
|
bids = @auction_state[:bids]
|
286
288
|
Casper::Entity::AuctionState.new(state_root_hash, block_height, era_validators, bids)
|
287
289
|
}
|
@@ -293,9 +295,10 @@ module Casper
|
|
293
295
|
|
294
296
|
# @param [Deploy] deploy
|
295
297
|
def put_deploy(deploy)
|
296
|
-
client = Jimson::Client.new(url)
|
297
|
-
response = client.account_put_deploy(
|
298
|
-
|
298
|
+
client = Jimson::Client.new(@url)
|
299
|
+
response = client.account_put_deploy({
|
300
|
+
"deploy" => deploy
|
301
|
+
})
|
299
302
|
end
|
300
303
|
|
301
304
|
end
|
@@ -3,15 +3,15 @@ require_relative '../types/cl_public_key.rb'
|
|
3
3
|
require_relative '../utils/hex_utils.rb'
|
4
4
|
require_relative '../utils/hash_utils.rb'
|
5
5
|
|
6
|
-
CLPublicKeyTag = {
|
7
|
-
|
8
|
-
|
9
|
-
}
|
6
|
+
# CLPublicKeyTag = {
|
7
|
+
# ED25519: 1,
|
8
|
+
# SECP256K1: 2
|
9
|
+
# }
|
10
10
|
|
11
|
-
SignatureAlgorithm = {
|
12
|
-
|
13
|
-
|
14
|
-
}
|
11
|
+
# SignatureAlgorithm = {
|
12
|
+
# Ed25519: 'ed25519',
|
13
|
+
# Secp256K1: 'secp256k1'
|
14
|
+
# }
|
15
15
|
|
16
16
|
class AsymmetricKey
|
17
17
|
attr_reader :public_key, :private_key, :signature_algorithm
|
@@ -19,7 +19,8 @@ class AsymmetricKey
|
|
19
19
|
# @param [CLPublicKey] public_key
|
20
20
|
# @param [Array] private_key
|
21
21
|
# @param [SignatureAlgorithm] signature_algorithm
|
22
|
-
def initialize(public_key,
|
22
|
+
def initialize(public_key = CLPublicKey.new([204, 238, 25, 54, 110, 175, 3, 72, 124, 184, 17, 151, 174, 142, 220,
|
23
|
+
177, 180, 127, 33, 76, 238, 0, 214, 89, 115, 128, 9, 107, 159, 132, 99, 193], 1), private_key = nil, signature_algorithm = nil)
|
23
24
|
@public_key = public_key
|
24
25
|
@private_key = private_key
|
25
26
|
@signature_algorithm = signature_algorithm
|
@@ -49,15 +50,15 @@ class AsymmetricKey
|
|
49
50
|
end
|
50
51
|
|
51
52
|
# @return [Array<Integer>]
|
52
|
-
def account_hash
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
end
|
53
|
+
# def account_hash
|
54
|
+
# @tag = @public_key.get_cl_public_key_tag
|
55
|
+
# key_name = CLPublicKeyTag.key(@tag).to_s
|
56
|
+
# prefix = key_name.downcase.unpack("C*") + [0]
|
57
|
+
# bytes = prefix + @public_key.get_value
|
58
|
+
# result_array = Utils::HashUtils.byte_hash(bytes)
|
59
|
+
# @public_key.get_value.length == 0 ? [] : result_array
|
60
|
+
# #*** @public_key.to_account_hash_byte_array
|
61
|
+
# end
|
61
62
|
|
62
63
|
# @param [String] path_to_private_key
|
63
64
|
def create_from_private_key_file(path_to_private_key)
|
@@ -0,0 +1,114 @@
|
|
1
|
+
require 'ed25519'
|
2
|
+
require 'blake2b'
|
3
|
+
require 'chilkat'
|
4
|
+
signing_key = Ed25519::SigningKey.generate
|
5
|
+
# puts "signing_key:\t #{signing_key}"
|
6
|
+
# puts "seed:\t #{signing_key.seed}"
|
7
|
+
# puts "keypair:\t #{signing_key.keypair}"
|
8
|
+
# puts "verify_key:\t #{signing_key.verify_key}"
|
9
|
+
# serialized_deploy_to_hash = "dc7edd3dde249343bc379564724b3e30116d8d84702a589513728f2e09bcd167"
|
10
|
+
# signature = Ed25519.provider.sign("MC4CAQAwBQYDK2VwBCIEIKf7pd4LhteUsRPmagsm7by7YWZVM+thD/fWoP+QDZO7", serialized_deploy_to_hash)
|
11
|
+
|
12
|
+
# key = Blake2b::Key.none
|
13
|
+
# signature = "01" + Blake2b.hex(signature, key, 64)
|
14
|
+
# puts signature
|
15
|
+
# message = "hello"
|
16
|
+
# signature = signing_key.sign(message)
|
17
|
+
# puts "signature:\t #{signature}"
|
18
|
+
|
19
|
+
# verify_key = signing_key.verify_key
|
20
|
+
# puts "verify_key:\t #{verify_key}"
|
21
|
+
|
22
|
+
# check_validity_of_signature = verify_key.verify(signature, message)
|
23
|
+
# puts "check_validity_of_signature:\t #{check_validity_of_signature}"
|
24
|
+
|
25
|
+
# # Serializing Keys
|
26
|
+
# signature_key_bytes = signing_key.to_bytes
|
27
|
+
# puts "signature_key_bytes:\t #{signature_key_bytes}"
|
28
|
+
# verify_key_bytes = verify_key.to_bytes
|
29
|
+
# puts "verify_key_bytes:\t #{verify_key_bytes}"
|
30
|
+
|
31
|
+
# signing_key = Ed25519::SigningKey.new(signature_key_bytes)
|
32
|
+
# puts "signing_key:\t #{signing_key}"
|
33
|
+
# verify_key = Ed25519::VerifyKey.new(verify_key_bytes)
|
34
|
+
# puts "verify_key:\t #{verify_key}
|
35
|
+
|
36
|
+
|
37
|
+
#************************************************************************************************************
|
38
|
+
|
39
|
+
|
40
|
+
# Load an Ed25519 key
|
41
|
+
privKey = Chilkat::CkPrivateKey.new()
|
42
|
+
|
43
|
+
# Load an Ed25519 key from an unencrypted PEM file (no password required).
|
44
|
+
success = privKey.LoadAnyFormatFile("#{Dir.home}/Downloads/ed25519_secret_key.pem","")
|
45
|
+
if (success == false)
|
46
|
+
print privKey.lastErrorText() + "\n";
|
47
|
+
exit
|
48
|
+
end
|
49
|
+
|
50
|
+
# The key type should be "ed25519" to indicate an Ed25519 key.
|
51
|
+
print "key type = " + privKey.keyType() + "\n";
|
52
|
+
# key type = ed25519
|
53
|
+
|
54
|
+
# # What is the size of the private key in bits? (should always be 256 bits for Ed25519)
|
55
|
+
print "size in bits = " + privKey.get_BitLength().to_s() + "\n";
|
56
|
+
# size in bits = 256
|
57
|
+
|
58
|
+
# # Get the private and public key parts in raw hex format:
|
59
|
+
sbPubKeyHex = Chilkat::CkStringBuilder.new()
|
60
|
+
privKeyHex = privKey.getRawHex(sbPubKeyHex)
|
61
|
+
|
62
|
+
# # We should have a 32-byte private key (a 64 character hex string).
|
63
|
+
print "private key = " + privKeyHex + "\n";
|
64
|
+
# private key = a7fba5de0b86d794b113e66a0b26edbcbb61665533eb610ff7d6a0ff900d93bb
|
65
|
+
|
66
|
+
# # We should have a 32-byte public key (a 64 character hex string).
|
67
|
+
print "public key = " + sbPubKeyHex.getAsString() + "\n";
|
68
|
+
# public key = ccee19366eaf03487cb81197ae8edcb1b47f214cee00d6597380096b9f8463c1
|
69
|
+
|
70
|
+
|
71
|
+
|
72
|
+
# This example assumes the Chilkat API to have been previously unlocked.
|
73
|
+
# See Global Unlock Sample for sample code.
|
74
|
+
|
75
|
+
privKeyHex = "a7fba5de0b86d794b113e66a0b26edbcbb61665533eb610ff7d6a0ff900d93bb"
|
76
|
+
pubKeyHex = "ccee19366eaf03487cb81197ae8edcb1b47f214cee00d6597380096b9f8463c1"
|
77
|
+
|
78
|
+
privKey = Chilkat::CkPrivateKey.new()
|
79
|
+
# This example shows only one way of loading an Ed25519 private key.
|
80
|
+
# Chilkat can load other formats (JWK, PEM, ASN.1 DER, etc.)
|
81
|
+
# You may do so by calling LoadAnyFormat or LoadAnyFormatFile.
|
82
|
+
success = privKey.LoadEd25519(privKeyHex,pubKeyHex)
|
83
|
+
if (success == false)
|
84
|
+
print privKey.lastErrorText() + "\n";
|
85
|
+
exit
|
86
|
+
end
|
87
|
+
|
88
|
+
# The data to be signed...
|
89
|
+
bd = Chilkat::CkBinData.new()
|
90
|
+
deploy_hash = "633435d9660122917fd5b4de16b7f495959cd832b9ef293486c6893dc694ec26"
|
91
|
+
bd.AppendString(deploy_hash,"utf-8")
|
92
|
+
eddsa = Chilkat::CkEdDSA.new()
|
93
|
+
hexSig = eddsa.signBdENC(bd,"hexlower",privKey)
|
94
|
+
|
95
|
+
print "signature = " + "01" + hexSig + "\n";
|
96
|
+
|
97
|
+
# The expected output is: 016d49ac6138e556c9174c9c8e0d512bbb4697bbe3e96a28d8c1be83ea05c3a5945b6b87e4c974ae04e6cbcbac78bbbce672648444e269bdf30d27686fa03a440e
|
98
|
+
|
99
|
+
# # Verify the signature..
|
100
|
+
pubKey = Chilkat::CkPublicKey.new()
|
101
|
+
success = pubKey.LoadEd25519(pubKeyHex)
|
102
|
+
if (success == false)
|
103
|
+
print pubKey.lastErrorText() + "\n";
|
104
|
+
exit
|
105
|
+
end
|
106
|
+
puts pubKey
|
107
|
+
bVerified = eddsa.VerifyBdENC(bd,hexSig,"hexlower",pubKey)
|
108
|
+
if (bVerified == false)
|
109
|
+
print eddsa.lastErrorText() + "\n";
|
110
|
+
print "Failed to verify the signature." + "\n";
|
111
|
+
exit
|
112
|
+
end
|
113
|
+
|
114
|
+
print "The Ed25519 signature is verified!" + "\n";
|
data/lib/crypto/ed25519_key.rb
CHANGED
@@ -1,23 +1,129 @@
|
|
1
1
|
require 'openssl'
|
2
2
|
require 'ed25519'
|
3
|
-
|
3
|
+
require 'blake2b'
|
4
|
+
require 'chilkat'
|
5
|
+
|
6
|
+
# CLPublicKeyTag = {
|
7
|
+
# ED25519: 1,
|
8
|
+
# SECP256K1: 2
|
9
|
+
# }
|
4
10
|
|
5
11
|
# ED25519 private key length in bytes
|
6
12
|
PRIVATE_KEY_LENGTH = 32
|
7
13
|
|
8
|
-
class Ed25519Key
|
14
|
+
class Ed25519Key
|
15
|
+
# attr_reader :public_key, :private_key, :signature_algorithm
|
16
|
+
attr_accessor :public_key_hex, :signature_algorithm, :privKey, :private_key_hex
|
17
|
+
# attr_reader :private_key_hex, :privKey
|
18
|
+
include Utils::HashUtils
|
19
|
+
|
20
|
+
def initialize()
|
21
|
+
# file_path = "#{Dir.home}/ed25519_secret_key.pem"
|
22
|
+
@file_path = "#{Dir.home}/ed25519_secret_key.pem"
|
23
|
+
@privKey = Chilkat::CkPrivateKey.new()
|
24
|
+
|
25
|
+
# This loads an Ed25519 key from an unencrypted PEM file (no password required).
|
26
|
+
success = @privKey.LoadAnyFormatFile(@file_path,"")
|
27
|
+
if (success == false)
|
28
|
+
print @privKey.lastErrorText() + "\n";
|
29
|
+
exit
|
30
|
+
end
|
31
|
+
|
32
|
+
@signature_algorithm = @privKey.keyType()
|
33
|
+
|
34
|
+
# 32-byte (256-bit)
|
35
|
+
@private_key_bit_length = @privKey.get_BitLength
|
36
|
+
|
37
|
+
# Get the private and public key parts in raw hex format
|
38
|
+
sbPubKeyHex = Chilkat::CkStringBuilder.new()
|
39
|
+
|
40
|
+
@private_key_hex = @privKey.getRawHex(sbPubKeyHex)
|
41
|
+
|
42
|
+
@public_key_hex = sbPubKeyHex.getAsString()
|
43
|
+
|
44
|
+
success = @privKey.LoadEd25519(@private_key_hex, @public_key_hex)
|
45
|
+
if (success == false)
|
46
|
+
print @privKey.lastErrorText() + "\n";
|
47
|
+
exit
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def get_public_key
|
52
|
+
raise ArgumentError, "Expected a 64 character hex String" unless @public_key_hex.length == 64
|
53
|
+
return "01" + @public_key_hex
|
54
|
+
end
|
55
|
+
|
56
|
+
def get_private_key
|
57
|
+
raise ArgumentError, "Expected a 64 character hex String" unless @private_key_hex.length == 64
|
58
|
+
return @private_key_hex
|
59
|
+
end
|
60
|
+
|
61
|
+
# @return [String] an encoded string, as specified by the encoding argument.
|
62
|
+
def get_private_key_base_encoded_format(encoding)
|
63
|
+
# encoding can be "base64"
|
64
|
+
privKey.getPkcs1ENC(encoding)
|
65
|
+
end
|
66
|
+
|
67
|
+
def sign(message)
|
68
|
+
success = @privKey.LoadEd25519(@private_key_hex, @public_key_hex)
|
69
|
+
if (success == false)
|
70
|
+
print @privKey.lastErrorText() + "\n";
|
71
|
+
exit
|
72
|
+
end
|
73
|
+
@message = message
|
74
|
+
# @message = Utils::ByteUtils.hex_to_byte_array(@message)
|
75
|
+
|
76
|
+
|
77
|
+
byteData = Chilkat::CkByteData.new()
|
78
|
+
byteData.appendEncoded(@message, "hex");
|
79
|
+
|
80
|
+
@bd = Chilkat::CkBinData.new()
|
81
|
+
@bd.AppendBinary(byteData)
|
82
|
+
|
83
|
+
@signer = Chilkat::CkEdDSA.new()
|
84
|
+
@signature = @signer.signBdENC(@bd, "hexlower", @privKey)
|
85
|
+
if @signature_algorithm == "ed25519"
|
86
|
+
@prefix = "0#{CLPublicKeyTag[:ED25519]}"
|
87
|
+
@signature = @prefix + @signature
|
88
|
+
end
|
89
|
+
@signature
|
90
|
+
end
|
91
|
+
|
92
|
+
# Verify the signature
|
93
|
+
def verify(signature, message)
|
94
|
+
pubKey = Chilkat::CkPublicKey.new()
|
95
|
+
success = pubKey.LoadEd25519(@public_key_hex)
|
96
|
+
if (success == false)
|
97
|
+
print pubKey.lastErrorText() + "\n";
|
98
|
+
exit
|
99
|
+
end
|
100
|
+
# Remove prefix "01"
|
101
|
+
signature = signature[2...]
|
102
|
+
verified = @signer.VerifyBdENC(@bd, signature, "hex", pubKey);
|
103
|
+
if (verified == false)
|
104
|
+
print @signer.lastErrorText() + "\n";
|
105
|
+
print "Failed to verify the signature." + "\n";
|
106
|
+
exit
|
107
|
+
end
|
108
|
+
return true
|
9
109
|
|
10
|
-
def initialize(public_key, private_key)
|
11
|
-
super(public_key, private_key, SignatureAlgorithm[:Ed25519])
|
12
110
|
end
|
13
111
|
|
112
|
+
def public_key
|
113
|
+
if @signature_algorithm == "ed25519" && @private_key_hex.length == 64
|
114
|
+
prefix = "01"
|
115
|
+
@public_key = prefix + @public_key_hex
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
|
14
120
|
# @param [Array] public_key
|
15
121
|
# @return [String]
|
16
122
|
# def self.account_hex(public_key)
|
17
123
|
# '01' + Utils::Base16.encode16(public_key)
|
18
124
|
# end
|
19
125
|
|
20
|
-
|
126
|
+
# @param [String] private_key_path
|
21
127
|
def create_from_private_key_file(private_key_path)
|
22
128
|
|
23
129
|
end
|
@@ -28,11 +134,6 @@ class Ed25519Key < AsymmetricKey
|
|
28
134
|
def export_private_key_in_pem
|
29
135
|
end
|
30
136
|
|
31
|
-
def sign(msg)
|
32
|
-
end
|
33
|
-
|
34
|
-
def verify(signature, msg)
|
35
|
-
end
|
36
137
|
|
37
138
|
def private_to_public_key(private_key)
|
38
139
|
end
|