Added a few utility files
This commit is contained in:
parent
2cd5415396
commit
318bf043ed
|
@ -0,0 +1,39 @@
|
|||
from ethereum import utils
|
||||
|
||||
def mk_forwarder(address):
|
||||
code = b'\x36\x60\x00\x60\x00\x37' # CALLDATACOPY 0 0 (CALLDATASIZE)
|
||||
code += b'\x61\x20\x00\x60\x00\x36\x60\x00' # 8192 0 CALLDATASIZE 0
|
||||
code += b'\x73' + utils.normalize_address(address) + b'\x5a' # address gas
|
||||
code += b'\xf4' # delegatecall
|
||||
code += b'\x61\x20\x00\x60\x00\xf3' # 8192 0 RETURN
|
||||
return code
|
||||
|
||||
def mk_wrapper(code):
|
||||
lencodepush = b'\x60' + utils.encode_int(len(code)) # length of code
|
||||
returner = lencodepush + b'\x60\x0c\x60\x00' # start from 12 in code, 0 in memory
|
||||
returner += b'\x39' # CODECOPY
|
||||
returner += lencodepush + b'\x60\x00' + b'\xf3' # return code
|
||||
assert len(returner) == 12
|
||||
return returner + code
|
||||
|
||||
kode = """
|
||||
moose: num
|
||||
def increment_moose(i: num) -> num:
|
||||
self.moose += i
|
||||
return self.moose
|
||||
"""
|
||||
|
||||
def test():
|
||||
from ethereum.tools import tester2
|
||||
c = tester2.Chain()
|
||||
x = c.contract(kode, language='viper')
|
||||
fwdcode = mk_forwarder(x.address)
|
||||
initcode = mk_wrapper(fwdcode)
|
||||
y = c.contract(initcode, language='evm')
|
||||
assert c.head_state.get_code(y) == fwdcode
|
||||
z = tester2.ABIContract(c, x.translator, y)
|
||||
assert z.increment_moose(3) == 3
|
||||
assert z.increment_moose(5) == 8
|
||||
|
||||
if __name__ == '__main__':
|
||||
test()
|
|
@ -0,0 +1,23 @@
|
|||
from ethereum import utils
|
||||
|
||||
def mk_multisend_code(payments): # expects a dictionary, {address: wei}
|
||||
kode = b''
|
||||
for address, wei in payments.items():
|
||||
kode += b'\x60\x00\x60\x00\x60\x00\x60\x00' # 0 0 0 0
|
||||
encoded_wei = utils.encode_int(wei) or b'\x00'
|
||||
kode += utils.ascii_chr(0x5f + len(encoded_wei)) + encoded_wei # value
|
||||
kode += b'\x73' + utils.normalize_address(address) # to
|
||||
kode += b'\x60\x00\xf1\x50' # 0 CALL POP
|
||||
kode += b'\x33\xff' # CALLER SELFDESTRUCT
|
||||
return kode
|
||||
|
||||
def get_multisend_gas(payments):
|
||||
o = 26002 # 21000 + 2 (CALLER) + 5000 (SELFDESTRUCT)
|
||||
for address, wei in payments.items():
|
||||
encoded_wei = utils.encode_int(wei) or b'\x00'
|
||||
# 20 bytes in txdata for address = 1360
|
||||
# bytes in txdata for wei = 68 * n
|
||||
# gas for pushes and pops = 3 * 7 + 2 = 23
|
||||
# CALL = 9700 + 25000 (possible if new account)
|
||||
o += 1360 + 68 * len(encoded_wei) + 23 + 34700
|
||||
return o
|
|
@ -0,0 +1,14 @@
|
|||
from mk_sendmany import mk_multisend_code, get_multisend_gas
|
||||
from ethereum.tools import tester2
|
||||
from ethereum import utils
|
||||
|
||||
# from ethereum.slogging import get_logger, configure_logging
|
||||
# logger = get_logger()
|
||||
# configure_logging(':trace')
|
||||
|
||||
c = tester2.Chain()
|
||||
args = {utils.int_to_addr(10000 + i ** 3): i ** 3 for i in range(1, 101)}
|
||||
c.tx(to=b'', value=sum(args.values()), data=mk_multisend_code(args), startgas=get_multisend_gas(args), gasprice=20 * 10**9)
|
||||
for addr, value in args.items():
|
||||
assert c.head_state.get_balance(addr) == value
|
||||
print("Test successful")
|
|
@ -24,7 +24,7 @@ G2 = (FQ2([108570469990230571359445707622328294813707563595785180869905199932856
|
|||
|
||||
# Check that a point is on the curve defined by y**2 == x**3 + b
|
||||
def is_on_curve(pt, b):
|
||||
if pt is None:
|
||||
if pt[-1] == pt[-1].__class__.zero():
|
||||
return True
|
||||
x, y, z = pt
|
||||
return y**2 * z - x**3 == b * z**3
|
||||
|
@ -49,7 +49,7 @@ def double(pt):
|
|||
def add(p1, p2):
|
||||
one, zero = p1[0].__class__.one(), p1[0].__class__.zero()
|
||||
if p1[2] == zero or p2[2] == zero:
|
||||
return p1 if zero else p2
|
||||
return p1 if p2[2] == zero else p2
|
||||
x1, y1, z1 = p1
|
||||
x2, y2, z2 = p2
|
||||
U1 = y2 * z1
|
||||
|
@ -75,7 +75,7 @@ def add(p1, p2):
|
|||
# Elliptic curve point multiplication
|
||||
def multiply(pt, n):
|
||||
if n == 0:
|
||||
return None
|
||||
return (pt[0].__class__.one(), pt[0].__class__.one(), pt[0].__class__.zero())
|
||||
elif n == 1:
|
||||
return pt
|
||||
elif not n % 2:
|
||||
|
|
|
@ -64,7 +64,7 @@ assert linefunc(one, one, two)[0] != FQ(0)
|
|||
assert linefunc(one, one, negtwo)[0] == FQ(0)
|
||||
|
||||
# Main miller loop
|
||||
def miller_loop(Q, P):
|
||||
def miller_loop(Q, P, final_exponentiate=True):
|
||||
if Q is None or P is None:
|
||||
return FQ12.one()
|
||||
R = Q
|
||||
|
@ -97,10 +97,18 @@ def miller_loop(Q, P):
|
|||
_n2, _d2 = linefunc(R, nQ2, P)
|
||||
f = f_num * _n1 * _n2 / (f_den * _d1 * _d2)
|
||||
# R = add(R, nQ2) This line is in many specifications but it technically does nothing
|
||||
return f ** ((field_modulus ** 12 - 1) // curve_order)
|
||||
if final_exponentiate:
|
||||
return f ** ((field_modulus ** 12 - 1) // curve_order)
|
||||
else:
|
||||
return f
|
||||
|
||||
# Pairing computation
|
||||
def pairing(Q, P):
|
||||
def pairing(Q, P, final_exponentiate=True):
|
||||
assert is_on_curve(Q, b2)
|
||||
assert is_on_curve(P, b)
|
||||
return miller_loop(twist(Q), cast_point_to_fq12(P))
|
||||
if P[-1] == P[-1].__class__.zero() or Q[-1] == Q[-1].__class__.zero():
|
||||
return FQ12.one()
|
||||
return miller_loop(twist(Q), cast_point_to_fq12(P), final_exponentiate=final_exponentiate)
|
||||
|
||||
def final_exponentiate(p):
|
||||
return p ** ((field_modulus ** 12 - 1) // curve_order)
|
||||
|
|
Loading…
Reference in New Issue