Request type PK name and default set to dropper if not specified

pull/882/head
kompotkot 2023-08-08 12:17:49 +00:00
rodzic 1bd2f3706b
commit ba78712cc5
4 zmienionych plików z 67 dodań i 86 usunięć

Wyświetl plik

@ -50,26 +50,19 @@ def upgrade():
# Types
op.create_table('call_request_types',
sa.Column('id', sa.UUID(), nullable=False),
sa.Column('request_type', sa.VARCHAR(length=128), nullable=False),
sa.Column('name', sa.VARCHAR(length=128), nullable=False),
sa.Column('description', sa.String(), nullable=True),
sa.Column('required_params', postgresql.ARRAY(sa.String()), nullable=True),
sa.Column('method', sa.String(), nullable=True),
sa.PrimaryKeyConstraint('id', name=op.f('pk_call_request_types')),
sa.UniqueConstraint('id', name=op.f('uq_call_request_types_id'))
sa.PrimaryKeyConstraint('name', name=op.f('pk_call_request_types')),
sa.UniqueConstraint('name', name=op.f('uq_call_request_types_name'))
)
op.create_index(op.f('ix_call_request_types_request_type'), 'call_request_types', ['request_type'], unique=True)
op.add_column('call_requests', sa.Column('call_request_type_id', sa.UUID(), nullable=True))
op.create_foreign_key(op.f('fk_call_requests_call_request_type_id_call_request_types'), 'call_requests', 'call_request_types', ['call_request_type_id'], ['id'], ondelete='CASCADE')
op.add_column('call_requests', sa.Column('call_request_type_name', sa.VARCHAR(length=128), nullable=True))
op.create_foreign_key(op.f('fk_call_requests_call_request_type_name_call_request_types'), 'call_requests', 'call_request_types', ['call_request_type_name'], ['name'], ondelete='CASCADE')
# Manual - Start
op.execute(f"INSERT INTO call_request_types (id, request_type, description, required_params, method) VALUES ('{str(uuid.uuid4())}', 'raw', 'A generic smart contract. You can ask users to submit arbitrary calldata to this contract.',ARRAY ['calldata'],''),('{str(uuid.uuid4())}', 'dropper-v0.2.0', 'A Dropper v0.2.0 contract. You can authorize users to submit claims against this contract.',ARRAY ['dropId','requestID','blockDeadline','amount','signer','signature'],'claim');")
op.execute("UPDATE call_requests SET call_request_type_id = (SELECT call_request_types.id FROM call_request_types INNER JOIN registered_contracts ON call_requests.registered_contract_id = registered_contracts.id WHERE call_request_types.request_type = registered_contracts.contract_type);")
op.alter_column("call_requests", "call_request_type_id", nullable=False)
op.alter_column("call_request_types", "required_params", nullable=False)
op.alter_column("call_request_types", "method", nullable=False)
op.execute(f"INSERT INTO call_request_types (name, description) VALUES ('raw','A generic smart contract. You can ask users to submit arbitrary calldata to this contract.'),('dropper-v0.2.0','A Dropper v0.2.0 contract. You can authorize users to submit claims against this contract.');")
op.execute("UPDATE call_requests SET call_request_type_name = (SELECT call_request_types.name FROM call_request_types INNER JOIN registered_contracts ON call_requests.registered_contract_id = registered_contracts.id WHERE call_request_types.name = registered_contracts.contract_type);")
op.alter_column("call_requests", "call_request_type_name", nullable=False)
# Manual - End
op.drop_index('ix_registered_contracts_contract_type', table_name='registered_contracts')
@ -105,10 +98,10 @@ def upgrade():
# Other
op.create_unique_constraint(op.f('uq_registered_contracts_blockchain_id'), 'registered_contracts', ['blockchain_id', 'metatx_requester_id', 'address'])
op.create_unique_constraint(op.f('uq_call_requests_id'), 'call_requests', ['id'])
op.create_unique_constraint(op.f('uq_registered_contracts_id'), 'registered_contracts', ['id'])
op.create_unique_constraint(op.f('uq_leaderboard_scores_id'), 'leaderboard_scores', ['id'])
op.create_unique_constraint(op.f('uq_leaderboards_id'), 'leaderboards', ['id'])
# op.create_unique_constraint(op.f('uq_call_requests_id'), 'call_requests', ['id'])
# op.create_unique_constraint(op.f('uq_registered_contracts_id'), 'registered_contracts', ['id'])
# op.create_unique_constraint(op.f('uq_leaderboard_scores_id'), 'leaderboard_scores', ['id'])
# op.create_unique_constraint(op.f('uq_leaderboards_id'), 'leaderboards', ['id'])
# ### end Alembic commands ###

Wyświetl plik

@ -82,14 +82,14 @@ def parse_registered_contract_response(
def parse_call_request_response(
obj: Tuple[CallRequest, RegisteredContract, CallRequestType, CallRequestType]
obj: Tuple[CallRequest, RegisteredContract]
) -> data.CallRequestResponse:
return data.CallRequestResponse(
id=obj[0].id,
contract_id=obj[0].registered_contract_id,
contract_address=obj[1].address,
metatx_requester_id=obj[0].metatx_requester_id,
call_request_type=obj[2].request_type,
call_request_type=obj[0].call_request_type_name,
caller=obj[0].caller,
method=obj[0].method,
parameters=obj[0].parameters,
@ -100,38 +100,48 @@ def parse_call_request_response(
def validate_method_and_params(
call_request_type: str,
method: str,
parameters: Dict[str, Any],
request_types: List[CallRequestType],
) -> CallRequestType:
method: str, parameters: Dict[str, Any], call_request_type: Optional[str] = None
) -> str:
"""
Validate the given method and parameters for the specified contract_type.
"""
for rt in request_types:
if rt.request_type == call_request_type:
if method != rt.method:
raise CallRequestMethodValueError(
f"Method must be {rt.method} for {rt.request_type} request type"
)
if call_request_type is None or call_request_type == "dropper-v0.2.0":
call_request_type = "dropper-v0.2.0"
if method != "claim":
raise CallRequestMethodValueError(
"Method must be 'claim' for dropper contract type"
)
required_params = {
"dropId",
"requestID",
"blockDeadline",
"amount",
"signer",
"signature",
}
if set(parameters.keys()) != required_params:
raise CallRequestRequiredParamsValueError(
f"Parameters must have {required_params} keys for dropper contract type"
)
try:
Web3.toChecksumAddress(parameters["signer"])
except:
raise InvalidAddressFormat("Parameter signer must be a valid address")
required_params_set = set(rt.required_params)
if set(parameters.keys()) != required_params_set:
raise CallRequestRequiredParamsValueError(
f"Parameters must have only {rt.required_params} key for {rt.request_type} request type"
)
elif call_request_type == "raw":
if method != "":
raise CallRequestMethodValueError(
"Method must be empty string for raw contract type"
)
if set(parameters.keys()) != {"calldata"}:
raise CallRequestRequiredParamsValueError(
"Parameters must have only 'calldata' key for raw contract type"
)
if "signer" in parameters:
try:
Web3.toChecksumAddress(parameters["signer"])
except:
raise InvalidAddressFormat(
"Parameter signer must be a valid address"
)
else:
raise UnsupportedCallRequestType(f"Unknown contract type {call_request_type}")
return rt
raise UnsupportedCallRequestType(f"Unknown request type {call_request_type}")
return call_request_type
def register_contract(
@ -353,8 +363,6 @@ def request_calls(
except NoResultFound:
raise ValueError("Invalid registered_contract_id or metatx_requester_id")
request_types = db_session.query(CallRequestType).all()
# Normalize the caller argument using Web3.toChecksumAddress
for specification in call_specs:
normalized_caller = Web3.toChecksumAddress(specification.caller)
@ -362,10 +370,9 @@ def request_calls(
# Validate the method and parameters for the contract_type
try:
call_request_type = validate_method_and_params(
specification.call_request_type,
specification.method,
specification.parameters,
request_types,
method=specification.method,
parameters=specification.parameters,
call_request_type=specification.call_request_type,
)
except UnsupportedCallRequestType as err:
raise UnsupportedCallRequestType(err)
@ -379,6 +386,7 @@ def request_calls(
logger.error(
f"Unhandled error occurred during methods and parameters validation, err: {err}"
)
raise Exception()
expires_at = None
if ttl_days is not None:
@ -386,7 +394,7 @@ def request_calls(
request = CallRequest(
registered_contract_id=registered_contract.id,
call_request_type_id=call_request_type.id,
call_request_type_name=call_request_type,
metatx_requester_id=metatx_requester_id,
caller=normalized_caller,
method=specification.method,
@ -408,20 +416,16 @@ def request_calls(
def get_call_requests(
db_session: Session,
request_id: uuid.UUID,
) -> Tuple[CallRequest, RegisteredContract, CallRequestType, CallRequestType]:
) -> Tuple[CallRequest, RegisteredContract]:
"""
Get call request by ID.
"""
results = (
db_session.query(CallRequest, RegisteredContract, CallRequestType)
db_session.query(CallRequest, RegisteredContract)
.join(
RegisteredContract,
CallRequest.registered_contract_id == RegisteredContract.id,
)
.join(
CallRequestType,
CallRequest.call_request_type_id == CallRequestType.id,
)
.filter(CallRequest.id == request_id)
.all()
)
@ -432,9 +436,9 @@ def get_call_requests(
f"Incorrect number of results found for request_id {request_id}"
)
call_request, registered_contract, call_request_type = results[0]
call_request, registered_contract = results[0]
return (call_request, registered_contract, call_request_type)
return (call_request, registered_contract)
def list_blockchains(
@ -473,15 +477,11 @@ def list_call_requests(
# If show_expired is False, filter out expired requests using current time on database server
query = (
db_session.query(CallRequest, RegisteredContract, CallRequestType)
db_session.query(CallRequest, RegisteredContract)
.join(
RegisteredContract,
CallRequest.registered_contract_id == RegisteredContract.id,
)
.join(
CallRequestType,
CallRequest.call_request_type_id == CallRequestType.id,
)
.filter(CallRequest.caller == Web3.toChecksumAddress(caller))
)

Wyświetl plik

@ -204,8 +204,7 @@ class DropUpdatedResponse(BaseModel):
class CallRequestTypeResponse(BaseModel):
id: UUID
request_type: str
name: str
description: str
class Config:
@ -271,7 +270,7 @@ class RegisteredContractResponse(BaseModel):
class CallSpecification(BaseModel):
caller: str
method: str
call_request_type: str
call_request_type: Optional[str] = None
parameters: Dict[str, Any]
@validator("caller")

Wyświetl plik

@ -165,22 +165,12 @@ class CallRequestType(Base): # type: ignore
__tablename__ = "call_request_types"
id = Column(
UUID(as_uuid=True),
name = Column(
VARCHAR(128),
primary_key=True,
default=uuid.uuid4,
unique=True,
)
request_type = Column(VARCHAR(128), nullable=False, unique=True, index=True)
description = Column(String, nullable=True)
required_params = Column(ARRAY(String), nullable=False)
method = Column(String, nullable=False)
call_requests = relationship(
"CallRequest",
back_populates="call_request_type",
cascade="all, delete, delete-orphan",
)
class MetatxRequester(Base): # type: ignore
@ -301,9 +291,9 @@ class CallRequest(Base):
ForeignKey("registered_contracts.id", ondelete="CASCADE"),
nullable=False,
)
call_request_type_id = Column(
UUID(as_uuid=True),
ForeignKey("call_request_types.id", ondelete="CASCADE"),
call_request_type_name = Column(
VARCHAR(128),
ForeignKey("call_request_types.name", ondelete="CASCADE"),
nullable=False,
)
metatx_requester_id = Column(
@ -332,7 +322,6 @@ class CallRequest(Base):
registered_contract = relationship(
"RegisteredContract", back_populates="call_requests"
)
call_request_type = relationship("CallRequestType", back_populates="call_requests")
metatx_requester = relationship("MetatxRequester", back_populates="call_requests")