Compare commits

...

5 Commits

3 changed files with 244 additions and 4 deletions

View File

@ -10,6 +10,7 @@ from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.types import Float from sqlalchemy.types import Float
from sqlalchemy_json import MutableJson from sqlalchemy_json import MutableJson
from sqlalchemy import and_, or_, not_
import hashlib import hashlib
import json import json
@ -93,6 +94,23 @@ class Slate(db.Model):
list_slates.append(slate_db.slate) list_slates.append(slate_db.slate)
return list_slates return list_slates
@classmethod
def delete_slate(cls, address, slate):
q = cls.query
q = q.filter(and_(Slate.receivingAddress == address, Slate.slate == slate) )
result = q.first()
if result is None:
print("none guy")
return True
try:
db.session.delete(result)
db.session.commit()
db.session.flush()
return True
except Exception as ex:
db.session.rollback()
return False
@classmethod @classmethod
def add(cls, slate, receivingAddress): def add(cls, slate, receivingAddress):
from funding.factory import db from funding.factory import db
@ -112,3 +130,73 @@ class Slate(db.Model):
except Exception as ex: except Exception as ex:
db.session.rollback() db.session.rollback()
raise raise
class Cancel(db.Model):
__tablename__ = "cancels"
id = db.Column(db.Integer, primary_key=True)
slate_id = db.Column(db.String())
# TODO: clear slatse that have been in the database past a certain time
posted_time = db.Column(db.DateTime)
receivingAddress = db.Column(db.String(52), nullable=False)
sendersAddress = db.Column(db.String(52), nullable=False)
def __init__(self, slate_id, receivingAddress, sendersAddress):
from funding.factory import bcrypt
self.slate_id = slate_id
self.receivingAddress = receivingAddress
self.sendersAddress = sendersAddress
self.posted_time = datetime.utcnow()
def __repr__(self):
return "<Cancel(slate_id='%s', receivingAddress='%s', sendersAddress='%s', posted_time='%s)>" % (
self.slate_id, self.receivingAddress, self.sendersAddress, self.posted_time)
@classmethod
def find_slate_ids(cls, address):
q = cls.query
q = q.filter(Cancel.receivingAddress == address)
result = q.all()
print(f'{result}')
list_slates = []
for slate_db in result:
list_slates.append({slate_db.slate_id: slate_db.sendersAddress})
return list_slates
@classmethod
def delete_slate_id(cls, address, slate_id):
q = cls.query
q = q.filter(and_(Cancel.receivingAddress == address, Cancel.slate_id == slate_id))
result = q.first()
if result is None:
print("none guy")
return True
try:
db.session.delete(result)
db.session.commit()
db.session.flush()
return True
except Exception as ex:
db.session.rollback()
return False
@classmethod
def add(cls, slate_id, receivingAddress, sendersAddress):
from funding.factory import db
try:
previous = cls.query.filter(Cancel.slate_id == slate_id).first()
if previous is not None:
print(previous)
print("was inputted before")
return
# put in new one
new_cancel_request = Cancel(slate_id=slate_id, receivingAddress=receivingAddress, sendersAddress=sendersAddress)
db.session.add(new_cancel_request)
db.session.commit()
db.session.flush()
return new_cancel_request
except Exception as ex:
db.session.rollback()
raise

View File

@ -8,7 +8,10 @@ import json
import settings import settings
from funding.factory import app, db, cache from funding.factory import app, db, cache
from funding.orm import Address, Slate from funding.orm import Address, Slate, Cancel
import secp256k1
import base58
@app.route('/') @app.route('/')
@ -50,15 +53,162 @@ def postSlate(receivingAddress, slate):
@app.route('/getSlates', methods=['POST']) @app.route('/getSlates', methods=['POST'])
@endpoint.api( @endpoint.api(
parameter('receivingAddress', type=str, required=True), parameter('receivingAddress', type=str, required=True),
parameter('signature', type=str, required=True)
) )
def getSlates(receivingAddress): def getSlates(receivingAddress, signature):
try: try:
if receivingAddress is None: if receivingAddress is None or signature is None:
return make_response(jsonify({'status': 'failure', 'error': str("missing correct arguments")})) return make_response(jsonify({'status': 'failure', 'error': str("missing correct arguments")}))
# Deserialize the base-58 address to an internal public key format
# NOTE: This assumes that the network version (which is not part of the key) is exactly 2 bytes
public_key = secp256k1.PublicKey(base58.b58decode_check(receivingAddress)[2:], raw=True)
# Prepare the message bound to the signature: a domain separator and the encoded address
# For some reason, the original client code calls this the "challenge"
message = 'SubscribeRequest_' + receivingAddress
# Deserialize and verify the provided signature against the message and address public key
if not public_key.ecdsa_verify(message.encode(),
public_key.ecdsa_deserialize(bytes(bytearray.fromhex(signature)))):
return make_response(jsonify({'status': 'failure', 'error': str("bad signature")}))
slates = Slate.find_slates(address=receivingAddress) slates = Slate.find_slates(address=receivingAddress)
return make_response(jsonify({'status': 'success', 'slates': slates})) return make_response(jsonify({'status': 'success', 'slates': slates}))
except Exception as ex: except Exception as ex:
print(f'{ex}') print(f'{ex}')
return make_response(jsonify({'status': 'failure', 'error': str(ex)})) return make_response(jsonify({'status': 'failure', 'error': str(ex)}))
@app.route('/deleteSlate', methods=['POST'])
@endpoint.api(
parameter('receivingAddress', type=str, required=True),
parameter('signature', type=str, required=True),
parameter('slate', type=str, required=True)
)
def deleteSlate(receivingAddress, signature, slate):
try:
if slate is None or signature is None or receivingAddress is None:
return make_response(jsonify({'status': 'failure', 'error': str("missing correct arguments")}))
# Deserialize the base-58 address to an internal public key format
# NOTE: This assumes that the network version (which is not part of the key) is exactly 2 bytes
public_key = secp256k1.PublicKey(base58.b58decode_check(receivingAddress)[2:], raw=True)
# Prepare the message bound to the signature: a domain separator and the encoded address
# For some reason, the original client code calls this the "challenge"
message = 'SubscribeRequest_' + receivingAddress
# Deserialize and verify the provided signature against the message and address public key
if not public_key.ecdsa_verify(message.encode(),
public_key.ecdsa_deserialize(bytes(bytearray.fromhex(signature)))):
return make_response(jsonify({'status': 'failure', 'error': str("bad signature")}))
is_deleted = Slate.delete_slate(address=receivingAddress, slate=slate)
return make_response(jsonify({'status': 'success', 'is_deleted': is_deleted}))
except Exception as ex:
print(f'{ex}')
return make_response(jsonify({'status': 'failure', 'error': str(ex)}))
@app.route('/postCancel', methods=['POST'])
@endpoint.api(
parameter('receivingAddress', type=str, required=True),
parameter('signature', type=str, required=True),
parameter('slate', type=str, required=True),
parameter('sendersAddress', type=str, required=True),
)
def postCancel(receivingAddress, signature, slate, sendersAddress):
try:
if sendersAddress is None or slate is None or signature is None or receivingAddress is None:
return make_response(jsonify({'status': 'failure', 'error': str("missing correct arguments")}))
# Deserialize the base-58 address to an internal public key format
# NOTE: This assumes that the network version (which is not part of the key) is exactly 2 bytes
public_key = secp256k1.PublicKey(base58.b58decode_check(sendersAddress)[2:], raw=True)
# Prepare the message bound to the signature: a domain separator and the encoded address
# For some reason, the original client code calls this the "challenge"
message = 'SubscribeRequest_' + sendersAddress
# Deserialize and verify the provided signature against the message and address public key
if not public_key.ecdsa_verify(message.encode(),
public_key.ecdsa_deserialize(bytes(bytearray.fromhex(signature)))):
return make_response(jsonify({'status': 'failure', 'error': str("bad signature")}))
try:
Cancel.add(receivingAddress=receivingAddress, slate_id=slate, sendersAddress=sendersAddress)
except Exception as ex:
print(f'{ex}')
return make_response(jsonify({'status': 'success'}))
except Exception as ex:
print(f'{ex}')
return make_response(jsonify({'status': 'failure', 'error': str(ex)}))
@app.route('/getCancels', methods=['POST'])
@endpoint.api(
parameter('receivingAddress', type=str, required=True),
parameter('signature', type=str, required=True),
)
def getCancels(receivingAddress, signature):
try:
if receivingAddress is None or signature is None:
return make_response(jsonify({'status': 'failure', 'error': str("missing correct arguments")}))
# Deserialize the base-58 address to an internal public key format
# NOTE: This assumes that the network version (which is not part of the key) is exactly 2 bytes
public_key = secp256k1.PublicKey(base58.b58decode_check(receivingAddress)[2:], raw=True)
# Prepare the message bound to the signature: a domain separator and the encoded address
# For some reason, the original client code calls this the "challenge"
message = 'SubscribeRequest_' + receivingAddress
# Deserialize and verify the provided signature against the message and address public key
if not public_key.ecdsa_verify(message.encode(),
public_key.ecdsa_deserialize(bytes(bytearray.fromhex(signature)))):
return make_response(jsonify({'status': 'failure', 'error': str("bad signature")}))
slates = Cancel.find_slate_ids(address=receivingAddress)
return make_response(jsonify({'status': 'success', 'canceled_slates': slates}))
except Exception as ex:
print(f'{ex}')
return make_response(jsonify({'status': 'failure', 'error': str(ex)}))
@app.route('/deleteCancels', methods=['POST'])
@endpoint.api(
parameter('receivingAddress', type=str, required=True),
parameter('signature', type=str, required=True),
parameter('slate', type=str, required=True)
)
def deleteCancels(receivingAddress, signature, slate):
try:
if slate is None or signature is None or receivingAddress is None:
return make_response(jsonify({'status': 'failure', 'error': str("missing correct arguments")}))
# Deserialize the base-58 address to an internal public key format
# NOTE: This assumes that the network version (which is not part of the key) is exactly 2 bytes
public_key = secp256k1.PublicKey(base58.b58decode_check(receivingAddress)[2:], raw=True)
# Prepare the message bound to the signature: a domain separator and the encoded address
# For some reason, the original client code calls this the "challenge"
message = 'SubscribeRequest_' + receivingAddress
# Deserialize and verify the provided signature against the message and address public key
if not public_key.ecdsa_verify(message.encode(),
public_key.ecdsa_deserialize(bytes(bytearray.fromhex(signature)))):
return make_response(jsonify({'status': 'failure', 'error': str("bad signature")}))
is_deleted = Cancel.delete_slate_id(address=receivingAddress, slate_id=slate)
return make_response(jsonify({'status': 'success', 'is_deleted': is_deleted}))
except Exception as ex:
print(f'{ex}')
return make_response(jsonify({'status': 'failure', 'error': str(ex)}))

View File

@ -14,4 +14,6 @@ pypng
pillow-simd pillow-simd
Flask-Caching Flask-Caching
flask-sqlalchemy flask-sqlalchemy
sqlalchemy_json sqlalchemy_json
secp256k1
base58