| 362 | } |
| 363 | |
| 364 | Value wasm_gettable( const Array ¶ms, bool fHelp ) { |
| 365 | |
| 366 | RESPONSE_RPC_HELP( fHelp || params.size() < 2 || params.size() > 4 , wasm::rpc::get_table_wasm_rpc_help_message) |
| 367 | RPCTypeCheck(params, list_of(str_type)(str_type)); |
| 368 | |
| 369 | try{ |
| 370 | auto db_contract = pCdMan->pContractCache; |
| 371 | auto contract_regid = RPC_PARAM::ParseRegId(params[0], "contract"); |
| 372 | auto contract_table = wasm::name(params[1].get_str()); |
| 373 | auto key_prefix_arr = GetKeyPrefixArray(params, 2); |
| 374 | uint64_t numbers = (params.size() > 3) ? std::atoi(params[3].get_str().data()) : default_query_rows; |
| 375 | string start_key = (params.size() > 4) ? from_hex(params[4].get_str()) : ""; |
| 376 | |
| 377 | // JSON_RPC_ASSERT(!is_native_contract(contract_regid.value), RPC_INVALID_PARAMS, |
| 378 | // "cannot get table from native contract '%s'", contract_regid.to_string()) |
| 379 | auto contract = wasm::regid(contract_regid.GetIntValue()); |
| 380 | CHAIN_ASSERT( !is_native_contract(contract.value), wasm_chain::native_contract_access_exception, |
| 381 | "cannot get table from native contract '%s'", contract.to_string() ) |
| 382 | |
| 383 | CUniversalContractStore contract_store; |
| 384 | load_contract(db_contract, contract, contract_store); |
| 385 | std::vector<char> abi = std::vector<char>(contract_store.abi.begin(), contract_store.abi.end()); |
| 386 | |
| 387 | std::vector<char> key_prefix = wasm::pack(std::tuple<uint64_t, uint64_t>(contract.value, contract_table.value)); |
| 388 | string search_key(key_prefix.data(),key_prefix.size()); |
| 389 | if (!key_prefix_arr.empty()) { |
| 390 | auto keys = wasm::abi_serializer::pack_keys(abi, key_prefix_arr, max_serialization_time); |
| 391 | search_key.append(keys.begin(), keys.end()); |
| 392 | } |
| 393 | |
| 394 | auto pContractDataIt = db_contract->CreateContractDataIterator(contract_regid, search_key); |
| 395 | // JSON_RPC_ASSERT(pContractDataIt, RPC_INVALID_PARAMS, |
| 396 | // "cannot get table from contract '%s'", contract_regid.to_string()) |
| 397 | CHAIN_ASSERT( pContractDataIt, wasm_chain::table_not_found, |
| 398 | "cannot get table '%s' from contract '%s'", contract_table.to_string(), contract_regid.ToString() ) |
| 399 | |
| 400 | bool hasMore = false; |
| 401 | json_spirit::Object object_return; |
| 402 | json_spirit::Array row_json; |
| 403 | if (start_key.empty()) { |
| 404 | pContractDataIt->First(); |
| 405 | } else { |
| 406 | pContractDataIt->SeekUpper(&start_key); |
| 407 | } |
| 408 | for (; pContractDataIt->IsValid(); pContractDataIt->Next()) { |
| 409 | if (pContractDataIt->GotCount() > numbers) { |
| 410 | hasMore = true; |
| 411 | break; |
| 412 | } |
| 413 | const string& key = pContractDataIt->GetContractKey(); |
| 414 | const string& value = pContractDataIt->GetValue(); |
| 415 | |
| 416 | //unpack value in bytes to json |
| 417 | std::vector<char> value_bytes(value.begin(), value.end()); |
| 418 | json_spirit::Value value_json = wasm::abi_serializer::unpack(abi, contract_table.value, value_bytes, max_serialization_time); |
| 419 | json_spirit::Object& object_json = value_json.get_obj(); |
| 420 | |
| 421 | //append key and value |
nothing calls this directly
no test coverage detected