Check-in [a0b0b2d10b]
Overview
Comment:State blocks don't actually contain the state block pre-amble when stored/transmitted
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: a0b0b2d10b780dda8d42ede360d11e0c4a26a987c64dda684d18be763f8fe189
User & Date: rkeene on 2018-11-19 19:36:59
Other Links: manifest | tags
Context
2018-11-19
19:37
Support passing a path to tcllib check-in: 1c97659369 user: rkeene tags: trunk
19:36
State blocks don't actually contain the state block pre-amble when stored/transmitted check-in: a0b0b2d10b user: rkeene tags: trunk
2018-11-09
17:57
Fix description of "bulk_pull" check-in: b7740235b7 user: rkeene tags: trunk
Changes

Modified nano.tcl from [f990275d18] to [ecb41a3def].

309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
309
310
311
312
313
314
315

316
317
318
319
320
321
322







-








# Low-level block management
proc ::nano::block::dict::toBlock {blockDict} {
	array set block $blockDict

	switch -- $block(type) {
		"state" {
			append blockData $::nano::block::stateBlockPreamble
			append blockData [::nano::address::toPublicKey $block(account)]
			append blockData [binary decode hex $block(previous)]
			append blockData [::nano::address::toPublicKey $block(representative)]
			append blockData [binary decode hex [format %032llX $block(balance)]]
			if {![info exists block(link)] && [info exists block(link_as_account)]} {
				append blockData [::nano::address::toPublicKey $block(link_as_account)]
			} else {
461
462
463
464
465
466
467
468































































































































































469

470
471
472
473
474
475
476
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+







	}]
	set blockJSONEntries [join $blockJSONEntries]

	set blockJSON [json::write object {*}$blockJSONEntries]

	return $blockJSON
}

proc ::nano::block::typeIDFromType {type} {
	set outputFormat decimal
	foreach arg $args {
		switch -exact -- $arg {
			"-dec" - "-decimal" {
				set outputFormat "decimal"
			}
			"-hex" {
				set outputFormat "hex"
			}
			"-binary" {
				set outputFormat "bytes"
			}
			default {
				return -code error "Invalid option: $arg"
			}
		}
	}

	switch -- $type {
		"invalid"     { set typeId 0 }
		"not_a_block" { set typeId 1 }
		"send"        { set typeId 2 }
		"receive"     { set typeId 3 }
		"open"        { set typeId 4 }
		"change"      { set typeId 5 }
		"state"       { set typeId 6 }
	}

	switch -- $outputFormat {
		"decimal" {
			set result $typeId
		}
		"hex" {
			set result [format %02x $typeId]
		}
		"bytes" {
			set result [binary decode hex [format %02x $typeId]]
		}
	}

	return $result
}

proc ::nano::block::typeFromTypeID {typeId args} {
	set inputFormat decimal
	foreach arg $args {
		switch -exact -- $arg {
			"-dec" - "-decimal" {
				set inputFormat "decimal"
			}
			"-hex" {
				set inputFormat "hex"
			}
			"-binary" {
				set inputFormat "bytes"
			}
			default {
				return -code error "Invalid option: $arg"
			}
		}
	}

	switch -- $inputFormat {
		"decimal" { }
		"hex" {
			if {![string match "0x*" $typeId]} {
				set typeId "0x${typeId}"
			}
		}
		"bytes" {
			set typeId [binary encode hex $typeId]
			set typeId "0x${typeId}"
		}
	}

	switch -- [format %i $typeId] {
		0 { set type "invalid" }
		1 { set type "not_a_block" }
		2 { set type "send" }
		3 { set type "receive" }
		4 { set type "open" }
		5 { set type "change" }
		6 { set type "state" }
	}

	return $type
}

proc ::nano::block::lengthFromType {type args} {
	set includeType false
	set includeWork false
	set includeSig  false
	foreach arg $args {
		switch -exact -- $arg {
			"-full" {
				set includeType true
				set includeWork true
				set includeSig  true
			}
			"-work" {
				set includeWork true
			}
			"-signature" {
				set includeSig  true
			}
			"-type" {
				set includeType true
			}
			default {
				return -code error "Invalid option: $arg"
			}
		}
	}

	switch -- $type {
		"invalid" - "not_a_block" {
			set length 0
			set includeWork false
			set includeSig false
		}
		"state"   { set length 144 }
		"open"    { set length 96  }
		"send"    { set length 80  }
		"receive" { set length 64  }
		"change"  { set length 64  }
		default {
			return -code error "Unknown type: $type"
		}
	}

	if {$includeType} {
		incr length
	}

	if {$includeWork} {
		incr length 8
	}

	if {$includeSig} {
		incr length 64
	}

	return $length
}

proc ::nano::block::typeFromLength {length} {
	switch -- $length {
		144 { set type state }
		96  { set type open  }
		80  { set type send  }
		default {
			return -code error "Ambigious"
		}
	}

	return $type
}

proc ::nano::block::dict::fromBlock {blockData args} {
	set block(_blockData) $blockData
	set block(type) ""
	set addressPrefix "nano_"
	foreach arg $args {
		switch -glob -- $arg {
			"-type=*" {
				set block(type) [lindex [split $arg =] 1]
			}
485
486
487
488
489
490
491
492
493


494
495
496
497


498
499
500
501
502
503
504
505
506
507
508
509

510
511
512
513
514
515
516


517
518
519


520
521
522

523
524
525



526
527
528
529
530

531
532
533



534
535
536
537
538

539
540



541
542
543
544
545

546
547



548
549
550
551
552
553
554
555
556

557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584

585
586
587
588
589
590
591
644
645
646
647
648
649
650


651
652




653
654

655
656
657
658
659
660
661
662
663
664

665

666
667
668
669


670
671



672
673

674

675
676
677

678
679
680
681
682
683
684

685
686
687

688
689
690
691
692
693
694

695
696

697
698
699
700
701
702
703

704
705

706
707
708
709
710
711
712
713
714
715
716

717
718
719
720
721
722
723
724
725
726
727
728
729
730
731

732
733
734
735
736
737
738
739
740
741
742
743

744
745
746
747
748
749
750
751







-
-
+
+
-
-
-
-
+
+
-










-
+
-




-
-
+
+
-
-
-
+
+
-

-
+


-
+
+
+




-
+


-
+
+
+




-
+

-
+
+
+




-
+

-
+
+
+








-
+














-












-
+







			}
			default {
			}
		}
	}

	if {$block(type) eq ""} {
		switch -- [string length $blockData] {
			176 { set block(type) state   }
		if {[catch {
			set block(type) [::nano::block::typeFromLength [string length $blockData]]
			96  { set block(type) open    }
			80  { set block(type) send    }
			default {
				return -code error "Unable to parse block, must specify type"
		}]} {
			return -code error "Unable to parse block, must specify type"
			}
		}
	}

	set addArgs_fromPublicKey [list]
	if {$addressPrefix eq "xrb_"} {
		lappend addArgs_fromPublicKey "-xrb"
	}

	switch -- $block(type) {
		"state" {
			binary scan $blockData a32a32H64a32H32H64 \
			binary scan $blockData a32H64a32H32H64H128H16 \
				block(header) \
				block(account) \
				block(previous) \
				block(representative) \
				block(balance) \
				block(link)

				block(link) \
				block(signature) \
			if {$block(header) ne $::nano::block::stateBlockPreamble} {
				return -code error "Invalid block"
			}
				block(work)
		}
		}
		"open" {
			binary scan $blockData H64a32a32 \
			binary scan $blockData H64a32a32H128H16 \
				block(source) \
				block(representative) \
				block(account)
				block(account) \
				block(signature) \
				block(work)

			set block(_workData) $block(account)
		}
		"send" {
			binary scan $blockData H64a32H32 \
			binary scan $blockData H64a32H32H128H16 \
				block(previous) \
				block(destination) \
				block(balance)
				block(balance) \
				block(signature) \
				block(work)

			set block(_workData) $block(previous)
		}
		"receive" {
			binary scan $blockData H64H64 \
			binary scan $blockData H64H64H128H16 \
				block(previous) \
				block(source)
				block(source) \
				block(signature) \
				block(work)

			set block(_workData) $block(previous)
		}
		"change" {
			binary scan $blockData H64a32 \
			binary scan $blockData H64a32H128H16 \
				block(previous) \
				block(representative)
				block(representative) \
				block(signature) \
				block(work)

			set block(_workData) $block(previous)
		}
		default {
			return -code error "Invalid block type: $block(type)"
		}
	}

	foreach field {account representative link_as_account destination balance} {
	foreach field {account representative link_as_account destination balance work signature} {
		if {![info exists block($field)]} {
			continue
		}

		switch -exact -- $field {
			"account" - "representative" - "link_as_account" - "destination" {
				set block($field) [::nano::address::fromPublicKey $block($field) {*}$addArgs_fromPublicKey]
			}
			"balance" {
				set block($field) [format %lli "0x$block($field)"]
			}
		}
	}

	set block(_blockData) $blockData

	return [array get block]
}

proc ::nano::block::json::fromBlock {blockData args} {
	set blockDict [::nano::block::dict::fromBlock $blockData {*}$args]

	set blockJSON [::nano::block::json::fromDict $blockDict]

	return $blockJSON
}

proc ::nano::block::hash {blockData args} {
proc ::nano::block::_hash {blockData args} {
	set outputFormat "bytes"
	foreach arg $args {
		switch -exact -- $arg {
			"-hex" {
				set outputFormat "hex"
			}
			"-binary" {
601
602
603
604
605
606
607
















608
609
610
611
612
613
614
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








	if {$outputFormat eq "hex"} {
		set hash [string toupper [binary encode hex $hash]]
	}

	return $hash
}

proc ::nano::block::dict::toHash {blockDict args} {
	if {[dict get $blockDict type] eq "state"} {
		set blockData $::nano::block::stateBlockPreamble
	}

	append blockData [::nano::block::dict::toBlock $blockDict]

	tailcall ::nano::block::_hash $blockData {*}$args
}

proc ::nano::block::json::toHash {blockJSON args} {
	set blockDict [::nano::block::dict::fromJSON $blockJSON]

	tailcall ::nano::block::dict::toHash $blockDict {*}$args
}

proc ::nano::block::signBlockHash {blockHash privateKey args} {
	set outputFormat "bytes"
	foreach arg $args {
		switch -exact -- $arg {
			"-hex" {
				set outputFormat "hex"
635
636
637
638
639
640
641
642
643


644
645
646
647
648
649
650
811
812
813
814
815
816
817


818
819
820
821
822
823
824
825
826







-
-
+
+







	if {$outputFormat eq "hex"} {
		set signature [string toupper [binary encode hex $signature]]
	}

	return $signature
}

proc ::nano::block::sign {blockData args} {
	set blockHash [::nano::block::hash $blockData]
proc ::nano::block::_sign {blockData args} {
	set blockHash [::nano::block::_hash $blockData]

	tailcall ::nano::block::signBlockHash $blockHash {*}$args
}

proc ::nano::block::verifyBlockHash {blockHash signature publicKey} {
	if {[string length $blockHash] != $::nano::block::hashLength} {
		set blockHash [binary decode hex $blockHash]
659
660
661
662
663
664
665
666
667


668
669
670
671
672
673
674
835
836
837
838
839
840
841


842
843
844
845
846
847
848
849
850







-
-
+
+







	}

	set valid [::nano::internal::verifyDetached $blockHash $signature $publicKey]

	return $valid
}

proc ::nano::block::verifyBlock {blockData args} {
	set blockHash [::nano::block::hash $blockData]
proc ::nano::block::_verifyBlock {blockData args} {
	set blockHash [::nano::block::_hash $blockData]

	tailcall ::nano::block::verifyBlockHash $blockHash {*}$args
}

proc ::nano::block::dict::_addBlockData {blockDict} {
	if {[dict exists $blockDict _blockData]} {
		return $blockDict
685
686
687
688
689
690
691




692

693
694
695
696
697
698
699
861
862
863
864
865
866
867
868
869
870
871

872
873
874
875
876
877
878
879







+
+
+
+
-
+







	if {[dict exists $blockDict _blockHash]} {
		return $blockDict
	}

	set blockDict [_addBlockData $blockDict]
	set blockData [dict get $blockDict _blockData]

	if {[dict get $blockDict type] eq "state"} {
		set blockData "${::nano::block::stateBlockPreamble}${blockData}"
	}

	set blockHash [::nano::block::hash $blockData -binary]
	set blockHash [::nano::block::_hash $blockData -binary]

	dict set blockDict _blockHash $blockHash

	return $blockDict
}

proc ::nano::block::dict::sign {blockDict privateKey args} {
1625
1626
1627
1628
1629
1630
1631



1632
1633
1634
1635
1636
1637
1638
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821







+
+
+








	foreach proc $procs {
		proc ::nano::node::ledger::$proc args [concat [list tailcall {*}$handle $proc] {{*}$args}]
	}
}

proc ::nano::node::configure {network args} {
	package require ip
	package require dns

	# Set default options
	## XXX:TODO: Handle other networks
	if {$network ne "main"} {
		return -code error "Only main network is supported right now"
	}
	set info(-configDirectory) [file normalize ~/RaiBlocks]

1913
1914
1915
1916
1917
1918
1919
1920
1921
1922



1923
1924
1925
1926
1927
1928
1929
2096
2097
2098
2099
2100
2101
2102



2103
2104
2105
2106
2107
2108
2109
2110
2111
2112







-
-
-
+
+
+







		}
	}

	return [string range $retval 0 143]
}

proc ::nano::network::client {sock messageType args} {
	set versionUsing 12
	set versionMin 1
	set versionMax 12
	set versionUsing 7
	set versionMin 7
	set versionMax 7
	set extensions 0

	set messageType [string tolower $messageType]
	set messageTypeID [lsearch -exact $::nano::network::messageTypes $messageType]
	if {$messageTypeID == -1} {
		return -code error "Invalid message type: $messageType"
	}
2301
2302
2303
2304
2305
2306
2307
2308

2309
2310
2311
2312
2313
2314
2315
2484
2485
2486
2487
2488
2489
2490

2491
2492
2493
2494
2495
2496
2497
2498







-
+







	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]"
#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"
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2551
2552
2553
2554
2555
2556
2557

2558

2559
2560
2561
2562
2563
2564
2565







-

-








		::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_
}