Library EVMOpSem.rlplem


Require Import Arith.
Require Import Bool.
Require Import List.
Require Import String.
Require Import Program.Wf.

Require Import Lem.coqharness.

Open Scope nat_scope.
Open Scope string_scope.


Require Import Lem.lem_pervasives.
Require Export Lem.lem_pervasives.

Require Import Lem.lem_word.
Require Export Lem.lem_word.

Require Import word256.
Require Export word256.

Require Import word160.
Require Export word160.

Require Import word8.
Require Export word8.

Require Import keccak.
Require Export keccak.

Definition byte0 : Type := word8 .
Definition byte0_default: byte0 := word8_default.

Inductive tree : Type :=
 | Leaf: list byte0 -> tree
 | Node: list tree -> tree .
Definition tree_default: tree := Leaf DAEMON.

Program Fixpoint BE_rev_prim (limit : nat ) (n : nat ) : list (word8 ):= match ( limit) with
 | 0%nat => []
 |S (limit) =>
   if beq_nat n( 0%nat) then [] else
   if nat_ltb n( 256%nat) then [word8FromNatural n] else
         (word8FromNatural ( Nat.modulo n( 256%nat)) :: BE_rev_prim limit ( Nat.div n( 256%nat)))
end.


Definition BE (n : nat ) : list (word8 ):= List.rev ((fun (n : nat ) => BE_rev_prim n n) n).

Definition BE_nat (n : nat ) : list (word8 ):= List.rev ((fun (n : nat ) => BE_rev_prim n n) ( n)).

Program Fixpoint BD_rev (lst : list (word8 )) : nat := match ( lst) with
 | [] => 0%nat
 | h :: t => Coq.Init.Peano.plus (Coq.Init.Peano.mult( 256%nat) (BD_rev t)) (word8ToNatural h)
end.

Definition BD (lst : list (word8 )) : nat := BD_rev (List.rev lst).

Definition r_b (lst : list (word8 )) : list (word8 ):= match ( lst) with
 | [] => [(word8FromNumeral 128%nat)]
 | [k] => if nat_ltb (word8ToNat k)( 128%nat) then [k] else [(word8FromNumeral 129%nat); k]
 | lst =>
   if nat_ltb (List.length lst)( 56%nat) then word8FromNat ( Coq.Init.Peano.plus( 128%nat) (List.length lst)) :: lst
    else word8FromNat ( Coq.Init.Peano.plus( 183%nat) (List.length (BE_nat (List.length lst)))) :: (@ List.app _)(BE_nat (List.length lst)) lst
end.

Definition read_n_bytes (n : nat ) (lst : list (word8 )) : option ((list (word8 )*list (word8 )) % type) :=
  if nat_gteb (List.length lst) n then Some (take n lst, drop n lst)
  else None.

Definition de_r_b (lst : list (word8 )) : option ((list (word8 )*list (word8 )) % type) := match ( lst) with
 | [] => None
 | k :: lst =>
   if classical_boolean_equivalence k(word8FromNumeral 128%nat) then Some ([], lst)
   else if w8Less k(word8FromNumeral 128%nat) then Some ([k], lst)
   else if w8Less k(word8FromNumeral 184%nat) then
       (let len := Coq.Init.Peano.minus (word8ToNat k)( 128%nat) in
       (if nat_gteb (List.length lst) len then Some (take len lst, drop len lst)
                                         else None))
   else if w8LessEqual k(word8FromNumeral 192%nat) then
      match ( read_n_bytes ( Coq.Init.Peano.minus(word8ToNat k)( 183%nat)) lst) with
       | None => None
       | Some (be_bytes, x_and_rest) =>
         read_n_bytes ( (BD be_bytes)) x_and_rest
      end
   else None
end.

Program Fixpoint RLP (tree1 : tree ) : list (word8 ):= match ( tree1) with
 | Leaf l => r_b l
 | Node lst =>
   let s := lem_list.concat (List.map RLP lst) in
   let len_s := List.length s in
   if nat_ltb len_s( 56%nat) then word8FromNat ( Coq.Init.Peano.plus( 192%nat) len_s) :: s
   else word8FromNat ( Coq.Init.Peano.plus( 247%nat) (List.length (BE_nat len_s))) :: ( (@ List.app _)(BE_nat len_s) s)
end.

Definition RLP_nat (i : nat ) : list (byte0 ):= RLP (Leaf (BE i)).

Definition RLP_w256 (i : (Bvector 256) ) : tree := Leaf (BE (Z.abs_nat ((two_compl_value 255 i)))).

Definition word_rsplit160 (w : word160 ) : list (keccak.byte ):= (word_rsplit_aux (boolListFromWord160 w)( 20%nat)).

Definition RLP_address (addr : word160 ) : tree := Leaf (word_rsplit160 addr).