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

Rework staged tx #957

Merged
merged 7 commits into from
Dec 12, 2024
Merged
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
30 changes: 16 additions & 14 deletions rust/psibase/src/services/transact.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,29 +153,31 @@ pub mod auth_interface {
unimplemented!()
}

/// Handle notification related to the acceptance of a staged transaction
/// Check whether a specified set of authorizer accounts are sufficient to authorize sending a
/// transaction from a specified sender.
///
/// An auth service is notified when the sender of the staged transaction
/// is an account that uses the auth service.
/// * `sender`: The sender account for the transaction potentially being authorized.
/// * `authorizers`: The set of accounts that have already authorized the execution of the transaction.
///
/// * `staged_tx_id`: The ID of the staged transaction, used to identify the
/// staged-tx record.
/// * `actor`: The account that accepts the specified staged transaction
/// Returns:
/// * `true`: The authorizers are sufficient to authorize a transaction from the sender.
/// * `false`: The authorizers are not sufficient to authorize a transaction from the sender.
#[action]
fn stagedAccept(staged_tx_id: u32, actor: crate::AccountNumber) {
fn isAuthSys(sender: crate::AccountNumber, authorizers: Vec<crate::AccountNumber>) -> bool {
unimplemented!()
}

/// Handle notification related to the rejection of a staged transaction
/// Check whether a specified set of rejecter accounts are sufficient to reject (cancel) a
/// transaction from a specified sender.
///
/// An auth service is notified when the sender of the staged transaction
/// is an account that uses the auth service.
/// * `sender`: The sender account for the transaction potentially being rejected.
/// * `rejecters`: The set of accounts that have already authorized the rejection of the transaction.
///
/// * `staged_tx_id`: The ID of the staged transaction, used to identify the
/// staged-tx record.
/// * `actor`: The account that rejects the specified staged transaction
/// Returns:
/// * `true`: The rejecters are sufficient to reject a transaction from the sender.
/// * `false`: The rejecters are not sufficient to reject a transaction from the sender.
#[action]
fn stagedReject(staged_tx_id: u32, actor: crate::AccountNumber) {
fn isRejectSys(sender: crate::AccountNumber, rejecters: Vec<crate::AccountNumber>) -> bool {
unimplemented!()
}
}
Expand Down
10 changes: 6 additions & 4 deletions services/system/AuthAny/include/services/system/AuthAny.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,17 @@ namespace SystemService

void canAuthUserSys(psibase::AccountNumber user);

void stagedAccept(uint32_t staged_tx_id, psibase::AccountNumber actor);
bool isAuthSys(psibase::AccountNumber sender,
std::vector<psibase::AccountNumber> authorizers);

void stagedReject(uint32_t staged_tx_id, psibase::AccountNumber actor);
bool isRejectSys(psibase::AccountNumber sender,
std::vector<psibase::AccountNumber> rejecters);
};
PSIO_REFLECT(AuthAny, //
method(checkAuthSys, flags, requester, sender, action, allowedActions, claims),
method(canAuthUserSys, user),
method(stagedAccept, staged_tx_id, actor),
method(stagedReject, staged_tx_id, actor)
method(isAuthSys, sender, authorizers),
method(isRejectSys, sender, rejecters)
//
)
} // namespace SystemService
19 changes: 11 additions & 8 deletions services/system/AuthAny/src/AuthAny.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,26 +20,29 @@ namespace SystemService
std::vector<Claim> claims)
{
if (enable_print)
std::printf("auth_check\n");
std::printf("checkAuthSys\n");
}

void AuthAny::canAuthUserSys(AccountNumber user)
{
if (enable_print)
std::printf("user_check\n");
std::printf("canAuthUserSys\n");
}

void AuthAny::stagedAccept(uint32_t stagedTxId, AccountNumber actor)
bool AuthAny::isAuthSys(AccountNumber sender, std::vector<AccountNumber> authorizers)
{
check(getSender() == StagedTxService::service, "can only be called by staged-tx");
if (enable_print)
std::printf("isAuthSys\n");

auto [execute, allowedActions] = to<StagedTxService>().get_exec_info(stagedTxId);
recurse().to<Transact>().runAs(std::move(execute), allowedActions);
return true;
}

void AuthAny::stagedReject(uint32_t stagedTxId, AccountNumber actor)
bool AuthAny::isRejectSys(AccountNumber sender, std::vector<AccountNumber> rejecters)
{
check(false, "not supported");
if (enable_print)
std::printf("isRejectSys\n");

return false;
}
} // namespace SystemService

Expand Down
32 changes: 22 additions & 10 deletions services/system/AuthSig/include/services/system/AuthSig.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,17 +70,29 @@ namespace SystemService
/// submits a transaction.
void setKey(SubjectPublicKeyInfo key);

/// Handle notification related to the acceptance of a staged transaction
/// Check whether a specified set of authorizer accounts are sufficient to authorize sending a
/// transaction from a specified sender.
///
/// Auth-sig will execute the staged transaction if the sender of the call to `accept`
/// is the same as the sender of the staged transaction.
void stagedAccept(uint32_t staged_tx_id, psibase::AccountNumber actor);
/// * `sender`: The sender account for the transaction potentially being authorized.
/// * `authorizers`: The set of accounts that have already authorized the execution of the transaction.
///
/// Returns:
/// * `true`: If the sender is among the authorizers
/// * `false`: If the sender is not among the authorizers
bool isAuthSys(psibase::AccountNumber sender,
std::vector<psibase::AccountNumber> authorizers);

/// Handle notification related to the rejection of a staged transaction
/// Check whether a specified set of rejecter accounts are sufficient to reject (cancel) a
/// transaction from a specified sender.
///
/// * `sender`: The sender account for the transaction potentially being rejected.
/// * `rejecters`: The set of accounts that have already authorized the rejection of the transaction.
///
/// Auth-sig will reject the staged transaction if the sender of the call to `reject` is
/// the same as the sender of the staged transaction.
void stagedReject(uint32_t staged_tx_id, psibase::AccountNumber actor);
/// Returns:
/// * `true`: If the sender is among the rejecters
/// * `false`: If the sender is not among the rejecters
bool isRejectSys(psibase::AccountNumber sender,
std::vector<psibase::AccountNumber> rejecters);

private:
Tables db{psibase::getReceiver()};
Expand All @@ -89,8 +101,8 @@ namespace SystemService
method(checkAuthSys, flags, requester, sender, action, allowedActions, claims),
method(canAuthUserSys, user),
method(setKey, key),
method(stagedAccept, staged_tx_id, actor),
method(stagedReject, staged_tx_id, actor)
method(isAuthSys, sender, authorizers),
method(isRejectSys, sender, rejecters)
//
)
} // namespace AuthSig
Expand Down
29 changes: 7 additions & 22 deletions services/system/AuthSig/src/AuthSig.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include <services/system/AuthSig.hpp>

#include <psibase/dispatch.hpp>
#include <services/system/Accounts.hpp>
#include <services/system/Spki.hpp>
#include <services/system/StagedTx.hpp>
#include <services/system/VerifySig.hpp>
Expand Down Expand Up @@ -83,32 +84,16 @@ namespace SystemService
authTable.put(AuthRecord{.account = getSender(), .pubkey = std::move(key)});
}

void AuthSig::stagedAccept(uint32_t staged_tx_id, psibase::AccountNumber actor)
bool AuthSig::isAuthSys(psibase::AccountNumber sender,
std::vector<psibase::AccountNumber> authorizers)
{
check(getSender() == StagedTxService::service, "can only be called by staged-tx");

auto staged_tx = to<StagedTxService>().get_staged_tx(staged_tx_id);
auto actions = staged_tx.action_list.actions;

check(actions.size() > 0, "staged tx has no actions");
if (actor == actions[0].sender)
{
auto [execute, allowedActions] = to<StagedTxService>().get_exec_info(staged_tx_id);
recurse().to<Transact>().runAs(std::move(execute), allowedActions);
}
return std::ranges::contains(authorizers, sender);
}

void AuthSig::stagedReject(uint32_t staged_tx_id, psibase::AccountNumber actor)
bool AuthSig::isRejectSys(psibase::AccountNumber sender,
std::vector<psibase::AccountNumber> rejecters)
{
check(getSender() == StagedTxService::service, "can only be called by staged-tx");

auto staged_tx = to<StagedTxService>().get_staged_tx(staged_tx_id);
auto actions = staged_tx.action_list.actions;
check(actions.size() > 0, "staged tx has no actions");
if (actor == actions[0].sender)
{
to<StagedTxService>().remove(staged_tx.id, staged_tx.txid);
}
return std::ranges::contains(rejecters, sender);
}
} // namespace AuthSig
} // namespace SystemService
Expand Down
1 change: 1 addition & 0 deletions services/system/StagedTx/service/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ edition.workspace = true
publish = false

[package.metadata.psibase]
flags = ["allowSudo"]
server = "r-staged-tx"
postinstall = [
{ sender = "staged-tx", service = "staged-tx", method = "init", rawData = "0000" },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,14 @@ namespace SystemService
/// * `actions` - The actions to be staged
uint32_t propose(const std::vector<psibase::Action>& actions);

/// Removes (deletes) a staged transaction
///
/// A staged transaction can only be removed by its proposer.
///
/// * `id`: The ID of the database record containing the staged transaction
/// * `txid`: The unique txid of the staged transaction
void remove(uint32_t id, psibase::Checksum256 txid);

/// Indicates that the caller accepts the specified staged transaction
///
/// Depending on the staging rules enforced by the auth service of the sender
Expand All @@ -72,44 +80,20 @@ namespace SystemService
/// * `txid`: The unique txid of the staged transaction
void reject(uint32_t id, psibase::Checksum256 txid);

/// Removes (deletes) a staged transaction
///
/// A staged transaction can only be removed by the proposer, the staged tx
/// first sender, or the first sender's auth service.
///
/// * `id`: The ID of the database record containing the staged transaction
/// * `txid`: The unique txid of the staged transaction
void remove(uint32_t id, psibase::Checksum256 txid);

/// Notifies the staged-tx service that a staged transaction should be executed.
/// Typically this call is facilitated by the staged transaction's first sender's auth
/// service on behalf of the staged transaction's first sender.
///
/// * `id`: The ID of the database record containing the staged transaction
/// * `txid`: The unique txid of the staged transaction
void execute(uint32_t id, psibase::Checksum256 txid);

/// Gets a staged transaction by id. Typically used inline by auth services.
/// Gets a staged transaction by id.
///
/// * `id`: The ID of the database record containing the staged transaction
StagedTx get_staged_tx(uint32_t id);

/// Gets info needed for staged tx execution. Typically used inline by auth services.
///
/// * `id`: The ID of the database record containing the staged transaction
std::tuple<psibase::Action, std::vector<ServiceMethod>> get_exec_info(uint32_t id);
};

// clang-format off
PSIO_REFLECT(StagedTxService,
method(init),
method(propose, actions),
method(remove, id, txid),
method(accept, id, txid),
method(reject, id, txid),
method(remove, id, txid),
method(execute, id, txid),
method(get_staged_tx, id),
method(get_exec_info, id)
);
// clang-format on

Expand Down
Loading
Loading