mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
initial commit
This commit is contained in:
commit
c2da007f40
1610 changed files with 398047 additions and 0 deletions
144
crypto/test/Ed25519.cpp
Normal file
144
crypto/test/Ed25519.cpp
Normal 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
92
crypto/test/fift.cpp
Normal 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
3
crypto/test/fift/bug.fif
Normal file
|
@ -0,0 +1,3 @@
|
|||
10000000000000000000000000000000000000000000000000000000 dup .
|
||||
dup 1 */ .
|
||||
|
12
crypto/test/fift/bug_div.fif
Normal file
12
crypto/test/fift/bug_div.fif
Normal 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
8
crypto/test/fift/cmdline.fif
Executable 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
|
18
crypto/test/fift/contfrac.fif
Normal file
18
crypto/test/fift/contfrac.fif
Normal 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 .
|
19
crypto/test/fift/fixed.fif
Normal file
19
crypto/test/fift/fixed.fif
Normal 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
27
crypto/test/fift/sort.fif
Normal 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
|
28
crypto/test/fift/sort2.fif
Normal file
28
crypto/test/fift/sort2.fif
Normal 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
24
crypto/test/fift/test.fif
Normal 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
102
crypto/test/fift/testdb.fif
Normal 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
|
||||
|
24
crypto/test/fift/testdict.fif
Normal file
24
crypto/test/fift/testdict.fif
Normal 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
|
10
crypto/test/fift/testvm.fif
Normal file
10
crypto/test/fift/testvm.fif
Normal 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
|
22
crypto/test/fift/testvm2.fif
Normal file
22
crypto/test/fift/testvm2.fif
Normal 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
|
8
crypto/test/fift/testvm3.fif
Normal file
8
crypto/test/fift/testvm3.fif
Normal 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.
|
||||
|
14
crypto/test/fift/testvm4.fif
Normal file
14
crypto/test/fift/testvm4.fif
Normal 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
|
5
crypto/test/fift/testvm4a.fif
Normal file
5
crypto/test/fift/testvm4a.fif
Normal file
|
@ -0,0 +1,5 @@
|
|||
169 13
|
||||
239 dup dup * swap
|
||||
289 17
|
||||
3
|
||||
x{6D01E502C8CB0F028010F442} runvmcode drop dup <s csr.
|
16
crypto/test/fift/testvm4b.fif
Normal file
16
crypto/test/fift/testvm4b.fif
Normal 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
|
52
crypto/test/fift/testvm4c.fif
Normal file
52
crypto/test/fift/testvm4c.fif
Normal 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
|
||||
|
26
crypto/test/fift/testvm4d.fif
Normal file
26
crypto/test/fift/testvm4d.fif
Normal 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)
|
||||
|
61
crypto/test/fift/testvm4e.fif
Normal file
61
crypto/test/fift/testvm4e.fif
Normal 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
|
11
crypto/test/fift/testvm5.fif
Normal file
11
crypto/test/fift/testvm5.fif
Normal 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
|
66
crypto/test/fift/testvm6.fif
Normal file
66
crypto/test/fift/testvm6.fif
Normal 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
|
47
crypto/test/fift/testvm7.fif
Normal file
47
crypto/test/fift/testvm7.fif
Normal 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
|
5
crypto/test/fift/testvm8.fif
Normal file
5
crypto/test/fift/testvm8.fif
Normal 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
|
7
crypto/test/fift/testvm9.fif
Normal file
7
crypto/test/fift/testvm9.fif
Normal 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
|
40
crypto/test/fift/testvmprog.fif
Normal file
40
crypto/test/fift/testvmprog.fif
Normal 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
571
crypto/test/test-cells.cpp
Normal 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
2008
crypto/test/test-db.cpp
Normal file
File diff suppressed because it is too large
Load diff
314
crypto/test/test-ed25519-crypto.cpp
Normal file
314
crypto/test/test-ed25519-crypto.cpp
Normal 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
427
crypto/test/vm.cpp
Normal 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());
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue