diff --git a/docs/predicate/bech32_address_2.md b/docs/predicate/bech32_address_2.md index c2a17b9f..7ded8852 100644 --- a/docs/predicate/bech32_address_2.md +++ b/docs/predicate/bech32_address_2.md @@ -42,12 +42,15 @@ bech32_address(Address, 'okp415wn30a9z4uc692s0kkx5fp5d4qfr3ac7sj9dqn'). - **Then** the answer we get is: ``` yaml -has_more: false -variables: ["Address"] -results: -- substitutions: - - variable: Address - expression: "okp4-[163,167,23,244,162,175,49,162,170,15,181,141,68,134,141,168,18,56,247,30]" +height: 42 +gas_used: 2222 +answer: + has_more: false + variables: ["Address"] + results: + - substitutions: + - variable: Address + expression: "okp4-[163,167,23,244,162,175,49,162,170,15,181,141,68,134,141,168,18,56,247,30]" ``` ### Decode Hrp and Address from a bech32 address @@ -68,14 +71,17 @@ bech32_address(-(Hrp, Address), 'okp415wn30a9z4uc692s0kkx5fp5d4qfr3ac7sj9dqn'). - **Then** the answer we get is: ``` yaml -has_more: false -variables: ["Hrp", "Address"] -results: -- substitutions: - - variable: Hrp - expression: "okp4" - - variable: Address - expression: "[163,167,23,244,162,175,49,162,170,15,181,141,68,134,141,168,18,56,247,30]" +height: 42 +gas_used: 2222 +answer: + has_more: false + variables: ["Hrp", "Address"] + results: + - substitutions: + - variable: Hrp + expression: "okp4" + - variable: Address + expression: "[163,167,23,244,162,175,49,162,170,15,181,141,68,134,141,168,18,56,247,30]" ``` ### Extract Address only for OKP4 bech32 address @@ -95,12 +101,15 @@ bech32_address(-(okp4, Address), 'okp415wn30a9z4uc692s0kkx5fp5d4qfr3ac7sj9dqn'). - **Then** the answer we get is: ``` yaml -has_more: false -variables: ["Address"] -results: -- substitutions: - - variable: Address - expression: "[163,167,23,244,162,175,49,162,170,15,181,141,68,134,141,168,18,56,247,30]" +height: 42 +gas_used: 2222 +answer: + has_more: false + variables: ["Address"] + results: + - substitutions: + - variable: Address + expression: "[163,167,23,244,162,175,49,162,170,15,181,141,68,134,141,168,18,56,247,30]" ``` ### Encode Address Pair into Bech32 Address @@ -119,12 +128,15 @@ bech32_address(-('okp4', [163,167,23,244,162,175,49,162,170,15,181,141,68,134,14 - **Then** the answer we get is: ``` yaml -has_more: false -variables: ["Bech32"] -results: -- substitutions: - - variable: Bech32 - expression: "okp415wn30a9z4uc692s0kkx5fp5d4qfr3ac7sj9dqn" +height: 42 +gas_used: 2222 +answer: + has_more: false + variables: ["Bech32"] + results: + - substitutions: + - variable: Bech32 + expression: "okp415wn30a9z4uc692s0kkx5fp5d4qfr3ac7sj9dqn" ``` ### Check if a bech32 address is part of the okp4 protocol @@ -149,9 +161,12 @@ okp4_addr('okp41p8u47en82gmzfm259y6z93r9qe63l25dfwwng6'). - **Then** the answer we get is: ``` yaml -has_more: false -results: -- substitutions: +height: 42 +gas_used: 2222 +answer: + has_more: false + results: + - substitutions: ``` ### Error on Incorrect Bech32 Address format @@ -172,10 +187,13 @@ bech32_address(Address, okp4incorrect). - **Then** the answer we get is: ``` yaml -has_more: false -variables: ["Address"] -results: -- error: "error(domain_error(encoding(bech32),okp4incorrect),[d,e,c,o,d,i,n,g, ,b,e,c,h,3,2, ,f,a,i,l,e,d,:, ,i,n,v,a,l,i,d, ,s,e,p,a,r,a,t,o,r, ,i,n,d,e,x, ,-,1],bech32_address/2)" +height: 42 +gas_used: 2222 +answer: + has_more: false + variables: ["Address"] + results: + - error: "error(domain_error(encoding(bech32),okp4incorrect),[d,e,c,o,d,i,n,g, ,b,e,c,h,3,2, ,f,a,i,l,e,d,:, ,i,n,v,a,l,i,d, ,s,e,p,a,r,a,t,o,r, ,i,n,d,e,x, ,-,1],bech32_address/2)" ``` ### Error on Incorrect Bech32 Address type @@ -196,8 +214,11 @@ bech32_address(-('okp4', X), foo(bar)). - **Then** the answer we get is: ``` yaml -has_more: false -variables: ["X"] -results: -- error: "error(type_error(atom,foo(bar)),bech32_address/2)" +height: 42 +gas_used: 2222 +answer: + has_more: false + variables: ["X"] + results: + - error: "error(type_error(atom,foo(bar)),bech32_address/2)" ``` diff --git a/docs/predicate/block_height_1.md b/docs/predicate/block_height_1.md index 7f12d96c..a50a5447 100644 --- a/docs/predicate/block_height_1.md +++ b/docs/predicate/block_height_1.md @@ -43,12 +43,15 @@ block_height(Height). - **Then** the answer we get is: ``` yaml -has_more: false -variables: ["Height"] -results: -- substitutions: - - variable: Height - expression: "100" +height: 100 +gas_used: 2222 +answer: + has_more: false + variables: ["Height"] + results: + - substitutions: + - variable: Height + expression: "100" ``` ### Check that the block height is greater than a certain value @@ -75,10 +78,13 @@ Height > 100. - **Then** the answer we get is: ``` yaml -has_more: false -variables: ["Height"] -results: -- substitutions: - - variable: Height - expression: "101" +height: 101 +gas_used: 2223 +answer: + has_more: false + variables: ["Height"] + results: + - substitutions: + - variable: Height + expression: "101" ``` diff --git a/docs/predicate/block_time_1.md b/docs/predicate/block_time_1.md index ef30d09d..fa279111 100644 --- a/docs/predicate/block_time_1.md +++ b/docs/predicate/block_time_1.md @@ -43,12 +43,15 @@ block_time(Time). - **Then** the answer we get is: ``` yaml -has_more: false -variables: ["Time"] -results: -- substitutions: - - variable: Time - expression: "1709550216" +height: 42 +gas_used: 2222 +answer: + has_more: false + variables: ["Time"] + results: + - substitutions: + - variable: Time + expression: "1709550216" ``` ### Check that the block time is greater than a certain time @@ -76,10 +79,13 @@ Time > 1709550216. - **Then** the answer we get is: ``` yaml -has_more: false -variables: ["Time"] -results: -- substitutions: - - variable: Time - expression: "1709550217" +height: 42 +gas_used: 2223 +answer: + has_more: false + variables: ["Time"] + results: + - substitutions: + - variable: Time + expression: "1709550217" ``` diff --git a/docs/predicate/consult_1.md b/docs/predicate/consult_1.md index c3713398..60956062 100644 --- a/docs/predicate/consult_1.md +++ b/docs/predicate/consult_1.md @@ -64,12 +64,15 @@ hello(Who). - **Then** the answer we get is: ``` yaml -has_more: false -variables: ["Who"] -results: -- substitutions: - - variable: Who - expression: "['W',o,r,l,d,!]" +height: 42 +gas_used: 2224 +answer: + has_more: false + variables: ["Who"] + results: + - substitutions: + - variable: Who + expression: "['W',o,r,l,d,!]" ``` ### Consult a Prolog program which also consults another Prolog program @@ -117,23 +120,26 @@ response: | - **Given** the query: ``` prolog -consult('cosmwasm:storage:okp415ekvz3qdter33mdnk98v8whv5qdr53yusksnfgc08xd26fpdn3ts8gddht?query=%7B%22object_data%22%3A%7B%22id%22%3A%20%224cbe36399aabfcc7158ee7a66cbfffa525bb0ceab33d1ff2cff08759fe0a9b05%22%7D%7D&base64Decode=false'), -program(X). + consult('cosmwasm:storage:okp415ekvz3qdter33mdnk98v8whv5qdr53yusksnfgc08xd26fpdn3ts8gddht?query=%7B%22object_data%22%3A%7B%22id%22%3A%20%224cbe36399aabfcc7158ee7a66cbfffa525bb0ceab33d1ff2cff08759fe0a9b05%22%7D%7D&base64Decode=false'), + program(X). ``` - **When** the query is run (limited to 2 solutions) - **Then** the answer we get is: ``` yaml -has_more: false -variables: ["X"] -results: -- substitutions: - - variable: X - expression: "b" -- substitutions: - - variable: X - expression: "a" +height: 42 +gas_used: 2223 +answer: + has_more: false + variables: ["X"] + results: + - substitutions: + - variable: X + expression: "b" + - substitutions: + - variable: X + expression: "a" ``` ### Consult several Prolog programs @@ -187,13 +193,16 @@ source_file(File). - **Then** the answer we get is: ``` yaml -has_more: false -variables: ["File"] -results: -- substitutions: - - variable: File - expression: "'cosmwasm:storage:okp412ssv28mzr02jffvy4x39akrpky9ykfafzyjzmvgsqqdw78yjevpqgmqnmk?query=%7B%22object_data%22%3A%7B%22id%22%3A%20%225d3933430d0a12794fae719e0db87b6ec5f549b2%22%7D%7D&base64Decode=false'" -- substitutions: - - variable: File - expression: "'cosmwasm:storage:okp415ekvz3qdter33mdnk98v8whv5qdr53yusksnfgc08xd26fpdn3ts8gddht?query=%7B%22object_data%22%3A%7B%22id%22%3A%20%224cbe36399aabfcc7158ee7a66cbfffa525bb0ceab33d1ff2cff08759fe0a9b05%22%7D%7D&base64Decode=false'" +height: 42 +gas_used: 2223 +answer: + has_more: false + variables: ["File"] + results: + - substitutions: + - variable: File + expression: "'cosmwasm:storage:okp412ssv28mzr02jffvy4x39akrpky9ykfafzyjzmvgsqqdw78yjevpqgmqnmk?query=%7B%22object_data%22%3A%7B%22id%22%3A%20%225d3933430d0a12794fae719e0db87b6ec5f549b2%22%7D%7D&base64Decode=false'" + - substitutions: + - variable: File + expression: "'cosmwasm:storage:okp415ekvz3qdter33mdnk98v8whv5qdr53yusksnfgc08xd26fpdn3ts8gddht?query=%7B%22object_data%22%3A%7B%22id%22%3A%20%224cbe36399aabfcc7158ee7a66cbfffa525bb0ceab33d1ff2cff08759fe0a9b05%22%7D%7D&base64Decode=false'" ``` diff --git a/docs/predicate/current_output_1.md b/docs/predicate/current_output_1.md new file mode 100644 index 00000000..db1e0cad --- /dev/null +++ b/docs/predicate/current_output_1.md @@ -0,0 +1,215 @@ +--- +sidebar_position: 10 +--- +[//]: # (This file is auto-generated. Please do not modify it yourself.) + +# current_output/1 + +## Description + +`current_output/1` is a predicate that unifies the given term with the current output stream. + +## Signature + +```text +current_output(-Stream) is det +``` + +where: + +- Stream represents the current output stream. + +This predicate connects to the default output stream available for user interactions, allowing the user to perform write operations. + +The outcome of the stream's content throughout the execution of a query is provided as a string within the user\_output field in the query's response. However, it's important to note that the maximum length of the output is constrained by the max\_query\_output\_size setting, meaning only the final max\_query\_output\_size bytes \(not characters\) of the output are included in the response. + +## Examples + +### Write a char to the current output + +This scenario demonstrates how to write a character to the current output, and get the content in the response of the +request. + +Here's the steps of the scenario: + +- **Given** the module configuration: + +``` json +{ + "limits": { + "max_user_output_size": "5" + } +} +``` + +- **Given** the program: + +``` prolog +write_char_to_user_output(C) :- + current_output(UserStream), % get the current output stream + put_char(UserStream, C). % write the char to the user stream +``` + +- **Given** the query: + +``` prolog +write_char_to_user_output(x). +``` + +- **When** the query is run +- **Then** the answer we get is: + +``` yaml +height: 42 +gas_used: 2241 +answer: + has_more: false + variables: + results: + - substitutions: +user_output: | + x +``` + +### Write characters to the current output (without limit) + +This scenario demonstrates how to write some characters to the current output, and get the content in the response of the +request. This is helpful for debugging purposes. + +Here's the steps of the scenario: + +- **Given** the module configuration: + +``` json +{ + "limits": { + "max_user_output_size": "15" + } +} +``` + +- **Given** the program: + +``` prolog +log_message(Message) :- + current_output(UserStream), % get the current output stream + write(UserStream, Message), % write the message to the user stream + put_char(UserStream, '\n'). +``` + +- **Given** the query: + +``` prolog +log_message('Hello world!'). +``` + +- **When** the query is run +- **Then** the answer we get is: + +``` yaml +height: 42 +gas_used: 2248 +answer: + has_more: false + variables: + results: + - substitutions: +user_output: | + Hello world! + +``` + +### Write characters to the current output (with limit) + +This scenario demonstrates the process of writing characters to the current user output, with a limit configured +in the logic module. So if the message is longer than this limit, the output will be truncated. + +Here's the steps of the scenario: + +- **Given** the module configuration: + +``` json +{ + "limits": { + "max_user_output_size": "5" + } +} +``` + +- **Given** the program: + +``` prolog +log_message(Message) :- + current_output(UserStream), % get the current output stream + write(UserStream, Message). % write the message to the user stream +``` + +- **Given** the query: + +``` prolog +log_message('Hello world!'). +``` + +- **When** the query is run +- **Then** the answer we get is: + +``` yaml +height: 42 +gas_used: 2241 +answer: + has_more: false + variables: + results: + - substitutions: +user_output: | + orld! +``` + +### Write UTF-8 character to the current output (with limit) + +This scenario illustrates the impact of UTF-8 characters on output limits measured in bytes, not character count. +Characters such as emojis require more space; for example, the wizard emoji (🧙) occupies 4 bytes, effectively counting +as four units. As a result, the limit is reached more quickly with these characters, which means that the number of +characters in the user output is less than expected. + +Here's the steps of the scenario: + +- **Given** the module configuration: + +``` json +{ + "limits": { + "max_user_output_size": "5" + } +} +``` + +- **Given** the program: + +``` prolog +log_message([]). +log_message([H|T]) :- + current_output(UserStream), + put_char(UserStream, H), + log_message(T). +``` + +- **Given** the query: + +``` prolog +log_message("Hello 🧙!"). +``` + +- **When** the query is run +- **Then** the answer we get is: + +``` yaml +height: 42 +gas_used: 2255 +answer: + has_more: false + variables: + results: + - substitutions: +user_output: "🧙!" +``` diff --git a/docs/predicate/did_components_2.md b/docs/predicate/did_components_2.md index 994af983..7b99e219 100644 --- a/docs/predicate/did_components_2.md +++ b/docs/predicate/did_components_2.md @@ -1,5 +1,5 @@ --- -sidebar_position: 10 +sidebar_position: 11 --- [//]: # (This file is auto-generated. Please do not modify it yourself.) diff --git a/docs/predicate/ecdsa_verify_4.md b/docs/predicate/ecdsa_verify_4.md index 98f9bdc9..465511f0 100644 --- a/docs/predicate/ecdsa_verify_4.md +++ b/docs/predicate/ecdsa_verify_4.md @@ -1,5 +1,5 @@ --- -sidebar_position: 11 +sidebar_position: 12 --- [//]: # (This file is auto-generated. Please do not modify it yourself.) diff --git a/docs/predicate/eddsa_verify_4.md b/docs/predicate/eddsa_verify_4.md index 7fe4308a..a27e5f4a 100644 --- a/docs/predicate/eddsa_verify_4.md +++ b/docs/predicate/eddsa_verify_4.md @@ -1,5 +1,5 @@ --- -sidebar_position: 12 +sidebar_position: 13 --- [//]: # (This file is auto-generated. Please do not modify it yourself.) diff --git a/docs/predicate/hex_bytes_2.md b/docs/predicate/hex_bytes_2.md index 7efaa96c..a10d7fc9 100644 --- a/docs/predicate/hex_bytes_2.md +++ b/docs/predicate/hex_bytes_2.md @@ -1,5 +1,5 @@ --- -sidebar_position: 13 +sidebar_position: 14 --- [//]: # (This file is auto-generated. Please do not modify it yourself.) diff --git a/docs/predicate/json_prolog_2.md b/docs/predicate/json_prolog_2.md index 3384ff85..bd803abf 100644 --- a/docs/predicate/json_prolog_2.md +++ b/docs/predicate/json_prolog_2.md @@ -1,5 +1,5 @@ --- -sidebar_position: 14 +sidebar_position: 15 --- [//]: # (This file is auto-generated. Please do not modify it yourself.) diff --git a/docs/predicate/open_3.md b/docs/predicate/open_3.md index 3c01ad69..debe8dee 100644 --- a/docs/predicate/open_3.md +++ b/docs/predicate/open_3.md @@ -1,5 +1,5 @@ --- -sidebar_position: 16 +sidebar_position: 17 --- [//]: # (This file is auto-generated. Please do not modify it yourself.) @@ -61,8 +61,11 @@ open( - **Then** the answer we get is: ``` yaml -has_more: false -variables: -results: -- substitutions: +height: 42 +gas_used: 2223 +answer: + has_more: false + variables: + results: + - substitutions: ``` diff --git a/docs/predicate/open_4.md b/docs/predicate/open_4.md index 8acfcf33..7ec4a306 100644 --- a/docs/predicate/open_4.md +++ b/docs/predicate/open_4.md @@ -1,5 +1,5 @@ --- -sidebar_position: 15 +sidebar_position: 16 --- [//]: # (This file is auto-generated. Please do not modify it yourself.) @@ -99,12 +99,15 @@ open(URI, read, _, []). - **Then** the answer we get is: ``` yaml -has_more: false -variables: ["URI"] -results: -- substitutions: - - variable: URI - expression: "'cosmwasm:storage:okp415ekvz3qdter33mdnk98v8whv5qdr53yusksnfgc08xd26fpdn3ts8gddht?query=%7B%22object_data%22%3A%7B%22id%22%3A%20%224cbe36399aabfcc7158ee7a66cbfffa525bb0ceab33d1ff2cff08759fe0a9b05%22%7D%7D&base64Decode=false'" +height: 42 +gas_used: 2228 +answer: + has_more: false + variables: ["URI"] + results: + - substitutions: + - variable: URI + expression: "'cosmwasm:storage:okp415ekvz3qdter33mdnk98v8whv5qdr53yusksnfgc08xd26fpdn3ts8gddht?query=%7B%22object_data%22%3A%7B%22id%22%3A%20%224cbe36399aabfcc7158ee7a66cbfffa525bb0ceab33d1ff2cff08759fe0a9b05%22%7D%7D&base64Decode=false'" ``` ### Open an existing resource and read its content @@ -148,12 +151,15 @@ read_resource('cosmwasm:storage:okp415ekvz3qdter33mdnk98v8whv5qdr53yusksnfgc08xd - **Then** the answer we get is: ``` yaml -has_more: false -variables: ["Chars"] -results: -- substitutions: - - variable: Chars - expression: "'Hello, World!'" +height: 42 +gas_used: 2224 +answer: + has_more: false + variables: ["Chars"] + results: + - substitutions: + - variable: Chars + expression: "'Hello, World!'" ``` ### Open an existing resource and read its content (base64-encoded) @@ -195,12 +201,15 @@ read_resource('cosmwasm:storage:okp415ekvz3qdter33mdnk98v8whv5qdr53yusksnfgc08xd - **Then** the answer we get is: ``` yaml -has_more: false -variables: ["Chars"] -results: -- substitutions: - - variable: Chars - expression: "'Hello, World!'" +height: 42 +gas_used: 2224 +answer: + has_more: false + variables: ["Chars"] + results: + - substitutions: + - variable: Chars + expression: "'Hello, World!'" ``` ### Try to open a non-existing resource @@ -219,10 +228,13 @@ open('cosmwasm:storage:okp415ekvz3qdter33mdnk98v8whv5qdr53yusksnfgc08xd26fpdn3ts - **Then** the answer we get is: ``` yaml -has_more: false -variables: ["Stream"] -results: -- error: "error(existence_error(source_sink,cosmwasm:storage:okp415ekvz3qdter33mdnk98v8whv5qdr53yusksnfgc08xd26fpdn3ts8gddht?query=foo),open/4)" +height: 42 +gas_used: 2222 +answer: + has_more: false + variables: ["Stream"] + results: + - error: "error(existence_error(source_sink,cosmwasm:storage:okp415ekvz3qdter33mdnk98v8whv5qdr53yusksnfgc08xd26fpdn3ts8gddht?query=foo),open/4)" ``` ### Try to open a resource for writing @@ -242,10 +254,13 @@ open('cosmwasm:storage:okp415ekvz3qdter33mdnk98v8whv5qdr53yusksnfgc08xd26fpdn3ts - **Then** the answer we get is: ``` yaml -has_more: false -variables: ["Stream"] -results: -- error: "error(permission_error(input,stream,cosmwasm:storage:okp415ekvz3qdter33mdnk98v8whv5qdr53yusksnfgc08xd26fpdn3ts8gddht?query=foo),open/4)" +height: 42 +gas_used: 2222 +answer: + has_more: false + variables: ["Stream"] + results: + - error: "error(permission_error(input,stream,cosmwasm:storage:okp415ekvz3qdter33mdnk98v8whv5qdr53yusksnfgc08xd26fpdn3ts8gddht?query=foo),open/4)" ``` ### Try to open a resource for appending @@ -265,10 +280,13 @@ open('cosmwasm:storage:okp415ekvz3qdter33mdnk98v8whv5qdr53yusksnfgc08xd26fpdn3ts - **Then** the answer we get is: ``` yaml -has_more: false -variables: ["Stream"] -results: -- error: "error(permission_error(input,stream,cosmwasm:storage:okp415ekvz3qdter33mdnk98v8whv5qdr53yusksnfgc08xd26fpdn3ts8gddht?query=foo),open/4)" +height: 42 +gas_used: 2222 +answer: + has_more: false + variables: ["Stream"] + results: + - error: "error(permission_error(input,stream,cosmwasm:storage:okp415ekvz3qdter33mdnk98v8whv5qdr53yusksnfgc08xd26fpdn3ts8gddht?query=foo),open/4)" ``` ### Pass incorrect options to open/4 @@ -287,8 +305,11 @@ open('cosmwasm:storage:okp415ekvz3qdter33mdnk98v8whv5qdr53yusksnfgc08xd26fpdn3ts - **Then** the answer we get is: ``` yaml -has_more: false -variables: ["Stream"] -results: -- error: "error(domain_error(empty_list,[non_existing_option]),open/4)" +height: 42 +gas_used: 2222 +answer: + has_more: false + variables: ["Stream"] + results: + - error: "error(domain_error(empty_list,[non_existing_option]),open/4)" ``` diff --git a/docs/predicate/read_string_3.md b/docs/predicate/read_string_3.md index 7daa11f5..c59005cc 100644 --- a/docs/predicate/read_string_3.md +++ b/docs/predicate/read_string_3.md @@ -1,5 +1,5 @@ --- -sidebar_position: 17 +sidebar_position: 18 --- [//]: # (This file is auto-generated. Please do not modify it yourself.) diff --git a/docs/predicate/source_file_1.md b/docs/predicate/source_file_1.md index 5730d22a..17052a0a 100644 --- a/docs/predicate/source_file_1.md +++ b/docs/predicate/source_file_1.md @@ -1,5 +1,5 @@ --- -sidebar_position: 18 +sidebar_position: 19 --- [//]: # (This file is auto-generated. Please do not modify it yourself.) diff --git a/docs/predicate/string_bytes_3.md b/docs/predicate/string_bytes_3.md index 9e4c3cde..c58eb195 100644 --- a/docs/predicate/string_bytes_3.md +++ b/docs/predicate/string_bytes_3.md @@ -1,5 +1,5 @@ --- -sidebar_position: 19 +sidebar_position: 20 --- [//]: # (This file is auto-generated. Please do not modify it yourself.) diff --git a/docs/predicate/uri_encoded_3.md b/docs/predicate/uri_encoded_3.md index 3697e6e2..983b97fb 100644 --- a/docs/predicate/uri_encoded_3.md +++ b/docs/predicate/uri_encoded_3.md @@ -1,5 +1,5 @@ --- -sidebar_position: 20 +sidebar_position: 21 --- [//]: # (This file is auto-generated. Please do not modify it yourself.) diff --git a/x/logic/interpreter/registry.go b/x/logic/interpreter/registry.go index 0741927f..ee79fd9f 100644 --- a/x/logic/interpreter/registry.go +++ b/x/logic/interpreter/registry.go @@ -50,7 +50,7 @@ var registry = map[string]any{ "bagof/3": engine.BagOf, "setof/3": engine.SetOf, "current_input/1": engine.CurrentInput, - "current_output/1": engine.CurrentOutput, + "current_output/1": predicate.CurrentOutput, "set_input/1": engine.SetInput, "set_output/1": engine.SetOutput, "open/4": predicate.Open, diff --git a/x/logic/keeper/features/bech32_address_2.feature b/x/logic/keeper/features/bech32_address_2.feature index 11bac19d..cc31417d 100644 --- a/x/logic/keeper/features/bech32_address_2.feature +++ b/x/logic/keeper/features/bech32_address_2.feature @@ -15,12 +15,15 @@ Feature: bech32_address/2 When the query is run Then the answer we get is: """ yaml - has_more: false - variables: ["Address"] - results: - - substitutions: - - variable: Address - expression: "okp4-[163,167,23,244,162,175,49,162,170,15,181,141,68,134,141,168,18,56,247,30]" + height: 42 + gas_used: 2222 + answer: + has_more: false + variables: ["Address"] + results: + - substitutions: + - variable: Address + expression: "okp4-[163,167,23,244,162,175,49,162,170,15,181,141,68,134,141,168,18,56,247,30]" """ @great_for_documentation Scenario: Decode Hrp and Address from a bech32 address @@ -35,14 +38,17 @@ Feature: bech32_address/2 When the query is run Then the answer we get is: """ yaml - has_more: false - variables: ["Hrp", "Address"] - results: - - substitutions: - - variable: Hrp - expression: "okp4" - - variable: Address - expression: "[163,167,23,244,162,175,49,162,170,15,181,141,68,134,141,168,18,56,247,30]" + height: 42 + gas_used: 2222 + answer: + has_more: false + variables: ["Hrp", "Address"] + results: + - substitutions: + - variable: Hrp + expression: "okp4" + - variable: Address + expression: "[163,167,23,244,162,175,49,162,170,15,181,141,68,134,141,168,18,56,247,30]" """ @great_for_documentation Scenario: Extract Address only for OKP4 bech32 address @@ -56,12 +62,15 @@ Feature: bech32_address/2 When the query is run Then the answer we get is: """ yaml - has_more: false - variables: ["Address"] - results: - - substitutions: - - variable: Address - expression: "[163,167,23,244,162,175,49,162,170,15,181,141,68,134,141,168,18,56,247,30]" + height: 42 + gas_used: 2222 + answer: + has_more: false + variables: ["Address"] + results: + - substitutions: + - variable: Address + expression: "[163,167,23,244,162,175,49,162,170,15,181,141,68,134,141,168,18,56,247,30]" """ @great_for_documentation Scenario: Encode Address Pair into Bech32 Address @@ -74,12 +83,15 @@ Feature: bech32_address/2 When the query is run Then the answer we get is: """ yaml - has_more: false - variables: ["Bech32"] - results: - - substitutions: - - variable: Bech32 - expression: "okp415wn30a9z4uc692s0kkx5fp5d4qfr3ac7sj9dqn" + height: 42 + gas_used: 2222 + answer: + has_more: false + variables: ["Bech32"] + results: + - substitutions: + - variable: Bech32 + expression: "okp415wn30a9z4uc692s0kkx5fp5d4qfr3ac7sj9dqn" """ @great_for_documentation Scenario: Check if a bech32 address is part of the okp4 protocol @@ -96,9 +108,12 @@ Feature: bech32_address/2 When the query is run Then the answer we get is: """ yaml - has_more: false - results: - - substitutions: + height: 42 + gas_used: 2222 + answer: + has_more: false + results: + - substitutions: """ Scenario: Check if a bech32 address is part of the okp4 protocol (not success) This scenario shows how to check if a bech32 address is part of the okp4 protocol. @@ -114,8 +129,11 @@ Feature: bech32_address/2 When the query is run Then the answer we get is: """ yaml - has_more: false - results: + height: 42 + gas_used: 2222 + answer: + has_more: false + results: """ Scenario: Check address equality This scenario demonstrates how to check if two bech32 addresses representation are equal. @@ -127,9 +145,12 @@ Feature: bech32_address/2 When the query is run Then the answer we get is: """ yaml - has_more: false - results: - - substitutions: + height: 42 + gas_used: 2222 + answer: + has_more: false + results: + - substitutions: """ Scenario: Decode HRP from a bech32 address This scenario demonstrates how to decode the human-readable part (Hrp) from a bech32 address string. @@ -141,12 +162,15 @@ Feature: bech32_address/2 When the query is run Then the answer we get is: """ yaml - has_more: false - variables: ["Hrp"] - results: - - substitutions: - - variable: Hrp - expression: "okp4" + height: 42 + gas_used: 2222 + answer: + has_more: false + variables: ["Hrp"] + results: + - substitutions: + - variable: Hrp + expression: "okp4" """ @great_for_documentation Scenario: Error on Incorrect Bech32 Address format @@ -161,10 +185,13 @@ Feature: bech32_address/2 When the query is run Then the answer we get is: """ yaml - has_more: false - variables: ["Address"] - results: - - error: "error(domain_error(encoding(bech32),okp4incorrect),[d,e,c,o,d,i,n,g, ,b,e,c,h,3,2, ,f,a,i,l,e,d,:, ,i,n,v,a,l,i,d, ,s,e,p,a,r,a,t,o,r, ,i,n,d,e,x, ,-,1],bech32_address/2)" + height: 42 + gas_used: 2222 + answer: + has_more: false + variables: ["Address"] + results: + - error: "error(domain_error(encoding(bech32),okp4incorrect),[d,e,c,o,d,i,n,g, ,b,e,c,h,3,2, ,f,a,i,l,e,d,:, ,i,n,v,a,l,i,d, ,s,e,p,a,r,a,t,o,r, ,i,n,d,e,x, ,-,1],bech32_address/2)" """ @great_for_documentation Scenario: Error on Incorrect Bech32 Address type @@ -179,10 +206,13 @@ Feature: bech32_address/2 When the query is run Then the answer we get is: """ yaml - has_more: false - variables: ["X"] - results: - - error: "error(type_error(atom,foo(bar)),bech32_address/2)" + height: 42 + gas_used: 2222 + answer: + has_more: false + variables: ["X"] + results: + - error: "error(type_error(atom,foo(bar)),bech32_address/2)" """ Scenario: Error on Incorrect Hrp type This scenario demonstrates the system's response to an incorrect Hrp type. @@ -196,10 +226,13 @@ Feature: bech32_address/2 When the query is run Then the answer we get is: """ yaml - has_more: false - variables: ["Bech32"] - results: - - error: "error(type_error(pair,foo(bar)),bech32_address/2)" + height: 42 + gas_used: 2222 + answer: + has_more: false + variables: ["Bech32"] + results: + - error: "error(type_error(pair,foo(bar)),bech32_address/2)" """ Scenario: Error on Incorrect Hrp type (2) This scenario demonstrates the system's response to an incorrect Hrp type. @@ -213,10 +246,13 @@ Feature: bech32_address/2 When the query is run Then the answer we get is: """ yaml - has_more: false - variables: ["Bech32"] - results: - - error: "error(type_error(atom,1),bech32_address/2)" + height: 42 + gas_used: 2222 + answer: + has_more: false + variables: ["Bech32"] + results: + - error: "error(type_error(atom,1),bech32_address/2)" """ Scenario: Error on Incorrect Address type This scenario demonstrates the system's response to an incorrect Address type. @@ -230,10 +266,13 @@ Feature: bech32_address/2 When the query is run Then the answer we get is: """ yaml - has_more: false - variables: ["Bech32"] - results: - - error: "error(type_error(byte,163),bech32_address/2)" + height: 42 + gas_used: 2222 + answer: + has_more: false + variables: ["Bech32"] + results: + - error: "error(type_error(byte,163),bech32_address/2)" """ Scenario: Error on Incorrect Address type (2) This scenario demonstrates the system's response to an incorrect Address type. @@ -247,10 +286,13 @@ Feature: bech32_address/2 When the query is run Then the answer we get is: """ yaml - has_more: false - variables: ["Bech32"] - results: - - error: "error(type_error(byte,x),bech32_address/2)" + height: 42 + gas_used: 2222 + answer: + has_more: false + variables: ["Bech32"] + results: + - error: "error(type_error(byte,x),bech32_address/2)" """ Scenario: Error on Incorrect Address type (3) This scenario demonstrates the system's response to an incorrect Address type. @@ -264,10 +306,13 @@ Feature: bech32_address/2 When the query is run Then the answer we get is: """ yaml - has_more: false - variables: ["Bech32"] - results: - - error: "error(type_error(list,hey(2)),bech32_address/2)" + height: 42 + gas_used: 2222 + answer: + has_more: false + variables: ["Bech32"] + results: + - error: "error(type_error(list,hey(2)),bech32_address/2)" """ Scenario: Not sufficiently instantiated This scenario shows the system's response when the query is not sufficiently instantiated. @@ -281,10 +326,13 @@ Feature: bech32_address/2 When the query is run Then the answer we get is: """ yaml - has_more: false - variables: ["Address", "Bech32"] - results: - - error: "error(instantiation_error,bech32_address/2)" + height: 42 + gas_used: 2222 + answer: + has_more: false + variables: ["Address", "Bech32"] + results: + - error: "error(instantiation_error,bech32_address/2)" """ Scenario: Not sufficiently instantiated (2) This scenario shows the system's response when the query is not sufficiently instantiated. @@ -298,8 +346,11 @@ Feature: bech32_address/2 When the query is run Then the answer we get is: """ yaml - has_more: false - variables: ["Hrp", "Bech32"] - results: - - error: "error(instantiation_error,bech32_address/2)" + height: 42 + gas_used: 2222 + answer: + has_more: false + variables: ["Hrp", "Bech32"] + results: + - error: "error(instantiation_error,bech32_address/2)" """ diff --git a/x/logic/keeper/features/block_height_1.feature b/x/logic/keeper/features/block_height_1.feature index b8679774..cf2bc6ef 100644 --- a/x/logic/keeper/features/block_height_1.feature +++ b/x/logic/keeper/features/block_height_1.feature @@ -15,12 +15,15 @@ Feature: block_height/1 When the query is run Then the answer we get is: """ yaml - has_more: false - variables: ["Height"] - results: - - substitutions: - - variable: Height - expression: "100" + height: 100 + gas_used: 2222 + answer: + has_more: false + variables: ["Height"] + results: + - substitutions: + - variable: Height + expression: "100" """ @great_for_documentation @@ -39,10 +42,13 @@ Feature: block_height/1 When the query is run Then the answer we get is: """ yaml - has_more: false - variables: ["Height"] - results: - - substitutions: - - variable: Height - expression: "101" + height: 101 + gas_used: 2223 + answer: + has_more: false + variables: ["Height"] + results: + - substitutions: + - variable: Height + expression: "101" """ diff --git a/x/logic/keeper/features/block_time_1.feature b/x/logic/keeper/features/block_time_1.feature index c07fe544..05d674e8 100644 --- a/x/logic/keeper/features/block_time_1.feature +++ b/x/logic/keeper/features/block_time_1.feature @@ -15,12 +15,15 @@ Feature: block_time/1 When the query is run Then the answer we get is: """ yaml - has_more: false - variables: ["Time"] - results: - - substitutions: - - variable: Time - expression: "1709550216" + height: 42 + gas_used: 2222 + answer: + has_more: false + variables: ["Time"] + results: + - substitutions: + - variable: Time + expression: "1709550216" """ @great_for_documentation @@ -40,10 +43,13 @@ Feature: block_time/1 When the query is run Then the answer we get is: """ yaml - has_more: false - variables: ["Time"] - results: - - substitutions: - - variable: Time - expression: "1709550217" + height: 42 + gas_used: 2223 + answer: + has_more: false + variables: ["Time"] + results: + - substitutions: + - variable: Time + expression: "1709550217" """ diff --git a/x/logic/keeper/features/consult_1.feature b/x/logic/keeper/features/consult_1.feature index e479553c..eb7297d5 100644 --- a/x/logic/keeper/features/consult_1.feature +++ b/x/logic/keeper/features/consult_1.feature @@ -33,12 +33,15 @@ Feature: consult/1 When the query is run Then the answer we get is: """ yaml - has_more: false - variables: ["Who"] - results: - - substitutions: - - variable: Who - expression: "['W',o,r,l,d,!]" + height: 42 + gas_used: 2224 + answer: + has_more: false + variables: ["Who"] + results: + - substitutions: + - variable: Who + expression: "['W',o,r,l,d,!]" """ @@ -80,21 +83,24 @@ Feature: consult/1 """ Given the query: """ prolog - consult('cosmwasm:storage:okp415ekvz3qdter33mdnk98v8whv5qdr53yusksnfgc08xd26fpdn3ts8gddht?query=%7B%22object_data%22%3A%7B%22id%22%3A%20%224cbe36399aabfcc7158ee7a66cbfffa525bb0ceab33d1ff2cff08759fe0a9b05%22%7D%7D&base64Decode=false'), - program(X). + consult('cosmwasm:storage:okp415ekvz3qdter33mdnk98v8whv5qdr53yusksnfgc08xd26fpdn3ts8gddht?query=%7B%22object_data%22%3A%7B%22id%22%3A%20%224cbe36399aabfcc7158ee7a66cbfffa525bb0ceab33d1ff2cff08759fe0a9b05%22%7D%7D&base64Decode=false'), + program(X). """ When the query is run (limited to 2 solutions) Then the answer we get is: """ yaml - has_more: false - variables: ["X"] - results: - - substitutions: - - variable: X - expression: "b" - - substitutions: - - variable: X - expression: "a" + height: 42 + gas_used: 2223 + answer: + has_more: false + variables: ["X"] + results: + - substitutions: + - variable: X + expression: "b" + - substitutions: + - variable: X + expression: "a" """ @great_for_documentation @@ -137,13 +143,16 @@ Feature: consult/1 When the query is run (limited to 2 solutions) Then the answer we get is: """ yaml - has_more: false - variables: ["File"] - results: - - substitutions: - - variable: File - expression: "'cosmwasm:storage:okp412ssv28mzr02jffvy4x39akrpky9ykfafzyjzmvgsqqdw78yjevpqgmqnmk?query=%7B%22object_data%22%3A%7B%22id%22%3A%20%225d3933430d0a12794fae719e0db87b6ec5f549b2%22%7D%7D&base64Decode=false'" - - substitutions: - - variable: File - expression: "'cosmwasm:storage:okp415ekvz3qdter33mdnk98v8whv5qdr53yusksnfgc08xd26fpdn3ts8gddht?query=%7B%22object_data%22%3A%7B%22id%22%3A%20%224cbe36399aabfcc7158ee7a66cbfffa525bb0ceab33d1ff2cff08759fe0a9b05%22%7D%7D&base64Decode=false'" + height: 42 + gas_used: 2223 + answer: + has_more: false + variables: ["File"] + results: + - substitutions: + - variable: File + expression: "'cosmwasm:storage:okp412ssv28mzr02jffvy4x39akrpky9ykfafzyjzmvgsqqdw78yjevpqgmqnmk?query=%7B%22object_data%22%3A%7B%22id%22%3A%20%225d3933430d0a12794fae719e0db87b6ec5f549b2%22%7D%7D&base64Decode=false'" + - substitutions: + - variable: File + expression: "'cosmwasm:storage:okp415ekvz3qdter33mdnk98v8whv5qdr53yusksnfgc08xd26fpdn3ts8gddht?query=%7B%22object_data%22%3A%7B%22id%22%3A%20%224cbe36399aabfcc7158ee7a66cbfffa525bb0ceab33d1ff2cff08759fe0a9b05%22%7D%7D&base64Decode=false'" """ diff --git a/x/logic/keeper/features/current_output_1.feature b/x/logic/keeper/features/current_output_1.feature new file mode 100644 index 00000000..014cafe2 --- /dev/null +++ b/x/logic/keeper/features/current_output_1.feature @@ -0,0 +1,155 @@ +Feature: current_output/1 + This feature is to test the current_output/1 predicate. + + @great_for_documentation + Scenario: Write a char to the current output + This scenario demonstrates how to write a character to the current output, and get the content in the response of the + request. + + Given the module configuration: + """ json + { + "limits": { + "max_user_output_size": "5" + } + } + """ + Given the program: + """ prolog + write_char_to_user_output(C) :- + current_output(UserStream), % get the current output stream + put_char(UserStream, C). % write the char to the user stream + """ + Given the query: + """ prolog + write_char_to_user_output(x). + """ + When the query is run + Then the answer we get is: + """ yaml + height: 42 + gas_used: 2241 + answer: + has_more: false + variables: + results: + - substitutions: + user_output: | + x + """ + + @great_for_documentation + Scenario: Write characters to the current output (without limit) + This scenario demonstrates how to write some characters to the current output, and get the content in the response of the + request. This is helpful for debugging purposes. + + Given the module configuration: + """ json + { + "limits": { + "max_user_output_size": "15" + } + } + """ + Given the program: + """ prolog + log_message(Message) :- + current_output(UserStream), % get the current output stream + write(UserStream, Message), % write the message to the user stream + put_char(UserStream, '\n'). + """ + Given the query: + """ prolog + log_message('Hello world!'). + """ + When the query is run + Then the answer we get is: + """ yaml + height: 42 + gas_used: 2248 + answer: + has_more: false + variables: + results: + - substitutions: + user_output: | + Hello world! + + """ + + @great_for_documentation + Scenario: Write characters to the current output (with limit) + This scenario demonstrates the process of writing characters to the current user output, with a limit configured + in the logic module. So if the message is longer than this limit, the output will be truncated. + + Given the module configuration: + """ json + { + "limits": { + "max_user_output_size": "5" + } + } + """ + Given the program: + """ prolog + log_message(Message) :- + current_output(UserStream), % get the current output stream + write(UserStream, Message). % write the message to the user stream + """ + Given the query: + """ prolog + log_message('Hello world!'). + """ + When the query is run + Then the answer we get is: + """ yaml + height: 42 + gas_used: 2241 + answer: + has_more: false + variables: + results: + - substitutions: + user_output: | + orld! + """ + + @great_for_documentation + Scenario: Write UTF-8 character to the current output (with limit) + This scenario illustrates the impact of UTF-8 characters on output limits measured in bytes, not character count. + Characters such as emojis require more space; for example, the wizard emoji (🧙) occupies 4 bytes, effectively counting + as four units. As a result, the limit is reached more quickly with these characters, which means that the number of + characters in the user output is less than expected. + + Given the module configuration: + """ json + { + "limits": { + "max_user_output_size": "5" + } + } + """ + Given the program: + """ prolog + log_message([]). + log_message([H|T]) :- + current_output(UserStream), + put_char(UserStream, H), + log_message(T). + """ + Given the query: + """ prolog + log_message("Hello 🧙!"). + """ + When the query is run + Then the answer we get is: + """ yaml + height: 42 + gas_used: 2255 + answer: + has_more: false + variables: + results: + - substitutions: + user_output: "🧙!" + """ diff --git a/x/logic/keeper/features/open_3.feature b/x/logic/keeper/features/open_3.feature index a10cbdd1..22d49f28 100644 --- a/x/logic/keeper/features/open_3.feature +++ b/x/logic/keeper/features/open_3.feature @@ -30,8 +30,11 @@ Feature: open/3 When the query is run Then the answer we get is: """ yaml - has_more: false - variables: - results: - - substitutions: + height: 42 + gas_used: 2223 + answer: + has_more: false + variables: + results: + - substitutions: """ diff --git a/x/logic/keeper/features/open_4.feature b/x/logic/keeper/features/open_4.feature index 2dec88e5..40270787 100644 --- a/x/logic/keeper/features/open_4.feature +++ b/x/logic/keeper/features/open_4.feature @@ -42,12 +42,15 @@ Feature: open/4 When the query is run Then the answer we get is: """ yaml - has_more: false - variables: ["URI"] - results: - - substitutions: - - variable: URI - expression: "'cosmwasm:storage:okp415ekvz3qdter33mdnk98v8whv5qdr53yusksnfgc08xd26fpdn3ts8gddht?query=%7B%22object_data%22%3A%7B%22id%22%3A%20%224cbe36399aabfcc7158ee7a66cbfffa525bb0ceab33d1ff2cff08759fe0a9b05%22%7D%7D&base64Decode=false'" + height: 42 + gas_used: 2228 + answer: + has_more: false + variables: ["URI"] + results: + - substitutions: + - variable: URI + expression: "'cosmwasm:storage:okp415ekvz3qdter33mdnk98v8whv5qdr53yusksnfgc08xd26fpdn3ts8gddht?query=%7B%22object_data%22%3A%7B%22id%22%3A%20%224cbe36399aabfcc7158ee7a66cbfffa525bb0ceab33d1ff2cff08759fe0a9b05%22%7D%7D&base64Decode=false'" """ @great_for_documentation @@ -82,12 +85,15 @@ Feature: open/4 When the query is run Then the answer we get is: """ yaml - has_more: false - variables: ["Chars"] - results: - - substitutions: - - variable: Chars - expression: "'Hello, World!'" + height: 42 + gas_used: 2224 + answer: + has_more: false + variables: ["Chars"] + results: + - substitutions: + - variable: Chars + expression: "'Hello, World!'" """ @great_for_documentation @@ -120,12 +126,15 @@ Feature: open/4 When the query is run Then the answer we get is: """ yaml - has_more: false - variables: ["Chars"] - results: - - substitutions: - - variable: Chars - expression: "'Hello, World!'" + height: 42 + gas_used: 2224 + answer: + has_more: false + variables: ["Chars"] + results: + - substitutions: + - variable: Chars + expression: "'Hello, World!'" """ @great_for_documentation @@ -139,10 +148,13 @@ Feature: open/4 When the query is run Then the answer we get is: """ yaml - has_more: false - variables: ["Stream"] - results: - - error: "error(existence_error(source_sink,cosmwasm:storage:okp415ekvz3qdter33mdnk98v8whv5qdr53yusksnfgc08xd26fpdn3ts8gddht?query=foo),open/4)" + height: 42 + gas_used: 2222 + answer: + has_more: false + variables: ["Stream"] + results: + - error: "error(existence_error(source_sink,cosmwasm:storage:okp415ekvz3qdter33mdnk98v8whv5qdr53yusksnfgc08xd26fpdn3ts8gddht?query=foo),open/4)" """ @great_for_documentation @@ -157,10 +169,13 @@ Feature: open/4 When the query is run Then the answer we get is: """ yaml - has_more: false - variables: ["Stream"] - results: - - error: "error(permission_error(input,stream,cosmwasm:storage:okp415ekvz3qdter33mdnk98v8whv5qdr53yusksnfgc08xd26fpdn3ts8gddht?query=foo),open/4)" + height: 42 + gas_used: 2222 + answer: + has_more: false + variables: ["Stream"] + results: + - error: "error(permission_error(input,stream,cosmwasm:storage:okp415ekvz3qdter33mdnk98v8whv5qdr53yusksnfgc08xd26fpdn3ts8gddht?query=foo),open/4)" """ @great_for_documentation @@ -175,10 +190,13 @@ Feature: open/4 When the query is run Then the answer we get is: """ yaml - has_more: false - variables: ["Stream"] - results: - - error: "error(permission_error(input,stream,cosmwasm:storage:okp415ekvz3qdter33mdnk98v8whv5qdr53yusksnfgc08xd26fpdn3ts8gddht?query=foo),open/4)" + height: 42 + gas_used: 2222 + answer: + has_more: false + variables: ["Stream"] + results: + - error: "error(permission_error(input,stream,cosmwasm:storage:okp415ekvz3qdter33mdnk98v8whv5qdr53yusksnfgc08xd26fpdn3ts8gddht?query=foo),open/4)" """ @@ -193,10 +211,13 @@ Feature: open/4 When the query is run Then the answer we get is: """ yaml - has_more: false - variables: ["Stream"] - results: - - error: "error(domain_error(empty_list,[non_existing_option]),open/4)" + height: 42 + gas_used: 2222 + answer: + has_more: false + variables: ["Stream"] + results: + - error: "error(domain_error(empty_list,[non_existing_option]),open/4)" """ @@ -210,10 +231,13 @@ Feature: open/4 When the query is run Then the answer we get is: """ yaml - has_more: false - variables: ["Stream"] - results: - - error: "error(type_error(io_mode,incorrect_mode),open/4)" + height: 42 + gas_used: 2222 + answer: + has_more: false + variables: ["Stream"] + results: + - error: "error(type_error(io_mode,incorrect_mode),open/4)" """ Scenario: Open a resource with incorrect mode (2) @@ -226,10 +250,13 @@ Feature: open/4 When the query is run Then the answer we get is: """ yaml - has_more: false - variables: ["Stream"] - results: - - error: "error(type_error(io_mode,666),open/4)" + height: 42 + gas_used: 2222 + answer: + has_more: false + variables: ["Stream"] + results: + - error: "error(type_error(io_mode,666),open/4)" """ Scenario: Insufficient instantiation error (1) @@ -242,10 +269,13 @@ Feature: open/4 When the query is run Then the answer we get is: """ yaml - has_more: false - variables: ["Resource", "Stream"] - results: - - error: "error(instantiation_error,open/4)" + height: 42 + gas_used: 2222 + answer: + has_more: false + variables: ["Resource", "Stream"] + results: + - error: "error(instantiation_error,open/4)" """ Scenario: Insufficient instantiation error (2) @@ -258,8 +288,11 @@ Feature: open/4 When the query is run Then the answer we get is: """ yaml - has_more: false - variables: ["Mode", "Stream"] - results: - - error: "error(instantiation_error,open/4)" + height: 42 + gas_used: 2222 + answer: + has_more: false + variables: ["Mode", "Stream"] + results: + - error: "error(instantiation_error,open/4)" """ diff --git a/x/logic/keeper/features_test.go b/x/logic/keeper/features_test.go index e2c741cb..60472511 100644 --- a/x/logic/keeper/features_test.go +++ b/x/logic/keeper/features_test.go @@ -12,6 +12,7 @@ import ( "testing" "time" + "dario.cat/mergo" "github.com/cucumber/godog" "github.com/golang/mock/gomock" "github.com/sergi/go-diff/diffmatchpatch" @@ -59,8 +60,9 @@ type testCase struct { accountKeeper *logictestutil.MockAccountKeeper bankKeeper *logictestutil.MockBankKeeper wasmKeeper *logictestutil.MockWasmKeeper + params types.Params request types.QueryServiceAskRequest - got *types.Answer + got *types.QueryServiceAskResponse } type SmartContractConfiguration struct { @@ -107,6 +109,23 @@ func givenABlockWithTheFollowingHeader(ctx context.Context, table *godog.Table) return nil } +func givenTheModuleConfiguration(ctx context.Context, configuration *godog.DocString) error { + params := types.Params{} + if err := json.Unmarshal([]byte(configuration.Content), ¶ms); err != nil { + return err + } + + x := testCaseFromContext(ctx).params + mergedParams := x + if err := mergo.Merge(&mergedParams, params); err != nil { + return err + } + + testCaseFromContext(ctx).params = mergedParams + + return nil +} + func givenTheProgram(ctx context.Context, program *godog.DocString) error { testCaseFromContext(ctx).request.Program = program.Content @@ -177,7 +196,7 @@ func whenTheQueryIsRun(ctx context.Context) error { return err } - tc.got = got.Answer + tc.got = got return nil } @@ -195,7 +214,7 @@ func whenTheQueryIsRunLimitedToNSolutions(ctx context.Context, n int) error { func theAnswerWeGetIs(ctx context.Context, want *godog.DocString) error { got := testCaseFromContext(ctx).got - wantAnswer := &types.Answer{} + wantAnswer := &types.QueryServiceAskResponse{} if err := yaml.Unmarshal([]byte(want.Content), &wantAnswer); err != nil { return err } @@ -237,16 +256,24 @@ func initializeScenario(t *testing.T) func(ctx *godog.ScenarioContext) { bankKeeper := logictestutil.NewMockBankKeeper(ctrl) wasmKeeper := logictestutil.NewMockWasmKeeper(ctrl) + header := testCtx.Ctx.BlockHeader() + header.ChainID = "okp4-testchain-1" + header.Height = 42 + header.Time = time.Date(2024, 4, 10, 10, 44, 27, 0, time.UTC) + testCtx.Ctx = testCtx.Ctx.WithBlockHeader(header) + tc := testCase{ ctx: testCtx, accountKeeper: accountKeeper, bankKeeper: bankKeeper, wasmKeeper: wasmKeeper, + params: logicKeeperParams(), } return testCaseToContext(ctx, tc), nil }) + ctx.Given(`the module configuration:`, givenTheModuleConfiguration) ctx.Given(`a block with the following header:`, givenABlockWithTheFollowingHeader) ctx.Given(`the CosmWasm smart contract "([^"]+)" and the behavior:`, givenASmartContractWithAddress) ctx.Given(`the query:`, givenTheQuery) @@ -274,7 +301,7 @@ func newQueryClient(ctx context.Context) (types.QueryServiceClient, error) { }, ) - if err := logicKeeper.SetParams(tc.ctx.Ctx, logicKeeperParams()); err != nil { + if err := logicKeeper.SetParams(tc.ctx.Ctx, tc.params); err != nil { return nil, err } diff --git a/x/logic/predicate/io.go b/x/logic/predicate/io.go new file mode 100644 index 00000000..9d1a7feb --- /dev/null +++ b/x/logic/predicate/io.go @@ -0,0 +1,23 @@ +package predicate + +import "github.com/ichiban/prolog/engine" + +// CurrentOutput is a predicate that unifies the given term with the current output stream. +// +// # Signature +// +// current_output(-Stream) is det +// +// where: +// - Stream represents the current output stream. +// +// This predicate connects to the default output stream available for user interactions, allowing the user to perform +// write operations. +// +// The outcome of the stream's content throughout the execution of a query is provided as a string within the +// user_output field in the query's response. However, it's important to note that the maximum length of the output +// is constrained by the max_query_output_size setting, meaning only the final max_query_output_size bytes (not characters) +// of the output are included in the response. +func CurrentOutput(vm *engine.VM, output engine.Term, cont engine.Cont, env *engine.Env) *engine.Promise { + return engine.CurrentOutput(vm, output, cont, env) +}