Overview
Comment: | More work on the networking support |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
e79f2e18002877cd0f5d5ed782eaed87 |
User & Date: | rkeene on 2018-08-17 20:39:03 |
Other Links: | manifest | tags |
Context
2018-08-17
| ||
21:52 | Ensure that the "work" is copied from the offload engine after it is updated and before it is used check-in: 42237e5a18 user: rkeene tags: trunk | |
20:39 | More work on the networking support check-in: e79f2e1800 user: rkeene tags: trunk | |
20:37 | Start of work on OpenMP GPU offloading for work generation check-in: f87706a75e user: rkeene tags: trunk | |
Changes
Modified nano.tcl from [18bb2a993f] to [98726f21ea].
︙ | ︙ | |||
18 19 20 21 22 23 24 | 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::server {} namespace eval ::nano::node::bootstrap {} | | > > | 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 47 48 49 50 51 52 53 54 | 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::server {} namespace eval ::nano::node::bootstrap {} namespace eval ::nano::node::realtime {} namespace eval ::nano::network::client {} namespace eval ::nano::network::server {} namespace eval ::nano::network::_dns {} # Constants set ::nano::block::stateBlockPreamble [binary decode hex "0000000000000000000000000000000000000000000000000000000000000006"] set ::nano::block::zero "0000000000000000000000000000000000000000000000000000000000000000" set ::nano::address::zero $::nano::block::zero set ::nano::address::base32alphabet {13456789abcdefghijkmnopqrstuwxyz} set ::nano::network::messageTypes { "invalid" "not_a_type" "keepalive" "publish" "confirm_req" "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 |
︙ | ︙ | |||
1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 | proc ::nano::account::receive {account blockHash signKey} { set accountPubKey [::nano::address::toPublicKey $account -hex] set frontierInfo [getFrontier $account] dict with frontierInfo {} set blockInfo [getPending $account $blockHash] set amount [dict get $blockInfo amount] set blockArgs [list to $account previousBalance $balance \ amount $amount sourceBlock $blockHash \ signKey $signKey representative $representative] if {[info exists frontierHash]} { | > > > > | 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 | proc ::nano::account::receive {account blockHash signKey} { set accountPubKey [::nano::address::toPublicKey $account -hex] set frontierInfo [getFrontier $account] dict with frontierInfo {} set blockInfo [getPending $account $blockHash] if {![info exists representative]} { set representative $account } set amount [dict get $blockInfo amount] set blockArgs [list to $account previousBalance $balance \ amount $amount sourceBlock $blockHash \ signKey $signKey representative $representative] if {[info exists frontierHash]} { |
︙ | ︙ | |||
1534 1535 1536 1537 1538 1539 1540 | "port" 7076 \ ] catch { set basis_node [dict create] set basis_node [dict get $basis "node"] } | | > > | 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 | "port" 7076 \ ] catch { set basis_node [dict create] set basis_node [dict get $basis "node"] } set default_node [dict create \ "client_id" [binary encode hex [::nano::internal::randomBytes 32]] ] catch { set basis_node_database [dict create] set basis_node_database [dict get $basis "node" "database"] } set default_node_database [dict create \ "backend" "lmdb" \ |
︙ | ︙ | |||
1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 | } return [binary format a32a32 \ $accountPubKey \ $end \ ] } proc ::nano::network::client::frontier_req {{startAccount ""} {age ""} {count ""}} { if {$startAccount eq ""} { set accountPubKey [binary decode hex $::nano::address::zero] } else { set accountPubKey [::nano::address::toPublicKey $startAccount -binary] } if {$age eq ""} { set age [expr {2**32-1}] } if {$count eq ""} { set count [expr {2**32-1}] } return [binary format a32ii $accountPubKey $age $count] } | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > | > > | > > > > | | | | > > > > > > > > | > > > > | > > | > | > | | | > > > > | > > | | > > | | | 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 | } return [binary format a32a32 \ $accountPubKey \ $end \ ] } proc ::nano::network::client::bulk_pull_account {account {minPending 0} {flags ""}} { set accountPubKey [::nano::address::toPublicKey $account -binary] set minPendingHex [format %032llx $minPending] if {[string length $minPendingHex] > 32} { return -code error "Invalid amount: $minPending" } set flagsInt 0 foreach flagName $flags { unset -nocomplain flagValue switch -- $flagName { "pendingAddressOnly" { set flagValue 1 } default { if {[string is integer -strict $flagName]} { set flagValue $flagName } else { return -code error "Invalid flag: $flagName" } } } set flagsInt [expr {$flagsInt | $flagValue}] } return [binary format a32H32c \ $accountPubKey \ $minPendingHex \ $flagsInt \ ] } proc ::nano::network::client::bulk_pull_account_response {sock account {minPending 0} {flags ""}} { set frontierBlockhash [::nano::network::_recv $sock 32] set frontierBalance [::nano::network::_recv $sock 16] set frontierBlockhash [binary encode hex $frontierBlockhash] set frontierBlockhash [string toupper $frontierBlockhash] set frontierBalance [binary encode hex $frontierBalance] set frontierBalance 0x$frontierBalance set frontierBalance [expr {$frontierBalance}] set fullPendingInfo true if {[lsearch -exact $flags "pendingAddressOnly"] != -1} { # XXX:TODO: We support numeric flags in the generation # side but not here, should we ? set fullPendingInfo false } set pendingInfo [list] while true { if {$fullPendingInfo} { set pendingBlockhash [binary encode hex [::nano::network::_recv $sock 32]] set pendingAmount [binary encode hex [::nano::network::_recv $sock 16]] if {$pendingBlockhash eq $::nano::block::zero} { break } set pendingBlockhash [string toupper $pendingBlockhash] set pendingAmount 0x$pendingAmount set pendingAmount [expr {$pendingAmount}] lappend pendingInfo [dict create \ blockhash $pendingBlockhash \ amount $pendingAmount \ ] } else { set pendingFrom [binary encode hex [::nano::network::_recv $sock 32]] if {$pendingFrom eq $::nano::address::zero} { break } set pendingFrom [::nano::address::fromPublicKey $pendingFrom] lappend pendingInfo [dict create \ from $pendingFrom \ ] } } set retval [dict create \ frontier \ [dict create \ blockhash $frontierBlockhash \ balance $frontierBalance \ ] \ pending $pendingInfo \ ] return $retval } proc ::nano::network::client::frontier_req {{startAccount ""} {age ""} {count ""}} { if {$startAccount eq ""} { set accountPubKey [binary decode hex $::nano::address::zero] } else { set accountPubKey [::nano::address::toPublicKey $startAccount -binary] } if {$age eq ""} { set age [expr {2**32-1}] } if {$count eq ""} { set count [expr {2**32-1}] } return [binary format a32ii $accountPubKey $age $count] } proc ::nano::network::client::node_id_handshake {nodeID} { set nodeID [binary decode hex $nodeID] return $nodeID } proc ::nano::network::_localIP {version} { if {[info exists ::nano::network::_localIP($version)]} { return $::nano::network::_localIP($version) } ## XXX:TODO: Work out a better system for determining ones own IP switch -exact -- $version { v4 { set url "http://ipv4.rkeene.org/whatismyip" set localIPPrefix "::ffff:" } v6 { set url "http://ipv6.rkeene.org/whatismyip" set localIPPrefix "" } } set localIP [exec curl -sS $url] if {$localIP eq ""} { return -code error "Unable to lookup local IP $version" } set localIP [string trim $localIP] set localIP "${localIPPrefix}${localIP}" set ::nano::network::_localIP($version) $localIP return $::nano::network::_localIP($version) } proc ::nano::network::client::keepalive {} { # Encode our local IP address in the packet set localIPs [list] foreach ipVersion {v4 v6} { unset -nocomplain localIP catch { set localIP [::nano::network::_localIP $ipVersion] } if {![info exists localIP]} { continue } lappend localIPs [binary decode hex [string map [list ":" ""] [::ip::normalize $localIP]]] } # Encode port as a 16-bit integer in network byte order (big endian) set localPort [dict get $::nano::node::configuration "node" "peering_port"] set localPort [binary format s $localPort] |
︙ | ︙ | |||
1745 1746 1747 1748 1749 1750 1751 | ] append message [::nano::network::client::${messageType} {*}$args] ::nano::node::log "Sending message [binary encode hex $message] to socket $sock" catch { | | > > > > > > | | | | | > | | > | > | | < > > < > > > | < > | < > > | > > | | > > > > > | > | > > > | 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 | ] append message [::nano::network::client::${messageType} {*}$args] ::nano::node::log "Sending message [binary encode hex $message] to socket $sock" catch { if {[dict get $sock "type"] eq "realtime"} { set sockInfo $sock set sock [dict get $sock "socket"] } } if {[info exists sockInfo]} { fconfigure $sock -remote [dict get $sockInfo "remote"] } chan configure $sock -translation binary -encoding binary puts -nonewline $sock $message flush $sock set responseCommand ::nano::network::client::${messageType}_response set response "" if {[info command $responseCommand] ne ""} { set response [$responseCommand $sock {*}$args] } return $response } proc ::nano::node::bootstrap::peer {peer peerPort} { ::nano::node::log "Connecting to ${peer}:${peerPort}" catch { set sock [::nano::network::_connect $peer $peerPort] } err if {![info exists sock]} { ::nano::node::log "Failed to connect to ${peer} ${peerPort}: $::errorInfo" return } defer::defer close $sock ::nano::node::log "Connected to $peer:$peerPort ;; sock = $sock" if {$::nano::node::bootstrap::frontier_req_running} { while true { if {[llength $::nano::node::bootstrap::frontiers_to_pull] == 0} { if {!$::nano::node::bootstrap::frontier_req_running} { break } ::nano::node::_sleep 100 0 continue } set accountInfo [lindex $::nano::node::bootstrap::frontiers_to_pull 0] set ::nano::node::bootstrap::frontiers_to_pull [lrange $::nano::node::bootstrap::frontiers_to_pull 1 end] set account [dict get $accountInfo "account"] ::nano::node::log "Pulling $accountInfo" # XXX:TODO: Compare frontier, and supply our local one ::nano::network::client $sock "bulk_pull" $account while true { ::nano::network::_recv $sock 32 } } } else { set ::nano::node::bootstrap::frontier_req_running true defer::defer set ::nano::node::bootstrap::frontier_req_running false ::nano::node::log "Requesting frontiers" # XXX:TODO: Age? ::nano::network::client $sock "frontier_req" while true { set account [::nano::address::fromPublicKey [::nano::network::_recv $sock 32]] set frontier [binary encode hex [::nano::network::_recv $sock 32]] lappend ::nano::node::bootstrap::frontiers_to_pull [dict create account $account frontier $frontier] } } return } proc ::nano::network::_dns::toIPList {name} { if {[::ip::version $name] > 0} { return [list $name] } |
︙ | ︙ | |||
1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 | } else { return 1 } }} $salt] $list } proc ::nano::node::bootstrap {} { while true { set peerInfoList [::nano::network::getPeers] ::nano::node::log "Have [llength $peerInfoList] peers" foreach peerInfo $peerInfoList { set peer [dict get $peerInfo "address"] set peerPort [dict get $peerInfo "port"] | > > > < | 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 | } else { return 1 } }} $salt] $list } proc ::nano::node::bootstrap {} { set ::nano::node::bootstrap::frontiers_to_pull [list] set ::nano::node::bootstrap::frontier_req_running false while true { set peerInfoList [::nano::network::getPeers] ::nano::node::log "Have [llength $peerInfoList] peers" foreach peerInfo $peerInfoList { set peer [dict get $peerInfo "address"] set peerPort [dict get $peerInfo "port"] if {[llength [info command ::nano::node::bootstrap::peer_*]] >= [dict get $::nano::node::configuration node bootstrap_connections]} { continue } set peerId [binary encode hex [::nano::internal::hashData "$peer:$peerPort" 5]] if {[info command ::nano::node::bootstrap::peer_${peerId}] ne ""} { |
︙ | ︙ | |||
1900 1901 1902 1903 1904 1905 1906 | chan event $sock writable "" chan event $sock readable "" return $sock } | | > > > > > > | > | > | 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 | chan event $sock writable "" chan event $sock readable "" return $sock } ::nano::node::log "Waiting in the event loop for socket $sock to become writable" yield chan event $sock writable "" chan event $sock readable "" if {[eof $sock] || (![chan configure $sock -connecting] && [chan configure $sock -error] ne "") || [chan configure $sock -connecting]} { close $sock return -code error "EOF from socket" } } chan configure $sock -blocking false -translation binary -encoding binary return $sock } proc ::nano::network::_recv {sock bytes} { if {[info coroutine] ne ""} { chan event $sock readable [info coroutine] } else { chan configure $sock -blocking true } set retBuffer "" while {$bytes > 0} { if {[info coroutine] ne ""} { yield } set buffer [read $sock $bytes] set bufferLen [string length $buffer] if {$bufferLen == 0} { set chanError [chan configure $sock -error] if {$chanError ne ""} { return -code error "Short read on socket $sock ($bytes bytes remaining): $chanError" } if {[chan eof $sock]} { return -code error "Short read on socket $sock ($bytes bytes remaining): EOF" } continue } incr bytes -$bufferLen append retBuffer $buffer } chan event $sock readable "" return $retBuffer } proc ::nano::node::_sleep {ms {verbose 1}} { if {$verbose} { ::nano::node::log "Sleeping for $ms ms" } after $ms [info coroutine] yield } proc ::nano::network::getPeers {} { if {[info exists ::nano::node::configuration]} { |
︙ | ︙ | |||
2054 2055 2056 2057 2058 2059 2060 | proc ::nano::network::server::publish {blockData} { #puts "block: [binary encode hex $blockData]" #9e1272edade3c247c738a4bd303eb0cfc3da298444bb9d13b8ffbced34ff036f4e1ff833324efc81c237776242928ef76a2cdfaa53f4c4530ee39bfff1977e26e382dd09ec8cafc2427cf817e9afe1f372ce81085ab4feb1f3de1f25ee818e5d000000008fc492fd20e57d048e000000204e7a62f25df739eaa224d403cb107b3f9caa0280113b0328fad3b402c465169006f988549a8b1e20e0a09b4b4dcae5397f6fcc4d507675f58c2b29ae02341b0a4fe562201a61bf27481aa4567c287136b4fd26b4840c93c42c7d1f5c518503d68ec561af4b8cf8 #9e1272edade3c247c738a4bd303eb0cfc3da298444bb9d13b8ffbced34ff036fa5e3647d3d296ec72baea013ba7fa1bf5c3357c33c90196f078ba091295e6e03e382dd09ec8cafc2427cf817e9afe1f372ce81085ab4feb1f3de1f25ee818e5d000000008fb2604ebd1fe098b8000000204e7a62f25df739eaa224d403cb107b3f9caa0280113b0328fad3b402c465165287cd9c61752dc9d011f666534dbdc10461e927503f9599791d73b1cca7fdc032d76db3f91e5b5c3d6206fa48b01bd08da4a89f2e880242e9917cfc3db80d0b9bfe8e6d1dd183d5 } proc ::nano::network::server {message {networkType "bootstrap"}} { | | > | | | | > | | > | | | 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 | proc ::nano::network::server::publish {blockData} { #puts "block: [binary encode hex $blockData]" #9e1272edade3c247c738a4bd303eb0cfc3da298444bb9d13b8ffbced34ff036f4e1ff833324efc81c237776242928ef76a2cdfaa53f4c4530ee39bfff1977e26e382dd09ec8cafc2427cf817e9afe1f372ce81085ab4feb1f3de1f25ee818e5d000000008fc492fd20e57d048e000000204e7a62f25df739eaa224d403cb107b3f9caa0280113b0328fad3b402c465169006f988549a8b1e20e0a09b4b4dcae5397f6fcc4d507675f58c2b29ae02341b0a4fe562201a61bf27481aa4567c287136b4fd26b4840c93c42c7d1f5c518503d68ec561af4b8cf8 #9e1272edade3c247c738a4bd303eb0cfc3da298444bb9d13b8ffbced34ff036fa5e3647d3d296ec72baea013ba7fa1bf5c3357c33c90196f078ba091295e6e03e382dd09ec8cafc2427cf817e9afe1f372ce81085ab4feb1f3de1f25ee818e5d000000008fb2604ebd1fe098b8000000204e7a62f25df739eaa224d403cb107b3f9caa0280113b0328fad3b402c465165287cd9c61752dc9d011f666534dbdc10461e927503f9599791d73b1cca7fdc032d76db3f91e5b5c3d6206fa48b01bd08da4a89f2e880242e9917cfc3db80d0b9bfe8e6d1dd183d5 } proc ::nano::network::server {message {networkType "bootstrap"}} { set messageParsed [binary scan $message a2ccccsa* \ packetMagic \ versionMax \ versionUsing \ versionMin \ messageTypeID \ extensions \ args ] if {$packetMagic ne "RC"} { return "" } # XXX:TODO: Check versions and extensions set messageType [lindex $::nano::network::messageTypes $messageTypeID] puts "*** Incoming: $messageType ($messageTypeID on $networkType) [binary encode hex $message]" set retval "" if {[catch { set retval [::nano::node::server::${messageType} $args] } err]} { if {![string match "invalid command name *" $err]} { ::nano::node::log "Error handling ${messageType}: $err" } } return $retval } proc ::nano::node::realtime::incoming {socket} { set data [read $socket 8192] if {$data eq ""} { return } set remote [chan configure $socket -peer] set response [::nano::network::server $data "realtime"] if {$response eq ""} { return } # XXX:TODO: Send response set peerSock [list type "realtime" remote $remote socket $socket] #::nano::network::client $peerSock ... return } proc ::nano::node::realtime {} { package require udp set peeringPort [dict get $::nano::node::configuration node peering_port] set clientID [dict get $::nano::node::configuration node client_id] # Start a UDP listening socket set socket(v6) [udp_open $peeringPort ipv6 reuse] set socket(v4) [udp_open $peeringPort reuse] foreach {protocolVersion protocolSocket} [array get socket] { fconfigure $protocolSocket -blocking false -encoding binary -translation binary chan event $protocolSocket readable [list ::nano::node::realtime::incoming $protocolSocket] } # Periodically send keepalives to all known peers ## XXX:TODO: Limit this to only a few peers while true { foreach peerInfo [::nano::network::getPeers] { set peerAddress [dict get $peerInfo "address"] set peerPort [dict get $peerInfo "port"] set protocolVersion "v[::ip::version $peerAddress]" set peerSock [list type "realtime" remote [list $peerAddress $peerPort] socket $socket(${protocolVersion})] ::nano::network::client $peerSock "node_id_handshake" $clientID ::nano::network::client $peerSock "keepalive" } ::nano::node::_sleep [expr {1 * 60 * 1000}] } } proc ::nano::node::start {} { package require defer package require ip package require udp package require dns coroutine ::nano::node::bootstrap::run ::nano::node::bootstrap coroutine ::nano::node::realtime::run ::nano::node::realtime vwait ::nano::node::_FOREVER_ } # RPC Client ## Side-effect: Sets ::nano::rpc::client::config proc ::nano::rpc::client::init args { |
︙ | ︙ |