Skip to content

Commit

Permalink
Add read locks to the Lua runner
Browse files Browse the repository at this point in the history
Support requesting read locks from Lua contracts instead
of only write-locks.

Signed-off-by: Michael Maurer <[email protected]>
  • Loading branch information
maurermi committed May 6, 2024
1 parent 376fdf1 commit c8e806b
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 6 deletions.
8 changes: 7 additions & 1 deletion scripts/gen_bytecode.lua
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
function gen_bytecode()
pay_contract = function(param)
-- 0 is a read lock, 1 is a write lock in C++ scope
Locks = {
READ = 0,
WRITE = 1,
}
from, to, value, sequence, sig = string.unpack("c32 c32 I8 I8 c64", param)

function get_account_key(name)
Expand All @@ -10,7 +15,8 @@ function gen_bytecode()

function get_account(name)
account_key = get_account_key(name)
account_data = coroutine.yield(account_key)

account_data = coroutine.yield(account_key, Locks.READ)
if string.len(account_data) > 0 then
account_balance, account_sequence
= string.unpack("I8 I8", account_data)
Expand Down
2 changes: 1 addition & 1 deletion src/parsec/agent/runners/interface.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ namespace cbdc::parsec::agent::runner {
internal_error,
/// Function yielded more than one key to lock.
yield_count,
/// Function yielded a non-string key.
/// Function yielded a invalid datatype.
yield_type,
/// Error acquiring lock on key.
lock_error,
Expand Down
34 changes: 30 additions & 4 deletions src/parsec/agent/runners/lua/impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,25 +138,51 @@ namespace cbdc::parsec::agent::runner {
return buf;
}

auto lua_runner::get_stack_integer(int index) -> std::optional<int64_t> {
if(lua_isinteger(m_state.get(), index) != 1) {
return std::nullopt;
}
return lua_tointeger(m_state.get(), index);
}

void lua_runner::schedule_contract() {
int n_results{};
auto resume_ret = lua_resume(m_state.get(), nullptr, 1, &n_results);
if(resume_ret == LUA_YIELD) {
if(n_results != 1) {
m_log->error("Contract yielded more than one key");
if(n_results > 2) {
m_log->error("Contract yielded more than two keys");
m_result_callback(error_code::yield_count);
return;
}

auto lock_level = broker::lock_type::write;
if(n_results == 2) {
auto lock_type = get_stack_integer(-1);
if(!lock_type.has_value()) {
m_log->error("Contract yielded two keys, but the second "
"is not an integer");
m_result_callback(error_code::yield_type);
return;
}
lua_pop(m_state.get(), 1);

lock_level = (lock_type.value() == 0)
? broker::lock_type::read
: broker::lock_type::write;
}

auto key_buf = get_stack_string(-1);
if(!key_buf.has_value()) {
m_log->error("Contract did not yield a string");
m_result_callback(error_code::yield_type);
return;
}
lua_pop(m_state.get(), n_results);

lua_pop(m_state.get(), 1);

auto success
= m_try_lock_callback(std::move(key_buf.value()),
broker::lock_type::write,
lock_level,
[&](auto res) {
handle_try_lock(std::move(res));
});
Expand Down
6 changes: 6 additions & 0 deletions src/parsec/agent/runners/lua/impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ namespace cbdc::parsec::agent::runner {
/// function execution, signature checking and commiting execution results.
/// Class cannot be re-used for different functions/transactions, manages
/// the lifecycle of a single transaction.
/// NOTE: When writing contracts, to pass data between the Lua environment
/// and the C++ environment, use `coroutine.yield()`. To request a
/// read-lock use coroutine.yield(<data>, 0). To request a write-lock use
/// coroutine.yield(<data>, 1) or coroutine.yield(<data>).
class lua_runner : public interface {
public:
/// \copydoc interface::interface()
Expand Down Expand Up @@ -47,6 +51,8 @@ namespace cbdc::parsec::agent::runner {

auto get_stack_string(int index) -> std::optional<buffer>;

auto get_stack_integer(int index) -> std::optional<int64_t>;

void schedule_contract();

void
Expand Down

0 comments on commit c8e806b

Please sign in to comment.