From 7d89b531ffa0fb97d9039b96f1e369d6ef52a5f7 Mon Sep 17 00:00:00 2001 From: JamesPiechota Date: Sat, 27 May 2023 13:43:08 -0400 Subject: [PATCH] N.2.6.8.old (#424) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Release 2.6.8 Release Number 63 This release introduces a patch that adds to the transition period before the activation of Arweave 2.6’s trustless price oracle, in order to give miners additional time to on-board packed data to the network. The release delays the onset of the transition window by 4 months, and extends the interpolation between of old and new pricing systems to 18 months, from 12. This release introduces a hard fork that activates at height 1,189,560, approximately 2023-05-30 16:00 UTC. You will need to make sure you have upgraded your miner before this time to connect to the network. --- apps/arweave/include/ar.hrl | 2 +- apps/arweave/include/ar_pricing.hrl | 28 ++++ apps/arweave/src/ar_fork.erl | 10 +- apps/arweave/src/ar_pricing.erl | 11 +- apps/arweave/src/ar_tx.erl | 174 +++++++++++++++++++++---- apps/arweave/src/arweave.app.src | 2 +- apps/arweave/test/ar_pricing_tests.erl | 11 +- rebar.config | 2 +- 8 files changed, 203 insertions(+), 37 deletions(-) diff --git a/apps/arweave/include/ar.hrl b/apps/arweave/include/ar.hrl index 2352d3aad..ef444f224 100644 --- a/apps/arweave/include/ar.hrl +++ b/apps/arweave/include/ar.hrl @@ -29,7 +29,7 @@ -define(CLIENT_VERSION, 5). %% The current build number -- incremented for every release. --define(RELEASE_NUMBER, 62). +-define(RELEASE_NUMBER, 63). -define(DEFAULT_REQUEST_HEADERS, [ diff --git a/apps/arweave/include/ar_pricing.hrl b/apps/arweave/include/ar_pricing.hrl index 07c112209..629f0bbde 100644 --- a/apps/arweave/include/ar_pricing.hrl +++ b/apps/arweave/include/ar_pricing.hrl @@ -1,5 +1,8 @@ %% @doc Pricing macros. +%% The number of bytes in a gibibyte. +-define(GiB, (1024 * 1024 * 1024)). + %% For a new account, we charge the fee equal to the price of uploading %% this number of bytes. The fee is about 0.1$ at the time. -define(NEW_ACCOUNT_FEE_DATA_SIZE_EQUIVALENT, 20_000_000). @@ -82,6 +85,29 @@ end). -endif. -endif. +-ifdef(DEBUG). + -define(PRICE_2_6_8_TRANSITION_START, 2). +-else. + -ifdef(FORKS_RESET). + -define(PRICE_2_6_8_TRANSITION_START, 0). + -else. + -define(PRICE_2_6_8_TRANSITION_START, (30 * 24 * 30 * 4)). % ~4 months; + -endif. +-endif. + +-ifdef(DEBUG). + -define(PRICE_2_6_8_TRANSITION_BLOCKS, 2). +-else. + -ifdef(FORKS_RESET). + -define(PRICE_2_6_8_TRANSITION_BLOCKS, 0). + -else. + -ifndef(PRICE_2_6_8_TRANSITION_BLOCKS). + -define(PRICE_2_6_8_TRANSITION_BLOCKS, (30 * 24 * 30 * 18)). % ~18 months. + -endif. + -endif. +-endif. + + %% The number of recent blocks contributing data points to the continuous estimation %% of the average price of storing a gibibyte for a minute. Also, the reward history %% is used to tracking the reserved mining rewards. @@ -243,6 +269,8 @@ end). %% Used until the transition to the new fee calculation method is complete. -define(USD_PER_GBY_2019, {925, 1000000}). % 0.000925 +-define(STATIC_2_6_8_FEE_WINSTON, 858_000_000_000). + %% The largest possible multiplier for a one-step increase of the USD to AR Rate. -define(USD_TO_AR_MAX_ADJUSTMENT_UP_MULTIPLIER, {1005, 1000}). diff --git a/apps/arweave/src/ar_fork.erl b/apps/arweave/src/ar_fork.erl index b2bca5adb..4495a05f5 100644 --- a/apps/arweave/src/ar_fork.erl +++ b/apps/arweave/src/ar_fork.erl @@ -5,7 +5,7 @@ -module(ar_fork). -export([height_1_6/0, height_1_7/0, height_1_8/0, height_1_9/0, height_2_0/0, height_2_2/0, - height_2_3/0, height_2_4/0, height_2_5/0, height_2_6/0]). + height_2_3/0, height_2_4/0, height_2_5/0, height_2_6/0, height_2_6_8/0]). -include_lib("arweave/include/ar.hrl"). -include_lib("arweave/include/ar_consensus.hrl"). @@ -94,3 +94,11 @@ height_2_6() -> 1132210. % Targeting 2023-03-06 14:00 UTC -endif. -endif. + +-ifdef(FORKS_RESET). +height_2_6_8() -> + 0. +-else. +height_2_6_8() -> + 1189560. % Targeting 2023-05-30 16:00 UTC +-endif. diff --git a/apps/arweave/src/ar_pricing.erl b/apps/arweave/src/ar_pricing.erl index 34701e71f..7011c8fba 100644 --- a/apps/arweave/src/ar_pricing.erl +++ b/apps/arweave/src/ar_pricing.erl @@ -18,9 +18,6 @@ -include_lib("eunit/include/eunit.hrl"). -%% The number of bytes in a gibibyte. --define(GiB, 1024 * 1024 * 1024). - %%%=================================================================== %%% Types. %%%=================================================================== @@ -39,10 +36,10 @@ %% @doc Return true if the given height is a height where the transition to the %% new pricing algorithm is complete. is_v2_pricing_height(Height) -> - Fork_2_6 = ar_fork:height_2_6(), - Height >= Fork_2_6 % First check just this because it may be infinity. - andalso Height >= Fork_2_6 + (?PRICE_2_6_TRANSITION_START) - + (?PRICE_2_6_TRANSITION_BLOCKS). + Fork_2_6_8 = ar_fork:height_2_6_8(), + Height >= Fork_2_6_8 % First check just this because it may be infinity. + andalso Height >= Fork_2_6_8 + (?PRICE_2_6_8_TRANSITION_START) + + (?PRICE_2_6_8_TRANSITION_BLOCKS). %% @doc Return the price per gibibyte minute estimated from the given history of %% network hash rates and block rewards. The total reward used in calculations diff --git a/apps/arweave/src/ar_tx.erl b/apps/arweave/src/ar_tx.erl index 08caea4d3..c2ed20301 100644 --- a/apps/arweave/src/ar_tx.erl +++ b/apps/arweave/src/ar_tx.erl @@ -559,32 +559,64 @@ get_tx_fee(Args) -> {DataSize, Rate, PricePerGiBMinute, KryderPlusRateMultiplier, Addr, Timestamp, Accounts, Height} = Args, Fork_2_6 = ar_fork:height_2_6(), - Args2 = {DataSize, Rate, Height, Accounts, Addr, Timestamp}, - case Height >= Fork_2_6 of - false -> - get_tx_fee_pre_fork_2_6(Args2); - true -> - Args3 = {DataSize, PricePerGiBMinute, KryderPlusRateMultiplier, Addr, Accounts, + Fork_2_6_8 = ar_fork:height_2_6_8(), + PreFork26Args = {DataSize, Rate, Height, Accounts, Addr, Timestamp}, + V2PricingArgs = {DataSize, PricePerGiBMinute, KryderPlusRateMultiplier, Addr, Accounts, Height}, - case ar_pricing:is_v2_pricing_height(Height) of - true -> - get_tx_fee2(Args3); - false -> - TransitionStart = Fork_2_6 + ?PRICE_2_6_TRANSITION_START, - TransitionEnd = TransitionStart + ?PRICE_2_6_TRANSITION_BLOCKS, - case Height >= TransitionStart of - true -> - Fee1 = get_tx_fee_pre_fork_2_6(Args2), - Fee2 = get_tx_fee2(Args3), - Interval1 = Height - TransitionStart + 1, - Interval2 = TransitionEnd - (Height + 1), - (Fee1 * Interval2 + Fee2 * Interval1) div (Interval1 + Interval2); - false -> - get_tx_fee_pre_fork_2_6(Args2) - end - end + + V2PricingHeight = Fork_2_6_8 + (?PRICE_2_6_8_TRANSITION_START) + + (?PRICE_2_6_8_TRANSITION_BLOCKS), + + TransitionStart_2_6 = Fork_2_6 + ?PRICE_2_6_TRANSITION_START, + TransitionEnd_2_6 = TransitionStart_2_6 + ?PRICE_2_6_TRANSITION_BLOCKS, + TransitionStart_2_6_8 = Fork_2_6_8 + ?PRICE_2_6_8_TRANSITION_START, + TransitionEnd_2_6_8 = TransitionStart_2_6_8 + ?PRICE_2_6_8_TRANSITION_BLOCKS, + + case Height of + H when H >= V2PricingHeight -> + %% New pricing is fully live + get_tx_fee2(V2PricingArgs); + H when H >= TransitionStart_2_6_8 -> + %% 2.6.8 transition period. Interpolate between a static fee-based pricing and + %% new pricing throughout the 2.6.8 transition period + get_transition_tx_fee( + get_static_2_6_8_tx_fee(DataSize, Addr, Accounts), %% StartFee + get_tx_fee2(V2PricingArgs), %% EndFee + TransitionStart_2_6_8, + TransitionEnd_2_6_8, + Height); + H when H >= Fork_2_6_8 -> + %% Pre-2.6.8 transition period. Use a static fee-based pricing + new account fee. + get_static_2_6_8_tx_fee(DataSize, Addr, Accounts); + H when H >= TransitionStart_2_6 -> + %% 2.6 transition period. Interpolate between pre-2.6 pricing and new pricing + %% throughout the 2.6 transition period + get_transition_tx_fee( + get_tx_fee_pre_fork_2_6(PreFork26Args), %% StartFee + get_tx_fee2(V2PricingArgs), %% EndFee + TransitionStart_2_6, + TransitionEnd_2_6, + Height); + _ -> + get_tx_fee_pre_fork_2_6(PreFork26Args) + end. + +get_static_2_6_8_tx_fee(DataSize, Addr, Accounts) -> + UploadFee = (?STATIC_2_6_8_FEE_WINSTON div ?GiB) * (DataSize + ?TX_SIZE_BASE), + case Addr == <<>> orelse maps:is_key(Addr, Accounts) of + true -> + UploadFee; + false -> + NewAccountFee = (?STATIC_2_6_8_FEE_WINSTON div ?GiB) * + ?NEW_ACCOUNT_FEE_DATA_SIZE_EQUIVALENT, + UploadFee + NewAccountFee end. +get_transition_tx_fee(StartFee, EndFee, StartHeight, EndHeight, Height) -> + Interval1 = Height - StartHeight + 1, + Interval2 = EndHeight - (Height + 1), + (StartFee * Interval2 + EndFee * Interval1) div (Interval1 + Interval2). + get_tx_fee2(Args) -> {DataSize, PricePerGiBMinute, KryderPlusRateMultiplier, Addr, Accounts, Height} = Args, Args2 = {DataSize + ?TX_SIZE_BASE, PricePerGiBMinute, KryderPlusRateMultiplier, Height}, @@ -907,3 +939,99 @@ get_weave_size_increase_test() -> get_weave_size_increase(#tx{ data_size = 1 }, ar_fork:height_2_5() - 1)), ?assertEqual(262144, get_weave_size_increase(#tx{ data_size = 256 * 1024 }, ar_fork:height_2_5() - 1)). + +%% @doc Primarily test the different branches in the ar_tx:get_tx_fee logic. Several +%% of the pricing constants have test specific values which means the fees asserted here +%% will not match true mainnet fees. +get_tx_fee_test() -> + meck:new(ar_fork, [passthrough]), + meck:expect(ar_fork, height_2_6, fun() -> 1132210 end), + meck:expect(ar_fork, height_2_6_8, fun() -> 1189560 end), + + Addr = crypto:strong_rand_bytes(32), + + %% After the 2.6 transition starts + Height3 = ar_fork:height_2_6() + ?PRICE_2_6_TRANSITION_START, + test_get_tx_fee(1, Height3, <<>>, 2748223), + test_get_tx_fee(2, Height3, <<>>, 2749079), + test_get_tx_fee(2 * ?GiB, Height3, <<>>, 1837986144189), + %% +new account fee + test_get_tx_fee(1, Height3, Addr, 21460170515), + test_get_tx_fee(2, Height3, Addr, 21460171371), + test_get_tx_fee(2 * ?GiB, Height3, Addr, 1859443566481), + + %% After the 2.6 transition starts, with interpolation. + Height4 = ar_fork:height_2_6() + ?PRICE_2_6_TRANSITION_START + 1, + test_get_tx_fee(1, Height4, <<>>, 5284478), + test_get_tx_fee(2, Height4, <<>>, 5286124), + test_get_tx_fee(2 * ?GiB, Height4, <<>>, 3534209808925), + %% +new account fee + test_get_tx_fee(1, Height4, Addr, 32920129062), + test_get_tx_fee(2, Height4, Addr, 32920130708), + test_get_tx_fee(2 * ?GiB, Height4, Addr, 3567124653509), + + %% After the 2.6.8 hard fork + Height5 = ar_fork:height_2_6_8(), + test_get_tx_fee(1, Height5, <<>>, 2565589), + test_get_tx_fee(2, Height5, <<>>, 2566388), + test_get_tx_fee(2 * ?GiB, Height5, <<>>, 1715841999542), + %% +new account fee + test_get_tx_fee(1, Height5, Addr, 15982565589), + test_get_tx_fee(2, Height5, Addr, 15982566388), + test_get_tx_fee(2 * ?GiB, Height5, Addr, 1731821999542), + + %% After the 2.6.8 hard fork. Second sample to confirm static pricing. + Height6 = ar_fork:height_2_6_8() + 1, + test_get_tx_fee(1, Height6, <<>>, 2565589), + test_get_tx_fee(2, Height6, <<>>, 2566388), + test_get_tx_fee(2 * ?GiB, Height6, <<>>, 1715841999542), + %% +new account fee + test_get_tx_fee(1, Height6, Addr, 15982565589), + test_get_tx_fee(2, Height6, Addr, 15982566388), + test_get_tx_fee(2 * ?GiB, Height6, Addr, 1731821999542), + + %% After the 2.6.8 transition starts + Height7 = ar_fork:height_2_6_8() + ?PRICE_2_6_8_TRANSITION_START, + test_get_tx_fee(1, Height7, <<>>, 3925033), + test_get_tx_fee(2, Height7, <<>>, 3926256), + test_get_tx_fee(2 * ?GiB, Height7, <<>>, 2625025904233), + %% +new account fee + test_get_tx_fee(1, Height7, Addr, 24451347325), + test_get_tx_fee(2, Height7, Addr, 24451348548), + test_get_tx_fee(2 * ?GiB, Height7, Addr, 2649473326525), + + %% After the 2.6 transition starts, with interpolation + Height8 = ar_fork:height_2_6_8() + ?PRICE_2_6_8_TRANSITION_START + 1, + test_get_tx_fee(1, Height8, <<>>, 5284478), + test_get_tx_fee(2, Height8, <<>>, 5286124), + test_get_tx_fee(2 * ?GiB, Height8, <<>>, 3534209808925), + %% +new account fee + test_get_tx_fee(1, Height8, Addr, 32920129062), + test_get_tx_fee(2, Height8, Addr, 32920130708), + test_get_tx_fee(2 * ?GiB, Height8, Addr, 3567124653509), + + %% V2Pricing + Height9 = ar_fork:height_2_6_8() + ?PRICE_2_6_8_TRANSITION_START + ?PRICE_2_6_8_TRANSITION_BLOCKS, + test_get_tx_fee(1, Height9, <<>>, 5284478), + test_get_tx_fee(2, Height9, <<>>, 5286124), + test_get_tx_fee(2 * ?GiB, Height9, <<>>, 3534209808925), + %% +new account fee + test_get_tx_fee(1, Height9, Addr, 32920129062), + test_get_tx_fee(2, Height9, Addr, 32920130708), + test_get_tx_fee(2 * ?GiB, Height9, Addr, 3567124653509), + + meck:unload(ar_fork). + + +test_get_tx_fee(DataSize, Height, Addr, ExpectedFee) -> + Rate = {1, 10}, + PricePerGiBMinute = 8025, + KryderPlusRateMultiplier = 1, + Timestamp = os:system_time(seconds), + Accounts = #{}, + + ?assertEqual(ExpectedFee, + ar_tx:get_tx_fee({DataSize, Rate, PricePerGiBMinute, + KryderPlusRateMultiplier, Addr, Timestamp, Accounts, Height})). + + \ No newline at end of file diff --git a/apps/arweave/src/arweave.app.src b/apps/arweave/src/arweave.app.src index 39c5eb415..e64a04065 100644 --- a/apps/arweave/src/arweave.app.src +++ b/apps/arweave/src/arweave.app.src @@ -1,6 +1,6 @@ {application, arweave, [ {description, "Arweave"}, - {vsn, "2.6.7.1"}, + {vsn, "2.6.8"}, {mod, {ar, []}}, {applications, [ kernel, diff --git a/apps/arweave/test/ar_pricing_tests.erl b/apps/arweave/test/ar_pricing_tests.erl index bb00692b6..9c4a0f5de 100644 --- a/apps/arweave/test/ar_pricing_tests.erl +++ b/apps/arweave/test/ar_pricing_tests.erl @@ -19,6 +19,7 @@ read_block_when_stored/1]). -define(HUGE_WEAVE_SIZE, 1000000000000000). +-define(DISTANT_FUTURE_BLOCK_HEIGHT, 262800000). %% 1,000 years from genesis auto_redenomination_and_endowment_debt_test_() -> {timeout, 120, fun test_auto_redenomination_and_endowment_debt/0}. @@ -348,7 +349,8 @@ assert_new_account_fee() -> updates_pool_and_assigns_rewards_correctly_before_burden_test_() -> test_with_mocked_functions( - [{ar_fork, height_2_6, fun() -> infinity end}], + [{ar_fork, height_2_6, fun() -> ?DISTANT_FUTURE_BLOCK_HEIGHT end}, + {ar_fork, height_2_6_8, fun() -> ?DISTANT_FUTURE_BLOCK_HEIGHT end}], fun updates_pool_and_assigns_rewards_correctly_before_burden/0 ). @@ -362,13 +364,16 @@ updates_pool_and_assigns_rewards_correctly_after_burden_test_() -> {ar_pricing, get_miner_reward_and_endowment_pool, fun ar_pricing_tests:get_miner_reward_and_endowment_pool/1}, {ar_inflation, calculate, fun(_Height) -> 1 end}, - {ar_fork, height_2_6, fun() -> infinity end} + {ar_fork, height_2_6, fun() -> ?DISTANT_FUTURE_BLOCK_HEIGHT end}, + {ar_fork, height_2_6_8, fun() -> ?DISTANT_FUTURE_BLOCK_HEIGHT end} ], fun updates_pool_and_assigns_rewards_correctly_after_burden/0 ). unclaimed_rewards_go_to_endowment_pool_test_() -> - ar_test_node:test_with_mocked_functions([{ar_fork, height_2_6, fun() -> infinity end}], + ar_test_node:test_with_mocked_functions([ + {ar_fork, height_2_6, fun() -> ?DISTANT_FUTURE_BLOCK_HEIGHT end}, + {ar_fork, height_2_6_8, fun() -> ?DISTANT_FUTURE_BLOCK_HEIGHT end}], fun test_unclaimed_rewards_go_to_endowment_pool/0). get_miner_reward_and_endowment_pool(Args) -> diff --git a/rebar.config b/rebar.config index 84a923dad..bbdefe646 100644 --- a/rebar.config +++ b/rebar.config @@ -26,7 +26,7 @@ ]}. {relx, [ - {release, {arweave, "2.6.7.1"}, [ + {release, {arweave, "2.6.8"}, [ {arweave, load}, ar_sqlite3, b64fast,