Skip to content
This repository has been archived by the owner on Nov 18, 2022. It is now read-only.

Commit

Permalink
Merge pull request #142 from nervosnetwork/v0.8
Browse files Browse the repository at this point in the history
v0: fix copy_code evmc host interface
  • Loading branch information
Flouse authored Apr 8, 2022
2 parents 9bde021 + 5296f7c commit 261970c
Show file tree
Hide file tree
Showing 29 changed files with 923 additions and 249 deletions.
72 changes: 50 additions & 22 deletions c/polyjuice.h
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ int load_account_code(gw_context_t* gw_ctx, uint32_t account_id,
return 0;
}

debug_print_int("[load_account_code] account_id:", account_id);
debug_print_int("[load_account_code] account_id", account_id);
uint8_t key[32];
uint8_t data_hash[32];
polyjuice_build_contract_code_key(account_id, key);
Expand All @@ -299,22 +299,25 @@ int load_account_code(gw_context_t* gw_ctx, uint32_t account_id,
return 0;
}

uint64_t old_code_size = *code_size;
debug_print_int("[load_account_code] code_size before loading", *code_size);
ret = gw_ctx->sys_load_data(gw_ctx, data_hash, code_size, offset, code);
debug_print_int("[load_account_code] code_size after loading", *code_size);
if (ret != 0) {
ckb_debug("[load_account_code] sys_load_data failed");
return ret;
}
if (*code_size > old_code_size) {
debug_print_int("[load_account_code] code can't be larger than", MAX_DATA_SIZE);
return -1;
if (*code_size > MAX_DATA_SIZE) {
debug_print_int("[load_account_code] code_size can't be larger than",
MAX_DATA_SIZE);
return GW_FATAL_BUFFER_OVERFLOW;
}

return 0;
}

////////////////////////////////////////////////////////////////////////////
//// Callbacks
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//// Callbacks - EVMC Host Interfaces
////////////////////////////////////////////////////////////////////////////////
struct evmc_tx_context get_tx_context(struct evmc_host_context* context) {
struct evmc_tx_context ctx{0};
/* gas price = 1 */
Expand Down Expand Up @@ -412,14 +415,16 @@ size_t get_code_size(struct evmc_host_context* context,
ckb_debug("get contract account id failed");
return 0;
}

uint8_t code[MAX_DATA_SIZE];
uint64_t code_size = MAX_DATA_SIZE;
ret = load_account_code(context->gw_ctx, account_id, &code_size, 0, code);
if (ret != 0) {
ckb_debug("load_account_code failed");
debug_print_int("[get_code_size] load_account_code failed", ret);
context->error_code = ret;
return 0;
}

ckb_debug("END get_code_size");
return code_size;
}
Expand All @@ -441,7 +446,7 @@ evmc_bytes32 get_code_hash(struct evmc_host_context* context,
uint64_t code_size = MAX_DATA_SIZE;
ret = load_account_code(context->gw_ctx, account_id, &code_size, 0, code);
if (ret != 0) {
ckb_debug("load_account_code failed");
debug_print_int("[get_code_hash] load_account_code failed", ret);
context->error_code = ret;
return hash;
}
Expand All @@ -454,28 +459,48 @@ evmc_bytes32 get_code_hash(struct evmc_host_context* context,
return hash;
}

/**
* @brief Copy code callback function.
*
* This callback function is used by an EVM to request a copy of the code of the
* given account to the memory buffer provided by the EVM. The Client MUST copy
* the requested code, starting with the given offset, to the provided memory
* buffer up to the size of the buffer or the size of the code, whichever is
* smaller.
*
* @param context The pointer to the Host execution context.
* @param address The address of the account.
* @param code_offset The offset of the code to copy.
* @param buffer_data The pointer to the memory buffer allocated by the EVM to
* store a copy of the requested code.
* @param buffer_size The size of the memory buffer.
* @return size_t The number of bytes copied to the buffer by the Client.
*/
size_t copy_code(struct evmc_host_context* context, const evmc_address* address,
size_t code_offset, uint8_t* buffer_data, size_t buffer_size) {
ckb_debug("BEGIN copy_code");
int ret;
debug_print_int("[copy_code] code_offset", code_offset);
debug_print_int("[copy_code] buffer_size", buffer_size);

uint32_t account_id = 0;
ret = address_to_account_id(context->gw_ctx, address->bytes, &account_id);
int ret = address_to_account_id(context->gw_ctx, address->bytes, &account_id);
if (ret != 0) {
ckb_debug("get contract account id failed");
context->error_code = ret;
return 0;
}

uint64_t code_size = (uint32_t)buffer_size;
uint64_t code_size = buffer_size;
ret = load_account_code(context->gw_ctx, account_id, &code_size,
(uint32_t)code_offset, buffer_data);
code_offset, buffer_data);
if (ret != 0) {
ckb_debug("load account code failed");
debug_print_int("[copy_code] load_account_code failed", ret);
context->error_code = ret;
return 0;
}

ckb_debug("END copy_code");
return 0;
return code_size >= buffer_size ? buffer_size : code_size;
}

evmc_uint256be get_balance(struct evmc_host_context* context,
Expand Down Expand Up @@ -1008,26 +1033,28 @@ int handle_message(gw_context_t* ctx,
uint8_t* code_data = NULL;
size_t code_size = 0;
uint8_t code_data_buffer[MAX_DATA_SIZE];
uint64_t code_size_u32 = MAX_DATA_SIZE;
if (is_create(msg.kind)) {
/* use input as code */
code_data = (uint8_t*)msg.input_data;
code_size = msg.input_size;
msg.input_data = NULL;
msg.input_size = 0;
} else if (to_address_exists) {
uint64_t code_size_tmp = MAX_DATA_SIZE;
/* call kind: CALL/CALLCODE/DELEGATECALL */
ret = load_account_code(ctx, to_id, &code_size_u32, 0, code_data_buffer);
ret = load_account_code(ctx, to_id, &code_size_tmp, 0, code_data_buffer);
if (ret != 0) {
debug_print_int("[handle_message] load_account_code failed", ret);
return ret;
}
if (code_size_u32 == 0) {
debug_print_int("[handle_message] empty contract code for account (EoA account)", to_id);
if (code_size_tmp == 0) {
debug_print_int("[handle_message] account with empty code (EoA account)",
to_id);
code_data = NULL;
} else {
code_data = code_data_buffer;
}
code_size = (size_t)code_size_u32;
code_size = (size_t)code_size_tmp;
} else {
// Call non-exists address
}
Expand Down Expand Up @@ -1223,7 +1250,8 @@ int run_polyjuice() {
return clean_evmc_result_and_return(&res, ret);
}

ret = context.sys_set_program_return_data(&context, (uint8_t *)res.output_data,
ret = context.sys_set_program_return_data(&context,
(uint8_t *)res.output_data,
res.output_size);
if (ret != 0) {
ckb_debug("set return data failed");
Expand Down
12 changes: 7 additions & 5 deletions devtools/ci/integration-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ if [ -d "$GODWOKEN_DIR" ]
then
echo "godwoken project already exists"
else
git clone -b develop https://github.com/nervosnetwork/godwoken.git $GODWOKEN_DIR
git clone --depth=1 https://github.com/nervosnetwork/godwoken.git $GODWOKEN_DIR
fi
cd $GODWOKEN_DIR
git checkout 7527776abf53ab069015b66e2569148341425bd8 # https://github.com/nervosnetwork/godwoken/commits/7527776a
# https://github.com/nervosnetwork/godwoken/releases/tag/v0.10.4
git fetch origin v0.10.4
git checkout FETCH_HEAD
git submodule update --init --recursive --depth=1

cd $PROJECT_ROOT
Expand All @@ -25,10 +27,10 @@ make all-via-docker
# fetch godwoken-scripts from godwoken-prebuilds image,
# including meta-contract and sudt-contract
GW_SCRIPTS_DIR=$PROJECT_ROOT/build
docker pull nervos/godwoken-prebuilds:latest
mkdir -p $GW_SCRIPTS_DIR && echo "Create dir"
docker run --rm -v $GW_SCRIPTS_DIR:/build-dir \
nervos/godwoken-prebuilds:latest \
IMAGE=nervos/godwoken-prebuilds:v0.10.3
docker pull $IMAGE
docker run --rm -v $GW_SCRIPTS_DIR:/build-dir $IMAGE \
cp -r /scripts/godwoken-scripts /build-dir \
&& echo "Copy godwoken-scripts"

Expand Down
Loading

0 comments on commit 261970c

Please sign in to comment.