Skip to content

Commit

Permalink
Backported some opts, organized code and docs
Browse files Browse the repository at this point in the history
  • Loading branch information
Skydev0h committed Oct 13, 2023
1 parent 07b73f2 commit 4f2cf58
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 15 deletions.
30 changes: 27 additions & 3 deletions Improvements.rst
Original file line number Diff line number Diff line change
Expand Up @@ -105,15 +105,39 @@ total level, with further commits do a `stable development` of contest test case
+----------------------------------------------------------------+------+------+------+-------+------+-------+-------+-------+-------+--------+
| Backported FunC optimizations from entrypoint branch | 2782 | 3373 | 1824 | 7979 | 2245 | 22.1% | 60011 | 64810 | 34138 | 158959 |
+----------------------------------------------------------------+------+------+------+-------+------+-------+-------+-------+-------+--------+
| Use SDBEGINS to enforce "sign" prefix in external message | 2710 | 3373 | 1824 | 7907 | 2343 | 22.9% | 59147 | 64810 | 34138 | 158095 |
| Use SDBEGINS to enforce prefix in external message | 2710 | 3373 | 1824 | 7907 | 2343 | 22.9% | 59147 | 64810 | 34138 | 158095 |
+----------------------------------------------------------------+------+------+------+-------+------+-------+-------+-------+-------+--------+
| Use SDBEGINSQ to check internal message prefixes | 2710 | 3283 | 1736 | 7729 | 2521 | 24.6% | 59237 | 64090 | 33578 | 156905 |
+----------------------------------------------------------------+------+------+------+-------+------+-------+-------+-------+-------+--------+
| *Reminder and origin point: INITIAL* | 3235 | 4210 | 2760 | 10250 | 0 | 0.00% | 64038 | 71163 | 38866 | 174067 |
| Backport some optimizations from EP and coalesce code | 2699 | 3165 | 1828 | 7692 | 2558 | 25.0% | 59108 | 63031 | 34141 | 156280 |
+----------------------------------------------------------------+------+------+------+-------+------+-------+-------+-------+-------+--------+
| *Current state of the latest entrypoint branch commit* | 2718 | 2984 | 1647 | 7349 | 2901 | 28.3% | 59045 | 61210 | 33044 | 153299 |
| *Reminder and origin point: INITIAL* | 3235 | 4210 | 2760 | 10250 | 0 | 0.00% | 64038 | 71163 | 38866 | 174067 |
+----------------------------------------------------------------+------+------+------+-------+------+-------+-------+-------+-------+--------+

*It seems that backporting optimization wiggles around values here and there.* To get the maximum possible gas savings please consider taking
a look at `entrypoint` ("radical") branch. Since optimizations are carefully made there, they decrease used gas by all cases without compromises.

As an example, here is a comparison of used gas in main ("conservative") and entrypoint ("radical") branches:

+-----------------+----------+----------------+
| Test case | main gas | entrypoint gas |
+=================+==========+================+
| External | 2699 | **2707** |
+-----------------+----------+----------------+
| Internal | 3165 | **2963** |
+-----------------+----------+----------------+
| Extension | 1828 | **1626** |
+-----------------+----------+----------------+
| External GGC | 59108 | **58893** |
+-----------------+----------+----------------+
| Internal GGC | 63031 | **61011** |
+-----------------+----------+----------------+
| Extension GGC | 34141 | **32929** |
+-----------------+----------+----------------+

The external test case uses a tiny miniscule more gas due to if ordering, making it way around messes up cell slicing completely.
Nevertheless, external global counter is still less, therefore the overall result is not that bad.

N.B. Contest multiplier: 9905/10250 = 0.9663 (approximate) -> place multipliers ~ 0.3221138, 0.0966341, 0.048317

Details and rationale
Expand Down
33 changes: 33 additions & 0 deletions contracts/imports/entrypoint.fc
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
;; Basic entry point for received messages (both external and internal).
;; recv_internal and recv_external are NOT implicitly used anymore!
;; use msg_value or full_msg ONLY if you are sure these are supplied - if is_external = 0! ~ a very thin ice here!

;; N.B. If compiled by an compiler that does not support entry_point_recv this method will be ignored and the
;; contract would compile, however the gas usage will be higher due to recv_internal/external not inlined in root

;; Not supported in the main (conservative) branch.
;; Please use the entrypoint branch for the best gas optimizations and usage!
{-
Direct gas comparison on a specific commit between main and entrypoint:
main entrypoint
External test case: 2699 2707 (a bit more due to if ordering, making it way around messes up cell slicing completely)
Internal test case: 3165 2963
Extension test case: 1828 1626

main entrypoint
External global ctr: 59108 58893 (not all is bad with external messages overall)
Internal global ctr: 63031 61011
Extension global ctr: 34141 32929
-}


{-
() entry_point_recv(int msg_value, cell full_msg, slice body, int is_external) impure {
ifnot (is_external) {
recv_internal(msg_value, full_msg, body);
return();
}
recv_external(body);
ignore_int_params(msg_value, full_msg); ;; does nothing but prevents dropping them which will cause stack underflow
}
-}
40 changes: 28 additions & 12 deletions contracts/wallet_v5.fc
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
}
-}
() return_if_bounce(int flags) impure asm "1 PUSHINT" "AND" "IFRET";
;; () extravagant_return_if_bounce(int flags) impure asm "c0 PUSH" "0 IFBITJMP" "DROP";

;; SDCNTTRAIL1 will count trailing ones in slice. If bounced flag (last bit) is set it will be non-zero, else zero.
() slicy_return_if_bounce(slice s_flags) impure asm "SDCNTTRAIL1" "IFRET";

() return_if_not_equal(int a, int b) impure asm "EQUAL" "IFNOTRET";
() return_if_not(int a) impure asm "IFNOTRET";
Expand All @@ -24,6 +28,15 @@

() ignore_int_params(int msg_value, cell full_msg) impure asm "NOP";

(slice) enforce_and_remove_sign_prefix(slice body) impure asm "x{7369676E} SDBEGINS";
(slice) enforce_and_remove_extn_prefix(slice body) impure asm "x{6578746E} SDBEGINS";

(slice, int) check_and_remove_sign_prefix(slice body) impure asm "x{7369676E} SDBEGINSQ";
(slice, int) check_and_remove_extn_prefix(slice body) impure asm "x{6578746E} SDBEGINSQ";

(slice) check_and_remove_sign_prefix_or_ret(slice body) impure asm "x{7369676E} SDBEGINSQ" "IFNOTRET";
(slice) check_and_remove_extn_prefix_or_ret(slice body) impure asm "x{6578746E} SDBEGINSQ" "IFNOTRET";

;; Extensible wallet contract v5

;; Compresses 8+256-bit address into 256-bit uint by cutting off one bit from sha256.
Expand All @@ -40,7 +53,7 @@ int pack_address(int wc, int hash) impure asm "SWAP INC XOR"; ;; hash ^ (wc+1)
return ();
}
-}
() set_actions_if_simple(slice cs) impure asm "DUP" "1 PLDU" "IFNOTJMP:<{ PLDREF c5 POP }>" "DROP";
() set_actions_if_simple(slice cs) impure asm "x{4_} SDBEGINSQ" "IFJMP:<{ PLDREF c5 POP }>" "DROP";

;; Dispatches already authenticated request.
() dispatch_complex_request_inline(slice cs) impure inline {
Expand Down Expand Up @@ -146,28 +159,25 @@ int pack_address(int wc, int hash) impure asm "SWAP INC XOR"; ;; hash ^ (wc+1)
dispatch_complex_request_iref(cs);
}

(slice) enforce_and_remove_sign_prefix(slice body) impure asm "x{7369676E} SDBEGINS";

() recv_external(slice body) impure {
() recv_external(slice body) impure inline {
;; int auth_kind = body~load_uint(32);
;; return_if_not_equal(auth_kind, 0x7369676E); ;; "sign"
body = enforce_and_remove_sign_prefix(body);
process_signed_request(body);
return();
}

(slice, int) check_and_remove_sign_prefix(slice body) impure asm "x{7369676E} SDBEGINSQ";
(slice, int) check_and_remove_extn_prefix(slice body) impure asm "x{6578746E} SDBEGINSQ";

(slice) check_and_remove_sign_prefix_or_ret(slice body) impure asm "x{7369676E} SDBEGINSQ" "IFNOTRET";

() recv_internal(int msg_value, cell full_msg, slice body) impure {
() recv_internal(int msg_value, cell full_msg, slice body) impure inline {
;; Any attempt to postpone msg_value deletion will result in s2 POP -> SWAP change. No use at all.
var full_msg_slice = full_msg.begin_parse();

var flags = full_msg_slice~load_uint(4); ;; int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool src:MsgAddressInt ...
;; var flags = full_msg_slice~load_uint(4); ;; int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool src:MsgAddressInt ...
;; return_if_bounce(3); <- as a test (since there are no bounce tests) - this works (breaks tests)!
return_if_bounce(flags); ;; <- if (flags & 1) { return (); }
;; return_if_bounce(flags); ;; <- if (flags & 1) { return (); }
var s_flags = full_msg_slice~load_bits(4);
slicy_return_if_bounce(s_flags);

;; slicy_return_if_bounce(begin_cell().store_uint(3, 4).end_cell().begin_parse()); ;; TEST!!!

;; (int auth_kind, body) = body.load_uint32_or_ret(); ;; loads uint32 from body or returns if not enough bits right away

Expand Down Expand Up @@ -205,6 +215,12 @@ int pack_address(int wc, int hash) impure asm "SWAP INC XOR"; ;; hash ^ (wc+1)

}

;; N.B. If compiled by an compiler that does not support entry_point_recv this method will be ignored and the
;; contract would compile, however the gas usage will be higher due to recv_internal/external not inlined in root

;; Moved to separate file to make it easier to backport stuff from entrypoint branch to main branch
#include "imports/entrypoint.fc";

;; Get methods

int seqno() method_id {
Expand Down

0 comments on commit 4f2cf58

Please sign in to comment.