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.types import Float
from sqlalchemy_json import MutableJson
from sqlalchemy import and_, or_, not_
import hashlib
import json
@ -93,6 +94,23 @@ class Slate(db.Model):
list_slates.append(slate_db.slate)
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
def add(cls, slate, receivingAddress):
from funding.factory import db
@ -112,3 +130,73 @@ class Slate(db.Model):
except Exception as ex:
db.session.rollback()
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
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('/')
@ -50,15 +53,162 @@ def postSlate(receivingAddress, slate):
@app.route('/getSlates', methods=['POST'])
@endpoint.api(
parameter('receivingAddress', type=str, required=True),
parameter('signature', type=str, required=True)
)
def getSlates(receivingAddress):
def getSlates(receivingAddress, signature):
try:
if receivingAddress is None:
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 = Slate.find_slates(address=receivingAddress)
return make_response(jsonify({'status': 'success', 'slates': slates}))
except Exception as ex:
print(f'{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

@ -15,3 +15,5 @@ pillow-simd
Flask-Caching
flask-sqlalchemy
sqlalchemy_json
secp256k1
base58