Skip to content

Commit

Permalink
[HC]: configuration cleanup/overhaul (#4251)
Browse files Browse the repository at this point in the history
* Refactor node_spec() for HC parent connector

* Better HC consensus config default value handling
  • Loading branch information
hanssv committed Jan 22, 2024
1 parent f960a84 commit 47ae2ad
Show file tree
Hide file tree
Showing 9 changed files with 380 additions and 432 deletions.
199 changes: 79 additions & 120 deletions apps/aecore/src/aec_consensus_hc.erl
Original file line number Diff line number Diff line change
Expand Up @@ -87,56 +87,45 @@ can_be_turned_off() -> false.
assert_config(_Config) -> ok.

start(Config, #{block_production := BlockProduction}) ->
#{<<"stakers">> := StakersEncoded,
<<"parent_chain">> :=
#{ <<"start_height">> := StartHeight,
<<"confirmations">> := Confirmations,
<<"consensus">> :=
#{ <<"type">> := PCType,
<<"network_id">> := NetworkId,
<<"spend_address">> := PCSpendAddress,
<<"fee">> := Fee,
<<"amount">> := Amount
},
<<"polling">> :=
#{ <<"fetch_interval">> := FetchInterval,
<<"nodes">> := Nodes0
} = Polling,
<<"producing_commitments">> := ProducingCommitments
},
<<"lazy_leader_trigger_time">> := _TimeTillDeclaringLazy
} = Config,
#{ <<"stakers">> := StakersConfig,
<<"parent_chain">> := PCConfig } = Config,

StakersConfig = maps:get(<<"stakers">>, Config, []),
PCConfig = maps:get(<<"parent_chain">>, Config),

Confirmations = maps:get(<<"confirmations">>, PCConfig, 6),
StartHeight = maps:get(<<"start_height">>, PCConfig, 0),
ProducingCommitments = maps:get(<<"producing_commitments">>, PCConfig, false),
ConsensusConfig = maps:get(<<"consensus">>, PCConfig, #{}),
PollingConfig = maps:get(<<"polling">>, PCConfig, #{}),

PCType = maps:get(<<"type">>, ConsensusConfig, <<"AE2AE">>),
NetworkId = maps:get(<<"network_id">>, ConsensusConfig, <<"ae_mainnet">>),
PCSpendAddress = maps:get(<<"spend_address">>, ConsensusConfig, <<"">>),
Fee = maps:get(<<"fee">>, ConsensusConfig, 100000000000000),
Amount = maps:get(<<"amount">>, ConsensusConfig, 1),

FetchInterval = maps:get(<<"fetch_interval">>, PollingConfig, 500),
CacheSize = maps:get(<<"cache_size">>, PollingConfig, 200),
Nodes = maps:get(<<"nodes">>, PollingConfig, []),
ParentHosts = lists:map(fun aehttpc:parse_node_url/1, Nodes),

%% assert the boolean type
case ProducingCommitments of
true -> ok;
false -> ok
end,
CacheSize = maps:get(<<"cache_size">>, Polling, 200),
ParentHosts =
lists:map(
fun(#{<<"host">> := Host,
<<"port">> := Port,
<<"user">> := User,
<<"password">> := Pass
}) ->
#{host => Host,
port => Port,
user => User,
password => Pass}
end,
Nodes0),

{ParentConnMod, PCSpendPubkey, HCPCPairs, SignModule} =
case PCType of
<<"AE2AE">> -> start_ae(StakersEncoded, PCSpendAddress);
<<"AE2BTC">> -> start_btc(StakersEncoded, PCSpendAddress, aehttpc_btc);
<<"AE2DOGE">> -> start_btc(StakersEncoded, PCSpendAddress, aehttpc_doge)
<<"AE2AE">> -> start_ae(StakersConfig, PCSpendAddress);
<<"AE2BTC">> -> start_btc(StakersConfig, PCSpendAddress, aehttpc_btc);
<<"AE2DOGE">> -> start_btc(StakersConfig, PCSpendAddress, aehttpc_doge)
end,
start_dependency(aec_parent_connector, [ParentConnMod, FetchInterval,
ParentHosts, NetworkId,
start_dependency(aec_parent_connector, [ParentConnMod, FetchInterval, ParentHosts, NetworkId,
SignModule, HCPCPairs, PCSpendPubkey, Fee, Amount]),
start_dependency(aec_parent_chain_cache, [StartHeight, CacheSize,
Confirmations, BlockProduction,
ProducingCommitments]),
start_dependency(aec_parent_chain_cache, [StartHeight, CacheSize, Confirmations,
BlockProduction, ProducingCommitments]),
ok.

start_btc(StakersEncoded, PCSpendAddress, ParentConnMod) ->
Expand Down Expand Up @@ -433,88 +422,48 @@ key_header_difficulty(H) ->

%% This is initial height; if neeeded shall be reinit at fork height
election_contract_pubkey() ->
aeu_ets_cache:get(
?ETS_CACHE_TABLE,
election_contract_pubkey,
fun() ->
{ok, EncContractId} =
aeu_env:user_config([<<"chain">>, <<"consensus">>,
<<"0">>,
<<"config">>, <<"election_contract">>]),
{ok, Pubkey} = aeser_api_encoder:safe_decode(contract_pubkey,
EncContractId),
Pubkey
end).
Fun = fun() ->
EncContractId = get_consensus_config_key([<<"election_contract">>]),
case aeser_api_encoder:safe_decode(contract_pubkey, EncContractId) of
{ok, Pubkey} -> Pubkey;
_ -> erlang:error({contract_owner_not_valid_contract, EncContractId})
end
end,
aeu_ets_cache:get(?ETS_CACHE_TABLE, election_contract_pubkey, Fun).

rewards_contract_pubkey() ->
aeu_ets_cache:get(
?ETS_CACHE_TABLE,
rewards_contract_pubkey,
fun() ->
{ok, EncContractId} =
aeu_env:user_config([<<"chain">>, <<"consensus">>,
<<"0">>,
<<"config">>, <<"rewards_contract">>]),
{ok, Pubkey} = aeser_api_encoder:safe_decode(contract_pubkey,
EncContractId),
Pubkey
end).
Fun = fun() ->
EncContractId = get_consensus_config_key([<<"rewards_contract">>]),
case aeser_api_encoder:safe_decode(contract_pubkey, EncContractId) of
{ok, Pubkey} -> Pubkey;
_ -> erlang:error({contract_owner_not_valid_contract, EncContractId})
end
end,
aeu_ets_cache:get(?ETS_CACHE_TABLE, rewards_contract_pubkey, Fun).

pc_start_height() ->
aeu_ets_cache:get(
?ETS_CACHE_TABLE,
pc_start_height,
fun() ->
{ok, H} =
aeu_env:user_config([<<"chain">>, <<"consensus">>,
<<"0">>,
<<"config">>, <<"parent_chain">>,
<<"start_height">>]),
H
end).
Fun = fun() -> get_consensus_config_key([<<"parent_chain">>, <<"start_height">>], 0) end,
aeu_ets_cache:get(?ETS_CACHE_TABLE, pc_start_height, Fun).

genesis_start_time() ->
aeu_ets_cache:get(
?ETS_CACHE_TABLE,
genesis_start_time,
fun() ->
case aeu_env:user_config([<<"chain">>, <<"consensus">>,
<<"0">>,
<<"config">>,
<<"genesis_start_time">>]) of
{ok, Timestamp} -> Timestamp;
undefined -> 0
end
end).

Fun = fun() -> get_consensus_config_key([<<"genesis_start_time">>], 0) end,
aeu_ets_cache:get(?ETS_CACHE_TABLE, genesis_start_time, Fun).

%% This is the contract owner, calls shall be only available via protocol
contract_owner() ->
aeu_ets_cache:get(
?ETS_CACHE_TABLE,
contract_owner,
fun() ->
{ok, EncOwner} =
aeu_env:user_config([<<"chain">>, <<"consensus">>,
<<"0">>,
<<"config">>, <<"contract_owner">>]),
{ok, Pubkey} = aeser_api_encoder:safe_decode(account_pubkey,
EncOwner),
Pubkey
end).
Fun = fun() ->
EncOwner = get_consensus_config_key([<<"contract_owner">>]),
case aeser_api_encoder:safe_decode(account_pubkey, EncOwner) of
{ok, Pubkey} -> Pubkey;
_ -> erlang:error({contract_owner_not_valid_account, EncOwner})
end
end,
aeu_ets_cache:get(?ETS_CACHE_TABLE, contract_owner, Fun).

%% TODO: do we need this in HC?
expected_key_block_rate() ->
aeu_ets_cache:get(
?ETS_CACHE_TABLE,
key_block_rate,
fun() ->
{ok, ExpectedRate} =
aeu_env:user_config([<<"chain">>, <<"consensus">>,
<<"0">>,
<<"config">>, <<"expected_key_block_rate">>]),
ExpectedRate
end).
Fun = fun() -> get_consensus_config_key([<<"expected_key_block_rate">>], 2000) end,
aeu_ets_cache:get(?ETS_CACHE_TABLE, key_block_rate, Fun).

genesis_protocol_version() ->
aeu_ets_cache:get(
Expand All @@ -524,6 +473,25 @@ genesis_protocol_version() ->
hd(lists:sort(maps:keys(aec_hard_forks:protocols())))
end).

lazy_leader_time_delta() ->
case aeu_env:user_config([<<"chain">>, <<"consensus">>, <<"0">>,
<<"config">>, <<"lazy_leader_trigger_time">>]) of
{ok, Interval} -> Interval;
undefined -> 10000
end.

get_consensus_config_key(Keys) ->
case aeu_env:user_config([<<"chain">>, <<"consensus">>, <<"0">>, <<"config">>] ++ Keys) of
{ok, Value} -> Value;
undefined -> erlang:error({missing_mandatory_chain_consensus_config_key, Keys})
end.

get_consensus_config_key(Keys, Default) ->
case aeu_env:user_config([<<"chain">>, <<"consensus">>, <<"0">>, <<"config">>] ++ Keys) of
{ok, Value} -> Value;
undefined -> Default
end.

log_consensus_call(TxEnv, FunName, EncodedCallData, Amount) ->
Height = aetx_env:height(TxEnv),
lager:debug("Height ~p, calling ~s with amount ~p aettos, encoded ~p",
Expand Down Expand Up @@ -650,14 +618,6 @@ next_beneficiary() ->
{error, not_in_cache}
end.

lazy_leader_time_delta() ->
{ok, Interval} =
aeu_env:user_config([<<"chain">>, <<"consensus">>,
<<"0">>,
<<"config">>,
<<"lazy_leader_trigger_time">>]),
Interval.

allow_lazy_leader() ->
Height = aec_chain:top_height(),
PCHeight = pc_height(Height),
Expand Down Expand Up @@ -858,4 +818,3 @@ elect_lazy_leader(Beneficiary, TxEnv, Trees) ->
{error, What} ->
aec_conductor:throw_error({failed_to_elect_new_leader, What})
end.

39 changes: 19 additions & 20 deletions apps/aecore/src/aec_parent_connector.erl
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,11 @@
-spec start_link() -> {ok, pid()} | {error, {already_started, pid()}} | {error, Reason::any()}.
start_link() ->
FetchInterval = 10000,
ParentHosts = [#{host => <<"127.0.0.1">>,
port => 3013,
user => "test",
password => "Pass"
ParentHosts = [#{host => <<"127.0.0.1">>,
port => 3013,
scheme => "http",
user => "test",
password => "Pass"
}],
ParentConnMod = aehttpc_aeternity,
start_link(ParentConnMod, FetchInterval, ParentHosts, <<"local_testnet">>,
Expand All @@ -93,7 +94,7 @@ start_link() ->
%% Start the parent connector process
%% ParentConnMod :: atom() - module name of the http client module aehttpc_btc | aehttpc_aeternity
%% FetchInterval :: integer() | on_demand - millisecs between parent chain checks or when asked (useful for test)
%% ParentHosts :: [#{host => Host, port => Port, user => User, password => Pass}]
%% ParentHosts :: [#{host => Host, port => Port, scheme => Scheme, user => User, password => Pass}]
%% NetworkID :: binary() - the parent chain's network id
%% SignModule :: atom() - module name of the module that keeps the keys for the parent chain transactions to be signed
%% HCPCPairs :: [{binary(), binary()}] - mapping from hyperchain address to child chain address
Expand Down Expand Up @@ -247,45 +248,43 @@ code_change(_OldVsn, State, _Extra) ->
%%%===================================================================
fetch_parent_tops(Mod, ParentNodes, Seed, State) ->
FetchFun =
fun(Host, Port, User, Password) ->
Mod:get_latest_block(Host, Port, User, Password, Seed)
fun(NodeSpec) ->
Mod:get_latest_block(NodeSpec, Seed)
end,
Fun = fun(Parent) -> fetch_block(FetchFun, Parent, State) end,
{Good, Errors} = aeu_lib:pmap(Fun, ParentNodes, 10000),
responses_consensus(Good, Errors, length(ParentNodes)).

fetch_block_by_hash(Hash, Mod, ParentNodes, Seed, State) ->
FetchFun =
fun(Host, Port, User, Password) ->
Mod:get_header_by_hash(Hash, Host, Port, User, Password, Seed)
fun(NodeSpec) ->
Mod:get_header_by_hash(Hash, NodeSpec, Seed)
end,
Fun = fun(Parent) -> fetch_block(FetchFun, Parent, State) end,
{Good, Errors} = aeu_lib:pmap(Fun, ParentNodes, 10000),
responses_consensus(Good, Errors, length(ParentNodes)).

fetch_block_by_height(Height, Mod, ParentNodes, Seed, State) ->
FetchFun =
fun(Host, Port, User, Password) ->
Mod:get_header_by_height(Height, Host, Port, User, Password, Seed)
fun(NodeSpec) ->
Mod:get_header_by_height(Height, NodeSpec, Seed)
end,
Fun = fun(Parent) -> fetch_block(FetchFun, Parent, State) end,
{Good, Errors} = aeu_lib:pmap(Fun, ParentNodes, 10000),
responses_consensus(Good, Errors, length(ParentNodes)).

fetch_block(FetchFun,
#{host := Host, port := Port,
user := User, password := Password} = Node,
fetch_block(FetchFun, NodeSpec,
#state{parent_conn_mod = Mod,
rpc_seed = Seed,
c_details = CDetails}) ->
#commitment_details{recipient = Receiver} = CDetails,
case FetchFun(Host, Port, User, Password) of
case FetchFun(NodeSpec) of
{ok, BlockHash, PrevHash, Height} ->
Block = aec_parent_chain_block:new(BlockHash, Height, PrevHash),
case Mod:get_commitment_tx_in_block(Host, Port, User, Password, Seed, BlockHash,
case Mod:get_commitment_tx_in_block(NodeSpec, Seed, BlockHash,
PrevHash, Receiver) of
{ok, Commitments} ->
{ok, {aec_parent_chain_block:set_commitments(Block, Commitments), Node}};
{ok, {aec_parent_chain_block:set_commitments(Block, Commitments), NodeSpec}};
{error, _} = Err ->
Err
end;
Expand Down Expand Up @@ -361,10 +360,10 @@ post_commitment(Who, Commitment,
amount = Amount,
fee = Fee} = CDetails,
Fun =
fun(#{host := Host, port := Port, user := User, password := Password} = Node) ->
case Mod:post_commitment(Host, Port, User, Password, Who, Receiver, Amount, Fee,
fun(NodeSpec) ->
case Mod:post_commitment(NodeSpec, Who, Receiver, Amount, Fee,
Commitment, PCNetworkId, SignModule) of
{ok, #{<<"tx_hash">> := TxHash}} -> {ok, {TxHash, Node}};
{ok, #{<<"tx_hash">> := TxHash}} -> {ok, {TxHash, NodeSpec}};
{error, 400, _E} ->
{error, invalid_transaction}
end
Expand Down

0 comments on commit 47ae2ad

Please sign in to comment.