Skip to content

Commit

Permalink
test: send operations to RPC node
Browse files Browse the repository at this point in the history
  • Loading branch information
Awea committed May 7, 2024
1 parent 89603ff commit 9ea898c
Show file tree
Hide file tree
Showing 5 changed files with 142 additions and 63 deletions.
6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ cover: deps $(ex_files) $(exs_files)
mix coveralls.html
touch $@

.PHONY: import-ghostnet-keys
import-ghostnet-keys:
@echo "🔑 Importing some unencrypted ghostnet keys"
$(tezos_import) tezex-ghostnet-1 unencrypted:edsk33h91RysSBUiYyEWbeRwo41YeZrtMPTNsuZ9nzsYWwiV8CFyKi -f
$(tezos_import) tezex-ghostnet-2 unencrypted:edsk3TKLtjPV4kWVGSHBvF3RumqWrtp4U2JXVyxLbTuvPeKJxz4nN3 -f

clean-all:
@echo "🗑 Clean all artifacts"
rm -rf deps _build cover doc
10 changes: 5 additions & 5 deletions lib/crypto.ex
Original file line number Diff line number Diff line change
Expand Up @@ -312,35 +312,35 @@ defmodule Tezex.Crypto do
end

@spec decode_signature(binary()) :: {:error, :invalid_signature} | {:ok, binary()}
defp decode_signature("edsig" <> _ = sig) do
def decode_signature("edsig" <> _ = sig) do
case Base58Check.decode58(sig) do
{:ok, <<@prefix_edsig, sig::binary-size(64)>> <> _} -> {:ok, sig}
_ -> {:error, :invalid_signature}
end
end

defp decode_signature("spsig" <> _ = sig) do
def decode_signature("spsig" <> _ = sig) do
case Base58Check.decode58(sig) do
{:ok, <<@prefix_spsig, sig::binary-size(64)>> <> _} -> {:ok, sig}
_ -> {:error, :invalid_signature}
end
end

defp decode_signature("p2sig" <> _ = sig) do
def decode_signature("p2sig" <> _ = sig) do
case Base58Check.decode58(sig) do
{:ok, <<@prefix_p2sig, sig::binary-size(64)>> <> _} -> {:ok, sig}
_ -> {:error, :invalid_signature}
end
end

defp decode_signature("sig" <> _ = sig) do
def decode_signature("sig" <> _ = sig) do
case Base58Check.decode58(sig) do
{:ok, <<@prefix_sig, sig::binary-size(64)>> <> _} -> {:ok, sig}
_ -> {:error, :invalid_signature}
end
end

defp decode_signature(_) do
def decode_signature(_) do
{:error, :invalid_signature}
end

Expand Down
138 changes: 80 additions & 58 deletions lib/rpc.ex
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
defmodule Tezex.Rpc do
alias Tezex.Crypto
alias Tezex.Crypto.Base58Check
alias Tezex.ForgeOperation
# alias Tezex.Crypto
# alias Tezex.Crypto.Base58Check
# alias Tezex.ForgeOperation
alias Tezex.Rpc
alias Tezex.Transaction

Expand All @@ -15,62 +15,62 @@ defmodule Tezex.Rpc do
defstruct [:endpoint, chain_id: "main", headers: [], opts: []]

# Various constants for the Tezos platforms. Fees are expressed in µtz unless otherwise noted, storage unit is bytes.
@operation_group_watermark <<3>>
# @operation_group_watermark <<3>>

@default_simple_transaction_fee 1420
@default_transaction_storage_limit 496
@default_transaction_gas_limit 10600
# @default_simple_transaction_fee 1420
# @default_transaction_storage_limit 496
# @default_transaction_gas_limit 10600

@default_delegation_fee 1258
@default_delegation_storage_limit 0
@default_delegation_gas_limit 1100
# @default_delegation_fee 1258
# @default_delegation_storage_limit 0
# @default_delegation_gas_limit 1100

@default_key_reveal_fee 1270
@default_key_reveal_storage_limit 0
@default_key_reveal_gas_limit 1100
# @default_key_reveal_fee 1270
# @default_key_reveal_storage_limit 0
# @default_key_reveal_gas_limit 1100

@p005_manager_contract_withdrawal_gas_limit 26283
@p005_manager_contract_deposit_gas_limit 15285
@p005_manager_contract_withdrawal_storage_limit 496
# @p005_manager_contract_withdrawal_gas_limit 26283
# @p005_manager_contract_deposit_gas_limit 15285
# @p005_manager_contract_withdrawal_storage_limit 496

@p001_storage_rate 1_000_000 / 1000
@p007_storage_rate 250_000 / 1000
@storage_rate @p007_storage_rate
# @p001_storage_rate 1_000_000 / 1000
# @p007_storage_rate 250_000 / 1000
# @storage_rate @p007_storage_rate

@base_operation_fee 100
# @base_operation_fee 100

@p009_block_gas_cap 10_400_000
@p010_block_gas_cap 5_200_000
@p016_block_gas_cap 2_600_000
@p007_operation_gas_cap 1_040_000
@operation_gas_cap @p007_operation_gas_cap
@block_gas_cap @p016_block_gas_cap
# @p009_block_gas_cap 10_400_000
# @p010_block_gas_cap 5_200_000
# @p016_block_gas_cap 2_600_000
# @p007_operation_gas_cap 1_040_000
# @operation_gas_cap @p007_operation_gas_cap
# @block_gas_cap @p016_block_gas_cap

@p010_operation_storage_cap 60_000
@p011_operation_storage_cap 32_768
@operation_storage_cap @p011_operation_storage_cap
# @p010_operation_storage_cap 60_000
# @p011_operation_storage_cap 32_768
# @operation_storage_cap @p011_operation_storage_cap

@empty_account_storage_burn 257
# @empty_account_storage_burn 257

@default_baker_vig 200
# @default_baker_vig 200

@gas_limit_padding 1000
@storage_limit_padding 25
# @gas_limit_padding 1000
# @storage_limit_padding 25

@head_branch_offset 54
@max_branch_offset 64
# @head_branch_offset 54
# @max_branch_offset 64

# Outbound operation queue timeout in seconds. After this period, TezosOperationQueue will attempt to submit the transactions currently in queue.
@default_batch_delay 25
# @default_batch_delay 25

@p009_block_time 60
@p010_block_time 30
@default_block_time @p010_block_time
# @p009_block_time 60
# @p010_block_time 30
# @default_block_time @p010_block_time

@genesis_block_time ~U[2018-06-30 10:07:32.000Z]
# @genesis_block_time ~U[2018-06-30 10:07:32.000Z]

def build_contract_operation(
%Rpc{} = rpc,
%Rpc{} = _rpc,
public_key_hash,
counter,
contract,
Expand All @@ -80,7 +80,7 @@ defmodule Tezex.Rpc do
gas_limit,
entrypoint,
parameters,
encoded_private_key
_encoded_private_key
) do
parameters =
cond do
Expand All @@ -102,28 +102,28 @@ defmodule Tezex.Rpc do
}
end

def send_operation(%Rpc{} = rpc, operations, encoded_private_key, offset) do
{:ok, block_head} = get_block_at_offset(rpc, offset)
block_hash = binary_part(block_head["hash"], 0, 51)
# def send_operation(%Rpc{} = rpc, operations, encoded_private_key, offset) do
# {:ok, block_head} = get_block_at_offset(rpc, offset)
# block_hash = binary_part(block_head["hash"], 0, 51)

forged_operation_group =
ForgeOperation.operation_group(%{"branch" => block_hash, "contents" => operations})
# forged_operation_group =
# ForgeOperation.operation_group(%{"branch" => block_hash, "contents" => operations})

op_signature =
Crypto.sign_message(
encoded_private_key,
@operation_group_watermark <> forged_operation_group
)
# op_signature =
# Crypto.sign_message(
# encoded_private_key,
# @operation_group_watermark <> forged_operation_group
# )

signed_op_group = forged_operation_group <> op_signature
# signed_op_group = forged_operation_group <> op_signature

op_pair = %{bytes: signed_op_group, signature: op_signature}
# op_pair = %{bytes: signed_op_group, signature: op_signature}

# applied = preapply_operation(rpc, block_hash, block_head["protocol"], operations, op_pair)
# injected_op = inject_operation(rpc, op_pair)
# # applied = preapply_operation(rpc, block_hash, block_head["protocol"], operations, op_pair)
# # injected_op = inject_operation(rpc, op_pair)

# %{results: applied[0], operation_group_id: injected_op = inject_operation(rpc, op_pair)}
end
# # %{results: applied[0], operation_group_id: injected_op = inject_operation(rpc, op_pair)}
# end

def get_counter_for_account(%Rpc{} = rpc, address) do
with {:ok, n} <- get(rpc, "/blocks/head/context/contracts/#{address}/counter"),
Expand All @@ -149,6 +149,10 @@ defmodule Tezex.Rpc do
get(rpc, "/blocks/#{head["header"]["level"] - offset}")
end

def inject_operation(%Rpc{} = rpc, forged_operation, signature) do
post(rpc, "/injection/operation", forged_operation <> signature)
end

def get(%Rpc{} = rpc, path) do
url =
URI.parse(rpc.endpoint)
Expand All @@ -163,4 +167,22 @@ defmodule Tezex.Rpc do
{:error, _} = err -> err
end
end

def post(%Rpc{} = rpc, path, body) do
url =
URI.parse(rpc.endpoint)
# 🚧 Try to reproduce the same API as the rest of this file but it doesn't make sense for the injection endpoint since it doesn't include the /chains/id
# |> URI.append_path("/chains/#{rpc.chain_id}")
|> URI.append_path(path)
|> URI.to_string()

body = Jason.encode!(body)

Finch.build(:post, url, rpc.headers, body)
|> Finch.request(Tezex.Finch, rpc.opts)
|> case do
{:ok, %Finch.Response{status: 200, body: body}} -> Jason.decode(body)
{:error, _} = err -> err
end
end
end
2 changes: 2 additions & 0 deletions test/test_helper.exs
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
ExUnit.configure(exclude: [:tezos])

ExUnit.start()
49 changes: 49 additions & 0 deletions test/tezex_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
defmodule Tezex.TezexTest do
use ExUnit.Case, async: false

alias Tezex.ForgeOperation
alias Tezex.Rpc
alias Tezex.Crypto

doctest Tezex.Rpc

@wallet_address "tz1ZW1ZSN4ruXYc3nCon8EaTXp1t3tKWb9Ew"
@wallet_private_key "edsk33h91RysSBUiYyEWbeRwo41YeZrtMPTNsuZ9nzsYWwiV8CFyKi"

@endpoint "https://ghostnet.tezos.marigold.dev/"

@tag :tezos
test "inject an operation" do
rpc = %Rpc{endpoint: @endpoint}

{:ok, block_head} = Rpc.get_block_at_offset(rpc, 0)
branch = binary_part(block_head["hash"], 0, 51)

counter = Rpc.get_next_counter_for_account(rpc, @wallet_address)

operation = %{
"branch" => branch,
"contents" => [
%{
"amount" => "100",
"counter" => Integer.to_string(counter),
"destination" => "tz1cMcDFLgFe2picQbo4DY1i6mZJiVhPCu5B",
"fee" => "349",
"gas_limit" => "186",
"kind" => "transaction",
"source" => @wallet_address,
"storage_limit" => "0"
}
]
}

forged_operation = ForgeOperation.operation_group(operation)

signature = Crypto.sign_operation(@wallet_private_key, forged_operation)
{:ok, decoded_signature} = Crypto.decode_signature(signature)

decoded_signature = Base.encode16(decoded_signature, case: :lower)

assert {:ok, operation_id} = Rpc.inject_operation(rpc, forged_operation, decoded_signature)
end
end

0 comments on commit 9ea898c

Please sign in to comment.