require active premium for most websocket subscriptions

only newHeads is allowed without premium
This commit is contained in:
Bryan Stitt 2023-09-25 10:38:55 -07:00
parent d732b8a171
commit 3aee9071ad
4 changed files with 30 additions and 8 deletions

@ -13,6 +13,8 @@ db_replica_url = "mysql://root:dev_web3_proxy@127.0.0.1:13306/dev_web3_proxy"
deposit_factory_contract = "0x4e3BC2054788De923A04936C6ADdB99A05B0Ea36"
free_subscriptions = true
kafka_urls = "127.0.0.1:19092"
kafka_protocol = "plaintext"

@ -31,6 +31,22 @@ impl Web3ProxyApp {
// TODO: taking a sender for Message instead of the exact json we are planning to send feels wrong, but its easier for now
response_sender: mpsc::Sender<Message>,
) -> Web3ProxyResult<(AbortHandle, JsonRpcForwardedResponse)> {
let subscribe_to = jsonrpc_request
.params
.get(0)
.and_then(|x| x.as_str())
.ok_or_else(|| {
Web3ProxyError::BadRequest("unable to subscribe using these params".into())
})?;
// anyone can subscribe to newHeads
// only premium users are allowed to subscribe to the other things
if !(subscribe_to == "newHeads" || authorization.active_premium().await) {
return Err(Web3ProxyError::AccessDenied(
"eth_subscribe for this event requires an active premium account".into(),
));
}
let request_metadata = RequestMetadata::new(
self,
authorization.clone(),
@ -49,14 +65,6 @@ impl Web3ProxyApp {
// save the id so we can use it in the response
let id = jsonrpc_request.id.clone();
let subscribe_to = jsonrpc_request
.params
.get(0)
.and_then(|x| x.as_str())
.ok_or_else(|| {
Web3ProxyError::BadRequest("unable to subscribe using these params".into())
})?;
// TODO: calling `json!` on every request is probably not fast. but it works for now
// TODO: i think we need a stricter EthSubscribeRequest type that JsonRpcRequest can turn into
// TODO: DRY This up. lots of duplication between newHeads and newPendingTransactions

@ -122,6 +122,11 @@ pub struct AppConfig {
/// Default ERC address for out deposit contract
pub deposit_factory_contract: Option<Address>,
/// True if anonymous users should be able to eth_subscribe
/// newHeads is always allowed because that is cheap to send
#[serde_inline_default(false)]
pub free_subscriptions: bool,
/// minimum amount to increase eth_estimateGas results
pub gas_increase_min: Option<U256>,

@ -676,6 +676,13 @@ impl From<RpcSecretKey> for Uuid {
}
impl Authorization {
/// this acquires a read lock on the latest balance. Be careful not to deadlock!
pub async fn active_premium(&self) -> bool {
let user_balance = self.checks.latest_balance.read().await;
user_balance.active_premium()
}
pub fn internal() -> Web3ProxyResult<Self> {
let authorization_checks = AuthorizationChecks {
// any error logs on a local (internal) query are likely problems. log them all