Index: build/test/test.tcl ================================================================== --- build/test/test.tcl +++ build/test/test.tcl @@ -134,12 +134,12 @@ return false } set addrCheck [::nano::address::fromPublicKey $pub] if {$addrCheck ne $addr} { - puts "\[1.FAIL\] Got: $addrCheck" - puts "\[1.FAIL\] Exp: $addr" + puts "\[2.FAIL\] Got: $addrCheck" + puts "\[2.FAIL\] Exp: $addr" return false } return true @@ -148,27 +148,64 @@ proc test_blocks {} { set seed [binary decode hex C4D214F19E706E9C7487CEF00DE8059200C32414F0ED82E5E33B523AEDF719BA] set key [::nano::key::computeKey $seed 0 -hex] set address [::nano::address::fromPrivateKey $key -xrb] + # High-level primitives + ## Receive/Open set block [::nano::block::create::receive \ to $address \ amount 1000000000000000000000000000000 \ - sourceBlock 207D3043D77B84E892AD4949D147386DE4C2FE4B2C8DC13F9469BC4A764681A7 \ + sourceBlock "207D3043D77B84E892AD4949D147386DE4C2FE4B2C8DC13F9469BC4A764681A7" \ signKey $key ] + set blockDict [::json::json2dict $block] + set blockSignature [string toupper [dict get $blockDict signature]] + set blockSignature_expected "B574DE37F5FFF3DCFB5D0E505FC36B402444777CAA99BA86F89E9B82B6EB901B809554287F0B67D8C2A8306B4F69FE77FD0C9B3D0D10422A02CFEBB3810C7D02" + if {$blockSignature ne $blockSignature_expected} { + puts "\[1.FAIL\] Got: $blockSignature" + puts "\[1.FAIL\] Exp: $blockSignature_expected" + + return false + } + + ## Send set block [::nano::block::create::send \ from $address \ to "xrb_1unc5hriitrdjq5dnyhr3zmd8t5hm7rhm9a1u3uun5ycbaacpu649yh5c4b5" \ previous "D46BFC2E35B5A3CA4230839D67676F4A8498C2567F571D2B66A7F7B72214DEEE" \ previousBalance 1000000000000000000000000000000 \ amount 1000000000000000000000000000000 \ signKey $key ] - set block [::nano::block::toDict [::nano::block::fromJSON $block]] + set blockDict [::json::json2dict $block] + set blockSignature [string toupper [dict get $blockDict signature]] + set blockSignature_expected "BFE238A27FFBFBCF722EDC3700CA8E2405F5AE18E353E591917A2CBE393F0759C948E710DD723B3BFB21B491D9D0856EEFCAC0E25C7E5FF06185FE5D633B5204" + if {$blockSignature ne $blockSignature_expected} { + puts "\[2.FAIL\] Got: $blockSignature" + puts "\[2.FAIL\] Exp: $blockSignature_expected" + + return false + } + + # JSON Parsing a block + set blockDict [::nano::block::toDict [::nano::block::fromJSON $block]] + dict unset blockDict _blockData + dict set blockDict signKey $key + + set block [::nano::block::jsonFromDict $blockDict] + set blockDict [::json::json2dict $block] + set blockSignature [string toupper [dict get $blockDict signature]] + if {$blockSignature ne $blockSignature_expected} { + puts "\[3.FAIL\] Got: $blockSignature" + puts "\[3.FAIL\] Exp: $blockSignature_expected" + + return false + } + return true } set tests { Index: nano.tcl ================================================================== --- nano.tcl +++ nano.tcl @@ -256,27 +256,76 @@ } } return $blockData } + +proc ::nano::block::signBlockHash {blockHash key args} { + set outputFormat "bytes" + foreach arg $args { + switch -exact -- $arg { + "-hex" { + set outputFormat "hex" + } + "-binary" { + set outputFormat "bytes" + } + } + } + + if {[string length $blockHash] != 32} { + set blockHash [binary decode hex $blockHash] + } + + if {[string length $key] != 32} { + set key [binary decode hex $key] + } + + set signature [::nano::internal::signDetached $blockHash $key] + + if {$outputFormat eq "hex"} { + set signature [string toupper [binary encode hex $signature]] + } + + return $signature +} + +proc ::nano::block::signBlock {blockData args} { + set blockHash [::nano::block::hash $blockData] + + tailcall ::nano::block::signBlockHash $blockHash {*}$args +} + +proc ::nano::block::verifyBlockHash {blockHash signature pubKey} { + if {[string length $blockHash] != 32} { + set blockHash [binary decode hex $blockHash] + } + + if {[string length $pubKey] != 32} { + set key [binary decode hex $pubKey] + } + + set valid [::nano::internal::verifyDetached $blockHash $signature $pubKey] + + return $signature +} + +proc ::nano::block::verifyBlock {blockData args} { + set blockHash [::nano::block::hash $blockData] + + tailcall ::nano::block::verifyBlockHash $blockHash {*}$args +} proc ::nano::block::_dictToJSON {blockDict} { array set block $blockDict if {[info exists block(signKey)] && ([info exists block(_blockData)] || [info exists block(_blockHash)])} { if {![info exists block(_blockHash)]} { set block(_blockHash) [binary encode hex [::nano::block::hash $block(_blockData)]] } - set signKey [binary decode hex $block(signKey)] - set blockHash [binary decode hex $block(_blockHash)] - - set signature [::nano::internal::signDetached $blockHash $signKey] - set signature [binary encode hex $signature] - set signature [string toupper $signature] - - set block(signature) $signature + set block(signature) [::nano::block::signBlockHash $block(_blockHash) $block(signKey) -hex] } if {$block(type) eq "state"} { if {![info exists block(link)]} { set block(link) [::nano::address::toPublicKey $block(link_as_account) -hex]