Current section
3 Versions
Jump to
Current section
3 Versions
Compare versions
43
files changed
+2899
additions
-1718
deletions
| @@ -0,0 +1,5 @@ | |
| 1 | + # Used by "mix format" |
| 2 | + [ |
| 3 | + inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"], |
| 4 | + line_length: 120 |
| 5 | + ] |
| @@ -0,0 +1,13 @@ | |
| 1 | + .PHONY: test |
| 2 | + |
| 3 | + test: |
| 4 | + mix test |
| 5 | + |
| 6 | + logs: |
| 7 | + docker-compose logs -f |
| 8 | + up: |
| 9 | + docker-compose up -d |
| 10 | + up-mocks: |
| 11 | + docker-compose -f docker-compose.yml -f docker-compose.conformance.yml up -d ganache mock-contracts |
| 12 | + down: |
| 13 | + docker-compose down |
| @@ -1,10 +1,7 @@ | |
| 1 | - [](https://coveralls.io/github/omisego/ex_plasma?branch=master) |
| 1 | + ## ExPlasma |
| 2 | + [](https://circleci.com/gh/omgnetwork/ex_plasma) |
| 2 3 | |
| 3 | - # ExPlasma |
| 4 | - |
| 5 | - **TODO: Add description** |
| 6 | - |
| 7 | - (ExPlasma)[] is an elixir client library to interact with the OmiseGO Plasma contracts. |
| 4 | + ExPlasma is an Elixir library for encoding, decoding and validating transactions used for the OMG Network Plasma contracts. |
| 8 5 | |
| 9 6 | ## Installation |
| 10 7 | |
| @@ -14,7 +11,7 @@ by adding `ex_plasma` to your list of dependencies in `mix.exs`: | |
| 14 11 | ```elixir |
| 15 12 | def deps do |
| 16 13 | [ |
| 17 | - {:ex_plasma, "~> 0.1.0"} |
| 14 | + {:ex_plasma, "~> 0.2.0"} |
| 18 15 | ] |
| 19 16 | end |
| 20 17 | ``` |
| @@ -23,31 +20,125 @@ You will also need to specify some configurations in your [config/config.exs](): | |
| 23 20 | |
| 24 21 | ```elixir |
| 25 22 | config :ex_plasma, |
| 26 | - authority_address: "0x22d491bde2303f2f43325b2108d26f1eaba1e32b", |
| 27 | - contract_address: "0xd17e1233a03affb9092d5109179b43d6a8828607", |
| 28 | - eth_vault_address: "0x1967d06b1faba91eaadb1be33b277447ea24fa0e", |
| 29 | - exit_game_address: "0x902719f192aa5240632f704aa7a94bab61b86550", |
| 30 | - gas: 1_000_000, |
| 31 | - gas_price: 1_000_000, |
| 32 | - standard_exit_bond_size: 14_000_000_000_000_000, |
| 33 | - eip_712_domain: [ |
| 34 | - name: "ExPlasma", |
| 35 | - salt: "some-salt", |
| 36 | - verifying_contract: "contract_address", |
| 23 | + eip_712_domain: %{ |
| 24 | + name: "OMG Network", |
| 25 | + salt: "0xfad5c7f626d80f9256ef01929f3beb96e058b8b4b0e3fe52d84f054c0e2a7a83", |
| 26 | + verifying_contract: "0xd17e1233a03affb9092d5109179b43d6a8828607", |
| 37 27 | version: "1" |
| 38 | - ] |
| 28 | + } |
| 39 29 | ``` |
| 40 30 | |
| 41 | - ## Setup (Mac OS) |
| 31 | + ## Setup |
| 42 32 | |
| 43 | - 1. Clone the repo to your desktop `git@github.com:omisego/ex_plasma.git` |
| 33 | + `ExPlasma` requires Rust to be installed because it uses Rust NIFs for keccak hash and secp256k1. |
| 34 | + |
| 35 | + 1. Clone the repo to your desktop `git@github.com:omgnetwork/ex_plasma.git` |
| 44 36 | 2. Run `mix compile` in your terminal. |
| 45 37 | 3. If there are any unavailable dependencies, run `mix deps.get`. |
| 46 | - *If you run into any issues with* ***libsecp256k1_source***, *run* `brew install automake pkg-config libtool libffi gmp` *in your terminal.* |
| 38 | + |
| 39 | + ## Usage |
| 40 | + |
| 41 | + To build a transaction use `ExPlasma.Builder` module: |
| 42 | + |
| 43 | + ``` elixir |
| 44 | + {:ok, txn} = |
| 45 | + ExPlasma.payment_v1() |
| 46 | + |> ExPlasma.Builder.new() |
| 47 | + |> ExPlasma.Builder.add_input(blknum: 1, txindex: 0, oindex: 0) |
| 48 | + |> ExPlasma.Builder.add_output(output_type: 1, output_data: %{output_guard: <<1::160>>, token: <<0::160>>, amount: 1}) |
| 49 | + |> ExPlasma.Builder.sign(["0x79298b0292bbfa9b15705c56b6133201c62b798f102d7d096d31d7637f9b2382"]) |
| 50 | + {:ok, |
| 51 | + %ExPlasma.Transaction{ |
| 52 | + inputs: [ |
| 53 | + %ExPlasma.Output{ |
| 54 | + output_data: nil, |
| 55 | + output_id: %{blknum: 1, oindex: 0, txindex: 0}, |
| 56 | + output_type: nil |
| 57 | + } |
| 58 | + ], |
| 59 | + metadata: <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 60 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0>>, |
| 61 | + nonce: nil, |
| 62 | + outputs: [ |
| 63 | + %ExPlasma.Output{ |
| 64 | + output_data: %{ |
| 65 | + amount: 1, |
| 66 | + output_guard: <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 67 | + 0, 1>>, |
| 68 | + token: <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0>> |
| 69 | + }, |
| 70 | + output_id: nil, |
| 71 | + output_type: 1 |
| 72 | + } |
| 73 | + ], |
| 74 | + sigs: [ |
| 75 | + <<236, 177, 165, 5, 109, 208, 210, 116, 68, 176, 199, 17, 168, 29, 30, 198, |
| 76 | + 77, 45, 233, 147, 149, 38, 93, 136, 24, 98, 53, 218, 52, 177, 200, 127, |
| 77 | + 26, 6, 138, 17, 36, 52, 97, 152, 240, 222, ...>> |
| 78 | + ], |
| 79 | + tx_data: 0, |
| 80 | + tx_type: 1, |
| 81 | + witnesses: [] |
| 82 | + }} |
| 83 | + ``` |
| 84 | + |
| 85 | + You can encode a transaction using `ExPlasma.encode/2`: |
| 86 | + |
| 87 | + ``` elixir |
| 88 | + {:ok, rlp} = ExPlasma.encode(txn, signed: false) |
| 89 | + {:ok, |
| 90 | + <<248, 116, 1, 225, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 91 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 154, 202, 0, 238, 237, 1, 235, 148, 0, 0, |
| 92 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 148, 0, 0, 0, 0, 0, 0, |
| 93 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 128, 160, 0, 0, 0, 0, 0, 0, 0, |
| 94 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0>>} |
| 95 | + ``` |
| 96 | + |
| 97 | + You can decode a transaction using `ExPlasma.decode/2`: |
| 98 | + |
| 99 | + ``` elixir |
| 100 | + {:ok, txn} = ExPlasma.decode(rlp, signed: false) |
| 101 | + {:ok, |
| 102 | + %ExPlasma.Transaction{ |
| 103 | + inputs: [ |
| 104 | + %ExPlasma.Output{ |
| 105 | + output_data: nil, |
| 106 | + output_id: %{blknum: 1, oindex: 0, position: 1000000000, txindex: 0}, |
| 107 | + output_type: nil |
| 108 | + } |
| 109 | + ], |
| 110 | + metadata: <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 111 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0>>, |
| 112 | + nonce: nil, |
| 113 | + outputs: [ |
| 114 | + %ExPlasma.Output{ |
| 115 | + output_data: %{ |
| 116 | + amount: 1, |
| 117 | + output_guard: <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 118 | + 0, 1>>, |
| 119 | + token: <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0>> |
| 120 | + }, |
| 121 | + output_id: nil, |
| 122 | + output_type: 1 |
| 123 | + } |
| 124 | + ], |
| 125 | + sigs: [], |
| 126 | + tx_data: 0, |
| 127 | + tx_type: 1, |
| 128 | + witnesses: [] |
| 129 | + }} |
| 130 | + ``` |
| 131 | + |
| 132 | + You can validate a transaction using `ExPlasma.validate/1`: |
| 133 | + |
| 134 | + ``` elixir |
| 135 | + ExPlasma.validate(txn) |
| 136 | + ``` |
| 137 | + |
| 138 | + View the [documentation](https://hexdocs.pm/ex_plasma) |
| 47 139 | |
| 48 140 | ## Testing |
| 49 141 | |
| 50 | - |
| 51 142 | You can run the tests by running; |
| 52 143 | |
| 53 144 | ```sh |
| @@ -56,21 +147,6 @@ mix credo | |
| 56 147 | mix dialyzer |
| 57 148 | ``` |
| 58 149 | |
| 59 | - ### exvcr |
| 60 | - |
| 61 | - The test suite has network requests recorded by [exvcr](). To record new cassettes, spin up docker: |
| 62 | - |
| 63 | - ```sh |
| 64 | - docker-compose up |
| 65 | - ``` |
| 66 | - |
| 67 | - Or alternatively, you can use the make command to spin up a detached docker compose. |
| 68 | - |
| 69 | - ```sh |
| 70 | - make up # docker-compose detached |
| 71 | - make logs # connects to logs from docker-compose |
| 72 | - ``` |
| 73 | - |
| 74 150 | This will load up Ganche and the plasma contracts to deploy. |
| 75 151 | |
| 76 152 | |
| @@ -86,18 +162,14 @@ mix test --only conformance | |
| 86 162 | |
| 87 163 | This will spin up ganache and deploy the mock contracts. |
| 88 164 | |
| 89 | - ### Integration test |
| 165 | + ## Contributing |
| 90 166 | |
| 91 | - We also have more integrated flows we need to test, such as the exit game. These use live interactions with |
| 92 | - the plasma framework contracts. To run those, you can execute: |
| 167 | + 1. [Fork it!](https://github.com/omgnetwork/ex_plasma) |
| 168 | + 2. Create your feature branch (`git checkout -b my-new-feature`) |
| 169 | + 3. Commit your changes (`git commit -am 'Add some feature'`) |
| 170 | + 4. Push to the branch (`git push origin my-new-feature`) |
| 171 | + 5. Create new Pull Request |
| 93 172 | |
| 94 | - ```sh |
| 95 | - make up |
| 96 | - mix test --only integration |
| 97 | - ``` |
| 173 | + ## License |
| 98 174 | |
| 99 | - This will spin up ganache and deploy the plasma framework and run the integration suite. |
| 100 | - |
| 101 | - Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc) |
| 102 | - and published on [HexDocs](https://hexdocs.pm). Once published, the docs can |
| 103 | - be found at [https://hexdocs.pm/ex_plasma](https://hexdocs.pm/ex_plasma). |
| 175 | + ExPlasma is released under the Apache-2.0 License. |
| @@ -1,58 +1,69 @@ | |
| 1 1 | {<<"app">>,<<"ex_plasma">>}. |
| 2 | - {<<"build_tools">>,[<<"mix">>]}. |
| 2 | + {<<"build_tools">>,[<<"mix">>,<<"make">>]}. |
| 3 3 | {<<"description">>, |
| 4 | - <<"Elixir client library to the OmiseGO Plasma Framework">>}. |
| 4 | + <<"A library for encoding, decoding and validating transactions used for the OMG Network Plasma contracts.">>}. |
| 5 5 | {<<"elixir">>,<<"~> 1.8">>}. |
| 6 6 | {<<"files">>, |
| 7 | - [<<"lib">>,<<"lib/ex_plasma.ex">>,<<"lib/ex_plasma">>, |
| 8 | - <<"lib/ex_plasma/transaction.ex">>,<<"lib/ex_plasma/typed_data">>, |
| 9 | - <<"lib/ex_plasma/typed_data/utxo.ex">>, |
| 10 | - <<"lib/ex_plasma/typed_data/transactions.ex">>,<<"lib/ex_plasma/utxo">>, |
| 11 | - <<"lib/ex_plasma/block.ex">>,<<"lib/ex_plasma/transaction">>, |
| 12 | - <<"lib/ex_plasma/transaction/payment.ex">>, |
| 13 | - <<"lib/ex_plasma/transaction/deposit.ex">>,<<"lib/ex_plasma/client.ex">>, |
| 14 | - <<"lib/ex_plasma/typed_data.ex">>,<<"lib/ex_plasma/utxo.ex">>, |
| 15 | - <<"lib/ex_plasma/encoding.ex">>,<<"lib/ex_plasma/client">>, |
| 16 | - <<"lib/ex_plasma/client/config.ex">>,<<"lib/ex_plasma/client/event.ex">>, |
| 17 | - <<"lib/ex_plasma/client/state.ex">>,<<"mix.exs">>,<<"README.md">>, |
| 18 | - <<"LICENSE">>]}. |
| 19 | - {<<"licenses">>,[<<"Apache-2.0">>]}. |
| 20 | - {<<"links">>,[{<<"GitHub">>,<<"https://github.com/omisego/ex_plasma">>}]}. |
| 7 | + [<<"lib">>,<<"lib/ex_plasma">>,<<"lib/ex_plasma/in_flight_exit.ex">>, |
| 8 | + <<"lib/ex_plasma/typed_data">>, |
| 9 | + <<"lib/ex_plasma/typed_data/transaction.ex">>, |
| 10 | + <<"lib/ex_plasma/typed_data/output.ex">>,<<"lib/ex_plasma/signature.ex">>, |
| 11 | + <<"lib/ex_plasma/configuration.ex">>,<<"lib/ex_plasma/encoding.ex">>, |
| 12 | + <<"lib/ex_plasma/transaction.ex">>,<<"lib/ex_plasma/output">>, |
| 13 | + <<"lib/ex_plasma/output/position.ex">>,<<"lib/ex_plasma/output/position">>, |
| 14 | + <<"lib/ex_plasma/output/position/position_validator.ex">>, |
| 15 | + <<"lib/ex_plasma/output/type">>, |
| 16 | + <<"lib/ex_plasma/output/type/payment_v1.ex">>, |
| 17 | + <<"lib/ex_plasma/output/type/abstract_payment.ex">>, |
| 18 | + <<"lib/ex_plasma/output/type/empty.ex">>, |
| 19 | + <<"lib/ex_plasma/output/type/abstract_payment">>, |
| 20 | + <<"lib/ex_plasma/output/type/abstract_payment/abstract_payment_validator.ex">>, |
| 21 | + <<"lib/ex_plasma/output/type/fee.ex">>,<<"lib/ex_plasma/builder.ex">>, |
| 22 | + <<"lib/ex_plasma/utils">>,<<"lib/ex_plasma/utils/rlp_decoder.ex">>, |
| 23 | + <<"lib/ex_plasma/typed_data.ex">>,<<"lib/ex_plasma/output.ex">>, |
| 24 | + <<"lib/ex_plasma/configuration">>, |
| 25 | + <<"lib/ex_plasma/configuration/validator.ex">>,<<"lib/ex_plasma/block.ex">>, |
| 26 | + <<"lib/ex_plasma/crypto.ex">>,<<"lib/ex_plasma/merkle.ex">>, |
| 27 | + <<"lib/ex_plasma/transaction">>, |
| 28 | + <<"lib/ex_plasma/transaction/type_mapper.ex">>, |
| 29 | + <<"lib/ex_plasma/transaction/type">>, |
| 30 | + <<"lib/ex_plasma/transaction/type/payment_v1.ex">>, |
| 31 | + <<"lib/ex_plasma/transaction/type/fee">>, |
| 32 | + <<"lib/ex_plasma/transaction/type/fee/fee_validator.ex">>, |
| 33 | + <<"lib/ex_plasma/transaction/type/payment_v1">>, |
| 34 | + <<"lib/ex_plasma/transaction/type/payment_v1/payment_v1_validator.ex">>, |
| 35 | + <<"lib/ex_plasma/transaction/type/fee.ex">>, |
| 36 | + <<"lib/ex_plasma/transaction/witness.ex">>, |
| 37 | + <<"lib/ex_plasma/transaction/signed.ex">>,<<"lib/ex_plasma.ex">>, |
| 38 | + <<".formatter.exs">>,<<"mix.exs">>,<<"README.md">>,<<"LICENSE">>, |
| 39 | + <<"Makefile">>]}. |
| 40 | + {<<"licenses">>,[<<"Apache-2.0 License">>]}. |
| 41 | + {<<"links">>,[{<<"GitHub">>,<<"https://github.com/omgnetwork/ex_plasma">>}]}. |
| 21 42 | {<<"name">>,<<"ex_plasma">>}. |
| 22 43 | {<<"requirements">>, |
| 23 | - [[{<<"app">>,<<"ethereumex">>}, |
| 24 | - {<<"name">>,<<"ethereumex">>}, |
| 25 | - {<<"optional">>,false}, |
| 26 | - {<<"repository">>,<<"hexpm">>}, |
| 27 | - {<<"requirement">>,<<"~> 0.5.5">>}], |
| 28 | - [{<<"app">>,<<"ex_abi">>}, |
| 44 | + [[{<<"app">>,<<"ex_abi">>}, |
| 29 45 | {<<"name">>,<<"ex_abi">>}, |
| 30 46 | {<<"optional">>,false}, |
| 31 47 | {<<"repository">>,<<"hexpm">>}, |
| 32 | - {<<"requirement">>,<<"~> 0.1.0">>}], |
| 48 | + {<<"requirement">>,<<"~> 0.5.1">>}], |
| 33 49 | [{<<"app">>,<<"ex_rlp">>}, |
| 34 50 | {<<"name">>,<<"ex_rlp">>}, |
| 35 51 | {<<"optional">>,false}, |
| 36 52 | {<<"repository">>,<<"hexpm">>}, |
| 37 | - {<<"requirement">>,<<"~> 0.5.2">>}], |
| 38 | - [{<<"app">>,<<"exth_crypto">>}, |
| 39 | - {<<"name">>,<<"exth_crypto">>}, |
| 53 | + {<<"requirement">>,<<"~> 0.5.3">>}], |
| 54 | + [{<<"app">>,<<"ex_keccak">>}, |
| 55 | + {<<"name">>,<<"ex_keccak">>}, |
| 40 56 | {<<"optional">>,false}, |
| 41 57 | {<<"repository">>,<<"hexpm">>}, |
| 42 | - {<<"requirement">>,<<"~> 0.1.0">>}], |
| 43 | - [{<<"app">>,<<"libsecp256k1">>}, |
| 44 | - {<<"name">>,<<"libsecp256k1">>}, |
| 58 | + {<<"requirement">>,<<"~> 0.1.2">>}], |
| 59 | + [{<<"app">>,<<"ex_secp256k1">>}, |
| 60 | + {<<"name">>,<<"ex_secp256k1">>}, |
| 45 61 | {<<"optional">>,false}, |
| 46 62 | {<<"repository">>,<<"hexpm">>}, |
| 47 | - {<<"requirement">>,<<"~> 0.1.0">>}], |
| 63 | + {<<"requirement">>,<<"~> 0.1.1">>}], |
| 48 64 | [{<<"app">>,<<"merkle_tree">>}, |
| 49 65 | {<<"name">>,<<"merkle_tree">>}, |
| 50 66 | {<<"optional">>,false}, |
| 51 67 | {<<"repository">>,<<"hexpm">>}, |
| 52 | - {<<"requirement">>,<<"~> 1.6.1">>}], |
| 53 | - [{<<"app">>,<<"ex_doc">>}, |
| 54 | - {<<"name">>,<<"ex_doc">>}, |
| 55 | - {<<"optional">>,false}, |
| 56 | - {<<"repository">>,<<"hexpm">>}, |
| 57 | - {<<"requirement">>,<<">= 0.0.0">>}]]}. |
| 58 | - {<<"version">>,<<"0.1.0">>}. |
| 68 | + {<<"requirement">>,<<"~> 2.0.0">>}]]}. |
| 69 | + {<<"version">>,<<"0.2.0">>}. |
| @@ -4,141 +4,168 @@ defmodule ExPlasma do | |
| 4 4 | """ |
| 5 5 | |
| 6 6 | alias ExPlasma.Transaction |
| 7 | - alias ExPlasma.Utxo |
| 7 | + alias ExPlasma.Transaction.TypeMapper |
| 8 | + |
| 9 | + # constants that identify payment types, make sure that |
| 10 | + # when we introduce a new payment type, you name it `paymentV2` |
| 11 | + # https://github.com/omisego/plasma-contracts/blob/6ab35256b805e25cfc30d85f95f0616415220b20/plasma_framework/docs/design/tx-types-dependencies.md |
| 12 | + @payment_v1 TypeMapper.tx_type_for(:tx_payment_v1) |
| 13 | + @fee TypeMapper.tx_type_for(:tx_fee_token_claim) |
| 14 | + |
| 15 | + @type transaction_type :: non_neg_integer() |
| 8 16 | |
| 9 17 | @doc """ |
| 18 | + Simple payment type V1 |
| 10 19 | |
| 11 | - Produces a RLP encoded transaction bytes for the given transaction data. |
| 20 | + ## Example |
| 12 21 | |
| 13 | - ## Examples |
| 14 | - |
| 15 | - # Encode a transaction |
| 16 | - iex> {:ok, txn} = ExPlasma.Transaction.Payment.new(%{inputs: [], outputs: []}) |
| 17 | - iex> ExPlasma.encode(txn) |
| 18 | - <<229, 1, 192, 192, 128, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 19 | - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0>> |
| 20 | - |
| 21 | - # Encode a transaction rlp |
| 22 | - iex> rlp = [1, [], [], 0, <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0>>] |
| 23 | - iex> ExPlasma.encode(rlp) |
| 24 | - <<217, 128, 192, 192, 128, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 25 | - 0, 0, 0, 0>> |
| 26 | - |
| 27 | - Encode a signed transaction |
| 28 | - iex> {:ok, txn} = ExPlasma.Transaction.Payment.new(%{inputs: [], outputs: [], sigs: []}) |
| 29 | - iex> ExPlasma.encode(txn) |
| 30 | - <<229, 1, 192, 192, 128, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 31 | - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0>> |
| 22 | + iex> ExPlasma.payment_v1() |
| 23 | + 1 |
| 32 24 | """ |
| 33 | - @spec encode(Transaction.t() | Transaction.rlp()) :: <<_::632>> |
| 34 | - def encode(txn) when is_map(txn), do: Transaction.encode(txn) |
| 35 | - |
| 36 | - def encode(txn) when is_list(txn) do |
| 37 | - with {:ok, transaction} <- Transaction.new(txn), do: Transaction.encode(transaction) |
| 38 | - end |
| 25 | + @spec payment_v1() :: 1 |
| 26 | + def payment_v1(), do: @payment_v1 |
| 39 27 | |
| 40 28 | @doc """ |
| 29 | + Transaction fee claim V1 |
| 41 30 | |
| 42 | - ## Examples |
| 31 | + ## Example |
| 43 32 | |
| 44 | - # Decodes an encoded transaction bytes |
| 45 | - iex> tx_bytes = <<229, 1, 192, 192, 128, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0>> |
| 46 | - iex> ExPlasma.decode(tx_bytes) |
| 47 | - {:ok, %ExPlasma.Transaction{ |
| 48 | - inputs: [], |
| 49 | - metadata: <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 50 | - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0>>, |
| 51 | - outputs: [], |
| 52 | - sigs: [], |
| 53 | - tx_data: "", |
| 54 | - tx_type: 1 |
| 55 | - } |
| 56 | - } |
| 33 | + iex> ExPlasma.fee() |
| 34 | + 3 |
| 35 | + """ |
| 36 | + @spec fee() :: 3 |
| 37 | + def fee(), do: @fee |
| 57 38 | |
| 58 | - # Decodes a signed encoded transaction bytes |
| 59 | - iex> tx_bytes = <<239, 201, 136, 48, 120, 49, 50, 51, 52, 53, 54, 1, 192, 192, 128, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0>> |
| 60 | - iex> ExPlasma.decode(tx_bytes) |
| 61 | - {:ok, %ExPlasma.Transaction{ |
| 62 | - inputs: [], |
| 63 | - metadata: <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 64 | - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0>>, |
| 65 | - outputs: [], |
| 66 | - sigs: ["0x123456"], |
| 67 | - tx_data: "", |
| 68 | - tx_type: <<1>> |
| 69 | - }} |
| 39 | + @doc """ |
| 40 | + Transaction types |
| 70 41 | |
| 71 | - Decodes a transaction rlp data |
| 72 | - iex> rlp = [1, [], [], 0, <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0>>] |
| 73 | - iex> ExPlasma.decode(rlp) |
| 74 | - {:ok, %ExPlasma.Transaction{ |
| 75 | - inputs: [], |
| 76 | - metadata: <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 77 | - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0>>, |
| 78 | - outputs: [], |
| 42 | + ## Example |
| 43 | + |
| 44 | + iex> ExPlasma.transaction_types() |
| 45 | + [1, 3] |
| 46 | + """ |
| 47 | + @spec transaction_types :: [1 | 3, ...] |
| 48 | + def transaction_types(), do: [payment_v1(), fee()] |
| 49 | + |
| 50 | + @doc """ |
| 51 | + Encode the given Transaction into an RLP encodable list. |
| 52 | + |
| 53 | + If `signed: false` is given in the list of opts, will encode the transaction without its signatures. |
| 54 | + |
| 55 | + ## Example |
| 56 | + |
| 57 | + iex> txn = |
| 58 | + ...> %ExPlasma.Transaction{ |
| 59 | + ...> inputs: [ |
| 60 | + ...> %ExPlasma.Output{ |
| 61 | + ...> output_data: nil, |
| 62 | + ...> output_id: %{blknum: 0, oindex: 0, position: 0, txindex: 0}, |
| 63 | + ...> output_type: nil |
| 64 | + ...> } |
| 65 | + ...> ], |
| 66 | + ...> metadata: <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0>>, |
| 67 | + ...> outputs: [ |
| 68 | + ...> %ExPlasma.Output{ |
| 69 | + ...> output_data: %{ |
| 70 | + ...> amount: 1, |
| 71 | + ...> output_guard: <<29, 246, 47, 41, 27, 46, 150, 159, 176, 132, 157, 153, |
| 72 | + ...> 217, 206, 65, 226, 241, 55, 0, 110>>, |
| 73 | + ...> token: <<46, 38, 45, 41, 28, 46, 150, 159, 176, 132, 157, 153, 217, 206, |
| 74 | + ...> 65, 226, 241, 55, 0, 110>> |
| 75 | + ...> }, |
| 76 | + ...> output_id: nil, |
| 77 | + ...> output_type: 1 |
| 78 | + ...> } |
| 79 | + ...> ], |
| 80 | + ...> sigs: [], |
| 81 | + ...> tx_data: 0, |
| 82 | + ...> tx_type: 1 |
| 83 | + ...> } |
| 84 | + iex> ExPlasma.encode(txn, signed: false) |
| 85 | + {:ok, <<248, 116, 1, 225, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 86 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 238, 237, 1, 235, 148, 29, 246, 47, |
| 87 | + 41, 27, 46, 150, 159, 176, 132, 157, 153, 217, 206, 65, 226, 241, 55, 0, 110, |
| 88 | + 148, 46, 38, 45, 41, 28, 46, 150, 159, 176, 132, 157, 153, 217, 206, 65, 226, |
| 89 | + 241, 55, 0, 110, 1, 128, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 90 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0>>} |
| 91 | + """ |
| 92 | + defdelegate encode(transaction, opts \\ []), to: Transaction |
| 93 | + |
| 94 | + @doc """ |
| 95 | + Throwing version of encode/2 |
| 96 | + """ |
| 97 | + defdelegate encode!(transaction, opts \\ []), to: Transaction |
| 98 | + |
| 99 | + @doc """ |
| 100 | + Attempt to decode the given RLP list into a Transaction. |
| 101 | + |
| 102 | + If `signed: false` is given in the list of opts, expects the underlying RLP to not contain signatures. |
| 103 | + |
| 104 | + Only validates that the RLP is structurally correct and that the tx type is supported. |
| 105 | + Does not perform any other kind of validation, use validate/1 for that. |
| 106 | + |
| 107 | + ## Example |
| 108 | + |
| 109 | + iex> rlp = <<248, 116, 1, 225, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 110 | + ...> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 238, 237, 1, 235, 148, |
| 111 | + ...> 29, 246, 47, 41, 27, 46, 150, 159, 176, 132, 157, 153, 217, 206, 65, 226, 241, |
| 112 | + ...> 55, 0, 110, 148, 46, 38, 45, 41, 28, 46, 150, 159, 176, 132, 157, 153, 217, |
| 113 | + ...> 206, 65, 226, 241, 55, 0, 110, 1, 128, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 114 | + ...> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0>> |
| 115 | + iex> ExPlasma.decode(rlp, signed: false) |
| 116 | + {:ok, |
| 117 | + %ExPlasma.Transaction{ |
| 118 | + inputs: [ |
| 119 | + %ExPlasma.Output{ |
| 120 | + output_data: nil, |
| 121 | + output_id: %{blknum: 0, oindex: 0, position: 0, txindex: 0}, |
| 122 | + output_type: nil |
| 123 | + } |
| 124 | + ], |
| 125 | + metadata: <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0>>, |
| 126 | + outputs: [ |
| 127 | + %ExPlasma.Output{ |
| 128 | + output_data: %{ |
| 129 | + amount: 1, |
| 130 | + output_guard: <<29, 246, 47, 41, 27, 46, 150, 159, 176, 132, 157, 153, |
| 131 | + 217, 206, 65, 226, 241, 55, 0, 110>>, |
| 132 | + token: <<46, 38, 45, 41, 28, 46, 150, 159, 176, 132, 157, 153, 217, 206, |
| 133 | + 65, 226, 241, 55, 0, 110>> |
| 134 | + }, |
| 135 | + output_id: nil, |
| 136 | + output_type: 1 |
| 137 | + } |
| 138 | + ], |
| 139 | + witnesses: [], |
| 79 140 | sigs: [], |
| 80 141 | tx_data: 0, |
| 81 142 | tx_type: 1 |
| 82 | - }} |
| 83 | - |
| 84 | - # Decodes a utxo position |
| 85 | - iex> ExPlasma.decode(1000000000) |
| 86 | - {:ok, |
| 87 | - %ExPlasma.Utxo{ |
| 88 | - amount: nil, |
| 89 | - blknum: 1, |
| 90 | - currency: nil, |
| 91 | - oindex: 0, |
| 92 | - output_type: 1, |
| 93 | - owner: nil, |
| 94 | - txindex: 0 |
| 95 | - }} |
| 96 | - |
| 97 | - # Decodes an output utxo rlp data |
| 98 | - iex> rlp = [<<1>>, [<<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1>>, <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0>>, <<1>>]] |
| 99 | - iex> ExPlasma.decode(rlp) |
| 100 | - {:ok, %ExPlasma.Utxo{ |
| 101 | - amount: 1, |
| 102 | - blknum: nil, |
| 103 | - currency: <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0>>, |
| 104 | - oindex: nil, |
| 105 | - output_type: 1, |
| 106 | - owner: <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1>>, |
| 107 | - txindex: nil |
| 108 | - }} |
| 143 | + } |
| 144 | + } |
| 109 145 | """ |
| 110 | - @spec decode(Transaction.rlp() | Utxo.output_rlp() | Utxo.input_rlp()) :: |
| 111 | - {:ok, Transaction.t()} | {:ok, Utxo.t()} | Utxo.validation_tuples() |
| 112 | - def decode([_output_type, [_owner, _currency, _amount]] = output_rlp), do: Utxo.new(output_rlp) |
| 113 | - |
| 114 | - def decode([_tx_type, _inputs, _outputs, _tx_data, _metadata] = tx_rlp), |
| 115 | - do: Transaction.new(tx_rlp) |
| 116 | - |
| 117 | - def decode([_sigs, _tx_type, _inputs, _outputs, _tx_data, _metadata] = tx_rlp), |
| 118 | - do: Transaction.new(tx_rlp) |
| 119 | - |
| 120 | - def decode(utxo_pos) when is_integer(utxo_pos), do: Utxo.new(utxo_pos) |
| 121 | - def decode(tx_bytes) when is_binary(tx_bytes), do: Transaction.decode(tx_bytes) |
| 146 | + defdelegate decode(tx_bytes, opts \\ []), to: Transaction |
| 122 147 | |
| 123 148 | @doc """ |
| 149 | + Keccak hash the Transaction. This is used in the contracts and events to to reference transactions. |
| 124 150 | |
| 125 | - ## Examples |
| 126 151 | |
| 127 | - # Hash a transaction |
| 128 | - iex> {:ok, txn} = ExPlasma.Transaction.Payment.new(%{inputs: [], outputs: []}) |
| 129 | - iex> ExPlasma.hash(txn) |
| 130 | - <<3, 225, 217, 46, 83, 133, 97, 248, 114, 1, 89, 94, 179, 68, 60, |
| 131 | - 39, 111, 80, 235, 153, 10, 175, 113, 195, 91, 188, 174, 39, 167, |
| 132 | - 20, 14, 81>> |
| 152 | + ## Example |
| 133 153 | |
| 134 | - # Hash an encoded transaction bytes |
| 135 | - iex> tx_bytes = <<229, 1, 192, 192, 128, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0>> |
| 136 | - iex> ExPlasma.hash(tx_bytes) |
| 137 | - <<3, 225, 217, 46, 83, 133, 97, 248, 114, 1, 89, 94, 179, 68, 60, |
| 138 | - 39, 111, 80, 235, 153, 10, 175, 113, 195, 91, 188, 174, 39, 167, |
| 139 | - 20, 14, 81>> |
| 154 | + iex> rlp = <<248, 74, 192, 1, 193, 128, 239, 174, 237, 1, 235, 148, 29, 246, 47, 41, 27, |
| 155 | + ...> 46, 150, 159, 176, 132, 157, 153, 217, 206, 65, 226, 241, 55, 0, 110, 148, 46, |
| 156 | + ...> 38, 45, 41, 28, 46, 150, 159, 176, 132, 157, 153, 217, 206, 65, 226, 241, 55, |
| 157 | + ...> 0, 110, 1, 128, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 158 | + ...> 0>> |
| 159 | + iex> ExPlasma.hash(rlp) |
| 160 | + {:ok, <<87, 132, 239, 36, 144, 239, 129, 88, 63, 88, 116, 147, 164, 200, 113, 191, |
| 161 | + 124, 14, 55, 131, 119, 96, 112, 13, 28, 178, 251, 49, 16, 127, 58, 96>>} |
| 140 162 | """ |
| 141 | - @spec hash(Transaction.t() | binary()) :: <<_::256>> |
| 142 | - def hash(txn) when is_map(txn), do: Transaction.hash(txn) |
| 143 | - def hash(txn) when is_binary(txn), do: Transaction.hash(txn) |
| 163 | + defdelegate hash(transaction), to: Transaction |
| 164 | + |
| 165 | + @doc """ |
| 166 | + Statelessly validate a transation. |
| 167 | + |
| 168 | + Returns :ok if valid or {:error, {atom, atom}} otherwise |
| 169 | + """ |
| 170 | + defdelegate validate(transaction), to: Transaction |
| 144 171 | end |
Loading more files…