Index: nano.tcl ================================================================== --- nano.tcl +++ nano.tcl @@ -206,10 +206,14 @@ } } if {[string length $publicKey] != $::nano::key::publicKeyLength} { set publicKey [binary decode hex $publicKey] + + if {[string length $publicKey] != $::nano::key::publicKeyLength} { + return -code error "Invalid public key (length: [string length $publicKey], expected $::nano::key::publicKeyLength)" + } } set checksum [string reverse [::nano::internal::hashData $publicKey 5]] append publicKey $checksum @@ -457,10 +461,17 @@ dict set blockDict "_workData" [dict get $blockDict "previous"] } else { dict set blockDict "_workData" [::nano::address::toPublicKey [dict get $blockDict "account"]] } } + + if {[dict exists $blockDict "work"]} { + set valid [::nano::work::validate [dict get $blockDict "_workData"] [dict get $blockDict "work"]] + if {!$valid} { + return -code error "Invalid work when adding block" + } + } return $blockDict } proc ::nano::block::dict::fromJSON {blockJSON} { @@ -3258,18 +3269,26 @@ } set now [clock seconds] # Cleanup nonces while we are here foreach {peerKey peerInfo} [array get ::nano::node::_node_id_nonces] { + if {![dict exists $peerInfo "lastSeen"]} { + continue + } + set lastSeen [dict get $peerInfo "lastSeen"] if {($now - $lastSeen) > (5 * 60)} { unset ::nano::node::_node_id_nonces($peerKey) } } # Come up with a list of peers that we have seen recently foreach {peerKeyInfo peerInfo} [array get ::nano::node::peers] { + if {![dict exists $peerInfo "lastSeen"]} { + continue + } + set lastSeen [dict get $peerInfo "lastSeen"] set address [dict get $peerKeyInfo "address"] set peerPort [dict get $peerKeyInfo "port"] set peerKey [dict create address $address port $peerPort] @@ -3339,11 +3358,10 @@ if {![info exists ::nano::node::_node_id_nonces($peer)]} { set node_id_nonce [::nano::internal::randomBytes 32] set ::nano::node::_node_id_nonces($peer) [dict create query $node_id_nonce lastSeen $now] set peerSock [::nano::node::createSocket realtime $address $port] -#puts "Querying $peerSock with node_id_handshake (1)" ::nano::network::client $peerSock "node_id_handshake" query -query $node_id_nonce } } } @@ -3371,10 +3389,18 @@ binary scan $messageData H64H128 result(key) result(signature) } return [array get result] } + +proc ::nano::network::_socketToPeer {realtimeSocket} { + set peerInfo [dict get $realtimeSocket remote] + set peerAddress [lindex $peerInfo 0] + set peerPort [lindex $peerInfo 1] + set peer [dict create address $peerAddress port $peerPort] + return $peer +} proc ::nano::network::server::node_id_handshake {messageDict} { set retval "" ::nano::node::stats::incr [list node_id_handshake] @@ -3387,25 +3413,22 @@ # Stats ::nano::node::stats::incr [list node_id_handshake query] } if {"response" in [dict get $messageDict flags]} { - set peerInfo [dict get $messageDict socket remote] - set peerAddress [lindex $peerInfo 0] - set peerPort [lindex $peerInfo 1] - set peer [dict create address $peerAddress port $peerPort] + set peer [::nano::network::_socketToPeer [dict get $messageDict socket]] # XXX:TODO: Verify the nonce if {![info exists ::nano::node::_node_id_nonces($peer)]} { return "" } set sentNonce $::nano::node::_node_id_nonces($peer) unset ::nano::node::_node_id_nonces($peer) # Add the peer to our list of peers -#puts "Got node_id_handshake response from $peer" - set ::nano::node::peers($peer) [dict create lastSeen [clock seconds]] + dict set ::nano::node::peers($peer) lastSeen [clock seconds] + dict set ::nano::node::peers($peer) nodeIdKey [dict get $messageDict key] # Stats ::nano::node::stats::incr [list node_id_handshake response] ::nano::node::stats::lappend [list node_id_handshake response uniqueKeys] [dict get $messageDict key] } @@ -3558,10 +3581,16 @@ return "" } ::nano::node::log "*** Incoming: $messageType ($messageTypeID on $networkType; from $peerSock) [binary encode hex $message] ($messageData)" + + catch { + set peer [::nano::network::_socketToPeer $peerSock] + dict set ::nano::node::peers($peer) lastPacket [clock seconds] + dict set ::nano::node::peers($peer) lastVersion $versionUsing + } if {![info exists messageDict]} { return "" } @@ -4379,22 +4408,48 @@ if {![string match $glob $peer] == !$globInvert} { continue } } + unset -nocomplain peerInfo + set fields [list] if {[info exists ::nano::node::peers($peer)]} { set peerInfo $::nano::node::peers($peer) - set lastSeen [dict get $peerInfo lastSeen] + } + + catch { + set versionUsing [dict get $peerInfo lastVersion] + + lappend fields "protocol $versionUsing" + } + catch { + set lastSeen [dict get $peerInfo lastSeen] set delta [expr {$now - $lastSeen}] set age "last seen $delta seconds ago" - } else { - set age "statically configured peer" + lappend fields $age + } + + catch { + set lastPacket [dict get $peerInfo lastPacket] + set delta [expr {$now - $lastPacket}] + + lappend fields "last packet $delta seconds ago" + } + + catch { + set nodeID [dict get $peerInfo nodeIdKey] + + lappend fields "node identifier $nodeID" + } + + if {[llength $fields] == 0} { + lappend fields "statically configured peer" } - lappend response " $peer: $age" + lappend response " $peer: [join $fields {, }]" } return [join $response "\n"] } proc ::nano::node::cli::_pull_chain {startBlockHash {endBlockHash "genesis"}} {