|
8 | 8 | #include "../../core/eosio/serialize.hpp" |
9 | 9 | #include "../../core/eosio/datastream.hpp" |
10 | 10 | #include "../../core/eosio/name.hpp" |
| 11 | +#include "../../core/eosio/fixed_bytes.hpp" |
11 | 12 | #include "../../core/eosio/ignore.hpp" |
12 | 13 | #include "../../core/eosio/time.hpp" |
13 | 14 |
|
@@ -52,9 +53,23 @@ namespace eosio { |
52 | 53 |
|
53 | 54 | __attribute__((eosio_wasm_import)) |
54 | 55 | uint64_t current_receiver(); |
| 56 | + |
| 57 | + __attribute__((eosio_wasm_import)) |
| 58 | + uint32_t get_code_hash( uint64_t account, uint32_t struct_version, char* result_buffer, size_t buffer_size ); |
55 | 59 | } |
56 | 60 | }; |
57 | 61 |
|
| 62 | + struct code_hash_result { |
| 63 | + unsigned_int struct_version; |
| 64 | + uint64_t code_sequence; |
| 65 | + checksum256 code_hash; |
| 66 | + uint8_t vm_type; |
| 67 | + uint8_t vm_version; |
| 68 | + |
| 69 | + CDT_REFLECT(struct_version, code_sequence, code_hash, vm_type, vm_version); |
| 70 | + EOSLIB_SERIALIZE(code_hash_result, (struct_version)(code_sequence)(code_hash)(vm_type)(vm_version)); |
| 71 | + }; |
| 72 | + |
58 | 73 | /** |
59 | 74 | * @defgroup action Action |
60 | 75 | * @ingroup contracts |
@@ -150,6 +165,30 @@ namespace eosio { |
150 | 165 | return name{internal_use_do_not_use::current_receiver()}; |
151 | 166 | } |
152 | 167 |
|
| 168 | + /** |
| 169 | + * Get the hash of the code currently published on the given account |
| 170 | + * @param account Name of the account to hash the code of |
| 171 | + * @param full_result Optional: If a full result struct is desired, a pointer to the struct to populate |
| 172 | + * @return The SHA256 hash of the specified account's code |
| 173 | + */ |
| 174 | + inline checksum256 get_code_hash( name account, code_hash_result* full_result = nullptr ) { |
| 175 | + if (full_result == nullptr) |
| 176 | + full_result = (code_hash_result*)alloca(sizeof(code_hash_result)); |
| 177 | + |
| 178 | + // Packed size is dynamic, so we don't know what it'll be. Try to have plenty of space. |
| 179 | + auto struct_buffer_size = sizeof(code_hash_result)*2; |
| 180 | + char* struct_buffer = (char*)alloca(struct_buffer_size); |
| 181 | + |
| 182 | + using VersionType = decltype(code_hash_result::struct_version); |
| 183 | + const VersionType STRUCT_VERSION = 0; |
| 184 | + internal_use_do_not_use::get_code_hash(account.value, STRUCT_VERSION, struct_buffer, struct_buffer_size); |
| 185 | + check(unpack<VersionType>(struct_buffer, struct_buffer_size) == STRUCT_VERSION, |
| 186 | + "Hypervisor returned unexpected code hash struct version"); |
| 187 | + unpack(*full_result, struct_buffer, struct_buffer_size); |
| 188 | + |
| 189 | + return full_result->code_hash; |
| 190 | + } |
| 191 | + |
153 | 192 | /** |
154 | 193 | * Copy up to length bytes of current action data to the specified location |
155 | 194 | * |
|
0 commit comments