Merge branch 'lash/symbol-proofs' into 'master'
feat: Add token symbol proof metadata references See merge request cicnet/cic-cli!1
This commit is contained in:
commit
5063b08b42
@ -44,7 +44,7 @@ class Attachment(Data):
|
||||
return self.contents
|
||||
|
||||
|
||||
def process(self, token_address=None, writer=None):
|
||||
def process(self, token_address=None, token_symbol=None, writer=None):
|
||||
if writer == None:
|
||||
writer = self.writer
|
||||
|
||||
@ -59,7 +59,6 @@ class Attachment(Data):
|
||||
|
||||
def __str__(self):
|
||||
s = ''
|
||||
#for i in range(len(self.contents)):
|
||||
for k in self.contents.keys():
|
||||
s += '{} = {}\n'.format(k, self.contents[k]) #self.digests[i].hex(), self.contents[i])
|
||||
|
||||
|
@ -12,7 +12,10 @@ from cic import (
|
||||
Proof,
|
||||
Processor,
|
||||
)
|
||||
from cic.output import HTTPWriter
|
||||
from cic.output import (
|
||||
HTTPWriter,
|
||||
KeyedWriterFactory,
|
||||
)
|
||||
from cic.meta import (
|
||||
Meta,
|
||||
MetadataWriter,
|
||||
@ -66,8 +69,8 @@ def execute(config, eargs):
|
||||
MetadataSigner.gpg_path = os.path.join('/tmp')
|
||||
MetadataSigner.key_file_path = '/home/lash/src/client/cic/grassrootseconomics/cic-internal-integration/apps/cic-ussd/tests/data/pgp/privatekeys_meta.asc'
|
||||
MetadataSigner.gpg_passphrase = 'merman'
|
||||
writers['proof'] = HTTPWriter
|
||||
writers['attachment'] = HTTPWriter
|
||||
writers['proof'] = KeyedWriterFactory(MetadataWriter, HTTPWriter).new
|
||||
writers['attachment'] = KeyedWriterFactory(None, HTTPWriter).new
|
||||
writers['meta'] = MetadataWriter
|
||||
output_writer_path_meta = eargs.metadata_endpoint
|
||||
|
||||
@ -77,10 +80,10 @@ def execute(config, eargs):
|
||||
cp = Proof(path=eargs.directory, attachments=ca, writer=writers['proof'](path=output_writer_path_meta))
|
||||
cn = Network(path=eargs.directory)
|
||||
|
||||
ca.load()
|
||||
ct.load()
|
||||
cp.load()
|
||||
cm.load()
|
||||
ca.load()
|
||||
cn.load()
|
||||
|
||||
chain_spec = None
|
||||
|
@ -2,5 +2,6 @@
|
||||
"version": 0,
|
||||
"namespace": "ge",
|
||||
"issuer": "",
|
||||
"description": ""
|
||||
"description": null,
|
||||
"proofs": []
|
||||
}
|
||||
|
@ -224,11 +224,15 @@ class CICEth(Extension):
|
||||
c = Declarator(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle, gas_oracle=gas_oracle)
|
||||
|
||||
results = []
|
||||
(main_proof, all_proofs) = self.proof.get()
|
||||
for proof in all_proofs:
|
||||
logg.debug('proof {} '.format(proof))
|
||||
k = 'address_declarator_' + proof
|
||||
o = c.add_declaration(contract_address, signer_address, self.token_address, proof, tx_format=self.tx_format)
|
||||
#(main_proof, all_proofs) = self.proof.get()
|
||||
|
||||
#for proof in all_proofs:
|
||||
#logg.debug('proof {} '.format(proof))
|
||||
|
||||
(k, v) = self.proof.root()
|
||||
|
||||
fk = 'address_declarator_' + k
|
||||
o = c.add_declaration(contract_address, signer_address, self.token_address, k, tx_format=self.tx_format)
|
||||
r = None
|
||||
if self.rpc != None:
|
||||
r = self.rpc.do(o[1])
|
||||
@ -237,11 +241,11 @@ class CICEth(Extension):
|
||||
r = o[1]
|
||||
else:
|
||||
r = o
|
||||
self.add_outputs(k, r)
|
||||
self.add_outputs(fk, r)
|
||||
results.append(r)
|
||||
v = r.encode('utf-8')
|
||||
if writer != None:
|
||||
writer.write(k, v)
|
||||
writer.write(fk, v)
|
||||
|
||||
return results
|
||||
|
||||
|
@ -95,6 +95,7 @@ class Extension:
|
||||
tasks = []
|
||||
self.token_address = self.resources['token']['reference']
|
||||
|
||||
# TODO: get token details when token address is not none
|
||||
if self.token_address == None:
|
||||
if self.token_details['code'] == None:
|
||||
raise RuntimeError('neither token address nor token code has been set')
|
||||
@ -114,4 +115,4 @@ class Extension:
|
||||
logg.debug('ciceth adapter process {}'.format(task))
|
||||
r = getattr(self, 'process_' + task)(writer=writer)
|
||||
|
||||
return self.token_address
|
||||
return (self.token_address, self.token_details['symbol'])
|
||||
|
28
cic/meta.py
28
cic/meta.py
@ -1,6 +1,8 @@
|
||||
# standard imports
|
||||
import os
|
||||
import json
|
||||
import logging
|
||||
import base64
|
||||
|
||||
# external imports
|
||||
from cic_types import MetadataPointer
|
||||
@ -14,6 +16,7 @@ from .base import (
|
||||
data_dir,
|
||||
)
|
||||
from cic.output import OutputWriter
|
||||
logg = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Meta(Data):
|
||||
@ -66,12 +69,18 @@ class Meta(Data):
|
||||
}
|
||||
|
||||
|
||||
def process(self, token_address=None, writer=None):
|
||||
def process(self, token_address=None, token_symbol=None, writer=None):
|
||||
if writer == None:
|
||||
writer = self.writer
|
||||
|
||||
k = self.reference(token_address)
|
||||
v = json.dumps(self.asdict())
|
||||
|
||||
token_address_bytes = bytes.fromhex(strip_0x(token_address))
|
||||
k = generate_metadata_pointer(token_address_bytes, MetadataPointer.TOKEN_META)
|
||||
writer.write(k, v.encode('utf-8'))
|
||||
|
||||
token_symbol_bytes = token_symbol.encode('utf-8')
|
||||
k = generate_metadata_pointer(token_symbol_bytes, MetadataPointer.TOKEN_META_SYMBOL)
|
||||
writer.write(k, v.encode('utf-8'))
|
||||
|
||||
return (k, v)
|
||||
@ -91,5 +100,16 @@ class Meta(Data):
|
||||
class MetadataWriter(OutputWriter):
|
||||
|
||||
def write(self, k, v):
|
||||
rq = MetadataRequestsHandler(MetadataPointer.TOKEN_META, bytes.fromhex(k))
|
||||
return rq.create(json.loads(v.decode('utf-8')))
|
||||
rq = MetadataRequestsHandler(MetadataPointer.NONE, bytes.fromhex(k))
|
||||
try:
|
||||
v = v.decode('utf-8')
|
||||
v = json.loads(v)
|
||||
logg.debug('metadatawriter bindecode {} {}'.format(k, v))
|
||||
except UnicodeDecodeError:
|
||||
v = base64.b64encode(v).decode('utf-8')
|
||||
v = json.loads(json.dumps(v))
|
||||
logg.debug('metadatawriter b64encode {} {}'.format(k, v))
|
||||
r = rq.create(v)
|
||||
logg.info('metadata submitted at {}'.format(k))
|
||||
return r
|
||||
|
||||
|
@ -48,6 +48,48 @@ class HTTPWriter(OutputWriter):
|
||||
|
||||
|
||||
def write(self, k, v):
|
||||
rq = urllib.request.Request(self.path, method='POST', data=v)
|
||||
path = self.path
|
||||
if k != None:
|
||||
path = os.path.join(path, k)
|
||||
logg.debug('http writer post {}'.format(path))
|
||||
rq = urllib.request.Request(path, method='POST', data=v)
|
||||
r = urllib.request.urlopen(rq)
|
||||
logg.info('proof submited at {}'.format(r.read))
|
||||
logg.info('http writer submitted at {}'.format(r.read()))
|
||||
|
||||
|
||||
class KeyedWriter(OutputWriter):
|
||||
|
||||
def __init__(self, writer_keyed, writer_immutable):
|
||||
self.writer_keyed = writer_keyed
|
||||
self.writer_immutable = writer_immutable
|
||||
|
||||
|
||||
def write(self, k, v):
|
||||
logg.debug('writing keywriter {} {}'.format(k, v))
|
||||
if isinstance(v, str):
|
||||
v = v.encode('utf-8')
|
||||
if self.writer_keyed != None:
|
||||
self.writer_keyed.write(k, v)
|
||||
if self.writer_immutable != None:
|
||||
self.writer_immutable.write(None, v)
|
||||
|
||||
|
||||
class KeyedWriterFactory:
|
||||
|
||||
def __init__(self, key_writer_constructor, immutable_writer_constructor, *args, **kwargs):
|
||||
self.key_writer_constructor = key_writer_constructor
|
||||
self.immutable_writer_constructor = immutable_writer_constructor
|
||||
self.x = {}
|
||||
for k in kwargs.keys():
|
||||
logg.debug('adding key {} t keyed writer factory'.format(k))
|
||||
self.x[k] = kwargs[k]
|
||||
|
||||
|
||||
def new(self, path=None, *args, **kwargs):
|
||||
writer_keyed = None
|
||||
writer_immutable = None
|
||||
if self.key_writer_constructor != None:
|
||||
writer_keyed = self.key_writer_constructor(path, **self.x)
|
||||
if self.immutable_writer_constructor != None:
|
||||
writer_immutable = self.immutable_writer_constructor(path, **self.x)
|
||||
return KeyedWriter(writer_keyed, writer_immutable)
|
||||
|
@ -39,7 +39,7 @@ class Processor:
|
||||
]
|
||||
|
||||
for ext in self.extensions:
|
||||
token_address = ext.process()
|
||||
(token_address, token_symbol) = ext.process()
|
||||
|
||||
for task in tasks:
|
||||
a = self.cores.get(task)
|
||||
@ -47,5 +47,5 @@ class Processor:
|
||||
if a == None:
|
||||
logg.debug('skipping missing task receiver "{}"'.format(task))
|
||||
continue
|
||||
v = a.process(token_address=token_address, writer=self.__outputs_writer)
|
||||
v = a.process(token_address=token_address, token_symbol=token_symbol, writer=self.__outputs_writer)
|
||||
self.outputs.append(v)
|
||||
|
88
cic/proof.py
88
cic/proof.py
@ -22,6 +22,7 @@ class Proof(Data):
|
||||
|
||||
def __init__(self, path='.', attachments=None, writer=None):
|
||||
super(Proof, self).__init__()
|
||||
self.proofs = []
|
||||
self.namespace = 'ge'
|
||||
self.description = None
|
||||
self.path = path
|
||||
@ -43,6 +44,15 @@ class Proof(Data):
|
||||
self.description = o['description']
|
||||
self.namespace = o['namespace']
|
||||
self.issuer = o['issuer']
|
||||
self.proofs = o['proofs']
|
||||
|
||||
if self.extra_attachments != None:
|
||||
a = self.extra_attachments.asdict()
|
||||
for k in a.keys():
|
||||
self.attachments[k] = a[k]
|
||||
|
||||
hshs = self.__get_ordered_hashes()
|
||||
self.proofs = list(map(strip_0x, hshs))
|
||||
|
||||
self.inited = True
|
||||
|
||||
@ -67,6 +77,7 @@ class Proof(Data):
|
||||
'namespace': self.namespace,
|
||||
'description': self.description,
|
||||
'issuer': self.issuer,
|
||||
'proofs': self.proofs,
|
||||
}
|
||||
|
||||
|
||||
@ -77,50 +88,65 @@ class Proof(Data):
|
||||
return ks
|
||||
|
||||
|
||||
def get(self):
|
||||
v = self.asdict()
|
||||
b = cbor2.dumps(v)
|
||||
# def get(self):
|
||||
# hsh = self.hash(b).hex()
|
||||
# self.attachments[hsh] = self.temp_proof_path
|
||||
# logg.debug('cbor of {} is {} hashes to {}'.format(v, b.hex(), hsh))
|
||||
|
||||
f = open(self.temp_proof_path, 'wb')
|
||||
|
||||
def root(self):
|
||||
v = self.asdict()
|
||||
#b = cbor2.dumps(v)
|
||||
b = json.dumps(v)
|
||||
|
||||
f = open(self.temp_proof_path, 'w')
|
||||
f.write(b)
|
||||
f.close()
|
||||
|
||||
hsh = self.hash(b).hex()
|
||||
self.attachments[hsh] = self.temp_proof_path
|
||||
logg.debug('cbor of {} is {} hashes to {}'.format(v, b.hex(), hsh))
|
||||
k = self.hash(b.encode('utf-8'))
|
||||
|
||||
if self.extra_attachments != None:
|
||||
a = self.extra_attachments.asdict()
|
||||
for k in a.keys():
|
||||
self.attachments[k] = a[k]
|
||||
|
||||
hshs = self.__get_ordered_hashes()
|
||||
|
||||
return (hsh, hshs)
|
||||
return (k.hex(), b)
|
||||
|
||||
|
||||
def process(self, token_address=None, writer=None):
|
||||
def process(self, token_address=None, token_symbol=None, writer=None):
|
||||
if writer == None:
|
||||
writer = self.writer
|
||||
|
||||
(hsh, hshs) = self.get()
|
||||
hshs = list(map(strip_0x, hshs))
|
||||
hshs_bin = list(map(bytes.fromhex, hshs))
|
||||
hshs_cat = b''.join(hshs_bin)
|
||||
|
||||
f = open(self.temp_proof_path, 'rb')
|
||||
v = f.read()
|
||||
(k, v) = self.root()
|
||||
writer.write(k, v)
|
||||
|
||||
token_symbol_bytes = token_symbol.encode('utf-8')
|
||||
k = generate_metadata_pointer(token_symbol_bytes, MetadataPointer.TOKEN_PROOF_SYMBOL)
|
||||
writer.write(k, v)
|
||||
|
||||
token_address_bytes = bytes.fromhex(strip_0x(token_address))
|
||||
k = generate_metadata_pointer(token_address_bytes, MetadataPointer.TOKEN_PROOF)
|
||||
writer.write(k, v)
|
||||
|
||||
# (hsh, hshs) = self.get()
|
||||
#hshs = list(map(strip_0x, hshs))
|
||||
# hshs_bin = list(map(bytes.fromhex, hshs))
|
||||
# hshs_cat = b''.join(hshs_bin)
|
||||
|
||||
# f = open(self.temp_proof_path, 'rb')
|
||||
# v = f.read()
|
||||
# f.close()
|
||||
# writer.write(hsh, v)
|
||||
|
||||
# r = self.hash(hshs_cat)
|
||||
# r_hex = r.hex()
|
||||
|
||||
#logg.debug('generated proof {} for hashes {}'.format(r_hex, hshs))
|
||||
|
||||
#writer.write(r_hex, hshs_cat)
|
||||
|
||||
o = self.asdict()
|
||||
f = open(self.proof_path, 'w')
|
||||
json.dump(o, f, sort_keys=True, indent="\t")
|
||||
f.close()
|
||||
writer.write(hsh, v)
|
||||
|
||||
r = self.hash(hshs_cat)
|
||||
r_hex = r.hex()
|
||||
|
||||
logg.debug('generated proof {} for hashes {}'.format(r_hex, hshs))
|
||||
|
||||
writer.write(r_hex, hshs_cat)
|
||||
|
||||
return r_hex
|
||||
return k
|
||||
|
||||
|
||||
def __str__(self):
|
||||
|
@ -1,5 +1,5 @@
|
||||
funga-eth>=0.5.0a1,<0.6.0
|
||||
cic-types>=0.2.0a4,<=0.2.0
|
||||
cic-types>=0.2.1a1,<=0.2.1
|
||||
confini>=0.4.2rc3,<0.5.0
|
||||
chainlib>=0.0.10a3,<0.1.0
|
||||
cbor2==5.4.1
|
||||
|
@ -22,8 +22,7 @@ test_data_dir = os.path.join(test_base_dir, 'testdata')
|
||||
proof_hash = '0f6fc017f29caf512c0feaaf83bc10614b488311cace2973dc248dc24b01e04f'
|
||||
foo_hash = '2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae'
|
||||
bar_hash = 'fcde2b2edba56bf408601fb721fe9b5c338d10ee429ea04fae5511b68fbf8fb9'
|
||||
root_merged_hash = 'ba135f8518d36af5fa65c59317ea9602c4b654d998ea9097ecf81e0638a03441'
|
||||
root_unmerged_hash = '68ccfe99fd905be439b09dcd780993865598605b8492462a6fc4f127b688fef6'
|
||||
root_merged_hash = '4bd0ad4305a5fee20fb80e179a437c296f6a769ca376d746a3848a80e9b7a1a6'
|
||||
|
||||
|
||||
class TestCICBase(unittest.TestCase):
|
||||
@ -37,6 +36,7 @@ class TestCICBase(unittest.TestCase):
|
||||
add_0x(random.randbytes(20).hex()),
|
||||
add_0x(random.randbytes(20).hex()),
|
||||
]
|
||||
self.token_symbol = 'FOO'
|
||||
self.token_address = add_0x(random.randbytes(32).hex())
|
||||
self.token_index_address = add_0x(random.randbytes(32).hex())
|
||||
self.address_declarator_address = add_0x(random.randbytes(32).hex())
|
||||
|
@ -12,7 +12,6 @@ from tests.base_cic import (
|
||||
test_data_dir,
|
||||
TestCICBase,
|
||||
root_merged_hash,
|
||||
root_unmerged_hash,
|
||||
)
|
||||
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
@ -20,14 +19,6 @@ logg = logging.getLogger()
|
||||
|
||||
class TestProof(TestCICBase):
|
||||
|
||||
def test_proof_serialize(self):
|
||||
proof_path = os.path.join(test_data_dir, 'proof')
|
||||
c = Proof(path=proof_path, writer=self.outputs_writer)
|
||||
c.load()
|
||||
v = c.process()
|
||||
self.assertEqual(v, root_unmerged_hash)
|
||||
|
||||
|
||||
def test_proof_serialize_merge(self):
|
||||
proof_path = os.path.join(test_data_dir, 'proof')
|
||||
|
||||
@ -36,7 +27,7 @@ class TestProof(TestCICBase):
|
||||
|
||||
c = Proof(path=proof_path, attachments=attach, writer=self.outputs_writer)
|
||||
c.load()
|
||||
v = c.process()
|
||||
v = c.process(token_address=self.token_address, token_symbol=self.token_symbol)
|
||||
self.assertEqual(v, root_merged_hash)
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user