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
2 changes: 1 addition & 1 deletion mst/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
# Use of this source code is governed by an MIT
# license that can be found in the LICENSE file.

__version__ = "0.1.1"
__version__ = "0.2.0"
16 changes: 8 additions & 8 deletions mst/args.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,18 +128,10 @@ def parse_msc_args(raw_args):

verify_group = parser_verify.add_mutually_exclusive_group()

verify_group.add_argument('-f', '--file', type=str,
dest='file',
help="Verify the commitment of the checksum of the specified file.")

verify_group.add_argument('-r', '--read', type=str,
dest='read',
help="Verify the sequence proof in the supplied file.")

verify_group.add_argument("-c","--commit", type=str,
dest='commitment',
help="Verify the attestation of a given commitment hex and return block details")

verify_group.add_argument("-p","--proof", type=str,
dest='proof',
help="Verify the given sequence proof (as a JSON object). If 0, a stored proof is verified.")
Expand Down Expand Up @@ -178,6 +170,14 @@ def parse_msc_args(raw_args):

list_group = parser_verify.add_mutually_exclusive_group()

list_group.add_argument("-c","--commit", type=str,
dest='commitment',
help="Verify the attestation of a given commitment hex and return block details")

list_group.add_argument('-f', '--file', type=str,
dest='file',
help="Verify the commitment of the checksum of the specified file.")

list_group.add_argument("-l","--list", type=str,
dest='list',
help="Verify the list of comma separated commitments against the sequence proof")
Expand Down
178 changes: 134 additions & 44 deletions mst/cmds.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,9 @@ def update_proofseq(service_url,seq,slot,txid):
"merkle_root":sproof["merkle_root"],
"ops":sproof["ops"],
"date":sproof["date"],
"height":'0'}
"height":'0',
"block": '',
"time": ''}
if "additions" in sproof:
addproof["additions"] = sproof["additions"]
if sproof["confirmed"]:
Expand Down Expand Up @@ -235,8 +237,13 @@ def attest_command(args):

if args.dropbox_checksum:
proof_checksum = dropbox_checksum
message = "Dropbox SHA256 hash"
elif args.md5_checksum:
proof_checksum = md5_checksum
message = "SHA256 derived from MD5 hash"
else:
proof_checksum = sha256sum
message = "SHA256"

if args.slot:
slot = str(args.slot)
Expand Down Expand Up @@ -274,15 +281,8 @@ def attest_command(args):
return False
commitment = args.commitment

if args.filename or args.md5_checksum:
if args.filename:
arg = args.filename
message = "SHA256"
proof_checksum = sha256sum
if args.md5_checksum:
arg = args.md5_checksum
message = "SHA256 derived from MD5 hash"
proof_checksum = md5_checksum
if args.filename:
arg = args.filename
if arg[0] == '/':
filename = arg
else:
Expand Down Expand Up @@ -567,10 +567,13 @@ def verify_command(args):

if args.dropbox_checksum:
proof_checksum = dropbox_checksum
message = "Dropbox SHA256 hash"
elif args.md5_checksum:
proof_checksum = md5_checksum
message = "SHA256 derived from MD5 hash"
else:
proof_checksum = sha256sum
message = "SHA256"

if args.bitcoin_node:
bitcoin_node = args.bitcoin_node
Expand Down Expand Up @@ -605,36 +608,74 @@ def verify_command(args):
if not is_hex(args.commitment):
logging.error("Invalid commitment string: not hex")
return False
addproof = get_proof_from_commit(slot,args.commitment)
if not addproof:
logging.info("Retrieving slot proof from "+args.service_url)
rstring = "/api/v1/commitment/commitment?commitment="+args.commitment
sproof = get_mainstay_api(args.service_url,rstring)
if 'response' not in sproof:
logging.info("Status: "+sproof["error"])
return False, sproof["error"]
addproof = {"txid":sproof["response"]["attestation"]["txid"],
"commitment":sproof["response"]["merkleproof"]["commitment"],
"merkle_root":sproof["response"]["merkleproof"]["merkle_root"],
"ops":sproof["response"]["merkleproof"]["ops"],
"date":sproof["response"]["attestation"]["inserted_at"]}
if sproof["response"]["attestation"]["confirmed"]:
ver,_ = verify_commitment(slot,addproof,bitcoin_node)
ver_com = "Verified commitment "+ver[0]+" in slot "+str(slot)+" in TxID "+ver[1]
ver_block = "In Bitcoin block "+ver[2]+" height "+ver[3]+" at "+ver[4]
if args.commitment != ver[0]:
try:
if verify_addition_proof(sproof["response"]["addproof"],sproof["response"]["merkleproof"]["commitment"]):
logging.info("Verified addition "+sproof["response"]["addproof"]["addition"]+" in commitment")
else:
logging.info("ERROR: Not verified addition "+sproof["addproof"]["addition"]+" in commitment")
except:
logging.error("ERROR: Commitment addition verification failure")
logging.info(ver_com+"\n"+ver_block)
return True, ver_com, ver_block
else:
logging.info("Status: Awaiting Confirmation")
return False, "Awaiting Confirmation"
logging.info("Retrieving slot proof from "+args.service_url)
rstring = "/api/v1/commitment/commitment?commitment="+args.commitment
sproof = get_mainstay_api(args.service_url,rstring)
if 'response' not in sproof:
logging.info("Status: "+sproof["error"])
return False, sproof["error"]
addproof = {"txid":sproof["response"]["attestation"]["txid"],
"commitment":sproof["response"]["merkleproof"]["commitment"],
"merkle_root":sproof["response"]["merkleproof"]["merkle_root"],
"ops":sproof["response"]["merkleproof"]["ops"],
"date":sproof["response"]["attestation"]["inserted_at"]}
if sproof["response"]["attestation"]["confirmed"]:
ver,_ = verify_commitment(slot,addproof,bitcoin_node)
ver_com = "Verified commitment "+ver[0]+" in slot "+str(slot)+" in TxID "+ver[1]
ver_block = "In Bitcoin block "+ver[2]+" height "+ver[3]+" at "+ver[4]
if args.commitment != ver[0]:
try:
if verify_addition_proof(sproof["response"]["addproof"],sproof["response"]["merkleproof"]["commitment"]):
logging.info("Verified addition "+sproof["response"]["addproof"]["addition"]+" in commitment")
else:
logging.info("ERROR: Not verified addition "+sproof["addproof"]["addition"]+" in commitment")
except:
logging.error("ERROR: Commitment addition verification failure")
logging.info(ver_com+"\n"+ver_block)
return True, ver_com, ver_block
else:
logging.info("Status: Awaiting Confirmation")
return False, "Awaiting Confirmation"

if args.file:
arg = args.filename
if arg[0] == '/':
filename = arg
else:
filename = os.getcwd() + '/' + arg
try:
commitment = proof_checksum(filename)
except:
logging.error("ERROR: could not open specified file")
return False
logging.info("Retrieving slot proof from "+args.service_url)
rstring = "/api/v1/commitment/commitment?commitment="+args.commitment
sproof = get_mainstay_api(args.service_url,rstring)
if 'response' not in sproof:
logging.info("Status: "+sproof["error"])
return False, sproof["error"]
addproof = {"txid":sproof["response"]["attestation"]["txid"],
"commitment":sproof["response"]["merkleproof"]["commitment"],
"merkle_root":sproof["response"]["merkleproof"]["merkle_root"],
"ops":sproof["response"]["merkleproof"]["ops"],
"date":sproof["response"]["attestation"]["inserted_at"]}
if sproof["response"]["attestation"]["confirmed"]:
ver,_ = verify_commitment(slot,addproof,bitcoin_node)
ver_com = "Verified commitment "+ver[0]+" in slot "+str(slot)+" in TxID "+ver[1]
ver_block = "In Bitcoin block "+ver[2]+" height "+ver[3]+" at "+ver[4]
if args.commitment != ver[0]:
try:
if verify_addition_proof(sproof["response"]["addproof"],sproof["response"]["merkleproof"]["commitment"]):
logging.info("Verified addition "+sproof["response"]["addproof"]["addition"]+" in commitment")
else:
logging.info("ERROR: Not verified addition "+sproof["addproof"]["addition"]+" in commitment")
except:
logging.error("ERROR: Commitment addition verification failure")
logging.info(ver_com+"\n"+ver_block)
return True, ver_com, ver_block
else:
logging.info("Status: Awaiting Confirmation")
return False, "Awaiting Confirmation"

if args.unspent:
if len(args.unspent) != 64:
Expand Down Expand Up @@ -669,8 +710,8 @@ def verify_command(args):
logging.info(ver_com+"\n"+ver_block)
return False

if args.filename:
seq = readfromfile(args.filename)
if args.read:
seq = readfromfile(args.file)
elif args.proof:
if args.proof == '0':
seq = load_proofseq(slot)
Expand Down Expand Up @@ -793,9 +834,7 @@ def verify_command(args):
except:
logging.error("ERROR: Invalid directory path.")
return False

filelist.sort()

if dir_path[-1] != '/':
dir_path += '/'
time = 0
Expand Down Expand Up @@ -850,6 +889,52 @@ def verify_command(args):
logging.warning("Last file attested: "+fmatch[0])
return True

if args.additions:
if args.directory == '0':
try:
dir_path = str(settings["directory"])
except:
logging.error("Missing directory path in config and argument")
return False
else:
dir_path = args.additions
try:
filelist = os.listdir(dir_path)
except:
logging.error("ERROR: Invalid directory path.")
return False
logging.info("Directory: "+dir_path+" contains "+str(len(filelist))+ "files")
if dir_path[-1] != '/':
dir_path += '/'
#create list of hashes
filehl = {}
for file in filelist:
filehl[file] = proof_checksum(dir_path+file)

#search sequence for file hashes
addedc = []
addedf = []
oads = []
for sproof in seq:
# zero commits are null and skipped
if sproof["commitment"] == '0'*64: continue
ads = sproof["additions"]
for ad in ads:
if ad not in addedc:
try:
filename = filehl[ad]
addedc.append(ad)
addedf.append(filename)
logging.info("File "+filename+" committed in block "+sproof["block"]+" "+sproof["date"])
except:
logging.info("WARNING: No file for commitment "+ad+" in block "+sproof["block"])
logging.info(" ")
for file in filelist:
if file not in addedf:
logging.info("WARNING: File "+file+" not committed to slot")
return True


verout = []
nseq = []
txin = None
Expand All @@ -867,10 +952,15 @@ def verify_command(args):
verout.append(ver)
logging.debug("Verified commitment "+ver[0]+" in slot "+str(slot)+" in TxID "+ver[1])
logging.debug("In Bitcoin block "+ver[2]+" height "+ver[3]+" at "+ver[4])
sproof["block"] = ver[2]
sproof["height"] = ver[3]
sproof["time"] = ver[4]
nseq.append(sproof)
schain.append(sproof["txid"])

#TODO:
#verify addition commitment paths to the slot commitment

if args.proof:
if args.proof == '0':
save_proofseq(slot,nseq)
Expand Down
10 changes: 5 additions & 5 deletions mst/verify.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@
import mst.rpchost as rpc
from mst.ecc import bfh, hfu, bh2u, to_bytes, sha256, Hash, hash_160

BASE_PUBKEYS = ["03639a65bfb3dd5a579e65231a4e70327aba358e956d6e10f7ea2e25dd631e4d66","024f714a1b93697c5a3865259ac3a865bb306e8b720c3bec46bae3298ef3fa7964","035ea174407b61b85fc83993084c471f78095779737a75adf2a2e52cdd2a36edd3"]
MAINSTAY_CHAINCODES = ["8c57ec95db9ddab3b17ea5ae8c1411bbc0859d1a5262ff67d475cc880e14cfd9","087c28f8989d4a5e692127dbaeffc86b7d2d44b878b3a585b2c98967c854ed8d","2f94eeb596c3c7d9a5746b17150412a3c5f4f9f999ffb2395fc59a14bcfc4271"]
BASE_PUBKEYS = ["024f714a1b93697c5a3865259ac3a865bb306e8b720c3bec46bae3298ef3fa7964"]
MAINSTAY_CHAINCODES = ["087c28f8989d4a5e692127dbaeffc86b7d2d44b878b3a585b2c98967c854ed8d"]

APPDIRS = appdirs.AppDirs('msc','mainstay')

Expand Down Expand Up @@ -66,8 +66,8 @@ def multisig_script(public_keys: Sequence[str], m: int) -> str:
n = len(public_keys)
assert n <= 15
assert m <= n
op_m = '52'
op_n = '53'
op_m = '51'
op_n = '51'
keylist = ['21' + k for k in public_keys]
return op_m + ''.join(keylist) + op_n + 'ae'

Expand Down Expand Up @@ -120,7 +120,7 @@ def tweak_script(path):
for index in path:
cK, c = CKD_pub(cK, c, int.from_bytes(index,'big'))
tweaked_keys.append(bh2u(cK))
tweaked_script = multisig_script(tweaked_keys, 2)
tweaked_script = multisig_script(tweaked_keys, 1)
return hash_160(bytes.fromhex(tweaked_script))

def verify_p2c_commitment(proof, tx):
Expand Down
7 changes: 7 additions & 0 deletions release-notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,10 @@
## v0.1.0

Initial release.

## v0.2.0

21st October 2020

Switch to new pubkey script and chain code.
Addition commit verification functionality.
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

# The project's main homepage.
url='https://github.com/commerceblock/pymainstay',
download_url='https://github.com/commerceblock/pymainstay/archive/0.1.1.tar.gz',
download_url='https://github.com/commerceblock/pymainstay/archive/0.2.0.tar.gz',

# Author details
author='CommerceBlock',
Expand Down