Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

C API level 0: core execution #1

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ set_target_properties(
)

# secp256k1
add_library(secp256k1 third_party/secp256k1/src/secp256k1.c)
add_library(secp256k1 STATIC third_party/secp256k1/src/secp256k1.c)
if(MSVC)
target_link_libraries(secp256k1 PRIVATE gmp)
target_compile_definitions(secp256k1 PUBLIC USE_NUM_GMP USE_FIELD_INV_NUM USE_SCALAR_INV_NUM)
Expand Down
56 changes: 56 additions & 0 deletions lib/silkpre/precompile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
limitations under the License.
*/

#undef NDEBUG

#include "precompile.h"

#include <gmp.h>
Expand All @@ -33,6 +35,10 @@
#include <silkpre/secp256k1n.hpp>
#include <silkpre/sha256.h>

inline void require(bool condition) {
if (!condition) __builtin_trap();
}

enum {
EVMC_ISTANBUL = 7,
EVMC_BERLIN = 8,
Expand Down Expand Up @@ -500,3 +506,53 @@ const SilkpreContract kSilkpreContracts[SILKPRE_NUMBER_OF_ISTANBUL_CONTRACTS] =
{silkpre_bn_mul_gas, silkpre_bn_mul_run}, {silkpre_snarkv_gas, silkpre_snarkv_run},
{silkpre_blake2_f_gas, silkpre_blake2_f_run},
};

SilkpreResult ethprecompiled_ecrecover(const uint8_t* input, size_t input_size, uint8_t* output, size_t output_size) {
assert(output_size == 32);
auto r = silkpre_ecrec_run(input, input_size);
std::copy_n(r.data, output_size, output);
return {0, r.size};
}

SilkpreResult ethprecompiled_sha256(const uint8_t* input, size_t input_size, uint8_t* output, size_t output_size) {
assert(output_size == 32);
silkpre_sha256(output, input, input_size, /*use_cpu_extensions=*/true);
return {0, 32};
}

SilkpreResult ethprecompiled_ripemd160(const uint8_t* input, size_t input_size, uint8_t* output, size_t output_size) {
assert(output_size == 32);
std::memset(output, 0, 12);
silkpre_rmd160(&output[12], input, input_size);
return {0, 32};
}

SilkpreResult ethprecompiled_expmod(const uint8_t* input, size_t input_size, uint8_t* output, size_t output_size) {
const auto r = silkpre_expmod_run(input, input_size);
assert(output_size == r.size);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are debating how to handle the case where user provides output buffer not big enough to handle the output produced by the library. This situation is programmer error caused by incorrectly computing the max output size and must be fixed in code. Reasonable handling is to abort/panic the process.

  1. The output_size parameter may be removed and library should assume the buffer is big enough. Related error can only be detected by crashes or ASan tools. This is also not compatible with Rust from_raw_parts().
  2. The library aborts execution with some log.
  3. The library reports the special error code which must be handled differently than EVM exceptions. The client does not have much options than abort in this case.

std::copy_n(r.data, r.size, output);
std::free(r.data);
return {0, r.size};
}

SilkpreResult ethprecompiled_ecmul(const uint8_t* input, size_t input_size, uint8_t* output, size_t output_size) {
const auto r = silkpre_bn_mul_run(input, input_size);
if (r.data == nullptr) return {1, 0}; // Error.

assert(r.size == 64);
assert(output_size == 64);
std::copy_n(r.data, r.size, output);
std::free(r.data);
return {0, r.size};
}

SilkpreResult ethprecompiled_blake2bf(const uint8_t* input, size_t input_size, uint8_t* output, size_t output_size) {
const auto r = silkpre_blake2_f_run(input, input_size);
if (r.data == nullptr) return {1, 0}; // Error.

assert(r.size == 64);
assert(output_size == 64);
std::copy_n(r.data, r.size, output);
std::free(r.data);
return {0, r.size};
}
25 changes: 22 additions & 3 deletions lib/silkpre/precompile.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
#ifndef SILKPRE_PRECOMPILE_H_
#define SILKPRE_PRECOMPILE_H_

#define EXPORT __attribute__((visibility("default")))

#include <stddef.h>
#include <stdint.h>

Expand Down Expand Up @@ -45,8 +47,8 @@ typedef struct SilkpreContract {
SilkpreRunFunction run;
} SilkpreContract;

uint64_t silkpre_ecrec_gas(const uint8_t* input, size_t len, int evmc_revision);
SilkpreOutput silkpre_ecrec_run(const uint8_t* input, size_t len);
EXPORT uint64_t silkpre_ecrec_gas(const uint8_t* input, size_t len, int evmc_revision);
EXPORT SilkpreOutput silkpre_ecrec_run(const uint8_t* input, size_t len);

uint64_t silkpre_sha256_gas(const uint8_t* input, size_t len, int evmc_revision);
SilkpreOutput silkpre_sha256_run(const uint8_t* input, size_t len);
Expand Down Expand Up @@ -78,7 +80,24 @@ SilkpreOutput silkpre_snarkv_run(const uint8_t* input, size_t len);
uint64_t silkpre_blake2_f_gas(const uint8_t* input, size_t len, int evmc_revision);
SilkpreOutput silkpre_blake2_f_run(const uint8_t* input, size_t len);

extern const SilkpreContract kSilkpreContracts[SILKPRE_NUMBER_OF_ISTANBUL_CONTRACTS];
EXPORT extern const SilkpreContract kSilkpreContracts[SILKPRE_NUMBER_OF_ISTANBUL_CONTRACTS];

struct SilkpreResult {
int status_code;
size_t output_size;
};

EXPORT SilkpreResult ethprecompiled_ecrecover(const uint8_t* input, size_t input_size, uint8_t* output,
size_t output_size);
EXPORT SilkpreResult ethprecompiled_sha256(const uint8_t* input, size_t input_size, uint8_t* output,
size_t output_size);
EXPORT SilkpreResult ethprecompiled_ripemd160(const uint8_t* input, size_t input_size, uint8_t* output,
size_t output_size);
EXPORT SilkpreResult ethprecompiled_expmod(const uint8_t* input, size_t input_size, uint8_t* output,
size_t output_size);
EXPORT SilkpreResult ethprecompiled_ecmul(const uint8_t* input, size_t input_size, uint8_t* output, size_t output_size);
EXPORT SilkpreResult ethprecompiled_blake2bf(const uint8_t* input, size_t input_size, uint8_t* output,
size_t output_size);

#if defined(__cplusplus)
}
Expand Down