1
0
Fork 0
mirror of https://github.com/ton-blockchain/ton synced 2025-03-09 15:40:10 +00:00

initial commit

This commit is contained in:
initial commit 2019-09-07 14:03:22 +04:00 committed by vvaltman
commit c2da007f40
1610 changed files with 398047 additions and 0 deletions

144
crypto/test/Ed25519.cpp Normal file
View file

@ -0,0 +1,144 @@
/*
This file is part of TON Blockchain Library.
TON Blockchain Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
TON Blockchain Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#include "crypto/Ed25519.h"
#include "td/utils/logging.h"
#include "td/utils/misc.h"
#include "td/utils/Slice.h"
#include "td/utils/tests.h"
#include <string>
unsigned char fixed_privkey[32] = "abacabadabacabaeabacabadabacaba";
unsigned char fixed_pubkey[32] = {0x6f, 0x9e, 0x5b, 0xde, 0xce, 0x87, 0x21, 0xeb, 0x57, 0x37, 0xfb,
0xb5, 0x92, 0x28, 0xba, 0x07, 0xf7, 0x88, 0x0f, 0x73, 0xce, 0x5b,
0xfa, 0xa1, 0xb7, 0x15, 0x73, 0x03, 0xd4, 0x20, 0x1e, 0x74};
unsigned char rfc8032_secret_key1[32] = {0x9d, 0x61, 0xb1, 0x9d, 0xef, 0xfd, 0x5a, 0x60, 0xba, 0x84, 0x4a,
0xf4, 0x92, 0xec, 0x2c, 0xc4, 0x44, 0x49, 0xc5, 0x69, 0x7b, 0x32,
0x69, 0x19, 0x70, 0x3b, 0xac, 0x03, 0x1c, 0xae, 0x7f, 0x60};
unsigned char rfc8032_public_key1[32] = {0xd7, 0x5a, 0x98, 0x01, 0x82, 0xb1, 0x0a, 0xb7, 0xd5, 0x4b, 0xfe,
0xd3, 0xc9, 0x64, 0x07, 0x3a, 0x0e, 0xe1, 0x72, 0xf3, 0xda, 0xa6,
0x23, 0x25, 0xaf, 0x02, 0x1a, 0x68, 0xf7, 0x07, 0x51, 0x1a};
unsigned char rfc8032_signature1[64] = {
0xe5, 0x56, 0x43, 0x00, 0xc3, 0x60, 0xac, 0x72, 0x90, 0x86, 0xe2, 0xcc, 0x80, 0x6e, 0x82, 0x8a,
0x84, 0x87, 0x7f, 0x1e, 0xb8, 0xe5, 0xd9, 0x74, 0xd8, 0x73, 0xe0, 0x65, 0x22, 0x49, 0x01, 0x55,
0x5f, 0xb8, 0x82, 0x15, 0x90, 0xa3, 0x3b, 0xac, 0xc6, 0x1e, 0x39, 0x70, 0x1c, 0xf9, 0xb4, 0x6b,
0xd2, 0x5b, 0xf5, 0xf0, 0x59, 0x5b, 0xbe, 0x24, 0x65, 0x51, 0x41, 0x43, 0x8e, 0x7a, 0x10, 0x0b,
};
unsigned char rfc8032_secret_key2[32] = {
0xc5, 0xaa, 0x8d, 0xf4, 0x3f, 0x9f, 0x83, 0x7b, 0xed, 0xb7, 0x44, 0x2f, 0x31, 0xdc, 0xb7, 0xb1,
0x66, 0xd3, 0x85, 0x35, 0x07, 0x6f, 0x09, 0x4b, 0x85, 0xce, 0x3a, 0x2e, 0x0b, 0x44, 0x58, 0xf7,
};
unsigned char rfc8032_public_key2[32] = {
0xfc, 0x51, 0xcd, 0x8e, 0x62, 0x18, 0xa1, 0xa3, 0x8d, 0xa4, 0x7e, 0xd0, 0x02, 0x30, 0xf0, 0x58,
0x08, 0x16, 0xed, 0x13, 0xba, 0x33, 0x03, 0xac, 0x5d, 0xeb, 0x91, 0x15, 0x48, 0x90, 0x80, 0x25,
};
unsigned char rfc8032_message2[2] = {0xaf, 0x82};
unsigned char rfc8032_signature2[64] = {
0x62, 0x91, 0xd6, 0x57, 0xde, 0xec, 0x24, 0x02, 0x48, 0x27, 0xe6, 0x9c, 0x3a, 0xbe, 0x01, 0xa3,
0x0c, 0xe5, 0x48, 0xa2, 0x84, 0x74, 0x3a, 0x44, 0x5e, 0x36, 0x80, 0xd7, 0xdb, 0x5a, 0xc3, 0xac,
0x18, 0xff, 0x9b, 0x53, 0x8d, 0x16, 0xf2, 0x90, 0xae, 0x67, 0xf7, 0x60, 0x98, 0x4d, 0xc6, 0x59,
0x4a, 0x7c, 0x15, 0xe9, 0x71, 0x6e, 0xd2, 0x8d, 0xc0, 0x27, 0xbe, 0xce, 0xea, 0x1e, 0xc4, 0x0a,
};
TEST(Crypto, ed25519) {
td::Ed25519::generate_private_key().ensure();
auto PK1 = td::Ed25519::generate_private_key().move_as_ok();
auto PK2 = td::Ed25519::PrivateKey(td::SecureString(td::Slice(fixed_privkey, 32)));
LOG(ERROR) << "PK1 = " << td::buffer_to_hex(PK1.as_octet_string());
auto priv2_export = PK2.as_octet_string();
LOG(ERROR) << "PK2 = " << td::buffer_to_hex(priv2_export);
auto PK3 = td::Ed25519::PrivateKey(std::move(priv2_export));
auto PubK1 = PK1.get_public_key().move_as_ok();
LOG(ERROR) << "PubK1 = " << td::buffer_to_hex(PubK1.as_octet_string());
auto PubK2 = PK2.get_public_key().move_as_ok();
LOG(ERROR) << "PubK2 = " << td::buffer_to_hex(PubK2.as_octet_string());
CHECK(td::Slice(fixed_pubkey, 32) == PubK2.as_octet_string());
auto PubK3 = PK3.get_public_key().move_as_ok();
LOG(ERROR) << "PubK3 = " << td::buffer_to_hex(PubK3.as_octet_string());
CHECK(td::Slice(fixed_pubkey, 32) == PubK3.as_octet_string());
LOG(ERROR) << "PubK1 = " << td::buffer_to_hex(PubK1.as_octet_string());
auto secret22 = td::Ed25519::compute_shared_secret(PubK3, PK2).move_as_ok();
LOG(ERROR) << "secret(PK2, PubK2)=" << td::buffer_to_hex(secret22);
auto secret12 = td::Ed25519::compute_shared_secret(PubK3, PK1).move_as_ok();
LOG(ERROR) << "secret(PK1, PubK2)=" << td::buffer_to_hex(secret12);
auto secret21 = td::Ed25519::compute_shared_secret(PubK1, PK2).move_as_ok();
LOG(ERROR) << "secret(PK2, PubK1)=" << td::buffer_to_hex(secret21);
CHECK(secret12 == secret21);
// for (int i = 0; i < 1000; i++) {
// td::Ed25519::compute_shared_secret(PubK2, PK1).ensure();
// td::Ed25519::compute_shared_secret(PubK1, PK2).ensure();
// }
auto signature = PK1.sign("abc").move_as_ok();
LOG(ERROR) << "PK1.signature=" << td::buffer_to_hex(signature);
// signature[63] ^= 1;
auto ok = PubK1.verify_signature("abc", signature);
LOG(ERROR) << "PubK1.check_signature=" << ok;
ok.ensure();
td::Ed25519::PrivateKey PK4(td::SecureString(td::Slice(rfc8032_secret_key1, 32)));
auto PubK4 = PK4.get_public_key().move_as_ok();
LOG(ERROR) << "PK4.private_key = " << td::buffer_to_hex(PK4.as_octet_string());
LOG(ERROR) << "PK4.public_key = " << td::buffer_to_hex(PubK4.as_octet_string());
CHECK(td::Slice(rfc8032_public_key1, 32) == PubK4.as_octet_string());
signature = PK4.sign("").move_as_ok();
LOG(ERROR) << "PK4.signature('') = " << td::buffer_to_hex(signature);
CHECK(signature == td::Slice(rfc8032_signature1, 64));
td::Ed25519::PrivateKey PK5(td::SecureString(td::Slice(rfc8032_secret_key2, 32)));
auto PubK5 = PK5.get_public_key().move_as_ok();
LOG(ERROR) << "PK5.private_key = " << td::buffer_to_hex(PK5.as_octet_string());
LOG(ERROR) << "PK5.public_key = " << td::buffer_to_hex(PubK5.as_octet_string());
CHECK(td::Slice(rfc8032_public_key2, 32) == PubK5.as_octet_string());
signature = PK5.sign(td::Slice(rfc8032_message2, 2)).move_as_ok();
LOG(ERROR) << "PK5.signature('') = " << td::buffer_to_hex(signature);
CHECK(signature == td::Slice(rfc8032_signature2, 64));
// for (int i = 0; i < 100000; i++) {
// PK5.sign(td::Slice(rfc8032_message2, 2));
// }
// for (int i = 0; i < 1000; i++) {
// PubK5.verify_signature(td::Slice(rfc8032_message2, 2), signature).ensure();
// }
/*
unsigned char temp_pubkey[32];
crypto::Ed25519::TempKeyGenerator TKG; // use one generator a lot of times
TKG.create_temp_shared_secret(temp_pubkey, secret12, PubK1, (const unsigned char*)"abc", 3);
LOG(ERROR) << "secret12=" << td::buffer_to_hex(secret12) << "; temp_pubkey=" << td::buffer_to_hex(temp_pubkey);
PK1.compute_temp_shared_secret(secret21, temp_pubkey);
LOG(ERROR) << "secret21=" << td::buffer_to_hex(secret21);
assert(!std::memcmp(secret12, secret21, 32));
*/
}

92
crypto/test/fift.cpp Normal file
View file

@ -0,0 +1,92 @@
/*
This file is part of TON Blockchain Library.
TON Blockchain Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
TON Blockchain Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#include "fift/words.h"
#include "fift/Fift.h"
#include "fift/utils.h"
#include "td/utils/tests.h"
#include "td/utils/PathView.h"
#include "td/utils/port/path.h"
#include "td/utils/filesystem.h"
std::string current_dir() {
return td::PathView(td::realpath(__FILE__).move_as_ok()).parent_dir().str();
}
std::string load_test(std::string name) {
return td::read_file_str(current_dir() + "fift/" + name).move_as_ok();
}
td::Status run_fift(std::string name, bool preload_fift = true) {
TRY_RESULT(res, fift::mem_run_fift(load_test(name)));
REGRESSION_VERIFY(res.output);
return td::Status::OK();
}
TEST(Fift, testvm) {
run_fift("testvm.fif");
}
TEST(Fift, testvm2) {
run_fift("testvm2.fif");
}
TEST(Fift, testvm3) {
run_fift("testvm3.fif");
}
TEST(Fift, testvm4) {
run_fift("testvm2.fif");
}
TEST(Fift, testvm4a) {
run_fift("testvm4a.fif");
}
TEST(Fift, testvm4b) {
run_fift("testvm4b.fif");
}
TEST(Fift, testvm4c) {
run_fift("testvm4c.fif");
}
TEST(Fift, testvm4d) {
run_fift("testvm4d.fif");
}
TEST(Fift, testvm5) {
run_fift("testvm5.fif");
}
TEST(Fift, testvm6) {
run_fift("testvm6.fif");
}
TEST(Fift, testvm7) {
run_fift("testvm7.fif");
}
TEST(Fift, testvm8) {
run_fift("testvm8.fif");
}
TEST(Fift, testvmprog) {
run_fift("testvmprog.fif");
}
TEST(Fift, bug) {
run_fift("bug.fif");
}
TEST(Fift, contfrac) {
run_fift("contfrac.fif");
}
TEST(Fift, test) {
run_fift("test.fif");
}
TEST(Fift, bug_div) {
run_fift("bug_div.fif");
}

3
crypto/test/fift/bug.fif Normal file
View file

@ -0,0 +1,3 @@
10000000000000000000000000000000000000000000000000000000 dup .
dup 1 */ .

View file

@ -0,0 +1,12 @@
"Asm.fif" include
1000 1 /r
x{7A71A905} runvmcode
<{ 1000 INT 1 INT DIVR }>s
dup csr.
runvmcode
.s

8
crypto/test/fift/cmdline.fif Executable file
View file

@ -0,0 +1,8 @@
#!/usr/bin/fift -s
{ ."usage: " $0 type ." <num1> <num2>" cr
."Computes the product of two integers." cr bye } : usage
{ ' usage if } : ?usage
$# 2 <> ?usage
$1 (number) 1- ?usage
$2 (number) 1- ?usage
* . cr

View file

@ -0,0 +1,18 @@
{ dup 2over rot } : 3dup
{ 2drop drop } : 3drop
{ { 5 roll } 3 times } : 3swap
{ -rot over + rot over + -rot over + rot } : step1
{ negate -rot negate swap negate } : step2
{ 0 3 -roll { 3dup step1 dup 0> } { 3swap 3drop 3 roll 1+ 3 -roll } while 3drop step2 } : nsteps1
{ ' nsteps1 swap times 3drop } : qcontfrac
{ -1 0 2swap qcontfrac } : sqrtcontfrac
{ rot 2 pick * + swap } : revstep1
{ 1 0 rot ' revstep1 swap times } : computecontfrac
1 { 10 * } 74 times constant One
{ 100 sqrtcontfrac 100 computecontfrac */r } : *sqrtint
{ One swap *sqrtint } : sqrtint
2 sqrtint .
3 sqrtint .
6 sqrtint .
7 sqrtint .
239 sqrtint .

View file

@ -0,0 +1,19 @@
1 { 10 * } 70 times constant One
{ bl word (number) dup 0= abort"invalid fixed-point constant"
1- { One swap */r } { One * } cond 1 'nop } ::_ F$
' + : F+
' - : F-
{ One */r } : F*
{ One swap */r } : F/
{ One dup rot */r } : Finv
{ One { 2dup F/ F+ 2/ } 9 times nip } : Fsqrt
{ ' Fsqrt 128 times One F- 128 << } : Fln
{ dup abs <# ' # 70 times char . hold #s rot sign #>
nip -trailing0 type space } : .F
F$17/12 .F
F$3.14159265 .F
{ 1 0 rot { -rot over + swap rot 2dup >= } until drop
} : fib-gtr
One fib-gtr F/ .F
F$2 Fsqrt .F
F$2 Fln .F

27
crypto/test/fift/sort.fif Normal file
View file

@ -0,0 +1,27 @@
{ null null rot
{ dup null? not }
{ uncons swap rot cons -rot } while drop
} : split
variable 'sort variable 'merge variable 'compare
{ 'sort @ execute } : sort
{ 'merge @ execute } : merge
{ 'compare @ execute } : compare
' < 'compare !
{ dup null? { drop } {
over null? { nip } {
over car over car compare ' swap if
uncons rot merge cons
} cond
} cond
} 'merge !
{ dup null? {
dup cdr null? {
split sort swap sort merge
} ifnot
} ifnot
} 'sort !
3 1 4 1 5 9 2 6 5 9 list
dup .l cr sort .l cr
"once" "upon" "a" "time" "there" "lived" "a" "very" "little" "kitten" 10 list
{ $cmp 0< } 'compare !
dup .l cr sort .l cr

View file

@ -0,0 +1,28 @@
{ hole dup 1 { @ execute } does create 1 ' ! does create } : defvect
defvect sort :sort
defvect merge :merge
defvect less :less
' < :less
{ null null rot
{ dup null? not }
{ uncons swap rot cons -rot } while drop
} : split
{ dup null? { drop } {
over null? { nip } {
over car over car less ' swap if
uncons rot merge cons
} cond
} cond
} :merge
{ dup null? {
dup cdr null? {
split sort swap sort merge
} ifnot
} ifnot
} :sort
3 1 4 1 5 9 2 6 5 9 list
dup .l cr sort .l cr
"once" "upon" "a" "time" "there" "lived" "a" "very" "little" "kitten" 10 list
{ $cmp 0< } :less
dup .l cr sort .l cr

24
crypto/test/fift/test.fif Normal file
View file

@ -0,0 +1,24 @@
{ bl word 1 2 ' (create) } "::" 1 (create)
{ bl word 0 2 ' (create) } :: :
{ bl word 2 2 ' (create) } :: :_
{ bl word 3 2 ' (create) } :: ::_
{ bl word 0 (create) } : create
{ char " word 1 ' type } ::_ ."
{ char " word 1 { swap { abort } if drop } } ::_ abort"
{ dup * } : square
6 square .
{ swap ({) over 2+ -roll swap (compile) (}) } : does
{ 1 'nop does create } : constant
10 constant ten
ten .
ten ten * .
{ 1 ' emit does create } : emits
42 emits star
34 emits quote
30000 emits figna
star star quote figna quote
{ 0 word drop 0 'nop } ::_ //
star quote // end-to-line comment
{ 1 ' * does create } : mulby
3 mulby 3*
4 3* .

102
crypto/test/fift/testdb.fif Normal file
View file

@ -0,0 +1,102 @@
"Asm.fif" include
PROGRAM{
NEWPROC load_dict
NEWPROC generate_dict
NEWPROC save_dict
NEWPROC do_get
NEWPROC do_set
NEWPROC do_erase
main PROC:<{
DUP 1 INT EQUAL IF:<{
DROP
do_get CALL
}>ELSE<{
DUP 2 INT EQUAL IF:<{
DROP
do_set CALL
}>ELSE<{
DUP 3 INT EQUAL IF:<{
DROP
do_erase CALL
}> }> }>
-1 INT
}>
do_get PROC:<{
load_dict CALL
32 INT
DICTIGET
}>
do_set PROC:<{
load_dict CALL
32 INT
DICTISET
save_dict CALL
}>
do_erase PROC:<{
load_dict CALL
32 INT
DICTIDEL
DROP
save_dict CALL
}>
generate_dict PROC:<{
4 INT 100 INT REPEAT:<{
DUP 2DUP MUL ROT 617 INT ADD 1000 INT MOD
}>
DROP 100 INT
NEWDICT
SWAP REPEAT:<{
s0 s2 XCHG
NEWC
16 STU
s0 s2 XCHG
32 INT
DICTISETB
}>
}>
load_dict PROC:<{
PUSHROOT
CTOS DUP SEMPTY IF:<{
DROP
generate_dict CALL
}>
}>
save_dict PROC:<{
NEWC
STSLICE
ENDC
POPROOT
}>
}END>s constant pmc_prog
{ 1 2 rot pmc_prog } : task_pmc_get
{ 2 3 rot pmc_prog } : task_pmc_set
{ 3 2 rot pmc_prog } : task_pmc_erase
{ task_pmc_get dbrunvm 2drop } : pmc_get
{ task_pmc_set dbrunvm 2drop } : pmc_set
{ task_pmc_erase dbrunvm 2drop } : pmc_erase
<b x{abacaba} s, <b x{dead} s, x{1dead} sr, b> <s sr, b> <s constant test_value
// 123 "a" pmc_get
// { csr. } if
// 123 "a" pmc_set
// test_value 123 x{a} task_pmc_set test_value 123 x{b} task_pmc_set test_value 123 x{c} task_pmc_set 3 3 dbrunvm-parallel
{ test_value 150 rot task_pmc_set } 0 { 1 + 2dup swap execute 7 roll 7 roll } 10000 times 2drop 10000 4 dbrunvm-parallel
// 123 "a" task_pmc_get 123 "b" task_pmc_get 123 "c" task_pmc_get 3 dbrunvm-parallel

View file

@ -0,0 +1,24 @@
"Lisp.fif" include
16 constant key-bits
16 constant val-bits
{ val-bits u, } : val,
{ val-bits u@ } : val@
{ swap unpair <b swap val, b> <s swap rot key-bits udict! not abort"cannot add key-value" } : +dictpair
{ dictnew { over null? not } { swap uncons swap rot +dictpair } while nip } : mkdict
{ dup null? { ."(null) " drop } { val@ . } cond } : .val
{ key-bits { swap . ."-> " .val ."; " true } dictforeach drop cr } : show-dict
{ key-bits { rot . ."-> " swap .val .val ."; " true } dictdiff drop cr } : show-dict-diff
{ key-bits { val@ swap val@ + val, true } dictmerge } : dict-sum
{ null swap key-bits { val@ pair swap cons true } dictforeach drop } : dict>list-rev
{ dict>list-rev list-reverse } : dict>list
( _( 13 169 ) _( 17 289 ) _( 10 100 ) ) mkdict =: Dict
_( 4 16 ) _( 9 81 ) Dict +dictpair +dictpair =: Dict1
_( 4 20 ) _( 101 10201 ) Dict +dictpair +dictpair =: Dict2
."Dict1 = " Dict1 show-dict
Dict1 dict>list .l cr
Dict1 <s csr. cr
."Dict2 = " Dict2 show-dict
Dict2 dict>list .l cr
Dict2 <s csr. cr
Dict1 Dict2 show-dict-diff
Dict2 Dict1 show-dict-diff

View file

@ -0,0 +1,10 @@
{ bl word 0 (create) } : create
{ swap ({) over 2+ -roll swap (compile) (}) } : does
{ 1 'nop does create } : constant
1 2 3 <b 0x01 8 u, 0x58 8 u, b> .s <s .s runvmcode .s
x{5352A85354A8A15224A8460525A8A104A85042A8A15112A90402A904} constant solvelineq_code
x{2523A82525A8A10322A80521A815A103A80314A80102A10122A90402A904} constant solvelineq_simple_code
x{2523A82525A8A1220104A80521A815A11504A81402A8A10122A90402A904} constant solvelineq_compiled_code
2 3 1 1 29 12 solvelineq_code runvmcode .s
2 3 1 1 29 12 solvelineq_simple_code runvmcode .s
2 3 1 1 29 12 solvelineq_compiled_code runvmcode .s

View file

@ -0,0 +1,22 @@
239 x{9220A8D8A601} runvmcode .s
55 x{719C2272B9DC5921A801A50220D920D83031} runvmcode .s
10 x{9E21C102925B71E021A50120D8A820D9} runvmcode .s
55 x{7101209466A801A5E430} runvmcode .s
x{71209A21A00121A020B7B5FCC4E60171804592A70AE401A985} runvmcode .s
x{71804592A70AE471209821A00121A05302BEE601A985} runvmcode .s
20 x{710192A70AE471209821A00121A05302BEE601A984} runvmcode .s
239 x{9F202071B093A703A492AB00E220C001E6} runvmcode drop .s
239 x{9320C301992093A703A4E380AB00E8} runvmcode drop .s
x{7791A0EC11717322D802D8} runvmcode drop .s
x{917720ED50D8} runvmcode drop .s
10 x{9A20C10DE30820C213E308EDF931} runvmcode drop .s
10 x{9720C11401C20CB0D8} runvmcode drop .s
15 x{9A20C10DE30820C213E308EDF931} runvmcode drop .s
15 x{9720C11401C20CB0D8} runvmcode drop .s
20 x{9A20C10DE30820C213E308EDF931} runvmcode drop .s
20 x{9720C11401C20CB0D8} runvmcode drop .s
x{E3C03077F001A4} x{3020A8} |_ runvmdict drop .s
x{71B0E30277F001A4} x{20A8} |_ runvmdict .s
17 x{30ED44D0D71131A020C8CB3FC9ED54} <b x{0000000012345678} s, b> runvm .s
100 19 7 x{92A9069620C004F2F571F321A0} runvmcode .s
19 0 x{92A9069620C004F2F571F321A0} runvmcode .s

View file

@ -0,0 +1,8 @@
x{C8}
x{62_}
x{A68054C_} |_
x{A08090C_} |_ |_
x{BEFDF21} |_
dup csr. s>c
13 x{218010F40C} runvmcode .s drop swap csr.

View file

@ -0,0 +1,14 @@
169 13
239 dup dup * swap
289 17
3
x{6D01E502C8CB0F028010F442} runvmcode .s drop dup <s csr.
1 { dup 2dup * swap rot 1+ } 100 times drop 100 .s
x{6D01E502C8CB0FC9D0028010F414} runvmcode .s drop dup <s csr.
0 { dup 2dup * rot 617 + 1000 mod } 1000 times drop 1000 .s
x{6D01E502C8CB0F028020F442} runvmcode .s drop dup <s csr.
<b x{C_} s, over ref, b> dup 15 boc+>B .s
B>boc .s

View file

@ -0,0 +1,5 @@
169 13
239 dup dup * swap
289 17
3
x{6D01E502C8CB0F028010F442} runvmcode drop dup <s csr.

View file

@ -0,0 +1,16 @@
169 13
239 dup dup * swap
289 17
3
x{6D01E502C8CB0F028010F442} runvmcode .s drop dup <s csr.
1 { dup 2dup * swap rot 1+ } 100 times drop 100 .s
x{6D01E502C8CB0FC9D0028010F414} runvmcode .s drop dup <s csr.
0 { dup 2dup * rot 617 + 1000 mod } 1000 times drop 1000 .s
x{6D01E502C8CB0F028020F442} runvmcode .s drop dup <s csr.
<b x{C_} s, over ref, b> dup 15 boc+>B .s
"dict1000.boc" B>file
"dict1000.boc" file>B
B>boc .s

View file

@ -0,0 +1,52 @@
"Asm.fif" include
<{ NEWDICT SWAP REPEAT:
s2 XCHG0 NEWC 16 STU s2 XCHG0
16 INT DICTISETB }>s
dup csr. constant mkdict(16,16).code
{ mkdict(16,16).code runvmcode abort"cannot create 16->16 dictionary" } : mkdict(16,16)
<{ ZERO WHILE:<{ SWAP 16 INT DICTIREMMAX }>DO<{ // n d' x i
SWAP 16 LDU ENDS // n d' i s
2SWAP SWAP INC
}> DROP
}>s dup csr. constant explode_dict(16,16).code
{ explode_dict(16,16).code runvmcode abort"cannot explode 16->16 dictionary" } : xdict(16,16)
{ xdict(16,16) ."{ " { swap . ."-> " . ."; " } swap times ."}" cr } : .dict(16,16)
{ xdict(16,16) { dup 0< not { ."+" } if ._ 64 + emit } swap times space } : .v
169 13
239 dup dup * swap
289 17
3
mkdict(16,16) constant dict
{ 16 { 16 i@+ s> 1+ 16 i, true } dictmap } : dict:1+
{ 16 { 16 i@+ s> swap 16 i@+ s> + 16 i, true } dictmerge } : dict:+
dict dict:1+ dup <s csr. constant dict2
dict .dict(16,16)
dict2 .dict(16,16)
10 13 20 20 2 mkdict(16,16) constant dict3
0 mkdict(16,16) constant dict0
169 13 1 mkdict(16,16) constant dict1a
100 10 1 mkdict(16,16) constant dict1b
dict dict3
2dup swap <s csr. <s csr. dict:+ dup <s csr. .dict(16,16)
{ 1 mkdict(16,16) } : cst*
{ 1 cst* } : A*
{ 2 cst* } : B*
{ 3 cst* } : C*
{ 4 cst* } : D*
{ 5 cst* } : E*
{ 6 cst* } : F*
' dict:+ : v+
2 A* 3 C* v+ 9 F* v+
1 A* 6 D* v+ 2 E* v+
over .v cr dup .v cr
v+ .v cr

View file

@ -0,0 +1,26 @@
"Asm.fif" include
<{ NEWDICT SWAP REPEAT:
s2 XCHG0 NEWC 16 STU s2 XCHG0
16 INT DICTISETB }>s
dup csr. constant mkdict(16,16).code
{ mkdict(16,16).code runvmcode abort"cannot create 16->16 dictionary" } : mkdict(16,16)
<{ ZERO WHILE:<{ SWAP 16 INT DICTIREMMAX }>DO<{ // n d' x i
SWAP 16 LDU ENDS // n d' i s
2SWAP SWAP INC
}> DROP
}>s dup csr. constant explode_dict(16,16).code
{ explode_dict(16,16).code runvmcode abort"cannot explode 16->16 dictionary" } : xdict(16,16)
{ xdict(16,16) ."{ " { swap . ."-> " . ."; " } swap times ."}" cr } : .dict(16,16)
{ 16 { 16 i@+ s> 1+ 16 i, true } dictmap } : dict:1+
{ 16 { 16 i@+ s> swap 16 i@+ s> + 16 i, true } dictmerge } : dict:+
{ 1 swap dup 1 { 2dup dup * + 2 swap 2swap 1+ } 100 times nip mkdict(16,16) } : mdisqpb
0 mdisqpb 0 { 1+ tuck dup * mdisqpb tuck dict:+ dict:+ swap } 100 times drop
dup <s csr. .dict(16,16)

View file

@ -0,0 +1,61 @@
"Asm.fif" include
<{ NEWDICT SWAP REPEAT:
s2 XCHG0 NEWC 16 STU s2 XCHG0
16 INT DICTUSETB }>s
dup csr. constant mkdict(16,16).code
{ mkdict(16,16).code runvmcode abort"cannot create 16->16 dictionary" } : mkdict(16,16)
<{ ZERO WHILE:<{ SWAP 16 INT DICTUREMMAX }>DO<{ // n d' x i
SWAP 16 LDU ENDS // n d' i s
2SWAP SWAP INC
}> DROP
}>s dup csr. constant explode_dict(16,16).code
{ explode_dict(16,16).code runvmcode abort"cannot explode 16->16 dictionary" } : xdict(16,16)
{ xdict(16,16) ."{ " { swap x. ."-> " x. ."; " } swap times ."}" } : .dict(16,16)
{ 16 { 16 u@+ s> 1+ 16 u, true } dictmap } : dict:1+
{ 16 { 16 u@+ s> swap 16 u@+ s> + 16 u, true } dictmerge } : dict:+
0x1000 0x1000
0x1234 0x1234
0x1357 0x1357
0xABCD 0xABCD
0xBFFF 0xBFFF
5 mkdict(16,16) constant D
D dup dict>s csr. .dict(16,16) ." <-- D" cr
D <{ 0 INT 0 INT ROT 16 INT SUBDICTUGET }>s dup csr. runvmcode drop
dup dict>s csr. .dict(16,16) ." <-- SubDict(D,_)" cr
D <{ 0x1 INT 4 INT ROT 16 INT SUBDICTUGET }>s runvmcode drop
dup dict>s csr. .dict(16,16) ." <-- SubDict(D,0001)" cr
D <{ 0x10 INT 8 INT ROT 16 INT SUBDICTUGET }>s runvmcode drop
dup dict>s csr. .dict(16,16) ." <-- SubDict(D,00010000)" cr
D <{ 0x12 INT 8 INT ROT 16 INT SUBDICTUGET }>s runvmcode drop
dup dict>s csr. .dict(16,16) ." <-- SubDict(D,00010010)" cr
D <{ 0x1357 INT 16 INT ROT OVER SUBDICTUGET }>s runvmcode drop
dup dict>s csr. .dict(16,16) ." <-- SubDict(D,x1357)" cr
D <{ 0 INT 2 INT ROT 16 INT SUBDICTUGET }>s runvmcode .s drop
dup dict>s csr. .dict(16,16) ." <-- SubDict(D,00)" cr
D <{ 1 INT 2 INT ROT 16 INT SUBDICTUGET }>s runvmcode .s drop
dup dict>s csr. .dict(16,16) ." <-- SubDict(D,01)" cr
D <{ 0 INT 1 INT ROT 16 INT SUBDICTUGET }>s runvmcode .s drop
dup dict>s csr. .dict(16,16) ." <-- SubDict(D,0)" cr
D <{ 1 INT 1 INT ROT 16 INT SUBDICTUGET }>s runvmcode .s drop
dup dict>s csr. .dict(16,16) ." <-- SubDict(D,1)" cr
D <{ 0xA INT 4 INT ROT 16 INT SUBDICTUGET }>s runvmcode .s drop
dup dict>s csr. .dict(16,16) ." <-- SubDict(D,1010)" cr
D <{ 0xB INT 4 INT ROT 16 INT SUBDICTUGET }>s runvmcode .s drop
dup dict>s csr. .dict(16,16) ." <-- SubDict(D,1011)" cr

View file

@ -0,0 +1,11 @@
"Asm.fif" include
<{ 2SWAP ADD s2 POP FALSE }>s b{00}
<{ 2SWAP MUL s2 POP FALSE }>s b{1}
<{ 2SWAP SUB s2 POP FALSE }>s b{01}
3
<{ NEWDICT SWAP REPEAT: 8 INT PFXDICTADD 11 THROWIFNOT }>s runvmcode
abort"cannot create prefix code dictionary"
dup dict>s csr.
<{ <{ rot 8 PFXDICTSWITCH TRUE }>UNTIL SDEMPTY 11 THROWIFNOT }>s
dup csr.
1 2 3 4 5 b{001011} 6 roll runvmcode .s

View file

@ -0,0 +1,66 @@
"Asm.fif" include
<{ 1 INT 70 INT
REPEAT:<{ 10 MULCONST }>
1 INT DUP <{ TUCK ADD DUP s3 PUSH GREATER }>UNTIL
MULDIVR
}>s
dup csr.
runvmcode .s
<{ 1 INT 70 INT REPEAT:<{ 10 MULCONST }>
1 INT DUP <{ TUCK ADD TUCK ADD SWAP DUP s3 PUSH GREATER }>UNTIL
MULDIVR
}>s
dup csr.
runvmcode .s
<{ WHILE:<{
DUP DEC
}>DO<{
DUP DUP 1 INT AND IF:<{
3 MULCONST INC
}>ELSE<{
1 RSHIFT#
}>
}>
}>s
dup csr.
<{ WHILE:<{
DUP DEC
}>DO:
DUP DUP 1 INT AND IF:<{
3 MULCONST INC
}>ELSE:
1 RSHIFT#
}>s
dup csr.
nip
17 swap runvmcode .s
<{ CONT:<{
TUCK DIVR SWAP DUP MUL NEGATE SWAP ZERO ONE
<{ SWAP s2 s1 PUSH2 DIVR ADD SWAP 2 ADDCONST
2SWAP OVER DIVR 2SWAP s2 PUSH ISZERO }>UNTIL
DROP s2 POP DROP
}>
8 PUSHPOW2 70 INT REPEAT:<{ 10 MULCONST }>
DUP 2 LSHIFT# 5 INT s3 PUSH EXECUTE
s0 s2 XCHG 239 INT SWAP EXECUTE SUB
6 RSHIFTR#
}>s dup csr.
runvmcode .s
<{ 8 PUSHPOW2 70 INT REPEAT:<{ 10 MULCONST }>
ZERO DUP
<{ s2 PUSH ADD -ROT INC TUCK DIVR -ROT SWAP s2 PUSH ISZERO }>UNTIL
NIP NIP 8 RSHIFTR#
}>s dup csr.
runvmcode .s

View file

@ -0,0 +1,47 @@
"Asm.fif" include
<{ -1 INT ZERO ROT
100 INT REPEAT:<{
ZERO WHILE:<{
3 3 BLKPUSH
// -ROT OVER ADD ROT OVER ADD -ROT OVER ADD ROT
s2 s1 PUXC ADD TUCK ADD s2 s1 PUXC ADD SWAP
DUP ISPOS
}>DO<{
s4 POP s4 POP s4 POP INC
}>
3 BLKDROP
s3 XCHG0 NEGATE s2 XCHG0 NEGATE SWAP NEGATE s2 XCHG0
}>
3 BLKDROP
}>s dup csr.
// 61 swap runvmcode .s
drop
<{ -1 INT ZERO ROT ONE ZERO s0 s1 PUSH2
<{ 3 6 BLKPUSH // a b c m11 m12 m21 m22 a' b' c'
s2 s1 PUXC ADD TUCK ADD s2 s1 PUXC ADD SWAP
DUP ISPOS IF:<{
s7 POP s7 POP s7 POP // a' b' c' m11 m12 m21 m22
s2 PUSH ADD SWAP s3 PUSH ADD SWAP
}>ELSE<{
3 BLKDROP // a b c m11 m12 m21 m22
2SWAP
3 4 BLKSWAP // m m m m a b c
NEGATE SWAP NEGATE // .. a -c -b
ROT NEGATE // -c -b -a
4 3 BLKSWAP
}>
DUP 250 QFITS ISNAN
}>UNTIL
2DROP s3 POP s3 POP DROP
}>s dup csr.
1 { 10 * } 75 times constant One
{ One swap */r } : frac*One
61 over runvmcode drop frac*One swap
2 over runvmcode drop frac*One swap
3 over runvmcode drop frac*One swap
5 over runvmcode drop frac*One swap
6 over runvmcode drop frac*One swap
7 over runvmcode drop frac*One swap
8 over runvmcode drop frac*One swap
.s

View file

@ -0,0 +1,5 @@
"Asm.fif" include
<{ 7 INT -4 INT NEWC 64 STI 4 STU ENDC
CTOS 64 LDI 4 LDU ENDS }>s
dup csr.
runvmcode .s

View file

@ -0,0 +1,7 @@
"Asm.fif" include
<{ 2 INT 3 INT 9 INT NULL CONS CONS CONS }>s dup csr. runvmcode .s
drop =: L
<{ ZERO WHILE:<{ OVER ISNULL NOT }>DO<{ SWAP SECOND SWAP INC }> NIP }>s dup csr. =: ListLength
L ListLength runvmcode .s 2drop
<{ CONT:<{ DUP ISNULL IF:<{ 2DROP ZERO }>ELSE: CDR OVER EXECUTE INC }> TUCK JMPX }>s dup csr. =: ListLengthRec
L ListLengthRec runvmcode .s 2drop

View file

@ -0,0 +1,40 @@
"Asm.fif" include
PROGRAM{
NEWPROC add
NEWPROC sub
NEWPROC mul
sub <{ s3 s3 XCHG2 SUB s2 XCHG0 SUB }>s PROC
// compute (5+i)^4 * (239-i)
main PROC:<{
5 INT 1 INT // 5+i
2DUP
mul CALL
2DUP
mul CALL
239 INT -1 INT
mul JMP
}>
add PROC:<{
s1 s2 XCHG
ADD -ROT ADD SWAP
}>
// a b c d -- ac-bd ad+bc : complex number multiplication
mul PROC:<{
s3 s1 PUSH2 // a b c d a c
MUL // a b c d ac
s3 s1 PUSH2 // a b c d ac b d
MUL // a b c d ac bd
SUB // a b c d ac-bd
s4 s4 XCHG2 // ac-bd b c a d
MUL // ac-bd b c ad
-ROT MUL ADD
}>
}END>s
dup csr. runvmdict .s

571
crypto/test/test-cells.cpp Normal file
View file

@ -0,0 +1,571 @@
/*
This file is part of TON Blockchain Library.
TON Blockchain Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
TON Blockchain Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#include <algorithm>
#include <string>
#include <vector>
#include <iostream>
#include <sstream>
#include <memory>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include "common/refcnt.hpp"
#include "common/bigint.hpp"
#include "common/refint.h"
#include "common/bitstring.h"
#include "common/util.h"
#include "vm/cells.h"
#include "vm/cellslice.h"
#include "td/utils/tests.h"
#include "td/utils/crypto.h"
#include "td/utils/misc.h"
static std::stringstream create_ss() {
std::stringstream ss;
ss.imbue(std::locale::classic());
ss.setf(std::ios_base::fixed, std::ios_base::floatfield);
ss.precision(6);
return ss;
}
static std::stringstream os = create_ss();
void show_total_cells(std::ostream& stream) {
stream << "total cells = " << vm::DataCell::get_total_data_cells() << std::endl;
}
TEST(Cells, simple) {
os = create_ss();
using namespace td::literals;
vm::CellBuilder cb1, cb2;
cb1.store_bytes("Hello, ", 7).reserve_slice(48) = td::BitSlice{(const unsigned char*)"world!", 48};
cb2.store_bits(td::BitSlice{(const unsigned char*)"\xd0", 4})
.store_long(17239, 16)
.store_long(-17, 11)
.store_long(1000000239, 32)
.store_long(1000000239LL * 1000000239)
.store_int256("-1000000000000000000000000239"_i256, 91);
cb1.store_ref(cb2.finalize_copy());
show_total_cells(os);
cb2.store_bytes("<->", 3);
td::Ref<vm::DataCell> c1{cb1.finalize_copy()}, c2{cb2.finalize_copy()};
unsigned char hbuff[vm::Cell::hash_bytes];
os << "cb1 = " << cb1 << "; hash=" << td::buffer_to_hex(td::Slice(cb1.compute_hash(hbuff), 32)) << "; c1 = " << *c1
<< std::endl;
os << "cb2 = " << cb2 << "; hash=" << td::buffer_to_hex(td::Slice(cb2.compute_hash(hbuff), 32)) << "; c2 = " << *c2
<< std::endl;
show_total_cells(os);
vm::CellSlice cr1(c1);
cr1.dump(os);
os << "fetch_octet() = " << cr1.fetch_octet() << std::endl;
cr1.dump(os);
os << "fetch_octet() = " << cr1.fetch_octet() << std::endl;
cr1.dump(os);
os << "fetch_octet() = " << cr1.fetch_octet() << std::endl;
cr1.dump(os);
os << "fetch_octet() = " << cr1.fetch_octet() << std::endl;
cr1.dump(os);
os << "fetch_ref()=" << td::buffer_to_hex(cr1.prefetch_ref()->get_hash().as_slice()) << std::endl;
vm::CellSlice cr(vm::NoVm(), cr1.fetch_ref());
cr.dump(os);
os << "prefetch_ulong(4)=" << cr.prefetch_ulong(4) << std::endl;
cr.dump(os);
os << "fetch_ulong(4)=" << cr.fetch_ulong(4) << std::endl;
cr.dump(os);
os << "fetch_long(16)=" << cr.fetch_long(16) << std::endl;
cr.dump(os);
os << "prefetch_long(11)=" << cr.prefetch_long(11) << std::endl;
cr.dump(os);
os << "fetch_int256(11)=" << cr.fetch_int256(11) << std::endl;
cr.dump(os);
os << "fetch_long(32)=" << cr.fetch_long(32) << std::endl;
cr.dump(os);
os << "prefetch_long(64)=" << cr.prefetch_long(64) << std::endl;
cr.dump(os);
os << "fetch_long(64)=" << cr.fetch_long(64) << std::endl;
cr.dump(os);
os << "prefetch_int256(91)=" << cr.prefetch_int256(91) << std::endl;
cr.dump(os);
os << "fetch_int256(91)=" << cr.fetch_int256(91) << std::endl;
cr.dump(os);
os << "fetch_long(24)=" << cr.fetch_long(24) << std::endl;
cr.dump(os);
cr.clear();
REGRESSION_VERIFY(os.str());
}
void test_two_bitstrings(const td::BitSlice& bs1, const td::BitSlice& bs2) {
using td::to_binary;
using td::to_hex;
os << "bs1 = " << bs1.to_binary() << " = " << bs1.to_hex() << std::endl;
os << "bs2 = " << to_binary(bs2) << " = " << to_hex(bs2) << std::endl;
td::BitString st{bs1};
//td::BitString st;
//st.append(bs1);
os << "st = " << to_binary(st) << " = " << to_hex(st) << std::endl;
st.append(bs2);
os << "st = " << to_binary(st) << " = " << to_hex(st) << std::endl;
ASSERT_EQ(to_binary(st), to_binary(bs1) + to_binary(bs2));
auto bs3 = st.subslice(bs1.size(), bs2.size());
os << "bs3 = " << to_binary(bs3) << " = " << to_hex(bs3) << std::endl;
ASSERT_EQ(to_binary(bs3), to_binary(bs2));
ASSERT_EQ(to_hex(bs3), to_hex(bs2));
bs1.dump(os);
bs2.dump(os);
bs3.dump(os);
std::string bs2_bin = to_binary(bs2);
for (unsigned i = 0; i <= bs2.size(); i++) {
for (unsigned j = 0; j <= bs2.size() - i; j++) {
auto bs4 = bs2.subslice(i, j);
auto bs5 = bs3.subslice(i, j);
if (!(to_binary(bs4) == to_binary(bs5) && to_hex(bs4) == to_hex(bs5) && to_binary(bs4) == bs2_bin.substr(i, j))) {
bs4.dump(os);
bs5.dump(os);
os << "bs2.subslice(" << i << ", " << j << ") = " << to_binary(bs4) << " = " << to_hex(bs4) << std::endl;
os << "bs3.subslice(" << i << ", " << j << ") = " << to_binary(bs5) << " = " << to_hex(bs5) << std::endl;
}
ASSERT_EQ(to_binary(bs4), to_binary(bs5));
ASSERT_EQ(to_hex(bs4), to_hex(bs5));
ASSERT_EQ(to_binary(bs4), bs2_bin.substr(i, j));
}
}
}
void test_one_bitstring(const td::BitSlice& bs) {
std::string bs_bin = bs.to_binary();
for (unsigned i1 = 0; i1 <= bs.size(); i1++) {
for (unsigned j1 = 0; j1 <= bs.size() - i1; j1++) {
auto bs1 = bs.subslice(i1, j1);
ASSERT_EQ(bs1.to_binary(), bs_bin.substr(i1, j1));
for (unsigned i2 = 0; i2 <= bs.size() && i2 < 8; i2++) {
for (unsigned j2 = 0; j2 <= bs.size() - i2; j2++) {
os << "(" << i1 << "," << j1 << ")+(" << i2 << "," << j2 << ")" << std::endl;
auto bs2 = bs.subslice(i2, j2);
ASSERT_EQ(bs2.to_binary(), bs_bin.substr(i2, j2));
test_two_bitstrings(bs1, bs2);
}
}
}
}
}
void test_bitstring_fill(unsigned n, unsigned p, unsigned k) {
td::BitString bs{n * 2};
std::string s;
auto sl1 = td::BitSlice{(const unsigned char*)"\x40", 2};
for (unsigned i = 0; i < n; i++) {
bs.append(sl1);
s += "01";
}
os << td::to_binary(bs) << " = " << td::to_hex(bs) << std::endl;
ASSERT_EQ(td::to_binary(bs), s);
unsigned q = k %= p;
for (unsigned i = 0; i < p; i++) {
unsigned a = (q * n * 2) / p;
unsigned b = ((q + 1) * n * 2) / p;
bs.subslice_write(a, b - a) = (q & 1);
std::fill(s.begin() + a, s.begin() + b, (q & 1) + '0');
os << "Step " << i << " (" << a << "," << b << "): " << td::to_binary(bs) << " = " << td::to_hex(bs) << std::endl;
ASSERT_EQ(td::to_binary(bs), s);
q = (q + k) % p;
}
bs.subslice_write(4, 16) = td::BitSlice{(const unsigned char*)"\x69\x96", 16};
os << td::to_binary(bs) << " = " << td::to_hex(bs) << std::endl;
std::string t = "0110100110010110";
std::copy(t.begin(), t.end(), s.begin() + 4);
ASSERT_EQ(td::to_binary(bs), s);
}
TEST(Bitstrings, main) {
os = create_ss();
auto test = td::BitSlice{(const unsigned char*)"test", 32};
ASSERT_EQ(test.to_hex(), "74657374");
test_two_bitstrings({(const unsigned char*)"\xf1\xd0", 12}, test);
test_two_bitstrings({(const unsigned char*)"\x9f", 3}, {(const unsigned char*)"t", 3});
test_bitstring_fill(17 * 3, 17, 4);
//test_one_bitstring({(const unsigned char*)"SuperTest", 72});
REGRESSION_VERIFY(os.str());
}
void test_parse_dec(std::string s) {
td::BigInt256 x, y;
os << "s=\"" << s << "\"" << std::endl;
x.parse_dec_slow(s);
y.parse_dec(s);
x.dump(os);
y.dump(os);
ASSERT_TRUE(x == y);
std::string s1 = x.to_dec_string();
os << s1 << std::endl;
ASSERT_EQ(s, s1);
std::string s2 = x.to_hex_string();
os << s2 << std::endl;
std::string s3 = x.to_hex_string_slow();
os << s3 << std::endl;
ASSERT_EQ(s2, s3);
}
void test_pow2(int exponent) {
td::BigInt256 x;
x.set_pow2(exponent);
os << "2^" << exponent << " = " << x.to_dec_string() << " = 0x" << x.to_hex_string() << std::endl;
x.dump(os);
}
void test_fits(const td::BigInt256& x) {
int m = 0, n = 0;
const int limit = 300;
os << "x=" << x.to_dec_string() << "; log2(|x|)=" << std::log2(std::abs(x.to_double())) << std::endl;
x.dump(os);
while (m < limit && !x.unsigned_fits_bits(m)) {
m++;
}
for (int i = m; i < limit; i++) {
ASSERT_TRUE(x.unsigned_fits_bits(i));
}
int su = x.bit_size(false);
while (n < limit && !x.signed_fits_bits(n)) {
n++;
}
for (int i = n; i < limit; i++) {
ASSERT_TRUE(x.signed_fits_bits(i));
}
int ss = x.bit_size();
os << "x=" << x.to_dec_string() << "=0x" << x.to_hex_string() << "; x=" << x.to_double()
<< "; log2(|x|)=" << std::log2(std::abs(x.to_double())) << "; unsigned: " << m << "=" << su
<< " bits; signed: " << n << "=" << ss << " bits" << std::endl;
ASSERT_TRUE(su == m || (su == 0x7fffffff && m == limit));
ASSERT_EQ(ss, n);
ASSERT_EQ(x.to_hex_string(), x.to_hex_string_slow());
td::BigInt256 y, z;
ASSERT_TRUE(y.parse_hex(x.to_hex_string()) && y == x);
ASSERT_TRUE(z.parse_dec(x.to_dec_string()) && z == x);
}
void test_divmod(const td::BigInt256& x, const td::BigInt256& y) {
td::BigInt256 q, r(x);
os << "x = " << x << " = ";
x.dump(os);
os << "y = " << y << " = ";
y.dump(os);
if (!r.mod_div_bool(y, q)) {
os << "division error!\n";
ASSERT_TRUE(0);
} else {
q.dump(os);
r.dump(os);
if (!q.normalize_bool() || !r.normalize_bool()) {
os << "cannot normalize q or r!\n";
ASSERT_TRUE(0);
} else {
os << "q = " << q << "; r = " << r << std::endl;
if (y.sgn() > 0) {
ASSERT_TRUE(r.sgn() >= 0);
ASSERT_TRUE(r.cmp(y) < 0);
} else {
ASSERT_TRUE(r.sgn() <= 0);
ASSERT_TRUE(r.cmp(y) > 0);
}
r.add_mul(q, y);
ASSERT_TRUE(r.normalize() == x);
}
}
}
void test_export_int(const td::BigInt256& x, bool sgnd = true) {
os << "x = " << x.to_hex_string() << std::endl;
int bad = 0, ok = 0;
for (int i = 1; i <= 33; i++) {
unsigned char buff[33];
std::memset(buff, 0xcc, sizeof(buff));
if (!x.export_bytes(buff, i, sgnd)) {
ASSERT_EQ(bad, i - 1);
bad = i;
continue;
} else if (++ok < 5) {
if (bad == i - 1) {
os << "export(" << bad << ", " << sgnd << ") = (bad)" << std::endl;
}
os << "export(" << i << ", " << sgnd << ") =";
char tmp[33 * 3 + 1];
for (int j = 0; j < i; j++) {
sprintf(tmp + 3 * j, " %02x", buff[j]);
}
os << tmp << std::endl;
td::BigInt256 y;
ASSERT_TRUE(y.import_bytes(buff, i, sgnd));
os << "import() = " << y.to_hex_string() << std::endl;
ASSERT_TRUE(!x.cmp_un(y));
}
}
if (!ok) {
os << "export(" << bad << ", " << sgnd << ") = (bad)" << std::endl;
}
}
TEST(Bigint, main) {
os = create_ss();
using namespace td::literals;
td::BigInt256 x, y, z;
test_parse_dec("0");
test_parse_dec("1");
test_parse_dec("-1");
test_parse_dec("123");
test_parse_dec("-239");
test_parse_dec("-115792089237316195423570985008687907853269984665640564039457584007913129639936");
test_parse_dec("115792089237316195423570985008687907853269984665640564039457584007913129639935");
test_parse_dec("143126893554044595713052252685501316785002612509329899766666973726012466208042");
test_parse_dec("100000000000000000000000000000000000000000000000000000000000000000000000000001");
x.parse_dec("11111111111111111111111111111111111111111111111111111111111111111111111111111");
y.parse_dec("22222222222222222222222222222222222");
x += y;
os << x.to_dec_string() << std::endl;
x -= y;
os << x.to_dec_string() << std::endl;
x -= y;
os << x.to_dec_string() << std::endl;
y -= x;
os << y.to_dec_string() << std::endl;
y += x;
os << x.to_dec_string() << std::endl;
x.parse_dec("10000000000000000000000000000001");
y.parse_dec("11111111111111111111111111111111");
z.add_mul(x, y);
os << x.to_dec_string() << " * " << y.to_dec_string() << " = " << z.to_dec_string() << std::endl;
test_pow2(0);
test_pow2(1);
test_pow2(54);
test_pow2(55);
test_pow2(56);
test_pow2(57);
test_pow2(4 * 56 - 2);
test_pow2(4 * 56 - 1);
test_pow2(4 * 56);
test_pow2(4 * 56 + 1);
test_pow2(255);
test_pow2(256);
test_fits("1111111111111111111111111111"_i256);
test_fits(
"0000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffff"_x256);
for (int i = 10; i >= -10; --i) {
test_fits(td::BigInt256(i));
}
test_export_int("10000000000000000000000000000000000000"_i256);
for (int k = 127; k <= 129; k++) {
x.set_pow2(k).add_tiny(-1);
test_export_int(x, true);
test_export_int(x, false);
x.add_tiny(1);
test_export_int(x, true);
test_export_int(x, false);
x.add_tiny(1);
test_export_int(x, true);
test_export_int(x, false);
x.negate();
test_export_int(x, true);
test_export_int(x, false);
x.add_tiny(1);
test_export_int(x, true);
test_export_int(x, false);
x.add_tiny(1);
test_export_int(x, true);
test_export_int(x, false);
}
for (x = 1, y.set_pow2(256).divmod_tiny(3); x.cmp(y) < 0; x.mul_tiny(3).normalize()) {
test_export_int(x, true);
x.negate();
test_export_int(x, true);
x.negate();
}
test_export_int("7fffffffffffffffffffffffffffffff"_x256);
test_export_int("ffffffffffffffffffffffffffffffff"_x256);
test_export_int("7fffffffffffffffffffffffffffffff"_x256);
test_export_int("ffffffffffffffffffffffffffffffff"_x256);
for (int i = 0; i <= 257; i++) {
x.set_pow2(i).add_tiny(-3);
for (int j = -3; j <= 3; j++) {
x.negate().normalize();
os << "-2^" << i << "+" << -j << ": ";
test_fits(x);
x.negate().normalize();
os << "2^" << i << "+" << j << ": ";
test_fits(x);
x.add_tiny(1);
}
}
for (auto t : {"fffffffffffffffffffffffffffffffffffffff"_x256, td::BigInt256{-1},
"123456789abcdef0123456789abcdef0123456789abcdef"_x256, "-8000000000000000000000000001"_x256}) {
for (int i = 0; i <= 256; i++) {
(x = t).mod_pow2(i).dump(os);
os << "mod 2^" << i << " : " << x.to_hex_string() << std::endl;
}
}
test_divmod(x.set_pow2(224), "10000000000000"_i256);
test_divmod(x.set_pow2(256), "100000000000000000000000000000000000000000"_i256);
test_divmod(x.set_pow2(256), "100000000000000000000000000000000000000000000"_i256);
test_divmod(x.set_pow2(80), "-100000000000000000000000000000000000000000000"_i256);
test_divmod(x.set_pow2(256), y.set_pow2(128).add_tiny(-1));
test_divmod(x.set_pow2(224), y.set_pow2(112).add_tiny(-1));
test_divmod(x.set_pow2(222), y.set_pow2(111).add_tiny(-1));
test_divmod(td::BigInt256(-1), y.set_pow2(256));
test_divmod("10000000000000000000000000000000000000000000000000000000000000000"_i256,
"142857142857142857142857142857142857"_i256);
test_divmod("100000000"_i256, "-253"_i256);
test_divmod("-100000000"_i256, "-253"_i256);
test_divmod("-100000000"_i256, "253"_i256);
test_divmod(x.set_pow2(222), td::BigInt256{std::numeric_limits<td::BigInt256::word_t>::min()});
test_divmod(x.set_pow2(222).negate(), td::BigInt256{std::numeric_limits<td::BigInt256::word_t>::min()});
REGRESSION_VERIFY(os.str());
}
TEST(RefInt, main) {
os = create_ss();
using namespace td::literals;
auto x = "10000000000000000000000"_ri256;
td::RefInt256 y{true, -239}, z{false};
auto v = x + y;
std::move(v);
os << x << " + " << y << " = " << x + y << std::endl;
os << x << " - " << y << " = " << x - y << std::endl;
os << x << " * " << y << " = " << x * y << std::endl;
os << x << " / " << y << " = " << x / y << std::endl;
os << x << " % " << y << " = " << x % y << std::endl;
os << x << " + " << y << " = " << x + y << std::endl;
os << "10000000000000000000000000000000000000000"_ri256 / "27182818284590"_ri256 << std::endl;
{
auto w(x + y);
z = w;
}
os << "(x-y)*(x+y) = " << (x - y) * (x + y) << std::endl;
os << "z = " << z << std::endl;
z = x;
x += y;
os << "new x = " << x << " = 0x" << hex_string(x) << std::endl;
os << "z = (old x) = " << std::move(z) << std::endl;
os << "x + y = " << std::move(x) + std::move(y) << std::endl;
z = "10000000000000000000000000000000000000000000000000000000000000000000000"_ri256;
//z = td::RefInt256{true}
//z.unique_write()->set_pow2(256);
x = td::RefInt256{true, 0};
int i = 1;
while (z->sgn() > 0) {
x += z;
z.write().add_tiny(i >> 1).divmod_tiny(i);
++i;
}
x.write().normalize();
os << x << " = " << hex_string(x) << std::endl;
REGRESSION_VERIFY(os.str());
}
TEST(crc16, main) {
os = create_ss();
std::string s = "EMSI_FCK";
unsigned crc16 = td::crc16(td::Slice{s});
os << "s = `" << s << "`; crc16 = " << std::hex << crc16 << std::dec << std::endl;
REGRESSION_VERIFY(os.str());
}
TEST(base64, main) {
os = create_ss();
std::vector<std::string> arr = {"TEST STRING NUMBER ONE", "TEST STRING NUMBER FOUR", "TEST STRING NUMBER THREE"};
for (std::string s : arr) {
std::string t = td::str_base64_encode(s);
std::string u = td::str_base64_decode(t);
os << "`" << s << "` -> `" << t << "` -> `" << u << "`" << std::endl;
os << (s == u) << std::endl;
}
std::string s;
int k = 0;
for (int i = 0; i < 1024; i++) {
s.push_back((char)(k >> 8));
k = 69069 * k + 1;
}
std::string t = td::str_base64_encode(s);
std::string u = td::str_base64_decode(t, true);
os << t << std::endl;
os << (s == u) << std::endl;
t = td::str_base64_encode(s, true);
u = td::str_base64_decode(t, true);
os << t << std::endl;
os << (s == u) << std::endl;
u = td::sha256(td::Slice{s});
for (int i = 0; i < 32; i++) {
os << std::hex << ((u[i] >> 4) & 15) << (u[i] & 15);
}
os << std::dec << std::endl;
REGRESSION_VERIFY(os.str());
}
void check_bits256_scan(std::ostream& os, td::Bits256 a, td::Bits256 b) {
auto c = a ^ b;
auto bit = c.count_leading_zeroes();
auto bit2 = a.count_matching(b);
// os << a.to_hex() << " and " << b.to_hex() << " match in " << bit << " or " << bit2 << " first bits" << std::endl;
// std::cerr << a.to_hex() << " and " << b.to_hex() << " match in " << bit << " or " << bit2 << " first bits (a XOR b = " << c.to_hex() << ")" << std::endl;
CHECK((int)bit >= 0 && bit <= 256);
for (td::uint32 i = 0; i < bit; i++) {
CHECK(a[i] == b[i]);
}
CHECK(bit == 256 || a[bit] != b[bit]);
CHECK(bit == bit2);
}
void check_bits_scan(std::ostream& os, td::ConstBitPtr a, bool value) {
auto bit = (unsigned)a.scan(value, 256);
CHECK((int)bit >= 0 && bit <= 256);
for (td::uint32 i = 0; i < bit; i++) {
CHECK(a[i] == value);
}
CHECK(bit == 256 || a[bit] != value);
}
TEST(bits256_scan, main) {
os = create_ss();
td::Bits256 a, b;
int k = 0;
unsigned char r[1024];
for (auto& c : r) {
c = (k & 0x80) ? (unsigned char)(k >> 8) : 0;
k = 69069 * k + 1;
}
for (k = 0; k < 32; k++) {
a = td::ConstBitPtr{r + 32 * k};
for (int j = 0; j < 32; j++) {
b = td::ConstBitPtr{r + 32 * j};
check_bits256_scan(os, a, b);
}
b = a;
unsigned i = r[7 + k];
b[i] = b[i] ^ true;
check_bits256_scan(os, a, b);
}
for (k = 0; k < 256; k++) {
check_bits_scan(os, td::ConstBitPtr{r} + k, false);
check_bits_scan(os, td::ConstBitPtr{r} + k, true);
}
os << "bits256_scan test OK";
REGRESSION_VERIFY(os.str());
}

2008
crypto/test/test-db.cpp Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,314 @@
/*
This file is part of TON Blockchain source code.
TON Blockchain is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
TON Blockchain is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with TON Blockchain. If not, see <http://www.gnu.org/licenses/>.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
You must obey the GNU General Public License in all respects for all
of the code used other than OpenSSL. If you modify file(s) with this
exception, you may extend this exception to your version of the file(s),
but you are not obligated to do so. If you do not wish to do so, delete this
exception statement from your version. If you delete this exception statement
from all source files in the program, then also delete it here.
Copyright 2017-2019 Telegram Systems LLP
*/
#include <iostream>
#include <iomanip>
#include <string>
#include <cstring>
#include "crypto/ellcurve/Ed25519.h"
static void my_assert_impl(bool cond, const char* str, const char* file, int line) {
if (!cond) {
std::cerr << "Failed " << str << " in " << file << " at " << line << ".\n";
}
}
#define my_assert(x) my_assert_impl(x, #x, __FILE__, __LINE__)
void print_buffer(const unsigned char buffer[32]) {
for (int i = 0; i < 32; i++) {
char buff[4];
sprintf(buff, "%02x", buffer[i]);
std::cout << buff;
}
}
std::string buffer_to_hex(const unsigned char* buffer, std::size_t size = 32) {
const char* hex = "0123456789ABCDEF";
std::string res(2 * size, '\0');
for (std::size_t i = 0; i < size; i++) {
auto c = buffer[i];
res[2 * i] = hex[c & 15];
res[2 * i + 1] = hex[c >> 4];
}
return res;
}
// export of (17/12)G on twisted Edwards curve
unsigned char test_vector1[32] = {0xfc, 0xb7, 0x42, 0x1e, 0x26, 0xad, 0x1b, 0x17, 0xf6, 0xb1, 0x52,
0x0c, 0xdb, 0x8a, 0x64, 0x7d, 0x28, 0xa7, 0x56, 0x69, 0xd4, 0xb6,
0x0c, 0xec, 0x63, 0x72, 0x5e, 0xe6, 0x32, 0x4d, 0xf7, 0xe6};
unsigned char rfc7748_output[32] = {
0x95, 0xcb, 0xde, 0x94, 0x76, 0xe8, 0x90, 0x7d, 0x7a, 0xad, 0xe4, 0x5c, 0xb4, 0xb8, 0x73, 0xf8,
0x8b, 0x59, 0x5a, 0x68, 0x79, 0x9f, 0xa1, 0x52, 0xe6, 0xf8, 0xf7, 0x64, 0x7a, 0xac, 0x79, 0x57,
};
bool test_ed25519_impl(void) {
std::cout << "************** Testing Curve25519 / Ed25519 operations ************\n";
auto& E = ellcurve::Curve25519();
auto& Edw = ellcurve::Ed25519();
arith::Bignum L = E.get_ell();
my_assert(arith::is_prime(L));
my_assert(L == Edw.get_ell());
arith::ResidueRing Fl(L);
arith::Bignum s = Fl.frac(17, 12).extract();
arith::Bignum t = Fl.frac(12, 17).extract();
std::cout << "l = " << L << std::endl;
std::cout << "s = 17/12 mod l = " << s << std::endl;
std::cout << "t = 12/17 mod l = " << t << std::endl;
auto sG = E.power_gen_xz(s);
auto u_sG = sG.get_u();
std::cout << "Curve25519 u(sG) = " << sG.get_u().extract() << std::endl;
std::cout << "Curve25519 y(sG) = " << sG.get_y().extract() << std::endl;
auto sG1 = Edw.power_gen(s);
std::cout << "Ed25519 u(sG) = " << sG1.get_u().extract() << std::endl;
std::cout << "Ed25519 y(sG) = " << sG1.get_y().extract() << std::endl;
std::cout << "Ed25519 x(sG) = " << sG1.get_x().extract() << std::endl;
my_assert(sG1.get_x().extract() != sG1.get_y().extract());
my_assert(sG.get_u() == sG1.get_u());
my_assert(sG.get_y() == sG1.get_y());
my_assert(
sG1.get_x().extract() ==
arith::Bignum(arith::dec_string{"9227429025021714590777223519505276506601225973596506606120015751301699519597"}));
my_assert(sG1.get_y().extract() ==
arith::Bignum(
arith::dec_string{"46572854587220149033453000581008590225032365765275643343836649812808016508924"}));
auto sG2 = Edw.power_gen(s, true);
my_assert(sG1.get_u() == sG2.get_u());
my_assert(sG1.get_y() == sG2.get_y());
unsigned char buff[32];
std::memset(buff, 0, 32);
my_assert(sG1.export_point(buff));
std::cout << "sG export = " << buffer_to_hex(buff) << std::endl;
bool ok;
auto sG3 = Edw.import_point(buff, ok);
my_assert(ok);
my_assert(!std::memcmp(buff, test_vector1, 32));
my_assert(sG3.get_u() == sG1.get_u());
my_assert(sG2.get_x() == sG2.get_x());
my_assert(sG2.get_y() == sG2.get_y());
auto stG = E.power_xz(u_sG, t);
std::cout << "Curve25519 u(stG) = " << stG.get_u().extract() << std::endl;
my_assert(stG.get_u().extract() == 9);
auto stG1 = Edw.power_point(sG1, t);
std::cout << "Ed25519 u(stG) = " << stG1.get_u().extract() << std::endl;
my_assert(stG1.get_u().extract() == 9);
stG1.normalize();
my_assert(stG1.XY == Edw.get_base_point().XY);
my_assert(stG1.X == Edw.get_base_point().X);
my_assert(stG1.Y == Edw.get_base_point().Y);
my_assert(stG1.Z == Edw.get_base_point().Z);
auto stG2 = Edw.power_point(sG2, t, true);
my_assert(stG2.get_u().extract() == 9);
stG2.normalize();
my_assert(stG2.XY == stG1.XY && stG2.X == stG1.X && stG2.Y == stG1.Y);
auto stG3 = Edw.power_point(sG3, t).normalize();
auto stG4 = Edw.power_point(sG3, t, true).normalize();
my_assert(stG3.XY == stG1.XY && stG3.X == stG1.X && stG3.Y == stG1.Y);
my_assert(stG4.XY == stG1.XY && stG4.X == stG1.X && stG4.Y == stG1.Y);
// RFC7748 test vector
auto u =
arith::Bignum(arith::dec_string{"8883857351183929894090759386610649319417338800022198945255395922347792736741"});
//u[255] = 0;
auto n =
arith::Bignum(arith::dec_string{"35156891815674817266734212754503633747128614016119564763269015315466259359304"});
//n[255] = 0; n[254] = 1;
//n[0] = n[1] = n[2] = 0;
auto umodp = arith::Residue(u, E.get_base_ring());
auto nP = E.power_xz(umodp, n);
std::cout << "u(P) = " << u.to_hex() << std::endl;
std::cout << "n = " << n.to_hex() << std::endl;
std::cout << "u(nP) = " << nP.get_u().extract().to_hex() << std::endl;
unsigned char buffer[32];
std::memset(buffer, 0, 32);
nP.export_point_u(buffer);
std::cout << "u(nP) export = " << buffer_to_hex(buffer) << std::endl;
my_assert(!std::memcmp(buffer, rfc7748_output, 32));
std::cout << "********* ok\n\n";
return true;
}
unsigned char fixed_privkey[32] = "abacabadabacabaeabacabadabacaba";
unsigned char fixed_pubkey[32] = {0x6f, 0x9e, 0x5b, 0xde, 0xce, 0x87, 0x21, 0xeb, 0x57, 0x37, 0xfb,
0xb5, 0x92, 0x28, 0xba, 0x07, 0xf7, 0x88, 0x0f, 0x73, 0xce, 0x5b,
0xfa, 0xa1, 0xb7, 0x15, 0x73, 0x03, 0xd4, 0x20, 0x1e, 0x74};
unsigned char rfc8032_secret_key1[32] = {0x9d, 0x61, 0xb1, 0x9d, 0xef, 0xfd, 0x5a, 0x60, 0xba, 0x84, 0x4a,
0xf4, 0x92, 0xec, 0x2c, 0xc4, 0x44, 0x49, 0xc5, 0x69, 0x7b, 0x32,
0x69, 0x19, 0x70, 0x3b, 0xac, 0x03, 0x1c, 0xae, 0x7f, 0x60};
unsigned char rfc8032_public_key1[32] = {0xd7, 0x5a, 0x98, 0x01, 0x82, 0xb1, 0x0a, 0xb7, 0xd5, 0x4b, 0xfe,
0xd3, 0xc9, 0x64, 0x07, 0x3a, 0x0e, 0xe1, 0x72, 0xf3, 0xda, 0xa6,
0x23, 0x25, 0xaf, 0x02, 0x1a, 0x68, 0xf7, 0x07, 0x51, 0x1a};
unsigned char rfc8032_signature1[64] = {
0xe5, 0x56, 0x43, 0x00, 0xc3, 0x60, 0xac, 0x72, 0x90, 0x86, 0xe2, 0xcc, 0x80, 0x6e, 0x82, 0x8a,
0x84, 0x87, 0x7f, 0x1e, 0xb8, 0xe5, 0xd9, 0x74, 0xd8, 0x73, 0xe0, 0x65, 0x22, 0x49, 0x01, 0x55,
0x5f, 0xb8, 0x82, 0x15, 0x90, 0xa3, 0x3b, 0xac, 0xc6, 0x1e, 0x39, 0x70, 0x1c, 0xf9, 0xb4, 0x6b,
0xd2, 0x5b, 0xf5, 0xf0, 0x59, 0x5b, 0xbe, 0x24, 0x65, 0x51, 0x41, 0x43, 0x8e, 0x7a, 0x10, 0x0b,
};
unsigned char rfc8032_secret_key2[32] = {
0xc5, 0xaa, 0x8d, 0xf4, 0x3f, 0x9f, 0x83, 0x7b, 0xed, 0xb7, 0x44, 0x2f, 0x31, 0xdc, 0xb7, 0xb1,
0x66, 0xd3, 0x85, 0x35, 0x07, 0x6f, 0x09, 0x4b, 0x85, 0xce, 0x3a, 0x2e, 0x0b, 0x44, 0x58, 0xf7,
};
unsigned char rfc8032_public_key2[32] = {
0xfc, 0x51, 0xcd, 0x8e, 0x62, 0x18, 0xa1, 0xa3, 0x8d, 0xa4, 0x7e, 0xd0, 0x02, 0x30, 0xf0, 0x58,
0x08, 0x16, 0xed, 0x13, 0xba, 0x33, 0x03, 0xac, 0x5d, 0xeb, 0x91, 0x15, 0x48, 0x90, 0x80, 0x25,
};
unsigned char rfc8032_message2[2] = {0xaf, 0x82};
unsigned char rfc8032_signature2[64] = {
0x62, 0x91, 0xd6, 0x57, 0xde, 0xec, 0x24, 0x02, 0x48, 0x27, 0xe6, 0x9c, 0x3a, 0xbe, 0x01, 0xa3,
0x0c, 0xe5, 0x48, 0xa2, 0x84, 0x74, 0x3a, 0x44, 0x5e, 0x36, 0x80, 0xd7, 0xdb, 0x5a, 0xc3, 0xac,
0x18, 0xff, 0x9b, 0x53, 0x8d, 0x16, 0xf2, 0x90, 0xae, 0x67, 0xf7, 0x60, 0x98, 0x4d, 0xc6, 0x59,
0x4a, 0x7c, 0x15, 0xe9, 0x71, 0x6e, 0xd2, 0x8d, 0xc0, 0x27, 0xbe, 0xce, 0xea, 0x1e, 0xc4, 0x0a,
};
bool test_ed25519_crypto() {
std::cout << "************** Testing Curve25519 / Ed25519 cryptographic primitives ************\n";
crypto::Ed25519::PrivateKey PK1, PK2, PK3, PK4, PK5;
PK1.random_private_key();
PK2.import_private_key(fixed_privkey);
unsigned char priv2_export[32];
bool ok = PK1.export_private_key(priv2_export);
std::cout << "PK1 = " << ok << " " << buffer_to_hex(priv2_export) << std::endl;
my_assert(ok);
ok = PK2.export_private_key(priv2_export);
std::cout << "PK2 = " << ok << " " << buffer_to_hex(priv2_export) << std::endl;
my_assert(ok);
PK3.import_private_key(priv2_export);
std::cout << "PK3 = " << PK3.ok() << std::endl;
my_assert(PK3.ok());
unsigned char pub_export[32];
ok = PK1.export_public_key(pub_export);
std::cout << "PubK1 = " << ok << " " << buffer_to_hex(pub_export) << std::endl;
my_assert(ok);
crypto::Ed25519::PublicKey PubK1(pub_export);
ok = PK2.export_public_key(pub_export);
std::cout << "PubK2 = " << ok << " " << buffer_to_hex(pub_export) << std::endl;
my_assert(ok);
my_assert(!std::memcmp(pub_export, fixed_pubkey, 32));
crypto::Ed25519::PublicKey PubK2(pub_export);
ok = PK3.export_public_key(pub_export);
std::cout << "PubK3 = " << ok << " " << buffer_to_hex(pub_export) << std::endl;
my_assert(ok);
my_assert(!std::memcmp(pub_export, fixed_pubkey, 32));
crypto::Ed25519::PublicKey PubK3(pub_export);
ok = PubK1.export_public_key(pub_export);
std::cout << "PubK1 = " << ok << " " << buffer_to_hex(pub_export) << std::endl;
my_assert(ok);
unsigned char secret22[32];
ok = PK2.compute_shared_secret(secret22, PubK3);
std::cout << "secret(PK2,PubK2)=" << ok << " " << buffer_to_hex(secret22) << std::endl;
my_assert(ok);
unsigned char secret12[32], secret21[32];
ok = PK1.compute_shared_secret(secret12, PubK3);
std::cout << "secret(PK1,PubK2)=" << ok << " " << buffer_to_hex(secret12) << std::endl;
my_assert(ok);
ok = PK2.compute_shared_secret(secret21, PubK1);
std::cout << "secret(PK2,PubK1)=" << ok << " " << buffer_to_hex(secret21) << std::endl;
my_assert(ok);
my_assert(!std::memcmp(secret12, secret21, 32));
// for (int i = 0; i < 1000; i++) {
// ok = PK1.compute_shared_secret(secret12, PubK3);
// my_assert(ok);
// ok = PK2.compute_shared_secret(secret21, PubK1);
// my_assert(ok);
// }
unsigned char signature[64];
ok = PK1.sign_message(signature, (const unsigned char*)"abc", 3);
std::cout << "PK1.signature=" << ok << " " << buffer_to_hex(signature, 64) << std::endl;
my_assert(ok);
// signature[63] ^= 1;
ok = PubK1.check_message_signature(signature, (const unsigned char*)"abc", 3);
std::cout << "PubK1.check_signature=" << ok << std::endl;
my_assert(ok);
PK4.import_private_key(rfc8032_secret_key1);
PK4.export_public_key(pub_export);
std::cout << "PK4.private_key = " << buffer_to_hex(rfc8032_secret_key1) << std::endl;
std::cout << "PK4.public_key = " << buffer_to_hex(pub_export) << std::endl;
my_assert(!std::memcmp(pub_export, rfc8032_public_key1, 32));
ok = PK4.sign_message(signature, (const unsigned char*)"", 0);
std::cout << "PK4.signature('') = " << buffer_to_hex(signature, 64) << std::endl;
my_assert(ok);
my_assert(!std::memcmp(signature, rfc8032_signature1, 32));
PK5.import_private_key(rfc8032_secret_key2);
PK5.export_public_key(pub_export);
std::cout << "PK5.private_key = " << buffer_to_hex(rfc8032_secret_key2) << std::endl;
std::cout << "PK5.public_key = " << buffer_to_hex(pub_export) << std::endl;
my_assert(!std::memcmp(pub_export, rfc8032_public_key2, 32));
ok = PK5.sign_message(signature, rfc8032_message2, 2);
std::cout << "PK5.signature('') = " << buffer_to_hex(signature, 64) << std::endl;
my_assert(ok);
my_assert(!std::memcmp(signature, rfc8032_signature2, 32));
crypto::Ed25519::PublicKey PubK5(pub_export);
// for (int i = 0; i < 10000; i++) {
// ok = PK5.sign_message (signature, rfc8032_message2, 2);
// my_assert (ok);
// }
// for (int i = 0; i < 10000; i++) {
// ok = PubK5.check_message_signature (signature, rfc8032_message2, 2);
// my_assert (ok);
// }
unsigned char temp_pubkey[32];
crypto::Ed25519::TempKeyGenerator TKG; // use one generator a lot of times
TKG.create_temp_shared_secret(temp_pubkey, secret12, PubK1, (const unsigned char*)"abc", 3);
std::cout << "secret12=" << buffer_to_hex(secret12) << "; temp_pubkey=" << buffer_to_hex(temp_pubkey) << std::endl;
PK1.compute_temp_shared_secret(secret21, temp_pubkey);
std::cout << "secret21=" << buffer_to_hex(secret21) << std::endl;
my_assert(!std::memcmp(secret12, secret21, 32));
std::cout << "********* ok\n\n";
return true;
}
int main(void) {
test_ed25519_impl();
test_ed25519_crypto();
return 0;
}

427
crypto/test/vm.cpp Normal file
View file

@ -0,0 +1,427 @@
/*
This file is part of TON Blockchain Library.
TON Blockchain Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
TON Blockchain Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#include "vm/continuation.h"
#include "vm/cp0.h"
#include "vm/dict.h"
#include "fift/utils.h"
#include "common/bigint.hpp"
#include "td/utils/tests.h"
#include "td/utils/ScopeGuard.h"
#include "td/utils/StringBuilder.h"
std::string run_vm(td::Ref<vm::Cell> cell) {
vm::init_op_cp0();
vm::DictionaryBase::get_empty_dictionary();
class Logger : public td::LogInterface {
public:
void append(td::CSlice slice) override {
res.append(slice.data(), slice.size());
}
std::string res;
};
static Logger logger;
logger.res = "";
td::set_log_fatal_error_callback([](td::CSlice message) { td::default_log_interface->append(logger.res); });
vm::VmLog log{&logger, td::LogOptions::plain()};
log.log_options.level = 4;
log.log_options.fix_newlines = true;
log.log_mask |= vm::VmLog::DumpStack;
auto total_data_cells_before = vm::DataCell::get_total_data_cells();
SCOPE_EXIT {
auto total_data_cells_after = vm::DataCell::get_total_data_cells();
ASSERT_EQ(total_data_cells_before, total_data_cells_after);
};
vm::Stack stack;
try {
vm::run_vm_code(vm::load_cell_slice_ref(cell), stack, 0 /*flags*/, nullptr /*data*/, std::move(log) /*VmLog*/);
} catch (...) {
LOG(FATAL) << "catch unhandled exception";
}
return logger.res; // must be a copy
}
td::Ref<vm::Cell> to_cell(const unsigned char *buff, int bits) {
return vm::CellBuilder().store_bits(buff, bits, 0).finalize();
}
void test_run_vm(td::Ref<vm::Cell> code) {
auto a = run_vm(code);
auto b = run_vm(code);
ASSERT_EQ(a, b);
REGRESSION_VERIFY(a);
}
void test_run_vm(td::Slice code_hex) {
unsigned char buff[128];
int bits = (int)td::bitstring::parse_bitstring_hex_literal(buff, sizeof(buff), code_hex.begin(), code_hex.end());
CHECK(bits >= 0);
test_run_vm(to_cell(buff, bits));
}
TEST(VM, simple) {
test_run_vm("ABCBABABABA");
}
TEST(VM, memory_leak_old) {
test_run_vm("90787FDB3B");
}
TEST(VM, memory_leak) {
test_run_vm("90707FDB3B");
}
TEST(VM, bug_div_short_any) {
test_run_vm("6883FF73A98D");
}
TEST(VM, assert_pfx_dict_lookup) {
test_run_vm("778B04216D73F43E018B04591277F473");
}
TEST(VM, assert_lookup_prefix) {
test_run_vm("78E58B008B028B04010000016D90ED5272F43A755D77F4A8");
}
TEST(VM, assert_code_not_null) {
test_run_vm("76ED40DE");
}
TEST(VM, bug_exec_dict_getnear) {
test_run_vm("8B048B00006D72F47573655F6D656D6D656D8B007F");
}
TEST(VM, bug_stack_overflow) {
test_run_vm("72A93AF8");
}
TEST(VM, assert_extract_minmax_key) {
test_run_vm("6D6DEB21807AF49C2180EB21807AF41C");
}
TEST(VM, memory_leak_new) {
test_run_vm("72E5ED40DB3603");
}
TEST(VM, unhandled_exception_1) {
test_run_vm("70EDA2ED00");
}
TEST(VM, unhandled_exception_2) {
// infinite loop now
// test_run_vm("EBEDB4");
}
TEST(VM, unhandled_exception_3) {
// infinite loop now
// test_run_vm("EBEDC0");
}
TEST(VM, unhandled_exception_4) {
test_run_vm("7F853EA1C8CB3E");
}
TEST(VM, unhandled_exception_5) {
test_run_vm("738B04016D21F41476A721F49F");
}
TEST(VM, bigint) {
td::StringBuilder sb({}, true);
using word_t = td::BigIntInfo::word_t;
std::vector<word_t> numbers{1,
-1,
2,
-2,
100,
-100,
std::numeric_limits<word_t>::max(),
std::numeric_limits<word_t>::min(),
std::numeric_limits<word_t>::max() - 1,
std::numeric_limits<word_t>::min() + 1};
for (auto x : numbers) {
for (auto y : numbers) {
word_t a;
word_t b;
td::BigIntInfo::set_mul(&a, &b, x, y);
sb << "set_mul " << x << " * " << y << " = " << a << " " << b << "\n";
td::BigIntInfo::add_mul(&a, &b, x, y);
sb << "add_mul " << x << " " << y << " = " << a << " " << b << "\n";
td::BigIntInfo::sub_mul(&a, &b, x, y);
sb << "sub_mul " << x << " " << y << " = " << a << " " << b << "\n";
}
}
auto base = td::BigIntInfo::Base;
std::vector<word_t> lo_numbers{1, -1, 2, -2, 100, -100, base - 1, base - 2, -base + 1, -base + 2};
for (auto x : numbers) {
for (auto y : lo_numbers) {
for (auto z : numbers) {
word_t a;
word_t b;
td::BigIntInfo::dbl_divmod(&a, &b, x, y, z);
sb << "dbl_divmod " << x << " " << y << " / " << z << " = " << a << " " << b << "\n";
}
}
}
REGRESSION_VERIFY(sb.as_cslice());
}
TEST(VM, report3_1) {
//WA: expect (1, 2, 6, 3)
td::Slice test1 =
R"A(
CONT:<{
DEPTH
}>
3 SETNUMARGS
c0 POPCTR
1 INT
2 INT
3 INT
4 INT
5 INT
6 INT
4 RETURNARGS
)A";
test_run_vm(fift::compile_asm(test1).move_as_ok());
}
TEST(VM, report3_2) {
td::Slice test1 =
R"A(
CONT:<{
DEPTH
}>
2 SETNUMARGS
c0 POPCTR
1 INT
2 INT
3 INT
4 INT
2 RETARGS
)A";
test_run_vm(fift::compile_asm(test1).move_as_ok());
}
TEST(VM, report3_3) {
// WA: expect (9)
td::Slice test1 =
R"A(
CONT:<{
8 INT
}>
c0 POPCTR
CONT:<{
9 INT
}>
c1 POPCTR
0 INT
BRANCH
)A";
test_run_vm(fift::compile_asm(test1).move_as_ok());
}
TEST(VM, report3_4) {
td::Slice test1 =
R"A(
CONT:<{
1 INT
2 INT
3 INT
2 RETARGS
}>
CALLX
ADD
)A";
test_run_vm(fift::compile_asm(test1).move_as_ok());
}
TEST(VM, report3_6) {
// WA: expect StackOverflow
td::Slice test1 =
R"A(
10 INT
20 INT
30 INT
CONT:<{
DEPTH
40 INT
SWAP
}>
2 SETNUMARGS
3 1 CALLXARGS
)A";
test_run_vm(fift::compile_asm(test1).move_as_ok());
}
//TEST(VM, report3_ce) {
//td::Slice test1 =
//R"A(
//s16 POP
//s16 PUSH
//s0 s16 XCHG
//)A";
//test_run_vm(fift::compile_asm(test1).move_as_ok());
//}
TEST(VM, report3_int_overflow_1) {
td::Slice test1 =
R"A(
4 INT
16 INT
-115792089237316195423570985008687907853269984665640564039457584007913129639936 INT
MULDIVMOD
)A";
test_run_vm(fift::compile_asm(test1).move_as_ok());
}
TEST(VM, report3_int_overflow_2) {
td::Slice test1 =
R"A(
4 INT
16 INT
-115792089237316195423570985008687907853269984665640564039457584007913129639936 INT
MULDIVR
)A";
test_run_vm(fift::compile_asm(test1).move_as_ok());
}
TEST(VM, report3_qnot) {
td::Slice test1 =
R"A(
PUSHNAN
QNOT
)A";
test_run_vm(fift::compile_asm(test1).move_as_ok());
}
TEST(VM, report3_loop_1) {
//WA
td::Slice test1 =
R"A(
CONT:<{
2 INT
}>
ATEXITALT
CONT:<{
1 INT
RETALT
-1 INT
}>
AGAIN
3 INT
)A";
test_run_vm(fift::compile_asm(test1).move_as_ok());
}
TEST(VM, report3_loop_2) {
//WA
td::Slice test1 =
R"A(
CONT:<{
2 INT
}>
ATEXITALT
CONT:<{
1 INT
RETALT
-1 INT
}>
UNTIL
3 INT
)A";
test_run_vm(fift::compile_asm(test1).move_as_ok());
}
TEST(VM, report3_loop_3) {
//WA
td::Slice test1 =
R"A(
1 INT
CONT:<{
UNTILEND
RET
-1 INT
}>
CALLX
)A";
test_run_vm(fift::compile_asm(test1).move_as_ok());
}
TEST(VM, report3_loop_4) {
//WA
td::Slice test1 =
R"A(
CONT:<{
2 INT
}>
ATEXITALT
CONT:<{
1 INT
RETALT
-1 PUSHINT
}>
CONT:<{
-1 INT
}>
WHILE
3 INT
)A";
test_run_vm(fift::compile_asm(test1).move_as_ok());
}
TEST(VM, report3_loop_5) {
//WA
td::Slice test1 =
R"A(
CONT:<{
1 INT
2 INT
}>
ATEXITALT
3 INT
AGAINEND
DEC
DUP
IFRET
DROP
RETALT
)A";
test_run_vm(fift::compile_asm(test1).move_as_ok());
}
TEST(VM, report3_loop_6) {
//WA
td::Slice test1 =
R"A(
CONT:<{
1 INT
2 INT
}>
3 INT
AGAINEND
DEC
DUP
IFRET
DROP
ATEXITALT
RETALT
)A";
test_run_vm(fift::compile_asm(test1).move_as_ok());
}