Giter Site home page Giter Site logo

omgnetwork / ex_plasma Goto Github PK

View Code? Open in Web Editor NEW
10.0 10.0 7.0 436 KB

Elixir library for the OMG Plasma Contracts Transaction Format

Home Page: https://omg.network/

License: Apache License 2.0

Elixir 99.62% Dockerfile 0.16% Makefile 0.10% JavaScript 0.11%
elixir ethereum omg plasma rlp

ex_plasma's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ex_plasma's Issues

Add `credo` and linting

We need to add credo and/or linting tools for the project.

  • Add credo
  • Add credo/lint build step for PRs

Implement POC child chain for test suite

For more complex flows like Payment transaction submission, we should create a simple child chain that will manage the UTXO (unspent transaction outputs) that are to be used in the inputs for a given transaction.

For testing, we could just leverage :ets as quick store just for the test case purposes.

Add more unit tests

A lot of unit tests could be added to almost every modules, indeed most modules contain only a few tests that don't cover every functions.

Create hex.pm documentation

We should get the package documentation ready for usage with hex.pm.

  • figure out how to deploy to hex.pm
  • clean up documentation for hex.pm

Add coveralls

Because who doesn't like test coverage numbers...

testing

leading zero

payment = %ExPlasma.Transaction.Payment{
  inputs: [
    %ExPlasma.Utxo{
      amount: nil,
      blknum: 13,
      currency: <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0>>,
      oindex: 0,
      output_type: 1,
      owner: "0x44ebe6dc4481ef64caf559b36a05283619632f5e",
      txindex: 0
    }
  ],
  metadata: nil,
  outputs: [
    %ExPlasma.Utxo{
      amount: 0,
      blknum: nil,
      currency: <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0>>,
      oindex: nil,
      output_type: 1,
      owner: "0x44ebe6dc4481ef64caf559b36a05283619632f5e",
      txindex: nil
    },
    %ExPlasma.Utxo{
      amount: 15000000000000000000,
      blknum: nil,
      currency: <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0>>,
      oindex: nil,
      output_type: 1,
      owner: "0x0c9cc021c95750dd25e094c372fb586727fab971",
      txindex: nil
    }
  ],
  sigs: [],
  tx_data: nil,
  tx_type: nil
}

that produces a RLP of

iex(2)> ExPlasma.Transaction.to_rlp payment
[
  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, 3, 6, 220, 66, 0>>
  ],
  [
    [
      <<1>>,
      [
        <<68, 235, 230, 220, 68, 129, 239, 100, 202, 245, 89, 179, 106, 5, 40,
          54, 25, 99, 47, 94>>,
        <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0>>,
        <<0>>
      ]
    ],
    [
      <<1>>,
      [
        <<12, 156, 192, 33, 201, 87, 80, 221, 37, 224, 148, 195, 114, 251, 88,
          103, 39, 250, 185, 113>>,
        <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0>>,
        <<208, 42, 180, 134, 206, 220, 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, 0, 0>>
]

makes the watcher API

transaction_submit_body_schema = %TransactionSubmitBodySchema{transaction: Encoding.to_hex(txbytes)}
    {:ok, response} = Transaction.submit(Watcher.new(), transaction_submit_body_schema)

have a fit with response:

%{
  "data" => %{
    "code" => "submit:leading_zeros_in_encoded_uint",
    "description" => nil,
    "object" => "error"
  },
  "service_name" => "watcher",
  "success" => false,
  "version" => "0.3.0+fea92f6"
}

`to_input_rlp/1` should guard against invalid attributes

If Utxo.to_input_rlp/1 or Utxo.pos/1 are given attributes exceeding the maximum, the functions will still generate a utxo position with said values. This can create situations where it will no longer re-produce the same struct:

iex(6)> utxo = %ExPlasma.Utxo{blknum: 1, txindex: 1_000_000_000, oindex: 0}
%ExPlasma.Utxo{
  amount: nil,
  blknum: 1,
  currency: nil,
  oindex: 0,
  output_type: 1,
  owner: nil,
  txindex: 1000000000 # :|
}
iex(7)> pos = ExPlasma.Utxo.pos(utxo)
10001000000000
iex(8)> ExPlasma.Utxo.new(pos)
{:ok,
 %ExPlasma.Utxo{
   amount: nil,
   blknum: 10001,  # :(
   currency: nil,
   oindex: 0,
   output_type: 1,
   owner: nil,
   txindex: 0
 }}

These functions should also run through the validation and return us an appropriate ok or error tuple.

ExPlasma.Utxo.new is fine with inputs representing too big blknums

There has been a new rule introduced in the contracts, with respect to the maximum blknum value https://github.com/omisego/plasma-contracts/blob/master/plasma_framework/contracts/src/utils/PosLib.sol#L23

As a consequence, the encoded Utxo position can only be as large as one that will accomodate the biggest blknum. Similar decoding checks should be present in Elixir handling of utxo pos, even despite such blknums being nonsensical.

Found in https://circleci.com/gh/omisego/elixir-omg/35202

Add CircleCI

We need to Add CircleCI for this project.

  • Add CircleCI and enforce it for PRs
  • Lock down Repository to PR squash/merge only
  • Add CircleCI badge

ExPlasma.Utxo.to_rlp misinterprets attempts to encode zero Utxo positions

iex(17)> ExPlasma.Utxo.to_rlp(%ExPlasma.Utxo{blknum: 0, txindex: 0, oindex: 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, 1>>

vs

iex(18)> ExPlasma.Utxo.to_rlp(%ExPlasma.Utxo{blknum: 0, txindex: 0, oindex: 0})
[
  <<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, 0, 0, 0, 0, 0, 0, 0>>,
    <<0>>
  ]
]

Spotted, when using the OMG.Utxo.Position module from elixir-omg:

iex(14)> Utxo.Position.get_data_for_rlp(Utxo.position(0, 0, 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, 1>>
iex(15)> Utxo.Position.get_data_for_rlp(Utxo.position(0, 0, 0))
[
  <<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, 0, 0, 0, 0, 0, 0, 0>>,
    <<0>>
  ]
]

which dispatches to said ex_plasma function.

at ex_plasma ecbba7d

ExPlasma.Utxo.new is fine with zero inputs and unpadded inputs

iex(24)> ExPlasma.Utxo.new(<<1::128>>)
%ExPlasma.Utxo{
  amount: 0,
  blknum: 0,
  currency: "0x0000000000000000000000000000000000000000",
  oindex: 1,
  output_type: 1,
  owner: "0x0000000000000000000000000000000000000000",
  txindex: 0
}
iex(25)> ExPlasma.Utxo.new(<<0::256>>)
%ExPlasma.Utxo{
  amount: 0,
  blknum: 0,
  currency: "0x0000000000000000000000000000000000000000",
  oindex: 0,
  output_type: 1,
  owner: "0x0000000000000000000000000000000000000000",
  txindex: 0
}

while neither should be legal, at least as far the requirements of https://github.com/omisego/elixir-omg/blob/master/apps/omg/lib/omg/utxo/position.ex#L171 go.

Note also that https://github.com/omisego/elixir-omg/blob/master/apps/omg/lib/omg/utxo/position.ex#L98 seems to not dispatch to ExPlasma at all, I think this has been mentioned to been not yet done. After this issue here is resolved I think elixir-omg should be tidied according to the resolution here.

This slipped under the tests in elixir-omg because of #18 - the test covering zero-inputs was generating malformed transactions for unrelated reasons.

Add ability to `submit_block` of transaction into the contract

We need to be able to submit blocks into the contract. This potentially requires a few pieces:

  • how do we currently hash the block of transactions
  • how do we / do we need? to sign transactions for the block

A potential API could look something like:

[ 
  %Payment{...},
  %Payment{...}
] 
|> Transaction.sign(key) # if it needs to be signed?
|> Transaction.encode() # or another function if this gets overloaded.
|> Client.submit_block(whatever_options)

Add synchronous version of ExPlasma.Client calls

After making a deposit it would be nice to know it's mined on Ethereum and to know it's blknum. Using ExPlasma to do that is cumbersome.
Currently in omg-load-testing we handle it this way: https://github.com/omisego/omg-load-testing/blob/1f1f34b6dee6b8c94256bb1f488dfe05fd487f77/lib/omg_perf/extended_perftest.ex#L86
(and it's not the best way as it assumes there is just one deposit from a given address in Ethereum block, but it's sufficient for our needs).
Could you add functions to synchronously make deposits and submit blocks? Preferably return value contains at least blknum.

missing decoding of unsigned integers

https://github.com/omisego/ex_plasma/blob/1e322870cb0e9f28650089110a18a556821b167c/lib/ex_plasma/encoding.ex#L82-L94
https://github.com/omisego/elixir-omg/blob/master/apps/omg/lib/omg/output.ex#L40-L42
https://github.com/omisego/elixir-omg/blob/master/apps/omg/lib/omg/raw_data.ex#L27

missing decoding of unsigned integers

ExPlasma.Utxo.new [
 <<1>>,
 [
   <<33, 127, 208, 111, 197, 209, 146, 19, 73, 66, 249, 152, 134, 190, 205,
     146, 47, 254, 67, 10>>,
   <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0>>,
   "0x"
 ]
]

elixir-omg example:

   OMG.TestHelper.create_recovered([{1, 0, 0, OMG.TestHelper.generate_entity()}],  OMG.Eth.zero_address(), [{OMG.TestHelper.generate_entity(), 12408}])

Add Example Usage on README

We should add example usage of the library on the README. We can also link to example code to perform some of the more complex interactions, like managing the UTXO list for inputs to be used in a payment transaction.

Don't restrict on owner being a zero value address

This is a double issue.

First, should we restrict on the owner being a zero value? Per contract, this is not a valid value for output_guard/owner. However, we use zero-value owner's when we produce the TypedData signature.

Second, when inserting Utxo structs with a zero address owner, no error is raised and we are able to produce the Transaction struct

outputs = [
  %Utxo{amount: 1, currency: <<0::160>>, owner: <<0::160>>},
  %Utxo{amount: 2, currency: <<0::160>>, owner: <<0::160>>},
  %Utxo{amount: 3, currency: <<0::160>>, owner: <<0::160>>}
 ]

transaction = Transaction.new(%Transaction{inputs: [], outputs: outputs})
#=> should return {:error, {:owner, :cannot_be_zero}}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.