Skip to content

Commit

Permalink
Leverage sharded origin keys
Browse files Browse the repository at this point in the history
  • Loading branch information
Neylix committed Apr 26, 2022
1 parent 53278d4 commit cdeb4e2
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 23 deletions.
36 changes: 36 additions & 0 deletions lib/archethic/bootstrap/network_init.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ defmodule ArchEthic.Bootstrap.NetworkInit do
"""

alias ArchEthic.Bootstrap
alias ArchEthic.Bootstrap.NetworkInit

alias ArchEthic.BeaconChain.ReplicationAttestation

Expand All @@ -31,13 +32,19 @@ defmodule ArchEthic.Bootstrap.NetworkInit do
alias ArchEthic.TransactionChain.TransactionData.Ledger
alias ArchEthic.TransactionChain.TransactionData.UCOLedger
alias ArchEthic.TransactionChain.TransactionData.UCOLedger.Transfer
alias ArchEthic.TransactionChain.TransactionData.Ownership

alias ArchEthic.TransactionChain.TransactionSummary

require Logger

@genesis_seed Application.compile_env(:archethic, [__MODULE__, :genesis_seed])

@genesis_origin_public_keys Application.compile_env!(
:archethic,
[NetworkInit, :genesis_origin_public_keys]
)

defp get_genesis_pools do
Application.get_env(:archethic, __MODULE__) |> Keyword.get(:genesis_pools, [])
end
Expand Down Expand Up @@ -74,6 +81,35 @@ defmodule ArchEthic.Bootstrap.NetworkInit do
|> self_replication()
end

@doc """
Create the first origin shared secret transaction
"""
@spec init_software_origin_shared_secrets_chain() :: :ok
def init_software_origin_shared_secrets_chain do
Logger.info("Create first software origin shared secret transaction")

origin_seed = :crypto.strong_rand_bytes(32)
secret_key = :crypto.strong_rand_bytes(32)
signing_seed = Crypto.storage_nonce() <> "software"

# Default keypair generation creates software public key
{origin_public_key, origin_private_key} = Crypto.generate_deterministic_keypair(origin_seed)

Transaction.new(
:origin_shared_secrets,
%TransactionData{
content: <<origin_public_key::binary>>,
ownerships: [
Ownership.new(origin_private_key, secret_key, @genesis_origin_public_keys)
]
},
signing_seed,
0
)
|> self_validation()
|> self_replication()
end

@doc """
Initializes the genesis wallets for the UCO distribution
"""
Expand Down
1 change: 1 addition & 0 deletions lib/archethic/bootstrap/sync.ex
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ defmodule ArchEthic.Bootstrap.Sync do
P2P.set_node_globally_available(Crypto.first_node_public_key())
P2P.authorize_node(Crypto.last_node_public_key(), DateTime.utc_now())

NetworkInit.init_software_origin_shared_secrets_chain()
NetworkInit.init_node_shared_secrets_chain()
NetworkInit.init_genesis_wallets()
end
Expand Down
24 changes: 1 addition & 23 deletions lib/archethic/shared_secrets/mem_tables/origin_key_lookup.ex
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,13 @@ defmodule ArchEthic.SharedSecrets.MemTables.OriginKeyLookup do

alias ArchEthic.Crypto

alias ArchEthic.Bootstrap.NetworkInit

alias ArchEthic.SharedSecrets

require Logger

@origin_key_table :archethic_origin_keys
@origin_key_by_type_table :archethic_origin_key_by_type

@genesis_origin_public_keys Application.compile_env!(
:archethic,
[NetworkInit, :genesis_origin_public_keys]
)
@doc """
Initialize memory tables to index public information from the shared secrets
Expand All @@ -39,10 +33,6 @@ defmodule ArchEthic.SharedSecrets.MemTables.OriginKeyLookup do
:ets.new(@origin_key_by_type_table, [:bag, :named_table, :public, read_concurrency: true])
:ets.new(@origin_key_table, [:set, :named_table, :public, read_concurrency: true])

Enum.each(@genesis_origin_public_keys, fn key ->
add_public_key(:software, key)
end)

{:ok, []}
end

Expand All @@ -60,21 +50,13 @@ defmodule ArchEthic.SharedSecrets.MemTables.OriginKeyLookup do
iex> { :ets.tab2list(:archethic_origin_keys), :ets.tab2list(:archethic_origin_key_by_type) }
{
[
{<<1, 0, 4, 171, 65, 41, 31, 132, 122, 96, 16, 85, 174, 221, 26, 242, 79, 247,
111, 169, 112, 214, 68, 30, 45, 202, 56, 24, 168, 49, 155, 0, 76, 150, 178,
123, 143, 235, 29, 163, 26, 4, 75, 160, 164, 128, 11, 67, 83, 53, 151, 53,
113, 158, 187, 58, 5, 249, 131, 147, 169, 204, 89, 156, 63, 175, 214>>, :software},
{"key1", :software},
{"key3", :hardware},
{"key2", :hardware}
],
[
{:hardware, "key2"},
{:hardware, "key3"},
{:software, <<1, 0, 4, 171, 65, 41, 31, 132, 122, 96, 16, 85, 174, 221, 26, 242, 79, 247,
111, 169, 112, 214, 68, 30, 45, 202, 56, 24, 168, 49, 155, 0, 76, 150, 178,
123, 143, 235, 29, 163, 26, 4, 75, 160, 164, 128, 11, 67, 83, 53, 151, 53,
113, 158, 187, 58, 5, 249, 131, 147, 169, 204, 89, 156, 63, 175, 214>>},
{:software, "key1"}
],
}
Expand Down Expand Up @@ -118,11 +100,7 @@ defmodule ArchEthic.SharedSecrets.MemTables.OriginKeyLookup do
iex> :ok = OriginKeyLookup.add_public_key(:hardware, "key3")
iex> OriginKeyLookup.list_public_keys()
[
<<1, 0, 4, 171, 65, 41, 31, 132, 122, 96, 16, 85, 174, 221, 26, 242, 79, 247,
111, 169, 112, 214, 68, 30, 45, 202, 56, 24, 168, 49, 155, 0, 76, 150, 178,
123, 143, 235, 29, 163, 26, 4, 75, 160, 164, 128, 11, 67, 83, 53, 151, 53,
113, 158, 187, 58, 5, 249, 131, 147, 169, 204, 89, 156, 63, 175, 214>>,
"key1",
"key1",
"key3",
"key2"
]
Expand Down
66 changes: 66 additions & 0 deletions test/archethic/bootstrap/network_init_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,18 @@ defmodule ArchEthic.Bootstrap.NetworkInitTest do

alias ArchEthic.TransactionChain.Transaction.ValidationStamp.LedgerOperations.UnspentOutput
alias ArchEthic.TransactionChain.TransactionData
alias ArchEthic.TransactionChain.TransactionData.Ownership
alias ArchEthic.TransactionChain.TransactionData.Ledger
alias ArchEthic.TransactionChain.TransactionData.UCOLedger
alias ArchEthic.TransactionChain.TransactionData.UCOLedger.Transfer
alias ArchEthic.TransactionChain.TransactionSummary
alias ArchEthic.TransactionFactory

@genesis_origin_public_keys Application.compile_env!(
:archethic,
[NetworkInit, :genesis_origin_public_keys]
)

import Mox

setup do
Expand Down Expand Up @@ -267,4 +273,64 @@ defmodule ArchEthic.Bootstrap.NetworkInitTest do
assert %{uco: 146_000_000_000_000_000} =
Account.get_balance(SharedSecrets.get_network_pool_address())
end

test "init_software_origin_shared_secrets_chain/1 should create first origin shared secret transaction" do
MockClient
|> stub(:send_message, fn
_, %GetTransaction{}, _ ->
{:ok, %NotFound{}}

_, %GetTransactionChain{}, _ ->
{:ok, %TransactionList{transactions: [], more?: false, paging_state: nil}}

_, %GetUnspentOutputs{}, _ ->
{:ok, %UnspentOutputList{unspent_outputs: []}}

_, %GetLastTransactionAddress{address: address}, _ ->
{:ok, %LastTransactionAddress{address: address}}
end)

me = self()

MockDB
|> expect(:write_transaction, fn tx ->
send(me, {:transaction, tx})
:ok
end)

P2P.add_and_connect_node(%Node{
first_public_key: Crypto.last_node_public_key(),
last_public_key: Crypto.last_node_public_key(),
ip: {127, 0, 0, 1},
port: 3000,
available?: true,
enrollment_date: DateTime.utc_now(),
network_patch: "AAA",
authorization_date: DateTime.utc_now(),
authorized?: true,
reward_address: <<0::8, :crypto.strong_rand_bytes(32)::binary>>
})

Crypto.generate_deterministic_keypair("daily_nonce_seed")
|> elem(0)
|> NetworkLookup.set_daily_nonce_public_key(DateTime.utc_now() |> DateTime.add(-10))

assert :ok = NetworkInit.init_software_origin_shared_secrets_chain()

assert 1 == SharedSecrets.list_origin_public_keys() |> Enum.count()

assert_receive {:transaction,
%Transaction{
type: :origin_shared_secrets,
data: %TransactionData{
ownerships: [
%Ownership{
authorized_keys: authorized_keys
}
]
}
}}

assert Map.keys(authorized_keys) == @genesis_origin_public_keys
end
end
3 changes: 3 additions & 0 deletions test/archethic/bootstrap/sync_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ defmodule ArchEthic.Bootstrap.SyncTest do
alias ArchEthic.P2P.Message.UnspentOutputList
alias ArchEthic.P2P.Node

alias ArchEthic.SharedSecrets
alias ArchEthic.SharedSecrets.NodeRenewalScheduler

alias ArchEthic.TransactionChain
Expand Down Expand Up @@ -271,6 +272,8 @@ defmodule ArchEthic.Bootstrap.SyncTest do
assert %Node{authorized?: true} = P2P.get_node_info()
assert 1 == Crypto.number_of_node_shared_secrets_keys()

assert 2 == SharedSecrets.list_origin_public_keys() |> Enum.count()

Application.get_env(:archethic, ArchEthic.Bootstrap.NetworkInit)[:genesis_pools]
|> Enum.each(fn %{address: address, amount: amount} ->
assert %{uco: amount, nft: %{}} == Account.get_balance(address)
Expand Down
3 changes: 3 additions & 0 deletions test/archethic/bootstrap_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ defmodule ArchEthic.BootstrapTest do

alias ArchEthic.SelfRepair.Scheduler, as: SelfRepairScheduler

alias ArchEthic.SharedSecrets
alias ArchEthic.SharedSecrets.NodeRenewalScheduler

alias ArchEthic.TransactionChain
Expand Down Expand Up @@ -133,6 +134,8 @@ defmodule ArchEthic.BootstrapTest do
P2P.list_nodes()

assert 1 == Crypto.number_of_node_shared_secrets_keys()

assert 2 == SharedSecrets.list_origin_public_keys() |> Enum.count()
end
end

Expand Down

0 comments on commit cdeb4e2

Please sign in to comment.