transact
HTTP Endpoints
Push transaction
POST /push_transaction pushes a transaction. The user must pack the transaction using fracpack and pass in the binary as the request body. See Pack transaction for an RPC request which packs transactions. The Content-Type of the request body should be application/octet-stream.
Http response timing
The /push_transaction endpoint accepts a wait_for query parameter with two options:
-
final(default): Returns a 200 response only after the transaction is included in an irreversible block. For failed transactions with traces, waits until expiration. This ensures finality but increases response time. -
applied: Returns immediately after transaction execution, regardless of whether it succeeds or fails. The transaction may still be forked out or included in a block later. Returns a 500 error if a failed transaction has no trace available.
Http response encoding
The trace can be returned either as JSON (application/json) or fracpack (application/octet-stream). The Accept header can be used to choose a representation.
{
"actionTraces": [...], // Detailed execution information for debugging.
"error": "..." // Error message. Field will be empty or missing on success.
// TODO: events?
}
➕ TODO: add lifetime tracking and reporting to psinode.
Future psinode versions may trim the action traces when not in a developer mode.
Login
POST /login takes a packed transaction with a single action of the form user => service::loginSys(root host). The transaction must have the do_not_broadcast_flag set. The action will not be executed and does not need to exist on the target service. The response is JSON containing a bearer token that can be used for query requests.
| Field | Type | Notes |
|---|---|---|
| access_token | String | The token |
| token_type | String | "bearer" |
The token can be submitted either in an Authorization header or in a cookie named __Host-SESSION.
SystemService::Transact
struct SystemService::Transact {
const psibase::AccountNumber service; // "transact"
const uint64_t serviceFlags; // Flags this service must run with
startBoot(...); // This action enables the boot procedure to be split across multiple blocks
finishBoot(...); // Only called once during chain initialization
startBlock(...); // Called by native code at the beginning of each block
execTrx(...); // Called by RTransact to execute a transaction speculatively
setSnapTime(...); // Sets the time between snapshots
addCallback(...); // Adds a callback that will be run whenever the trigger happens. - onTransaction is run at the end of every transaction - onBlock runs at the end of every block
removeCallback(...); // Removes an existing callback
regEvIdx(...); // Registers an event index service
runAs(...); // Run `action` using `action.sender's` authority
checkFirstAuth(...); // Checks authorization for the sender of the first action
resMonitoring(...); // Enable/disable resource monitoring
getTransaction(...); // Get the currently executing transaction
isTransaction(...); // Returns true if running a transaction
currentBlock(...); // Get the current block header
headBlock(...); // Get the head block header
headBlockTime(...); // Get the head block time
};
All transactions enter the chain through this service.
This privileged service dispatches top-level actions to other services, checks TAPoS, detects duplicate transactions, and checks authorizations using SystemService::AuthInterface.
Other services use it to get information about the chain, current block, and head block. They also use it to call actions using other accounts' authorities via runAs.
SystemService::Transact::startBoot
void SystemService::Transact::startBoot(
psio::view<const std::vector<psibase::Checksum256>> bootTransactions
);
This action enables the boot procedure to be split across multiple blocks.
It is only called once, immediately after the boot transaction.
bootTransactions defines the list of subsequent transaction hashes to which
the node operator is committing as part of the boot sequence. The subsequent
transactions listed must then be pushed in order, and no other transactions
will be accepted until finishBoot is run.
SystemService::Transact::finishBoot
void SystemService::Transact::finishBoot();
Only called once during chain initialization.
This enables the auth checking system. Before this point, Transact
allows all transactions to execute without auth checks. After this point,
Transact uses AuthInterface::checkAuthSys to authenticate
top-level actions and uses of runAs.
SystemService::Transact::startBlock
void SystemService::Transact::startBlock();
Called by native code at the beginning of each block.
SystemService::Transact::execTrx
void SystemService::Transact::execTrx(
psio::view<const psio::shared_view_ptr<psibase::Transaction>> trx,
bool speculative
);
Called by RTransact to execute a transaction speculatively.
SystemService::Transact::setSnapTime
void SystemService::Transact::setSnapTime(
uint32_t seconds
);
Sets the time between snapshots.
A value of 0 will disable snapshots. This is a chain-wide setting because snapshots are signed by the block producers.
SystemService::Transact::addCallback
void SystemService::Transact::addCallback(
CallbackType type,
bool objective,
psibase::Action act
);
Adds a callback that will be run whenever the trigger happens.
- onTransaction is run at the end of every transaction
- onBlock runs at the end of every block.
Objective callbacks are run by the transaction service and must have this service as the sender. If an objective callback fails, it will abort the block or transaction.
Subjective callbacks are run by native and must have no sender.
Callbacks are unique. addCallback will have no effect if an
identical callback is already registered.
The order in which callbacks are executed is unspecified.
SystemService::Transact::removeCallback
void SystemService::Transact::removeCallback(
CallbackType type,
bool objective,
psibase::Action act
);
Removes an existing callback.
SystemService::Transact::regEvIdx
void SystemService::Transact::regEvIdx(
psibase::AccountNumber service
);
Registers an event index service.
SystemService::Transact::runAs
std::vector<char> SystemService::Transact::runAs(
psibase::Action action,
std::vector<ServiceMethod> allowedActions
);
Run action using action.sender's authority.
Also adds allowedActions to the list of actions that action.service
may perform on action.sender's behalf, for as long as this call to
runAs is in the call stack. Use "" for service in
allowedActions to allow use of any service (danger!). Use "" for
method to allow any method.
Returns the action's return value, if any.
This will succeed if any of the following are true:
-
getSender() == action.sender's authService -
getSender() == action.sender. Requiresaction.sender's authServiceto approve with flagAuthInterface::runAsRequesterReq(normally succeeds). -
An existing
runAsis currently on the call stack,getSender()matchesaction.serviceon that earlier call, andactionmatchesallowedActionsfrom that same earlier call. Requiresaction.sender's authServiceto approve with flagAuthInterface::runAsMatchedReqifallowedActionsis empty (normally succeeds), orAuthInterface::runAsMatchedExpandedReqif not empty (normally fails). -
All other cases, requires
action.sender's authServiceto approve with flagAuthInterface::runAsOtherReq(normally fails).+---------------------------------------+ | call runAs(action, allowedActions) | +-------------------+-------------------+ | v +--------------------------------------+ | getSender() == action.sender.authSvc | +-------------------+------------------+ yes | | no v v +----+ +------------------------------+ | OK | | getSender() == action.sender | +----+ +---------------+--------------+ yes | | no v v +-------------------------+ +----------------------+ | Auth: runAsRequesterReq | | earlier runAs frame? | +-----------+-------------+ +----------+-----------+ | no | | yes v v | +----------------+ (FALLTHROUGH) | | Needs approval | | | (Normally OK) | v +----------------+ +-----------------------------------+ | getSender() == earlier.action.svc | +---------------+-------------------+ no | | yes | | v | (FALLTHROUGH) | v- +---------------------------------+ | action matches earlier.allowed? | +---------------+-----------------+ no | | yes v | (FALLTHROUGH) | | v +-------------------------------+ | current allowedActions empty? | +------------+------------------+ yes | | no v v +-------------------------+ +-------------------------------+ | Auth: runAsMatchedReq | | Auth: runAsMatchedExpandedReq | +-----------+-------------+ +---------------+---------------+ | | v v +------------------------------+ +------------------------------+ | Needs approval (normally OK) | | Needs approval (normally no) | +------------------------------+ +------------------------------+
(FALLTHROUGH) -> "Auth: runAsOtherReq" -> Needs approval (normally no)
SystemService::Transact::checkFirstAuth
bool SystemService::Transact::checkFirstAuth(
psibase::Checksum256 id,
psio::view<const psibase::Transaction> transaction
);
Checks authorization for the sender of the first action.
SystemService::Transact::resMonitoring
void SystemService::Transact::resMonitoring(
bool enable
);
Enable/disable resource monitoring.
SystemService::Transact::getTransaction
psio::view<const psibase::Transaction> SystemService::Transact::getTransaction() const;
Get the currently executing transaction.
SystemService::Transact::isTransaction
bool SystemService::Transact::isTransaction() const;
Returns true if running a transaction.
SystemService::Transact::currentBlock
psibase::BlockHeader SystemService::Transact::currentBlock() const;
Get the current block header.
SystemService::Transact::headBlock
psibase::BlockHeader SystemService::Transact::headBlock() const;
Get the head block header.
This is not the currently executing block. See currentBlock.
SystemService::Transact::headBlockTime
psibase::BlockTime SystemService::Transact::headBlockTime() const;
Get the head block time.
This is not the currently executing block time. TODO: remove
SystemService::ServiceMethod
struct SystemService::ServiceMethod {
psibase::AccountNumber service;
psibase::MethodNumber method;
};
Identify a service and method.
An empty service or method indicates a wildcard.
SystemService::AuthInterface
struct SystemService::AuthInterface {
const uint32_t readOnlyFlag; // See header
const uint32_t firstAuthFlag; // See header
const uint32_t requestMask; // Bits which identify kind of request
const uint32_t topActionReq; // Top-level action
const uint32_t runAsRequesterReq; // See header
const uint32_t runAsMatchedReq; // See header
const uint32_t runAsMatchedExpandedReq; // See header
const uint32_t runAsOtherReq; // See header
checkAuthSys(...); // Authenticate a top-level action or a `runAs` action
canAuthUserSys(...); // Verify that a particular user is allowed to use a particular auth service. Allows auth services to use user whitelists.
isAuthSys(...); // Check whether a specified set of authorizer accounts are sufficient to authorize sending a transaction from a specified sender.
isRejectSys(...); // Check whether a specified set of rejecter accounts are sufficient to reject (cancel) a transaction from a specified sender.
};
Authenticate actions.
Transact calls into auth services using this interface
to authenticate senders of top-level actions and uses of
Transact::runAs. Any service may become an auth
service by implementing AuthInterface. Any account may
select any service to be its authenticator. Be careful;
this allows that service to act on the account's behalf and
that service to authorize other accounts and services to
act on the account's behalf. It can also can lock out that
account. See AuthSig for a canonical example of
implementing this interface.
This interface can't authenticate non-top-level actions other
than Transact::runAs actions. Most services shouldn't
call or implement AuthInterface; use getSender().
Auth services shouldn't inherit from this struct. Instead, they should define methods with matching signatures.
SystemService::AuthInterface::checkAuthSys
void SystemService::AuthInterface::checkAuthSys(
uint32_t flags,
psibase::AccountNumber requester,
psibase::AccountNumber sender,
ServiceMethod action,
std::vector<ServiceMethod> allowedActions,
std::vector<psibase::Claim> claims
);
Authenticate a top-level action or a runAs action.
flags: One of the Req (request) constants, or'ed with 0 or more of the flag constantsrequester:""if this is a top-level action, or the sender of therunAsaction. This is often different fromaction.sender.senderThe sender being requested for the action.action: Action to authenticateallowedActions: Argument fromrunAsclaims: Claims in transaction (e.g. public keys). Empty ifrunAs
SystemService::AuthInterface::canAuthUserSys
void SystemService::AuthInterface::canAuthUserSys(
psibase::AccountNumber user
);
Verify that a particular user is allowed to use a particular auth service. Allows auth services to use user whitelists..
Called by Accounts.
user: The user being checked
SystemService::AuthInterface::isAuthSys
bool SystemService::AuthInterface::isAuthSys(
psibase::AccountNumber sender,
std::vector<psibase::AccountNumber> authorizers,
std::optional<ServiceMethod> method,
std::optional<std::vector<psibase::AccountNumber>> authSet
);
Check whether a specified set of authorizer accounts are sufficient to authorize sending a transaction from a specified sender..
sender: The sender account for the transaction potentially being authorized.authorizers: The set of accounts that have already authorized the execution of the transaction.authSet: The set of accounts that are already being checked for authorization. If the sender is already in this set, then the function should return false.
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.
SystemService::AuthInterface::isRejectSys
bool SystemService::AuthInterface::isRejectSys(
psibase::AccountNumber sender,
std::vector<psibase::AccountNumber> rejecters,
std::optional<ServiceMethod> method,
std::optional<std::vector<psibase::AccountNumber>> authSet
);
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.authSet: The set of accounts that are already being checked for authorization. If the sender is already in this set, then the function should return false.
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.