Skip to content

Commit

Permalink
introduce context, blockchain instructions
Browse files Browse the repository at this point in the history
  • Loading branch information
m-kus committed Feb 27, 2020
1 parent 68d650f commit 6f3cc77
Show file tree
Hide file tree
Showing 16 changed files with 487 additions and 277 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,14 @@ but if you feel lucky you can try to install natively:
### Installation

```
$ pip install pytezos[crypto]
$ pip install pytezos
```

#### Google Colab

`````python
>>> !apt install libsodium-dev libsecp256k1-dev libgmp-dev
>>> !pip install pytezos[crypto]
>>> !pip install pytezos
`````

### Usage
Expand Down
4 changes: 2 additions & 2 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,13 @@ but if you feel lucky you can try to install natively:

In console:
```
$ pip install pytezos[crypto]
$ pip install pytezos
```

In Google Colab notebook:
```python
>>> !apt install libsodium-dev libsecp256k1-dev libgmp-dev
>>> !pip install pytezos[crypto]
>>> !pip install pytezos
[RESTART RUNTIME]
```

Expand Down
11 changes: 4 additions & 7 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "pytezos"
version = "2.2.8"
version = "2.3.0"
description = "Python toolkit for Tezos"
license = "MIT"
authors = ["Michael Zaikin <[email protected]>", "Arthur Breitman", "Roman Serikov"]
Expand All @@ -27,12 +27,9 @@ ply = "*"
simplejson = "*"
mnemonic = "*"
fire = "*"
pysodium = { version = "^0.7.1", optional = true }
secp256k1 = { version = "^0.13.2", optional = true }
fastecdsa = { version = "^1.7.1", optional = true }

[tool.poetry.extras]
crypto = [ "pysodium", "secp256k1", "fastecdsa" ]
pysodium = "^0.7.1"
secp256k1 = "^0.13.2"
fastecdsa = "^1.7.1"

[tool.poetry.dev-dependencies]
parameterized = "^0.7.0"
Expand Down
8 changes: 8 additions & 0 deletions pytezos/encoding.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,14 @@ def is_key(v) -> bool:
return True


def is_chain_id(v) -> bool:
try:
_validate(v, prefixes=[b'Net'])
except (ValueError, TypeError):
return False
return True


def forge_nat(value) -> bytes:
"""
Encode a number using LEB128 encoding (Zarith)
Expand Down
4 changes: 4 additions & 0 deletions pytezos/michelson/forge.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,3 +221,7 @@ def forge_script(script):
code = forge_micheline(script['code'])
storage = forge_micheline(script['storage'])
return forge_array(code) + forge_array(storage)


def pack(data):
return b'\x05' + forge_micheline(data)
Empty file added pytezos/michelson/parse.py
Empty file.
4 changes: 3 additions & 1 deletion pytezos/operation/content.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,13 +200,14 @@ def transaction(self, destination, amount=0, parameters=None,
return self.operation(content)

@inline_doc
def origination(self, script, balance=0,
def origination(self, script, balance=0, delegate='',
source='', counter=0, fee=0, gas_limit=0, storage_limit=0):
"""
Deploy smart contract (scriptless KT accounts are not used for delegation since Babylon)
:param script: {"code": $Micheline, "storage": $Micheline}
:param balance: Amount transferred on the balance, WARNING: there is no default way to withdraw funds.
More info: https://tezos.stackexchange.com/questions/1315/can-i-withdraw-funds-from-an-empty-smart-contract
:param delegate: Set contract delegate
:param source: Address from which funds will be sent, leave None to use signatory address
:param counter: Current account counter, leave None for autocomplete
:param fee: Leave None for autocomplete
Expand All @@ -222,6 +223,7 @@ def origination(self, script, balance=0,
'gas_limit': str(gas_limit),
'storage_limit': str(storage_limit),
'balance': format_mutez(balance),
'delegate': delegate,
'script': script
}

Expand Down
104 changes: 52 additions & 52 deletions pytezos/repl/arithmetic.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,22 @@

from pytezos.crypto import blake2b_32, Key
from pytezos.repl.control import instruction
from pytezos.repl.stack import Stack
from pytezos.repl.context import Context
from pytezos.repl.types import assert_stack_type, Int, Nat, Timestamp, Mutez, Option, Pair, Bool, Bytes, Key, \
Signature, KeyHash, dispatch_type_map


@instruction('ABS')
def do_abs(stack: Stack, prim, args, annots):
top = stack.pop()
def do_abs(ctx: Context, prim, args, annots):
top = ctx.pop()
assert_stack_type(top, Int)
res = Nat(abs(int(top)))
return stack.ins(res, annots=annots)
return ctx.ins(res, annots=annots)


@instruction('ADD')
def do_add(stack: Stack, prim, args, annots):
a, b = stack.pop2()
def do_add(ctx: Context, prim, args, annots):
a, b = ctx.pop2()
res_type = dispatch_type_map(a, b, {
(Nat, Nat): Nat,
(Nat, Int): Int,
Expand All @@ -28,19 +28,19 @@ def do_add(stack: Stack, prim, args, annots):
(Mutez, Mutez): Mutez
})
res = res_type(int(a) + int(b))
return stack.ins(res, annots=annots)
return ctx.ins(res, annots=annots)


@instruction('COMPARE')
def do_compare(stack: Stack, prim, args, annots):
a, b = stack.pop2()
def do_compare(ctx: Context, prim, args, annots):
a, b = ctx.pop2()
res = Int(a.__cmp__(b))
return stack.ins(res, annots=annots)
return ctx.ins(res, annots=annots)


@instruction('EDIV')
def do_ediv(stack: Stack, prim, args, annots):
a, b = stack.pop2()
def do_ediv(ctx: Context, prim, args, annots):
a, b = ctx.pop2()
q_type, r_type = dispatch_type_map(a, b, {
(Nat, Nat): (Nat, Nat),
(Nat, Int): (Int, Nat),
Expand All @@ -57,12 +57,12 @@ def do_ediv(stack: Stack, prim, args, annots):
r += abs(int(b))
q += 1
res = Option.some(Pair.new(q_type(q), r_type(r)))
return stack.ins(res, annots=annots)
return ctx.ins(res, annots=annots)


@instruction(['EQ', 'GE', 'GT', 'LE', 'LT', 'NEQ'])
def do_eq(stack: Stack, prim, args, annots):
top = stack.pop()
def do_eq(ctx: Context, prim, args, annots):
top = ctx.pop()
assert_stack_type(top, Int)
handlers = {
'EQ': lambda x: x == 0,
Expand All @@ -73,44 +73,44 @@ def do_eq(stack: Stack, prim, args, annots):
'NEQ': lambda x: x != 0
}
res = Bool(handlers[prim](int(top)))
return stack.ins(res, annots=annots)
return ctx.ins(res, annots=annots)


@instruction('INT')
def do_int(stack: Stack, prim, args, annots):
top = stack.pop()
def do_int(ctx: Context, prim, args, annots):
top = ctx.pop()
assert_stack_type(top, Nat)
res = Int(int(top))
return stack.ins(res, annots=annots)
return ctx.ins(res, annots=annots)


@instruction('ISNAT')
def do_is_nat(stack: Stack, prim, args, annots):
top = stack.pop()
def do_is_nat(ctx: Context, prim, args, annots):
top = ctx.pop()
assert_stack_type(top, Int)
if int(top) >= 0:
res = Option.some(Nat(int(top)))
else:
res = Option.none(Nat().type_expr)
return stack.ins(res, annots=annots)
return ctx.ins(res, annots=annots)


@instruction(['LSL', 'LSR'])
def do_lsl(stack: Stack, prim, args, annots):
a, b = stack.pop2()
def do_lsl(ctx: Context, prim, args, annots):
a, b = ctx.pop2()
assert_stack_type(a, Nat)
assert_stack_type(b, Nat)
handlers = {
'LSL': lambda x: x[0] << x[1],
'LSR': lambda x: x[0] >> x[1]
}
res = Nat(handlers[prim]((int(a), int(b))))
return stack.ins(res, annots=annots)
return ctx.ins(res, annots=annots)


@instruction('MUL')
def do_mul(stack: Stack, prim, args, annots):
a, b = stack.pop2()
def do_mul(ctx: Context, prim, args, annots):
a, b = ctx.pop2()
res_type = dispatch_type_map(a, b, {
(Nat, Nat): Nat,
(Nat, Int): Int,
Expand All @@ -120,20 +120,20 @@ def do_mul(stack: Stack, prim, args, annots):
(Nat, Mutez): Mutez
})
res = res_type(int(a) * int(b))
return stack.ins(res, annots=annots)
return ctx.ins(res, annots=annots)


@instruction('NEG')
def do_neg(stack: Stack, prim, args, annots):
top = stack.pop()
def do_neg(ctx: Context, prim, args, annots):
top = ctx.pop()
assert_stack_type(top, [Int, Nat])
res = Int(-int(top))
return stack.ins(res, annots=annots)
return ctx.ins(res, annots=annots)


@instruction('SUB')
def do_sub(stack: Stack, prim, args, annots):
a, b = stack.pop2()
def do_sub(ctx: Context, prim, args, annots):
a, b = ctx.pop2()
res_type = dispatch_type_map(a, b, {
(Nat, Nat): Int,
(Nat, Int): Int,
Expand All @@ -144,12 +144,12 @@ def do_sub(stack: Stack, prim, args, annots):
(Mutez, Mutez): Mutez
})
res = res_type(int(a) - int(b))
return stack.ins(res, annots=annots)
return ctx.ins(res, annots=annots)


@instruction(['AND', 'OR', 'XOR'])
def do_and(stack: Stack, prim, args, annots):
a, b = stack.pop2()
def do_and(ctx: Context, prim, args, annots):
a, b = ctx.pop2()
val_type = dispatch_type_map(a, b, {
(Bool, Bool): bool,
(Nat, Nat): int
Expand All @@ -160,33 +160,33 @@ def do_and(stack: Stack, prim, args, annots):
'XOR': lambda x: x[0] ^ x[1]
}
res = type(a)(handlers[prim]((val_type(a), val_type(b))))
return stack.ins(res, annots=annots)
return ctx.ins(res, annots=annots)


@instruction('NOT')
def do_not(stack: Stack, prim, args, annots):
top = stack.pop()
def do_not(ctx: Context, prim, args, annots):
top = ctx.pop()
assert_stack_type(top, [Nat, Int, Bool])
if type(top) in [Nat, Int]:
res = Int(~int(top))
elif type(top) == Bool:
res = Bool(not bool(top))
else:
assert False
return stack.ins(res, annots=annots)
return ctx.ins(res, annots=annots)


@instruction('BLAKE2B')
def do_blake2b(stack: Stack, prim, args, annots):
top = stack.pop()
def do_blake2b(ctx: Context, prim, args, annots):
top = ctx.pop()
assert_stack_type(top, Bytes)
res = Bytes(blake2b_32(bytes(top)).digest())
return stack.ins(res, annots=annots)
return ctx.ins(res, annots=annots)


@instruction('CHECK_SIGNATURE')
def do_check_sig(stack: Stack, prim, args, annots):
pk, sig, msg = stack.pop3()
def do_check_sig(ctx: Context, prim, args, annots):
pk, sig, msg = ctx.pop3()
assert_stack_type(pk, Key)
assert_stack_type(sig, Signature)
assert_stack_type(msg, Bytes)
Expand All @@ -197,25 +197,25 @@ def do_check_sig(stack: Stack, prim, args, annots):
res = Bool(False)
else:
res = Bool(True)
return stack.ins(res, annots=annots)
return ctx.ins(res, annots=annots)


@instruction('HASH_KEY')
def do_hash_key(stack: Stack, prim, args, annots):
top = stack.pop()
def do_hash_key(ctx: Context, prim, args, annots):
top = ctx.pop()
assert_stack_type(top, Key)
key = Key.from_encoded_key(str(top))
res = KeyHash(key.public_key_hash())
return stack.ins(res, annots=annots)
return ctx.ins(res, annots=annots)


@instruction(['SHA256', 'SHA512'])
def do_sha(stack: Stack, prim, args, annots):
top = stack.pop()
def do_sha(ctx: Context, prim, args, annots):
top = ctx.pop()
assert_stack_type(top, Bytes)
handlers = {
'SHA256': lambda x: sha256(x).digest(),
'SHA512': lambda x: sha512(x).digest(),
}
res = Bytes(handlers[prim](bytes(top)))
return stack.ins(res, annots=annots)
return ctx.ins(res, annots=annots)
Loading

0 comments on commit 6f3cc77

Please sign in to comment.