From 5a9acaedc95c5721d2088f263bc99e3de574decf Mon Sep 17 00:00:00 2001 From: Saketh Are Date: Tue, 21 May 2024 12:56:20 -0400 Subject: [PATCH] add yield execution host functions (#1183) --- near-sdk/src/environment/env.rs | 51 ++++++++++++++++++++++++++++++++- near-sys/src/lib.rs | 15 ++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/near-sdk/src/environment/env.rs b/near-sdk/src/environment/env.rs index f45a30091..901d0bc45 100644 --- a/near-sdk/src/environment/env.rs +++ b/near-sdk/src/environment/env.rs @@ -14,7 +14,7 @@ use crate::promise::Allowance; use crate::types::{ AccountId, BlockHeight, Gas, NearToken, PromiseIndex, PromiseResult, PublicKey, StorageUsage, }; -use crate::{GasWeight, PromiseError}; +use crate::{CryptoHash, GasWeight, PromiseError}; use near_sys as sys; const REGISTER_EXPECTED_ERR: &str = @@ -769,6 +769,55 @@ pub fn promise_return(promise_idx: PromiseIndex) { unsafe { sys::promise_return(promise_idx.0) } } +/// Creates a promise that will execute a method on the current account with given arguments. +/// Writes a resumption token (data id) to the specified register. The callback method will execute +/// after promise_yield_resume is called with the data id OR enough blocks have passed. The timeout +/// length is specified as a protocol-level parameter yield_timeout_length_in_blocks = 200. +/// +/// The callback method will execute with a single promise input. Input will either be a payload +/// provided by the user when calling promise_yield_resume, or a PromiseError in case of timeout. +/// +/// Resumption tokens are specific to the local account; promise_yield_resume must be called from +/// a method of the same contract. +pub fn promise_yield_create( + function_name: &str, + arguments: &[u8], + gas: Gas, + weight: GasWeight, + register_id: u64, +) -> PromiseIndex { + unsafe { + PromiseIndex(sys::promise_yield_create( + function_name.len() as _, + function_name.as_ptr() as _, + arguments.len() as _, + arguments.as_ptr() as _, + gas.as_gas(), + weight.0, + register_id as _, + )) + } +} + +/// Accepts a resumption token `data_id` created by promise_yield_create on the local account. +/// `data` is a payload to be passed to the callback method as a promise input. Returns false if +/// no promise yield with the specified `data_id` is found. Returns true otherwise, guaranteeing +/// that the callback method will be executed with a user-provided payload. +/// +/// If promise_yield_resume is called multiple times with the same `data_id`, it is possible to get +/// back multiple 'true' results. The payload from the first successful call is passed to the +/// callback. +pub fn promise_yield_resume(data_id: &CryptoHash, data: &[u8]) -> bool { + unsafe { + sys::promise_yield_resume( + data_id.len() as _, + data_id.as_ptr() as _, + data.len() as _, + data.as_ptr() as _, + ) != 0 + } +} + // ############### // # Validator API # // ############### diff --git a/near-sys/src/lib.rs b/near-sys/src/lib.rs index 786476308..855c36f8d 100644 --- a/near-sys/src/lib.rs +++ b/near-sys/src/lib.rs @@ -146,6 +146,21 @@ extern "C" { beneficiary_id_len: u64, beneficiary_id_ptr: u64, ); + pub fn promise_yield_create( + function_name_len: u64, + function_name_ptr: u64, + arguments_len: u64, + arguments_ptr: u64, + gas: u64, + gas_weight: u64, + register_id: u64, + ) -> u64; + pub fn promise_yield_resume( + data_id_len: u64, + data_id_ptr: u64, + payload_len: u64, + payload_ptr: u64, + ) -> u32; // ####################### // # Promise API results # // #######################