Overview
Comment: | Added an RPC client REPL |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
e9fd1f6094151578975cbb7541263437 |
User & Date: | rkeene on 2018-12-09 22:10:47 |
Other Links: | manifest | tags |
Context
2018-12-09
| ||
22:11 | Removed extra auto_paths check-in: 542443e166 user: rkeene tags: trunk | |
22:10 | Added an RPC client REPL check-in: e9fd1f6094 user: rkeene tags: trunk | |
02:24 | Include information on what is required to build check-in: 5980af203a user: rkeene tags: trunk | |
Changes
Modified nano.tcl from [0b1342a368] to [58efd19329].
︙ | ︙ | |||
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | namespace eval ::nano::work {} namespace eval ::nano::account {} namespace eval ::nano::node {} namespace eval ::nano::ledger {} namespace eval ::nano::ledger::lmdb {} namespace eval ::nano::rpc {} namespace eval ::nano::rpc::client {} namespace eval ::nano::balance {} namespace eval ::nano::node::bootstrap {} namespace eval ::nano::node::realtime {} namespace eval ::nano::node::cli {} namespace eval ::nano::network::client {} namespace eval ::nano::network::server {} namespace eval ::nano::protocol::create {} namespace eval ::nano::protocol::parse {} namespace eval ::nano::protocol::extensions {} namespace eval ::nano::network::_dns {} # Constants set ::nano::block::genesis(main) {{ "type": "open", "source": "E89208DD038FBB269987689621D52292AE9C35941A7484756ECCED92A65093BA", "representative": "xrb_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3", "account": "xrb_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3", | > > | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | namespace eval ::nano::work {} namespace eval ::nano::account {} namespace eval ::nano::node {} namespace eval ::nano::ledger {} namespace eval ::nano::ledger::lmdb {} namespace eval ::nano::rpc {} namespace eval ::nano::rpc::client {} namespace eval ::nano::rpc::cli {} namespace eval ::nano::balance {} namespace eval ::nano::node::bootstrap {} namespace eval ::nano::node::realtime {} namespace eval ::nano::node::cli {} namespace eval ::nano::network::client {} namespace eval ::nano::network::server {} namespace eval ::nano::protocol::create {} namespace eval ::nano::protocol::parse {} namespace eval ::nano::protocol::extensions {} namespace eval ::nano::network::_dns {} namespace eval ::nano::_cli {} # Constants set ::nano::block::genesis(main) {{ "type": "open", "source": "E89208DD038FBB269987689621D52292AE9C35941A7484756ECCED92A65093BA", "representative": "xrb_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3", "account": "xrb_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3", |
︙ | ︙ | |||
61 62 63 64 65 66 67 68 69 70 71 72 73 74 | "confirm_ack" "bulk_pull" "bulk_push" "frontier_req" "bulk_pull_blocks" "node_id_handshake" "bulk_pull_account" } set ::nano::balance::_conversion { GNano 1000000000000000000000000000000000000000 MNano 1000000000000000000000000000000000000 Gnano 1000000000000000000000000000000000 Gxrb 1000000000000000000000000000000000 KNano 1000000000000000000000000000000000 | > > > > > > > > > | 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | "confirm_ack" "bulk_pull" "bulk_push" "frontier_req" "bulk_pull_blocks" "node_id_handshake" "bulk_pull_account" } set ::nano::block::blockTypes { "invalid" "not_a_block" "send" "receive" "open" "change" "state" } set ::nano::balance::_conversion { GNano 1000000000000000000000000000000000000000 MNano 1000000000000000000000000000000000000 Gnano 1000000000000000000000000000000000 Gxrb 1000000000000000000000000000000000 KNano 1000000000000000000000000000000000 |
︙ | ︙ | |||
508 509 510 511 512 513 514 | } default { return -code error "Invalid option: $arg" } } } | < | | | | < < < | | 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 | } default { return -code error "Invalid option: $arg" } } } set type [string tolower $type] set typeId [lsearch -exact $::nano::block::blockTypes $type] if {$typeId == -1} { error "Invalid type: $type" } switch -- $outputFormat { "decimal" { set result $typeId } "hex" { |
︙ | ︙ | |||
566 567 568 569 570 571 572 | } "bytes" { set typeId [binary encode hex $typeId] set typeId "0x${typeId}" } } | | < < | < | < < < | < | 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 | } "bytes" { set typeId [binary encode hex $typeId] set typeId "0x${typeId}" } } set typeId [format %i $typeId] set type [lindex $::nano::block::blockTypes $typeId] if {$type eq ""} { error "Invalid type ID: $typeId" } return $type } proc ::nano::block::lengthFromType {type args} { set includeType false |
︙ | ︙ | |||
3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 | if {[info coroutine] eq ""} { after $ms } else { after $ms [info coroutine] yield } } proc ::nano::node::getPeers {} { if {[info exists ::nano::node::configuration]} { set peers [dict get $::nano::node::configuration node preconfigured_peers] set defaultPeerPort [dict get $::nano::node::configuration node peering_port] } else { return [list] } set completePeers [list] foreach peer $peers { catch { foreach peer [::nano::network::_dns::toIPList $peer] { | > > > > > > > > > > > > > > > > > | | 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 | if {[info coroutine] eq ""} { after $ms } else { after $ms [info coroutine] yield } } proc ::nano::internal::parseAddress {address defaultPort} { set addressPort $defaultPort if {[string index $address 0] eq "\["} { regexp {\]:(.*)$} $address -> addressPort regexp {^\[(.*)\].*$} $address -> address regexp {^::ffff:([0-9\.]*$)} $address -> address } elseif {[string match "*:*" $address]} { set address [split $address :] set addressPort [lindex $address 1] set address [lindex $address 0] } return [list $address $addressPort] } proc ::nano::node::getPeers {} { if {[info exists ::nano::node::configuration]} { set peers [dict get $::nano::node::configuration node preconfigured_peers] set defaultPeerPort [dict get $::nano::node::configuration node peering_port] } else { return [list] } set completePeers [list] foreach peer $peers { lassign [::nano::internal::parseAddress $peer $defaultPeerPort] peer peerPort catch { foreach peer [::nano::network::_dns::toIPList $peer] { lappend completePeers [dict create address $peer port $peerPort] } } } set now [clock seconds] # Cleanup nonces while we are here foreach {peerKey peerInfo} [array get ::nano::node::_node_id_nonces] { |
︙ | ︙ | |||
3301 3302 3303 3304 3305 3306 3307 | set votedOn [llength $hashes] incr ::nano::node::stats([list confirm_ack votedOnCount]) $votedOn incr ::nano::node::stats([list confirm_ack rep $voteAccount votedOnCount]) $votedOn foreach hash $hashes { | | | | | 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 | set votedOn [llength $hashes] incr ::nano::node::stats([list confirm_ack votedOnCount]) $votedOn incr ::nano::node::stats([list confirm_ack rep $voteAccount votedOnCount]) $votedOn foreach hash $hashes { set ::nano::node::_stats_seen_hashes([list confirm_ack $hash]) 1 set ::nano::node::_stats_seen_hashes_by_rep([list $voteAccount $hash]) 1 } set ::nano::node::stats([list confirm_ack votedOnUniqueCount]) [llength [array names ::nano::node::_stats_seen_hashes [list confirm_ack *]]] set ::nano::node::stats([list confirm_ack rep $voteAccount votedOnUniqueCount]) [llength [array names ::nano::node::_stats_seen_hashes_by_rep [list $voteAccount *]]] return "" } proc ::nano::protocol::parse::publish {extensions messageData} { set blockTypeID [expr {($extensions >> 8) & 0x0f}] |
︙ | ︙ | |||
3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 | return [array get retval] } proc ::nano::network::server::publish {messageDict} { #puts "block: [binary encode hex $blockData]" #9e1272edade3c247c738a4bd303eb0cfc3da298444bb9d13b8ffbced34ff036f4e1ff833324efc81c237776242928ef76a2cdfaa53f4c4530ee39bfff1977e26e382dd09ec8cafc2427cf817e9afe1f372ce81085ab4feb1f3de1f25ee818e5d000000008fc492fd20e57d048e000000204e7a62f25df739eaa224d403cb107b3f9caa0280113b0328fad3b402c465169006f988549a8b1e20e0a09b4b4dcae5397f6fcc4d507675f58c2b29ae02341b0a4fe562201a61bf27481aa4567c287136b4fd26b4840c93c42c7d1f5c518503d68ec561af4b8cf8 #9e1272edade3c247c738a4bd303eb0cfc3da298444bb9d13b8ffbced34ff036fa5e3647d3d296ec72baea013ba7fa1bf5c3357c33c90196f078ba091295e6e03e382dd09ec8cafc2427cf817e9afe1f372ce81085ab4feb1f3de1f25ee818e5d000000008fb2604ebd1fe098b8000000204e7a62f25df739eaa224d403cb107b3f9caa0280113b0328fad3b402c465165287cd9c61752dc9d011f666534dbdc10461e927503f9599791d73b1cca7fdc032d76db3f91e5b5c3d6206fa48b01bd08da4a89f2e880242e9917cfc3db80d0b9bfe8e6d1dd183d5 return "" } # Namespace ::nano::protocol::parse deals with the network level protocol (outside the node) # Namespace ::nano::network::server deals with the node's actual interaction with the network proc ::nano::protocol::parse {message} { set messageParsed [binary scan $message a2ccccsa* \ | > > > > > > > > > | 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 | return [array get retval] } proc ::nano::network::server::publish {messageDict} { #puts "block: [binary encode hex $blockData]" #9e1272edade3c247c738a4bd303eb0cfc3da298444bb9d13b8ffbced34ff036f4e1ff833324efc81c237776242928ef76a2cdfaa53f4c4530ee39bfff1977e26e382dd09ec8cafc2427cf817e9afe1f372ce81085ab4feb1f3de1f25ee818e5d000000008fc492fd20e57d048e000000204e7a62f25df739eaa224d403cb107b3f9caa0280113b0328fad3b402c465169006f988549a8b1e20e0a09b4b4dcae5397f6fcc4d507675f58c2b29ae02341b0a4fe562201a61bf27481aa4567c287136b4fd26b4840c93c42c7d1f5c518503d68ec561af4b8cf8 #9e1272edade3c247c738a4bd303eb0cfc3da298444bb9d13b8ffbced34ff036fa5e3647d3d296ec72baea013ba7fa1bf5c3357c33c90196f078ba091295e6e03e382dd09ec8cafc2427cf817e9afe1f372ce81085ab4feb1f3de1f25ee818e5d000000008fb2604ebd1fe098b8000000204e7a62f25df739eaa224d403cb107b3f9caa0280113b0328fad3b402c465165287cd9c61752dc9d011f666534dbdc10461e927503f9599791d73b1cca7fdc032d76db3f91e5b5c3d6206fa48b01bd08da4a89f2e880242e9917cfc3db80d0b9bfe8e6d1dd183d5 # XXX:TODO: Validate set valid true incr ::nano::node::stats([list publish valid $valid]) set hash [dict get $messageDict hash] set ::nano::node::_stats_seen_hashes([list publish $hash]) 1 set ::nano::node::stats([list publish unique]) [llength [array names ::nano::node::_stats_seen_hashes [list publish *]]] return "" } # Namespace ::nano::protocol::parse deals with the network level protocol (outside the node) # Namespace ::nano::network::server deals with the node's actual interaction with the network proc ::nano::protocol::parse {message} { set messageParsed [binary scan $message a2ccccsa* \ |
︙ | ︙ | |||
3568 3569 3570 3571 3572 3573 3574 3575 3576 | vwait ::nano::node::_FOREVER_ } } # RPC Client ## Side-effect: Sets ::nano::rpc::client::config proc ::nano::rpc::client::init args { if {![info exists ::nano::rpc::client::config]} { set ::nano::rpc::client::config [dict create \ | > > | | | 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 | vwait ::nano::node::_FOREVER_ } } # RPC Client ## Side-effect: Sets ::nano::rpc::client::config proc ::nano::rpc::client::init args { package require http 2 if {![info exists ::nano::rpc::client::config]} { set ::nano::rpc::client::config [dict create \ -url "http://localhost:7076/" \ ] } if {[llength $args] > 0} { set ::nano::rpc::client::config [dict merge $::nano::rpc::client::config $args] } return true } proc ::nano::rpc::client {action args} { ::nano::rpc::client::init set rpcURL [dict get $::nano::rpc::client::config "-url"] set jsonArgs [list] foreach {key value} $args { switch -exact -- $key { "-count" {} "-accounts" { set valueAsStrings [lmap valueItem $value { json::write string $valueItem }] |
︙ | ︙ | |||
3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 | set data [json::json2dict $data] return $data } # Account balance manipulation proc ::nano::balance::toUnit {raw toUnit {decimals 0}} { set divisor [dict get $::nano::balance::_conversion $toUnit] if {$decimals == 0} { set balance [expr {entier(($raw / ($divisor * 1.0)) + 0.5)}] } else { set balance [expr {$raw / ($divisor * 1.0)}] set balance [format "%.${decimals}f" $balance] | > > > > > > > > | 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 | set data [json::json2dict $data] return $data } # Account balance manipulation proc ::nano::balance::toUnit {raw toUnit {decimals 0}} { if {![string is entier -strict $raw]} { error "Raw values must not be fractional" } if {$toUnit eq "raw"} { return $raw } set divisor [dict get $::nano::balance::_conversion $toUnit] if {$decimals == 0} { set balance [expr {entier(($raw / ($divisor * 1.0)) + 0.5)}] } else { set balance [expr {$raw / ($divisor * 1.0)}] set balance [format "%.${decimals}f" $balance] |
︙ | ︙ | |||
3684 3685 3686 3687 3688 3689 3690 | } } proc ::nano::balance::toHuman {raw {decimals 3}} { set humanUnit [normalizeUnitName _USER] set humanUnitMultiplier [dict get $::nano::balance::_conversion $humanUnit] | | > | > > | > > > > | > > > > > > > > > > > > > > > > > | | > > > > | < < | 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 | } } proc ::nano::balance::toHuman {raw {decimals 3}} { set humanUnit [normalizeUnitName _USER] set humanUnitMultiplier [dict get $::nano::balance::_conversion $humanUnit] if {$raw > [expr {$humanUnitMultiplier / (10 ** $decimals)}]} { set baseUnit $humanUnit } else { set baseUnit "raw" } set balance [toUnit $raw $baseUnit $decimals] set work [split $balance "."] set leading [lindex $work 0] set trailing [string trimright [lindex $work 1] "0"] set balance [join [list $leading $trailing] "."] set balance [string trimright $balance "."] set result [list $balance $baseUnit] return $result } # Generic CLI helpers proc ::nano::_cli {namespace args} { for {set argIndex 0} {$argIndex < [llength $args]} {incr argIndex} { set arg [lindex $args $argIndex] switch -exact -- $arg { "-prompt" { incr argIndex set prompt [lindex $args $argIndex] } "-interactive" { set mode "interactive" } "-import" { set mode "import" } default { error "Unknown argument: $arg" } } } if {![info exists mode]} { error "Must specify either -interactive or -import" } switch -exact -- $mode { "interactive" { set ::nano::${namespace}::cli::_using_repl true ::nano::_cli $namespace -import set use_tclreadline false catch { package require tclreadline set use_tclreadline true } if {![info exists prompt]} { set prompt { return "> " } } if {$use_tclreadline} { proc ::tclreadline::prompt1 {} $prompt ::tclreadline::Loop } else { fconfigure stdout -blocking false puts -nonewline "> " flush stdout fileevent stdin readable [list apply {{} { uplevel #0 { |
︙ | ︙ | |||
3747 3748 3749 3750 3751 3752 3753 | puts -nonewline "> " flush stdout }}] vwait forever } } | | < | | < | | | < | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 | puts -nonewline "> " flush stdout }}] vwait forever } } "import" { uplevel #0 [list namespace import ::nano::${namespace}::cli::*] } default { error "Not implemented: $mode" } } } proc ::nano::_cli::interval {interval} { set response [list] foreach {divisor unit} {60 seconds 60 minutes 24 hours 36527 days 1 century} { set amount [expr {$interval % $divisor}] if {$amount > 0} { if {$amount == 1} { set unit [string range $unit 0 end-1] } lappend response $unit $amount } set interval [expr {$interval / $divisor}] } return "[lreverse $response]" } proc ::nano::_cli::help {namespace commandRoot args} { set response [list] if {[llength $args] == 0} { lappend response "Commands:" set pattern [string trimleft "${commandRoot} *"] foreach command [lsort -dictionary [info command ::nano::${namespace}::cli::${pattern}]] { set command [namespace tail $command] if {[string match "_*" $command]} { continue } set extra [string trim [string range $command [string length $commandRoot] end]] if {[string first " " $extra] != -1} { continue } set description "" lappend response [format " %-12s - %s" $command $description] } } return [join $response "\n"] } proc ::nano::_cli::multiword {namespace baseCommand args} { if {[llength $args] == 0} { set args [list "help"] } set matched false set includeBaseCommand false foreach base [list $baseCommand multiword] { for {set included [expr {[llength $args] - 1}]} {$included >= 0} {incr included -1} { if {$base eq "multiword"} { set proc "::nano::_cli::${base} [join [lrange $args 0 $included] { }]" } else { set proc "::nano::${namespace}::cli::${base} [join [lrange $args 0 $included] { }]" } if {[info command $proc] ne ""} { set matched true break } } if {$matched} { if {$base eq "multiword"} { set includeBaseCommand true } break } } if {!$matched} { return -code error "No matching commands in $baseCommand [join $args { }]" } set args [lrange $args $included+1 end] if {$includeBaseCommand} { set args [concat [list $namespace $baseCommand] $args] } tailcall $proc {*}$args } proc {::nano::_cli::multiword help} {namespace base args} { tailcall help $namespace $base {*}$args } # Node CLI proc ::nano::node::cli {args} { tailcall ::nano::_cli node -prompt { return "\[[dict get $::nano::node::configuration network]\] nano-node [package present nano]> " } {*}$args } proc {::nano::node::cli::show uptime} {} { set now [clock seconds] set start $::nano::node::startTime set statsStart $::nano::node::statsStartTime set uptime [expr {$now - $start}] set uptimeStats [expr {$now - $statsStart}] set format {%-19s: %s} lappend response [format $format Uptime [::nano::_cli::interval $uptime]] lappend response [format $format "Stats last cleared" "[::nano::_cli::interval $uptimeStats] ago"] return [join $response "\n"] } proc {::nano::node::cli::show node-id} args { set nodeIDPrivate [dict get $::nano::node::configuration node client_id_private_key] set nodeIDPublic [::nano::key::publicKeyFromPrivateKey $nodeIDPrivate -hex] |
︙ | ︙ | |||
3857 3858 3859 3860 3861 3862 3863 | return } proc {::nano::node::cli::show version} {} { return [package present nano] } | < < < < < < < < < < < < < < < < < < < < < < < < < < | | 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 | return } proc {::nano::node::cli::show version} {} { return [package present nano] } proc ::nano::node::cli::help args { tailcall ::nano::_cli::help node "" {*}$args } proc {::nano::node::cli::show network} {} { return [dict get $::nano::node::configuration network] } proc {::nano::node::cli::show peers} args { |
︙ | ︙ | |||
3966 3967 3968 3969 3970 3971 3972 | } vwait ::nano::node::bootstrap::lazyRunning set endTime [clock seconds] set blocksPulled [::nano::node::bootstrap::TMP_LEDGER_BLOCKHASHCOUNT] set delta [expr {$endTime - $startTime}] | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | | 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 | } vwait ::nano::node::bootstrap::lazyRunning set endTime [clock seconds] set blocksPulled [::nano::node::bootstrap::TMP_LEDGER_BLOCKHASHCOUNT] set delta [expr {$endTime - $startTime}] puts "Pulled $blocksPulled blocks in [::nano::_cli::interval $delta]" } proc ::nano::node::cli::show {args} { tailcall ::nano::_cli::multiword node show {*}$args } proc ::nano::node::cli::config {args} { tailcall ::nano::_cli::multiword node config {*}$args } proc {::nano::node::cli::config get} {args} { set config $::nano::node::configuration dict set config node client_id_private_key [binary encode hex [dict get $config node client_id_private_key]] set subtreePrefix [lrange $args 0 end-1] set subtreeKey [lindex $args end] |
︙ | ︙ | |||
4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 | lappend response "" lappend response "New:" lappend response [{::nano::node::cli::config get} {*}$key] return [join $response "\n"] } namespace eval ::nano::node::cli { namespace export -clear * } if {[info exists ::nano::node::cli::_using_repl]} { ::nano::node::cli -import } | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 | lappend response "" lappend response "New:" lappend response [{::nano::node::cli::config get} {*}$key] return [join $response "\n"] } # RPC CLI proc ::nano::rpc::cli {args} { tailcall ::nano::_cli rpc -prompt { if {![info exists ::nano::rpc::cli::_cached_network]} { set ::nano::rpc::cli::_cached_network [{::nano::rpc::cli::show network}] } if {![info exists ::nano::rpc::cli::_cached_version]} { set ::nano::rpc::cli::_cached_version [{::nano::rpc::cli::show version} -vendor] } set network $::nano::rpc::cli::_cached_network set version $::nano::rpc::cli::_cached_version return "\[$network\] nano-rpc $version> " } {*}$args } proc ::nano::rpc::cli::help args { tailcall ::nano::_cli::help rpc "" {*}$args } proc ::nano::rpc::cli::show args { tailcall ::nano::_cli::multiword rpc show {*}$args } proc {::nano::rpc::cli::show uptime} args { set stats [::nano::rpc::client stats -type counters] set started [dict get $stats created] set started [clock scan $started -format {%Y.%m.%d %H:%M:%S}] set now [clock seconds] set delta [expr {$now - $started}] puts "$now, $started" return [::nano::_cli::interval $delta] } proc {::nano::rpc::cli::show stats} args { set response [list] if {[llength $args] == 0} { set args [list -counters -samples -bootstrap -blocks] } if {[lsearch -exact $args "-counters"] != -1} { lappend countersResponse "Counters:" set stats [::nano::rpc::client stats -type counters] foreach stat [dict get $stats entries] { set value [dict get $stat value] dict unset stat value lappend countersResponse " $stat = $value" } lappend response [join $countersResponse "\n"] } if {[lsearch -exact $args "-samples"] != -1} { unset -nocomplain stats set stats [::nano::rpc::client stats -type samples] set entries [dict get $stats entries] if {[llength $entries] > 0} { lappend samplesResponse "Samples:" foreach stat $entries { lappend samplesResponse " $stat" } lappend response [join $samplesResponse "\n"] } } if {[lsearch -exact $args "-bootstrap"] != -1} { catch { unset -nocomplain stats set stats [::nano::rpc::client bootstrap_status] } if {[info exists stats]} { lappend bootstrapResponse "Bootstrap:" set maxKeyLength 1 foreach {statName _} $stats { set keyLength [string length $statName] if {$keyLength > $maxKeyLength} { set maxKeyLength $keyLength } } foreach {statName statVal} $stats { lappend bootstrapResponse [format " %-${maxKeyLength}s = %s" $statName $statVal] } lappend response [join $bootstrapResponse "\n"] } } if {[lsearch -exact $args "-blocks"] != -1} { set blockCount [::nano::rpc::client block_count] lappend blocksResponse "Blocks:" lappend blocksResponse " Count = [dict get $blockCount count]" lappend blocksResponse " Unchecked = [dict get $blockCount unchecked]" lappend response [join $blocksResponse "\n"] } return [join $response "\n\n"] } proc {::nano::rpc::cli::show network} args { foreach network {main beta} { set genesisBlock [::nano::block::dict::genesis $network] set genesisBlockHash [::nano::block::dict::toHash $genesisBlock -hex] catch { set check [dict create] set check [::nano::rpc::client block -hash $genesisBlockHash] } if {[dict exists $check contents]} { return $network } } return "<unknown>" } proc {::nano::rpc::cli::show version} args { set versions [::nano::rpc::client version] set vendor [dict get $versions node_vendor] set vendorVersion [lindex [split $vendor] end] if {[lsearch -exact $args "-vendor"] != -1} { return $vendorVersion } return $versions } proc {::nano::rpc::cli::show peers} args { set peers [dict get [::nano::rpc::client peers] "peers"] if {[lindex $args 0] eq "-count"} { return [expr {[llength $peers] / 2}] } set result [list] foreach {peer peerVersion} $peers { lassign [::nano::internal::parseAddress $peer ""] peer peerPort set peer [list address $peer port $peerPort] lappend result " $peer: version $peerVersion" } return [join $result "\n"] } # Export namespaces namespace eval ::nano::node::cli { namespace export -clear * } namespace eval ::nano::rpc::cli { namespace export -clear * } if {[info exists ::nano::node::cli::_using_repl]} { ::nano::node::cli -import } if {[info exists ::nano::rpc::cli::_using_repl]} { ::nano::rpc::cli -import } |
Added rpc-client.tcl version [42f34ebffa].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | #! /usr/bin/env tclsh lappend auto_path [pwd] lappend auto_path /opt/appfs/rkeene.org/tcllib/platform/latest/lib lappend auto_path /opt/appfs/rkeene.org/tclreadline/platform/latest/lib lappend auto_path [file join [pwd] lib] package require nano ## Set defaults set url {http://[::1]:55000/} ## Process if {[llength $argv] % 2 != 0} { lappend argv "" } foreach {opt optval} $argv { switch -- $opt { "--url" { set url $optval } "-h" - "--help" { puts "Usage: rpc-client \[--help\] \[--url <rpc-url>\]" exit 0 } default { puts stderr "Invalid option: $opt" exit 1 } } } # Override logging, to file proc ::nano::node::user_log {line} { if {![info exists ::logfd]} { set ::logfd [open "node.log" a+] fconfigure $::logfd -blocking false } puts $::logfd $line flush $::logfd } nano::rpc::client::init -url $url ::nano::rpc::cli -interactive |