Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions nix/dep/tezos-bake-monitor-lib/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# DO NOT HAND-EDIT THIS FILE
let fetchGit = {url, rev, ref ? null, branch ? null, sha256 ? null, fetchSubmodules ? null}:
assert !fetchSubmodules; (import <nixpkgs> {}).fetchgit { inherit url rev sha256; };
in import (fetchGit (builtins.fromJSON (builtins.readFile ./git.json)))
7 changes: 7 additions & 0 deletions nix/dep/tezos-bake-monitor-lib/git.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"url": "ssh://git@gitlab.com/obsidian.systems/tezos-bake-monitor-lib.git",
"rev": "4e3ba952c24d37ff9f360e35ca4703670d78362d",
"sha256": "1y5a6v1k7vh9ch6ajb46qahiqj0dnf7k1jci95m9ixsfr84z0f5k",
"fetchSubmodules": false,
"branch": "jm@withdraw-delegate-op"
}
24 changes: 13 additions & 11 deletions src/operations.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,17 +124,6 @@ static inline uint64_t parse_z_michelson(void const *data, size_t *ix, size_t le

#define PARSE_Z_MICHELSON(data, ix, length) parse_z_michelson(data, ix, length, __LINE__)

// This macro assumes:
// * Beginning of data: const void *data
// * Total length of data: size_t length
// * Current index of data: size_t ix
// Any function that uses these macros should have these as local variables
#define NEXT_TYPE(type) ({ \
const type *val = data + ix; \
advance_ix(&ix, length, sizeof(type)); \
val; \
})

static inline signature_type_t parse_raw_tezos_header_signature_type(
raw_tezos_header_signature_type_t const *const raw_signature_type
) {
Expand Down Expand Up @@ -242,6 +231,18 @@ static void parse_operations_throws_parse_error(
bip32_path_t const *const bip32_path,
is_operation_allowed_t is_operation_allowed
) {

// This macro assumes:
// * Beginning of data: const void *data
// * Total length of data: size_t length
// * Current index of data: size_t ix
// Any function that uses these macros should have these as local variables
#define NEXT_TYPE(type) ({ \
const type *val = data + ix; \
advance_ix(&ix, length, sizeof(type)); \
val; \
})

check_null(out);
check_null(data);
check_null(bip32_path);
Expand Down Expand Up @@ -655,6 +656,7 @@ static void parse_operations_throws_parse_error(
if (out->operation.tag == OPERATION_TAG_NONE && !out->has_reveal) {
PARSE_ERROR(); // Must have at least one op
}
#undef NEXT_TYPE
}

bool parse_operations(
Expand Down
5 changes: 5 additions & 0 deletions test/tools/apdu-gen/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Revision history for apdu-gen

## 0.1.0.0 -- YYYY-mm-dd

* First version. Released on an unsuspecting world.
30 changes: 30 additions & 0 deletions test/tools/apdu-gen/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
Copyright (c) 2019, Obsidian Systems

All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.

* Neither the name of Obsidian Systems nor the names of other
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 changes: 25 additions & 0 deletions test/tools/apdu-gen/Main.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{-# LANGUAGE OverloadedStrings #-}

module Main where

import qualified Data.HexString as Hex

import Tezos.V005.Types

import Ops

main :: IO ()
main = do
-- A simple example that prints out the apdus for two different Tezos operations
-- Note: The ledger will switch to a signed hash if the src argument is not the pkh of the ledger's key
-- The following apdu: "8004000311048000002c800006c18000000080000000" (which sets up the ledger key)
-- should be sent before any call of the below apdu

print $ fmap Hex.fromBytes $ makeTezosAPDU LedgerInstruction_Sign Nothing $ transferSim src dst 4 60000
print $ fmap Hex.fromBytes $ makeTezosAPDU LedgerInstruction_Sign Nothing $ delegationSim src delegate 60000
where
src = "tz1eY5Aqa1kXDFoiebL28emyXFoneAoVg1zh"
dst = "tz1cCTB1S2UYtGVJyuTQ9ktnnkemuqaSwvZn"
delegate = "tz1cCTB1S2UYtGVJyuTQ9ktnnkemuqaSwvZn"


139 changes: 139 additions & 0 deletions test/tools/apdu-gen/Ops.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE OverloadedLists #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures #-}

module Ops
(
transferSim
, delegationSim
, makeTezosAPDU
, LedgerInstruction(..)
, SignatureType(..)

) where

-- import qualified Data.ByteString.Base16 as BS16
import qualified Data.ByteString as BS
import qualified Data.ByteString.Builder as BSB
import Data.ByteString.Lazy (toStrict)
import Data.Dependent.Sum
import qualified Data.HexString as Hex
import Data.Int (Int8)
import Data.Maybe (fromMaybe)

import qualified Tezos.Common.Binary as B
import Tezos.V005.Micheline
import Tezos.V005.Operation
import Tezos.V005.Types

data SignatureType =
SignatureType_UNSET
| SignatureType_SECP256K1
| SignatureType_SECP256R1
| SignatureType_ED25519EC
deriving (Eq, Show, Enum)

-- Order of the instructions listed in the type matters so that derive enum corresponds with
-- the apdu instruction bytecodes
-- TODO: Fix the above
data LedgerInstruction =
LedgerInstruction_Version
| LedgerInstruction_AuthorizeBaking
| LedgerInstruction_GetPublicKey
| LedgerInstruction_PromptPublicKey
| LedgerInstruction_Sign
| LedgerInstruction_SignUnsafe
| LedgerInstruction_Reset
| LedgerInstruction_QueryAuthKey
| LedgerInstruction_QueryMainHWM
| LedgerInstruction_Git
| LedgerInstruction_Setup
| LedgerInstruction_QueryAllHWM
| LedgerInstruction_Deauthorize
| LedgerInstruction_QueryAuthKeyWithCurve
| LedgerInstruction_HMAC
| LedgerInstruction_SignWithHash
deriving (Eq, Show, Enum)

transferSim :: PublicKeyHash -> ContractId -> Tez -> TezosWord64 -> BS.ByteString
transferSim source destination amount storageLimit =
B.encode $ tag :=> Op
{ _op_branch = "BLM3c4UQi5ebKtfKyVZfN3g9xxbw1EKczvJvGhMDrBCP8DVcWmm" -- mock branch name
, _op_contents = contents
, _op_signature = Nothing
}
where
tag = OpsKindTag_Single $ OpKindTag_Manager OpKindManagerTag_Transaction
contents = OpContentsList_Single $ OpContents_Transaction $
OpContentsManager
{ _opContentsManager_source = source
, _opContentsManager_fee = 1
, _opContentsManager_counter = 2590
, _opContentsManager_gasLimit = 800000
, _opContentsManager_storageLimit = storageLimit
, _opContentsManager_operation = transferOp
}
transferOp = OpContentsTransaction
{ _opContentsTransaction_amount = amount
, _opContentsTransaction_destination = destination
, _opContentsTransaction_parameters = Nothing
}


delegationSim :: PublicKeyHash -> PublicKeyHash -> TezosWord64 -> BS.ByteString
delegationSim source delegate storageLimit = B.encode $ tag :=> Op
{ _op_branch = "BLM3c4UQi5ebKtfKyVZfN3g9xxbw1EKczvJvGhMDrBCP8DVcWmm"
, _op_contents = contents
, _op_signature = Nothing
}
where
tag = OpsKindTag_Single $ OpKindTag_Manager OpKindManagerTag_Delegation
contents = OpContentsList_Single $ OpContents_Delegation $
OpContentsManager
{ _opContentsManager_source = source
, _opContentsManager_fee = 1
, _opContentsManager_counter = 2590
, _opContentsManager_gasLimit = 800000
, _opContentsManager_storageLimit = storageLimit
, _opContentsManager_operation = delegateOp
}
delegateOp = OpContentsDelegation
{ _opContentsDelegation_delegate = Just delegate
}

--TODO: Cover enums with over 128 elements
enumToByteB :: Enum a => a -> BSB.Builder
enumToByteB = BSB.int8 . (fromIntegral :: Int -> Int8) . fromEnum

makeTezosAPDU :: LedgerInstruction -> Maybe SignatureType -> BS.ByteString -> [BS.ByteString]
makeTezosAPDU instruction sigTypeM payload =
fmap (\bs -> toStrict $ BSB.toLazyByteString $ toAPDU (enumToByteB instruction) p2FinalB (enumToByteB sigType) bs) $ splitMsg payload
where
-- TODO: Get this to work
-- setupKeyAPDU :: BS.ByteString
-- setupKeyAPDU = "8004000311048000002c800006c18000000080000000" --this should be the same for all apdus
-- fullMsg = setupKeyAPDU : (splitMsg payload)

sigType = fromMaybe SignatureType_UNSET sigTypeM
claByteB = BSB.int8 128 -- 0x80
p2InitB = BSB.int8 1 -- 0x01
p2MiddleB = BSB.int8 0 -- 0x00
p2FinalB = BSB.int8 129 -- 0x81
magicByteB = BSB.int8 3 -- 0x03
maxRawMsgSize = 230

-- splitMsg :: BS.ByteString -> [BS.ByteString]
-- splitMsg rawTxn =
-- let txnWithMB = BSB.lazyByteString $ magicByteB <> byteString rawTxn in
-- if BS.length txnWithMB > maxRawMsgSize
-- then (BS.take maxRawTxnSize txnWithMB) : (splitMsg $ BS.drop maxRawTxnSize txnWithMB)
-- else [txnWithMB]

splitMsg :: BS.ByteString -> [BS.ByteString]
splitMsg rawTxn =
-- This is just a tmp implementation of the function, the above one has the real logic that should be used
[toStrict $ BSB.toLazyByteString $ magicByteB <> (BSB.byteString rawTxn) ]

toAPDU insB p2B curveB msg =
claByteB <> insB <> p2B <> curveB <> (enumToByteB $ BS.length msg) <> BSB.byteString msg
5 changes: 5 additions & 0 deletions test/tools/apdu-gen/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
```
nix-shell apdu-gen.nix --run 'cabal new-build'

nix-shell apdu-gen.nix --run 'cabal new-run'
```
2 changes: 2 additions & 0 deletions test/tools/apdu-gen/Setup.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import Distribution.Simple
main = defaultMain
32 changes: 32 additions & 0 deletions test/tools/apdu-gen/apdu-gen.cabal
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
cabal-version: 2.0
-- Initial package description 'apdu-gen.cabal' generated by 'cabal init'.
-- For further documentation, see http://haskell.org/cabal/users-guide/

name: apdu-gen
version: 0.1.0.0
-- synopsis:
-- description:
-- bug-reports:
license: BSD3
license-file: LICENSE
author: Obsidian Systems
maintainer: none
-- copyright:
-- category:
build-type: Simple
extra-source-files: CHANGELOG.md

executable apdu-gen
main-is: Main.hs
other-modules: Ops
other-extensions: OverloadedStrings, OverloadedLists, DataKinds, KindSignatures
build-depends: base ^>=4.12.0.0
, tezos-bake-monitor-lib
, dependent-sum
, binary
, base16-bytestring
, base58-bytestring
, bytestring
, hexstring
-- hs-source-dirs:
default-language: Haskell2010
25 changes: 25 additions & 0 deletions test/tools/apdu-gen/apdu-gen.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{ pkgs ? import (builtins.fetchTarball { url = "https://github.com/NixOS/nixpkgs/archive/9c9a249b0133c3cd30757c3594d18183689adc3f.tar.gz"; sha256 = "0g2wmys9qckz4awcp7img8672rhlhjhjq08ybgc0d4avgc7fkpw5"; }) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we already have a nixpkgs pin in this repo?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could just upgrade that if this version is necessary.

overlays = [ (self: super: {
all-cabal-hashes = self.fetchurl {
url = "https://github.com/commercialhaskell/all-cabal-hashes/archive/8ce20718874c5d1d258f436b0360cf04b6fd4b1e.tar.gz";
sha256 = "1ipjha4dakiff1rf3v8fz9cs2c2n1hw0mma7j5lwk7cr82rqg58b";
};
})]; }
, compiler ? "ghc864"
, reflex-platform ? import (builtins.fetchTarball {
url = "https://github.com/reflex-frp/reflex-platform/archive/9e306f72ed0dbcdccce30a4ba0eb37aa03cf91e3.tar.gz";
sha256 = "1crlwfw6zsx2izwsd57i5651p5pfyrpkfjwp6fc1yd4q4d4n7g2m";
}) {}
}:
let
inherit (reflex-platform) hackGet;
in pkgs.haskell.packages.${compiler}.developPackage {
name = "apdu-gen";
root = ./.;
source-overrides = {
constraints-extras = "0.3.0.1";
dependent-sum = "0.6.2.0";
dependent-sum-template = "0.1.0.0";
tezos-bake-monitor-lib = (hackGet ../../../nix/dep/tezos-bake-monitor-lib) + /tezos-bake-monitor-lib;
};
}