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

TVM instructions: SECP256K1_XONLY_PUBKEY_TWEAK_ADD, SETCONTCTRMANY(X) (#1404)

* TVM instructions: SECP256K1_XONLY_PUBKEY_TWEAK_ADD, SETCONTCTRMANY(X)

* Add tests for xonly_pubkey_tweak_add

* added secp256k1 as submodule, since we need extrakeys feature of secp256k1

* cleanup

* add ton_crypto_core secp256k1 dependency

* adjust Dockerfile, android and wasm builds

* adjust nix build

* test windows build with SECP256K1_ENABLE_MODULE_EXTRAKEYS

* test windows build with SECP256K1_ENABLE_MODULE_EXTRAKEYS

* adjust android build

* adjust emscripten build

* adjust emscripten build

* try macos-13

* emscripten build adjustments

* windows build adjustments

* final corrections

---------

Co-authored-by: neodix <neodix@ton.org>
This commit is contained in:
SpyCheese 2024-11-26 17:23:17 +04:00 committed by GitHub
parent 954a96a077
commit 25b4c6794a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
56 changed files with 2112 additions and 502 deletions

View file

@ -923,6 +923,41 @@ int exec_setcont_ctr_var(VmState* st) {
return 0;
}
int exec_setcont_ctr_many(VmState* st, unsigned args) {
unsigned mask = args & 255;
VM_LOG(st) << "execute SETCONTCTRMANY " << mask;
if (mask & (1 << 6)) {
throw VmError{Excno::range_chk, "no control register c6"};
}
Stack& stack = st->get_stack();
auto cont = stack.pop_cont();
for (int i = 0; i < 8; ++i) {
if (mask & (1 << i)) {
throw_typechk(force_cregs(cont)->define(i, st->get(i)));
}
}
st->get_stack().push_cont(std::move(cont));
return 0;
}
int exec_setcont_ctr_many_var(VmState* st) {
VM_LOG(st) << "execute SETCONTCTRMANYX";
Stack& stack = st->get_stack();
stack.check_underflow(2);
int mask = stack.pop_smallint_range(255);
if (mask & (1 << 6)) {
throw VmError{Excno::range_chk, "no control register c6"};
}
auto cont = stack.pop_cont();
for (int i = 0; i < 8; ++i) {
if (mask & (1 << i)) {
throw_typechk(force_cregs(cont)->define(i, st->get(i)));
}
}
st->get_stack().push_cont(std::move(cont));
return 0;
}
int exec_compos(VmState* st, unsigned mask, const char* name) {
Stack& stack = st->get_stack();
VM_LOG(st) << "execute " << name;
@ -1037,6 +1072,8 @@ void register_continuation_change_ops(OpcodeTable& cp0) {
cp0.insert(OpcodeInstr::mksimple(0xede0, 16, "PUSHCTRX", exec_push_ctr_var))
.insert(OpcodeInstr::mksimple(0xede1, 16, "POPCTRX", exec_pop_ctr_var))
.insert(OpcodeInstr::mksimple(0xede2, 16, "SETCONTCTRX", exec_setcont_ctr_var))
.insert(OpcodeInstr::mkfixed(0xede3, 16, 8, instr::dump_1c_l_add(1, "SETCONTCTRMANY "), exec_setcont_ctr_many)->require_version(9))
.insert(OpcodeInstr::mksimple(0xede4, 16, "SETCONTCTRMANYX", exec_setcont_ctr_many_var)->require_version(9))
.insert(OpcodeInstr::mksimple(0xedf0, 16, "BOOLAND", std::bind(exec_compos, _1, 1, "BOOLAND")))
.insert(OpcodeInstr::mksimple(0xedf1, 16, "BOOLOR", std::bind(exec_compos, _1, 2, "BOOLOR")))
.insert(OpcodeInstr::mksimple(0xedf2, 16, "COMPOSBOTH", std::bind(exec_compos, _1, 3, "COMPOSBOTH")))

View file

@ -661,7 +661,38 @@ int exec_ecrecover(VmState* st) {
}
st->consume_gas(VmState::ecrecover_gas_price);
unsigned char public_key[65];
if (td::ecrecover(hash_bytes, signature, public_key)) {
if (td::secp256k1::ecrecover(hash_bytes, signature, public_key)) {
td::uint8 h = public_key[0];
td::RefInt256 x1{true}, x2{true};
CHECK(x1.write().import_bytes(public_key + 1, 32, false));
CHECK(x2.write().import_bytes(public_key + 33, 32, false));
stack.push_smallint(h);
stack.push_int(std::move(x1));
stack.push_int(std::move(x2));
stack.push_bool(true);
} else {
stack.push_bool(false);
}
return 0;
}
int exec_secp256k1_xonly_pubkey_tweak_add(VmState* st) {
VM_LOG(st) << "execute SECP256K1_XONLY_PUBKEY_TWEAK_ADD";
Stack& stack = st->get_stack();
stack.check_underflow(2);
auto tweak_int = stack.pop_int();
auto key_int = stack.pop_int();
unsigned char key[32], tweak[32];
if (!key_int->export_bytes(key, 32, false)) {
throw VmError{Excno::range_chk, "key must fit in an unsigned 256-bit integer"};
}
if (!tweak_int->export_bytes(tweak, 32, false)) {
throw VmError{Excno::range_chk, "tweak must fit in an unsigned 256-bit integer"};
}
st->consume_gas(VmState::secp256k1_xonly_pubkey_tweak_add_gas_price);
unsigned char public_key[65];
if (td::secp256k1::xonly_pubkey_tweak_add(key, tweak, public_key)) {
td::uint8 h = public_key[0];
td::RefInt256 x1{true}, x2{true};
CHECK(x1.write().import_bytes(public_key + 1, 32, false));
@ -1214,6 +1245,7 @@ void register_ton_crypto_ops(OpcodeTable& cp0) {
.insert(OpcodeInstr::mksimple(0xf910, 16, "CHKSIGNU", std::bind(exec_ed25519_check_signature, _1, false)))
.insert(OpcodeInstr::mksimple(0xf911, 16, "CHKSIGNS", std::bind(exec_ed25519_check_signature, _1, true)))
.insert(OpcodeInstr::mksimple(0xf912, 16, "ECRECOVER", exec_ecrecover)->require_version(4))
.insert(OpcodeInstr::mksimple(0xf913, 16, "SECP256K1_XONLY_PUBKEY_TWEAK_ADD", exec_secp256k1_xonly_pubkey_tweak_add)->require_version(9))
.insert(OpcodeInstr::mksimple(0xf914, 16, "P256_CHKSIGNU", std::bind(exec_p256_chksign, _1, false))->require_version(4))
.insert(OpcodeInstr::mksimple(0xf915, 16, "P256_CHKSIGNS", std::bind(exec_p256_chksign, _1, true))->require_version(4))

View file

@ -127,6 +127,7 @@ class VmState final : public VmStateInterface {
rist255_validate_gas_price = 200,
ecrecover_gas_price = 1500,
secp256k1_xonly_pubkey_tweak_add_gas_price = 1250,
chksgn_free_count = 10,
chksgn_gas_price = 4000,
p256_chksgn_gas_price = 3500,