Use atomic types to speedup variable difficulty alogirthm #3

Merged
realaravinth merged 9 commits from optimize-libmcaptha into master 2023-12-31 01:31:22 +05:30
9 changed files with 516 additions and 81 deletions
Showing only changes of commit fd9ac9d312 - Show all commits

File diff suppressed because one or more lines are too long

View file

@ -119,29 +119,55 @@ class Learner(_message.Message):
addr: str addr: str
def __init__(self, id: _Optional[int] = ..., addr: _Optional[str] = ...) -> None: ... def __init__(self, id: _Optional[int] = ..., addr: _Optional[str] = ...) -> None: ...
class CaptchaExistsResponse(_message.Message):
__slots__ = ("exists",)
EXISTS_FIELD_NUMBER: _ClassVar[int]
exists: bool
def __init__(self, exists: bool = ...) -> None: ...
class GetVisitorCountResponse(_message.Message):
__slots__ = ("visitors",)
VISITORS_FIELD_NUMBER: _ClassVar[int]
visitors: int
def __init__(self, visitors: _Optional[int] = ...) -> None: ...
class OptionGetVisitorCountResponse(_message.Message):
__slots__ = ("result",)
RESULT_FIELD_NUMBER: _ClassVar[int]
result: GetVisitorCountResponse
def __init__(self, result: _Optional[_Union[GetVisitorCountResponse, _Mapping]] = ...) -> None: ...
class DcacheRequest(_message.Message): class DcacheRequest(_message.Message):
__slots__ = ("addCaptcha", "addVisitor", "renameCaptcha", "removeCaptcha", "cachePow", "cacheResult") __slots__ = ("addCaptcha", "addVisitor", "renameCaptcha", "removeCaptcha", "cachePow", "cacheResult", "captchaExists", "getVisitorCount")
ADDCAPTCHA_FIELD_NUMBER: _ClassVar[int] ADDCAPTCHA_FIELD_NUMBER: _ClassVar[int]
ADDVISITOR_FIELD_NUMBER: _ClassVar[int] ADDVISITOR_FIELD_NUMBER: _ClassVar[int]
RENAMECAPTCHA_FIELD_NUMBER: _ClassVar[int] RENAMECAPTCHA_FIELD_NUMBER: _ClassVar[int]
REMOVECAPTCHA_FIELD_NUMBER: _ClassVar[int] REMOVECAPTCHA_FIELD_NUMBER: _ClassVar[int]
CACHEPOW_FIELD_NUMBER: _ClassVar[int] CACHEPOW_FIELD_NUMBER: _ClassVar[int]
CACHERESULT_FIELD_NUMBER: _ClassVar[int] CACHERESULT_FIELD_NUMBER: _ClassVar[int]
CAPTCHAEXISTS_FIELD_NUMBER: _ClassVar[int]
GETVISITORCOUNT_FIELD_NUMBER: _ClassVar[int]
addCaptcha: AddCaptchaRequest addCaptcha: AddCaptchaRequest
addVisitor: CaptchaID addVisitor: CaptchaID
renameCaptcha: RenameCaptchaRequest renameCaptcha: RenameCaptchaRequest
removeCaptcha: CaptchaID removeCaptcha: CaptchaID
cachePow: CachePowRequest cachePow: CachePowRequest
cacheResult: CacheResultRequest cacheResult: CacheResultRequest
def __init__(self, addCaptcha: _Optional[_Union[AddCaptchaRequest, _Mapping]] = ..., addVisitor: _Optional[_Union[CaptchaID, _Mapping]] = ..., renameCaptcha: _Optional[_Union[RenameCaptchaRequest, _Mapping]] = ..., removeCaptcha: _Optional[_Union[CaptchaID, _Mapping]] = ..., cachePow: _Optional[_Union[CachePowRequest, _Mapping]] = ..., cacheResult: _Optional[_Union[CacheResultRequest, _Mapping]] = ...) -> None: ... captchaExists: CaptchaID
getVisitorCount: CaptchaID
def __init__(self, addCaptcha: _Optional[_Union[AddCaptchaRequest, _Mapping]] = ..., addVisitor: _Optional[_Union[CaptchaID, _Mapping]] = ..., renameCaptcha: _Optional[_Union[RenameCaptchaRequest, _Mapping]] = ..., removeCaptcha: _Optional[_Union[CaptchaID, _Mapping]] = ..., cachePow: _Optional[_Union[CachePowRequest, _Mapping]] = ..., cacheResult: _Optional[_Union[CacheResultRequest, _Mapping]] = ..., captchaExists: _Optional[_Union[CaptchaID, _Mapping]] = ..., getVisitorCount: _Optional[_Union[CaptchaID, _Mapping]] = ...) -> None: ...
class DcacheResponse(_message.Message): class DcacheResponse(_message.Message):
__slots__ = ("option_add_visitor_result", "other") __slots__ = ("option_add_visitor_result", "other", "captcha_exists", "get_visitor_count")
OPTION_ADD_VISITOR_RESULT_FIELD_NUMBER: _ClassVar[int] OPTION_ADD_VISITOR_RESULT_FIELD_NUMBER: _ClassVar[int]
OTHER_FIELD_NUMBER: _ClassVar[int] OTHER_FIELD_NUMBER: _ClassVar[int]
CAPTCHA_EXISTS_FIELD_NUMBER: _ClassVar[int]
GET_VISITOR_COUNT_FIELD_NUMBER: _ClassVar[int]
option_add_visitor_result: OptionAddVisitorResult option_add_visitor_result: OptionAddVisitorResult
other: RaftReply other: RaftReply
def __init__(self, option_add_visitor_result: _Optional[_Union[OptionAddVisitorResult, _Mapping]] = ..., other: _Optional[_Union[RaftReply, _Mapping]] = ...) -> None: ... captcha_exists: CaptchaExistsResponse
get_visitor_count: OptionGetVisitorCountResponse
def __init__(self, option_add_visitor_result: _Optional[_Union[OptionAddVisitorResult, _Mapping]] = ..., other: _Optional[_Union[RaftReply, _Mapping]] = ..., captcha_exists: _Optional[_Union[CaptchaExistsResponse, _Mapping]] = ..., get_visitor_count: _Optional[_Union[OptionGetVisitorCountResponse, _Mapping]] = ...) -> None: ...
class DcacheBatchRequest(_message.Message): class DcacheBatchRequest(_message.Message):
__slots__ = ("requests",) __slots__ = ("requests",)
@ -154,3 +180,39 @@ class DcacheBatchResponse(_message.Message):
RESPONSES_FIELD_NUMBER: _ClassVar[int] RESPONSES_FIELD_NUMBER: _ClassVar[int]
responses: _containers.RepeatedCompositeFieldContainer[DcacheResponse] responses: _containers.RepeatedCompositeFieldContainer[DcacheResponse]
def __init__(self, responses: _Optional[_Iterable[_Union[DcacheResponse, _Mapping]]] = ...) -> None: ... def __init__(self, responses: _Optional[_Iterable[_Union[DcacheResponse, _Mapping]]] = ...) -> None: ...
class RetrievePowRequest(_message.Message):
__slots__ = ("token", "key")
TOKEN_FIELD_NUMBER: _ClassVar[int]
KEY_FIELD_NUMBER: _ClassVar[int]
token: str
key: str
def __init__(self, token: _Optional[str] = ..., key: _Optional[str] = ...) -> None: ...
class RetrievePowResponse(_message.Message):
__slots__ = ("difficulty_factor", "duration", "key")
DIFFICULTY_FACTOR_FIELD_NUMBER: _ClassVar[int]
DURATION_FIELD_NUMBER: _ClassVar[int]
KEY_FIELD_NUMBER: _ClassVar[int]
difficulty_factor: int
duration: int
key: str
def __init__(self, difficulty_factor: _Optional[int] = ..., duration: _Optional[int] = ..., key: _Optional[str] = ...) -> None: ...
class CaptchaResultVerified(_message.Message):
__slots__ = ("verified",)
VERIFIED_FIELD_NUMBER: _ClassVar[int]
verified: bool
def __init__(self, verified: bool = ...) -> None: ...
class DeletePowRequest(_message.Message):
__slots__ = ("string",)
STRING_FIELD_NUMBER: _ClassVar[int]
string: str
def __init__(self, string: _Optional[str] = ...) -> None: ...
class OptionalRetrievePoWResponse(_message.Message):
__slots__ = ("result",)
RESULT_FIELD_NUMBER: _ClassVar[int]
result: RetrievePowResponse
def __init__(self, result: _Optional[_Union[RetrievePowResponse, _Mapping]] = ...) -> None: ...

View file

@ -39,11 +39,41 @@ class DcacheServiceStub(object):
request_serializer=dcache__pb2.CachePowRequest.SerializeToString, request_serializer=dcache__pb2.CachePowRequest.SerializeToString,
response_deserializer=dcache__pb2.RaftReply.FromString, response_deserializer=dcache__pb2.RaftReply.FromString,
) )
self.RetrievePow = channel.unary_unary(
'/dcache.DcacheService/RetrievePow',
request_serializer=dcache__pb2.RetrievePowRequest.SerializeToString,
response_deserializer=dcache__pb2.OptionalRetrievePoWResponse.FromString,
)
self.DeletePow = channel.unary_unary(
'/dcache.DcacheService/DeletePow',
request_serializer=dcache__pb2.DeletePowRequest.SerializeToString,
response_deserializer=dcache__pb2.RaftReply.FromString,
)
self.CacheResult = channel.unary_unary( self.CacheResult = channel.unary_unary(
'/dcache.DcacheService/CacheResult', '/dcache.DcacheService/CacheResult',
request_serializer=dcache__pb2.CacheResultRequest.SerializeToString, request_serializer=dcache__pb2.CacheResultRequest.SerializeToString,
response_deserializer=dcache__pb2.RaftReply.FromString, response_deserializer=dcache__pb2.RaftReply.FromString,
) )
self.VerifyCaptchaResult = channel.unary_unary(
'/dcache.DcacheService/VerifyCaptchaResult',
request_serializer=dcache__pb2.RetrievePowRequest.SerializeToString,
response_deserializer=dcache__pb2.CaptchaResultVerified.FromString,
)
self.DeleteCaptchaResult = channel.unary_unary(
'/dcache.DcacheService/DeleteCaptchaResult',
request_serializer=dcache__pb2.DeleteCaptchaResultRequest.SerializeToString,
response_deserializer=dcache__pb2.RaftReply.FromString,
)
self.CaptchaExists = channel.unary_unary(
'/dcache.DcacheService/CaptchaExists',
request_serializer=dcache__pb2.CaptchaID.SerializeToString,
response_deserializer=dcache__pb2.CaptchaExistsResponse.FromString,
)
self.GetVisitorCount = channel.unary_unary(
'/dcache.DcacheService/GetVisitorCount',
request_serializer=dcache__pb2.CaptchaID.SerializeToString,
response_deserializer=dcache__pb2.OptionGetVisitorCountResponse.FromString,
)
self.PipelineDcacheOps = channel.unary_unary( self.PipelineDcacheOps = channel.unary_unary(
'/dcache.DcacheService/PipelineDcacheOps', '/dcache.DcacheService/PipelineDcacheOps',
request_serializer=dcache__pb2.DcacheBatchRequest.SerializeToString, request_serializer=dcache__pb2.DcacheBatchRequest.SerializeToString,
@ -114,12 +144,48 @@ class DcacheServiceServicer(object):
context.set_details('Method not implemented!') context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!') raise NotImplementedError('Method not implemented!')
def RetrievePow(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def DeletePow(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def CacheResult(self, request, context): def CacheResult(self, request, context):
"""Missing associated documentation comment in .proto file.""" """Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!') context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!') raise NotImplementedError('Method not implemented!')
def VerifyCaptchaResult(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def DeleteCaptchaResult(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def CaptchaExists(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def GetVisitorCount(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def PipelineDcacheOps(self, request, context): def PipelineDcacheOps(self, request, context):
"""Missing associated documentation comment in .proto file.""" """Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_code(grpc.StatusCode.UNIMPLEMENTED)
@ -193,11 +259,41 @@ def add_DcacheServiceServicer_to_server(servicer, server):
request_deserializer=dcache__pb2.CachePowRequest.FromString, request_deserializer=dcache__pb2.CachePowRequest.FromString,
response_serializer=dcache__pb2.RaftReply.SerializeToString, response_serializer=dcache__pb2.RaftReply.SerializeToString,
), ),
'RetrievePow': grpc.unary_unary_rpc_method_handler(
servicer.RetrievePow,
request_deserializer=dcache__pb2.RetrievePowRequest.FromString,
response_serializer=dcache__pb2.OptionalRetrievePoWResponse.SerializeToString,
),
'DeletePow': grpc.unary_unary_rpc_method_handler(
servicer.DeletePow,
request_deserializer=dcache__pb2.DeletePowRequest.FromString,
response_serializer=dcache__pb2.RaftReply.SerializeToString,
),
'CacheResult': grpc.unary_unary_rpc_method_handler( 'CacheResult': grpc.unary_unary_rpc_method_handler(
servicer.CacheResult, servicer.CacheResult,
request_deserializer=dcache__pb2.CacheResultRequest.FromString, request_deserializer=dcache__pb2.CacheResultRequest.FromString,
response_serializer=dcache__pb2.RaftReply.SerializeToString, response_serializer=dcache__pb2.RaftReply.SerializeToString,
), ),
'VerifyCaptchaResult': grpc.unary_unary_rpc_method_handler(
servicer.VerifyCaptchaResult,
request_deserializer=dcache__pb2.RetrievePowRequest.FromString,
response_serializer=dcache__pb2.CaptchaResultVerified.SerializeToString,
),
'DeleteCaptchaResult': grpc.unary_unary_rpc_method_handler(
servicer.DeleteCaptchaResult,
request_deserializer=dcache__pb2.DeleteCaptchaResultRequest.FromString,
response_serializer=dcache__pb2.RaftReply.SerializeToString,
),
'CaptchaExists': grpc.unary_unary_rpc_method_handler(
servicer.CaptchaExists,
request_deserializer=dcache__pb2.CaptchaID.FromString,
response_serializer=dcache__pb2.CaptchaExistsResponse.SerializeToString,
),
'GetVisitorCount': grpc.unary_unary_rpc_method_handler(
servicer.GetVisitorCount,
request_deserializer=dcache__pb2.CaptchaID.FromString,
response_serializer=dcache__pb2.OptionGetVisitorCountResponse.SerializeToString,
),
'PipelineDcacheOps': grpc.unary_unary_rpc_method_handler( 'PipelineDcacheOps': grpc.unary_unary_rpc_method_handler(
servicer.PipelineDcacheOps, servicer.PipelineDcacheOps,
request_deserializer=dcache__pb2.DcacheBatchRequest.FromString, request_deserializer=dcache__pb2.DcacheBatchRequest.FromString,
@ -328,6 +424,40 @@ class DcacheService(object):
options, channel_credentials, options, channel_credentials,
insecure, call_credentials, compression, wait_for_ready, timeout, metadata) insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
@staticmethod
def RetrievePow(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(request, target, '/dcache.DcacheService/RetrievePow',
dcache__pb2.RetrievePowRequest.SerializeToString,
dcache__pb2.OptionalRetrievePoWResponse.FromString,
options, channel_credentials,
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
@staticmethod
def DeletePow(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(request, target, '/dcache.DcacheService/DeletePow',
dcache__pb2.DeletePowRequest.SerializeToString,
dcache__pb2.RaftReply.FromString,
options, channel_credentials,
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
@staticmethod @staticmethod
def CacheResult(request, def CacheResult(request,
target, target,
@ -345,6 +475,74 @@ class DcacheService(object):
options, channel_credentials, options, channel_credentials,
insecure, call_credentials, compression, wait_for_ready, timeout, metadata) insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
@staticmethod
def VerifyCaptchaResult(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(request, target, '/dcache.DcacheService/VerifyCaptchaResult',
dcache__pb2.RetrievePowRequest.SerializeToString,
dcache__pb2.CaptchaResultVerified.FromString,
options, channel_credentials,
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
@staticmethod
def DeleteCaptchaResult(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(request, target, '/dcache.DcacheService/DeleteCaptchaResult',
dcache__pb2.DeleteCaptchaResultRequest.SerializeToString,
dcache__pb2.RaftReply.FromString,
options, channel_credentials,
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
@staticmethod
def CaptchaExists(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(request, target, '/dcache.DcacheService/CaptchaExists',
dcache__pb2.CaptchaID.SerializeToString,
dcache__pb2.CaptchaExistsResponse.FromString,
options, channel_credentials,
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
@staticmethod
def GetVisitorCount(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(request, target, '/dcache.DcacheService/GetVisitorCount',
dcache__pb2.CaptchaID.SerializeToString,
dcache__pb2.OptionGetVisitorCountResponse.FromString,
options, channel_credentials,
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
@staticmethod @staticmethod
def PipelineDcacheOps(request, def PipelineDcacheOps(request,
target, target,

View file

@ -77,6 +77,20 @@ message Learner {
} }
message CaptchaExistsResponse {
bool exists = 1;
}
message GetVisitorCountResponse {
uint32 visitors = 1;
}
message OptionGetVisitorCountResponse {
optional GetVisitorCountResponse result = 1;
}
message DcacheRequest { message DcacheRequest {
oneof DcacheRequest { oneof DcacheRequest {
AddCaptchaRequest addCaptcha = 1; AddCaptchaRequest addCaptcha = 1;
@ -85,6 +99,8 @@ message DcacheRequest {
CaptchaID removeCaptcha = 4; CaptchaID removeCaptcha = 4;
CachePowRequest cachePow = 5; CachePowRequest cachePow = 5;
CacheResultRequest cacheResult = 6; CacheResultRequest cacheResult = 6;
CaptchaID captchaExists = 7;
CaptchaID getVisitorCount = 8;
} }
} }
@ -93,6 +109,8 @@ message DcacheResponse {
oneof DcacheResponse { oneof DcacheResponse {
OptionAddVisitorResult option_add_visitor_result = 1; OptionAddVisitorResult option_add_visitor_result = 1;
RaftReply other = 2; RaftReply other = 2;
CaptchaExistsResponse captcha_exists = 3;
OptionGetVisitorCountResponse get_visitor_count = 4;
} }
} }
@ -104,13 +122,43 @@ message DcacheBatchResponse {
repeated DcacheResponse responses = 1; repeated DcacheResponse responses = 1;
} }
message RetrievePowRequest {
string token = 1;
string key = 2;
}
message RetrievePowResponse {
uint32 difficulty_factor = 1;
uint64 duration = 2;
string key = 3;
}
message CaptchaResultVerified {
bool verified = 1;
}
message DeletePowRequest {
string string = 1;
}
message OptionalRetrievePoWResponse {
optional RetrievePowResponse result = 1;
}
service DcacheService { service DcacheService {
rpc AddCaptcha(AddCaptchaRequest) returns (RaftReply) {} rpc AddCaptcha(AddCaptchaRequest) returns (RaftReply) {}
rpc AddVisitor(CaptchaID) returns (OptionAddVisitorResult) {} rpc AddVisitor(CaptchaID) returns (OptionAddVisitorResult) {}
rpc RenameCaptcha(RenameCaptchaRequest) returns (RaftReply) {} rpc RenameCaptcha(RenameCaptchaRequest) returns (RaftReply) {}
rpc RemoveCaptcha(CaptchaID) returns (RaftReply) {} rpc RemoveCaptcha(CaptchaID) returns (RaftReply) {}
rpc CachePow(CachePowRequest) returns (RaftReply) {} rpc CachePow(CachePowRequest) returns (RaftReply) {}
rpc RetrievePow(RetrievePowRequest) returns (OptionalRetrievePoWResponse) {}
rpc DeletePow(DeletePowRequest) returns (RaftReply) {}
rpc CacheResult(CacheResultRequest) returns (RaftReply) {} rpc CacheResult(CacheResultRequest) returns (RaftReply) {}
rpc VerifyCaptchaResult(RetrievePowRequest) returns (CaptchaResultVerified) {}
rpc DeleteCaptchaResult(DeleteCaptchaResultRequest) returns (RaftReply) {}
rpc CaptchaExists(CaptchaID) returns (CaptchaExistsResponse) {}
rpc GetVisitorCount(CaptchaID) returns (OptionGetVisitorCountResponse) {}
rpc PipelineDcacheOps(DcacheBatchRequest) returns (DcacheBatchResponse) {} rpc PipelineDcacheOps(DcacheBatchRequest) returns (DcacheBatchResponse) {}

View file

@ -119,29 +119,6 @@ pub async fn start_example_raft_node(
raft.enable_heartbeat(true); raft.enable_heartbeat(true);
raft.enable_elect(true); raft.enable_elect(true);
let captcha = serde_json::json!({
"AddCaptcha": {
"id": "test_1",
"mcaptcha": {
"visitor_threshold": 0,
"defense": {
"levels": [
{"visitor_threshold": 50, "difficulty_factor": 500},
{"visitor_threshold": 5000, "difficulty_factor": 50000},
],
"current_visitor_threshold": 0,
},
"duration": 30,
}}});
#[derive(serde::Serialize)]
struct X {
data: String,
}
let x = X {
data: serde_json::to_string(&captcha).unwrap(),
};
println!("{}", serde_json::to_string(&x).unwrap());
// raft.enable_tick(true); // raft.enable_tick(true);
// Create an application that will store all the instances created above, this will // Create an application that will store all the instances created above, this will

View file

@ -42,8 +42,12 @@ impl HashCache {
duration: config.duration, duration: config.duration,
}; };
self.difficulty_map.insert(challenge, config); if self.difficulty_map.get(&challenge).is_none() {
Ok(()) self.difficulty_map.insert(challenge, config);
Ok(())
} else {
Err(CaptchaError::InvalidPoW)
}
} }
pub async fn clean_all_after_cold_start(&self, updated: HashCache) { pub async fn clean_all_after_cold_start(&self, updated: HashCache) {
@ -83,15 +87,12 @@ impl HashCache {
tokio::spawn(fut); tokio::spawn(fut);
} }
// retrive [PoWConfig] from cache. Deletes config post retrival // retrieve [PoWConfig] from cache. Deletes config post retrival
pub fn retrive_pow_config( pub fn retrieve_pow_config(&self, msg: VerifyCaptchaResult) -> Option<CachedPoWConfig> {
&self,
msg: VerifyCaptchaResult,
) -> CaptchaResult<Option<CachedPoWConfig>> {
if let Some(difficulty_factor) = self.remove_pow_config(&msg.token) { if let Some(difficulty_factor) = self.remove_pow_config(&msg.token) {
Ok(Some(difficulty_factor)) Some(difficulty_factor)
} else { } else {
Ok(None) None
} }
} }
@ -106,15 +107,15 @@ impl HashCache {
} }
// verify captcha result // verify captcha result
pub fn verify_captcha_result(&self, challenge: VerifyCaptchaResult) -> CaptchaResult<bool> { pub fn verify_captcha_result(&self, challenge: VerifyCaptchaResult) -> bool {
if let Some(captcha_id) = self.remove_cache_result(&challenge.token) { if let Some(captcha_id) = self.remove_cache_result(&challenge.token) {
if captcha_id == challenge.key { if captcha_id == challenge.key {
Ok(true) true
} else { } else {
Ok(false) false
} }
} else { } else {
Ok(false) false
} }
} }
@ -209,16 +210,13 @@ mod tests {
token: string.clone(), token: string.clone(),
key: KEY.into(), key: KEY.into(),
}; };
let cache_difficulty_factor = cache.retrive_pow_config(msg.clone()).unwrap(); let cache_difficulty_factor = cache.retrieve_pow_config(msg.clone()).unwrap();
let new_cache_difficulty_factor = new_cache.retrive_pow_config(msg.clone()).unwrap(); let new_cache_difficulty_factor = new_cache.retrieve_pow_config(msg.clone()).unwrap();
assert_eq!(DIFFICULTY_FACTOR, cache_difficulty_factor.difficulty_factor);
assert_eq!( assert_eq!(
DIFFICULTY_FACTOR, DIFFICULTY_FACTOR,
cache_difficulty_factor.unwrap().difficulty_factor new_cache_difficulty_factor.difficulty_factor
);
assert_eq!(
DIFFICULTY_FACTOR,
new_cache_difficulty_factor.unwrap().difficulty_factor
); );
let verify_msg = VerifyCaptchaResult { let verify_msg = VerifyCaptchaResult {
@ -226,23 +224,23 @@ mod tests {
token: RES.into(), token: RES.into(),
}; };
assert!(new_cache.verify_captcha_result(verify_msg.clone()).unwrap()); assert!(new_cache.verify_captcha_result(verify_msg.clone()));
assert!(!new_cache.verify_captcha_result(verify_msg.clone()).unwrap()); assert!(!new_cache.verify_captcha_result(verify_msg.clone()));
let duration: Duration = Duration::new(5, 0); let duration: Duration = Duration::new(5, 0);
//sleep(DURATION + DURATION).await; //sleep(DURATION + DURATION).await;
tokio::time::sleep(duration + duration).await; tokio::time::sleep(duration + duration).await;
let expired_string = cache.retrive_pow_config(msg.clone()).unwrap(); let expired_string = cache.retrieve_pow_config(msg.clone());
assert_eq!(None, expired_string); assert_eq!(None, expired_string);
let expired_string = new_cache.retrive_pow_config(msg).unwrap(); let expired_string = new_cache.retrieve_pow_config(msg);
assert_eq!(None, expired_string); assert_eq!(None, expired_string);
cache.cache_result(add_cache); cache.cache_result(add_cache);
new_cache.clean_all_after_cold_start(cache.clone()).await; new_cache.clean_all_after_cold_start(cache.clone()).await;
tokio::time::sleep(duration + duration).await; tokio::time::sleep(duration + duration).await;
assert!(!new_cache.verify_captcha_result(verify_msg.clone()).unwrap()); assert!(!new_cache.verify_captcha_result(verify_msg.clone()));
assert!(!cache.verify_captcha_result(verify_msg).unwrap()); assert!(!cache.verify_captcha_result(verify_msg));
} }
#[actix_rt::test] #[actix_rt::test]
@ -272,18 +270,15 @@ mod tests {
token: string.clone(), token: string.clone(),
key: KEY.into(), key: KEY.into(),
}; };
let cache_difficulty_factor = cache.retrive_pow_config(msg.clone()).unwrap(); let cache_difficulty_factor = cache.retrieve_pow_config(msg.clone()).unwrap();
assert_eq!( assert_eq!(DIFFICULTY_FACTOR, cache_difficulty_factor.difficulty_factor);
DIFFICULTY_FACTOR,
cache_difficulty_factor.unwrap().difficulty_factor
);
let duration: Duration = Duration::new(5, 0); let duration: Duration = Duration::new(5, 0);
//sleep(DURATION + DURATION).await; //sleep(DURATION + DURATION).await;
tokio::time::sleep(duration + duration).await; tokio::time::sleep(duration + duration).await;
let expired_string = cache.retrive_pow_config(msg).unwrap(); let expired_string = cache.retrieve_pow_config(msg);
assert_eq!(None, expired_string); assert_eq!(None, expired_string);
} }
@ -312,16 +307,16 @@ mod tests {
token: RES.into(), token: RES.into(),
}; };
assert!(cache.verify_captcha_result(verify_msg.clone()).unwrap()); assert!(cache.verify_captcha_result(verify_msg.clone()));
// duplicate // duplicate
assert!(!cache.verify_captcha_result(verify_msg).unwrap()); assert!(!cache.verify_captcha_result(verify_msg));
let verify_msg = VerifyCaptchaResult { let verify_msg = VerifyCaptchaResult {
key: "cz".into(), key: "cz".into(),
token: RES.into(), token: RES.into(),
}; };
assert!(!cache.verify_captcha_result(verify_msg).unwrap()); assert!(!cache.verify_captcha_result(verify_msg));
let duration: Duration = Duration::new(5, 0); let duration: Duration = Duration::new(5, 0);
tokio::time::sleep(duration + duration).await; tokio::time::sleep(duration + duration).await;
@ -330,6 +325,6 @@ mod tests {
key: KEY.into(), key: KEY.into(),
token: RES.into(), token: RES.into(),
}; };
assert!(!cache.verify_captcha_result(verify_msg).unwrap()); assert!(!cache.verify_captcha_result(verify_msg));
} }
} }

View file

@ -126,7 +126,7 @@ impl MCaptcha {
/// get [Counter]'s current visitor_threshold /// get [Counter]'s current visitor_threshold
pub fn get_visitors(&self) -> u32 { pub fn get_visitors(&self) -> u32 {
self.visitor_threshold.load(Ordering::Relaxed) self.visitor_threshold.load(Ordering::SeqCst)
} }
} }
@ -152,11 +152,9 @@ impl Manager {
} }
fn gc(captchas: Arc<DashMap<String, Arc<MCaptcha>>>) { fn gc(captchas: Arc<DashMap<String, Arc<MCaptcha>>>) {
println!("running gc");
for captcha in captchas.iter() { for captcha in captchas.iter() {
let visitor = { captcha.value().get_visitors() }; let visitor = { captcha.value().get_visitors() };
if visitor == 0 { if visitor == 0 {
println!("Removing captcha");
captchas.remove(captcha.key()); captchas.remove(captcha.key());
} }
} }
@ -255,7 +253,6 @@ impl Manager {
let msg = ManagerMessages::AddVisitor(id); let msg = ManagerMessages::AddVisitor(id);
for _ in 0..visitors { for _ in 0..visitors {
self.add_visitor(&msg); self.add_visitor(&msg);
println!("Adding visitor");
} }
} }
} }
@ -377,7 +374,6 @@ mod tests {
mcaptcha_data.get_mut(id).unwrap().add_visitor(); mcaptcha_data.get_mut(id).unwrap().add_visitor();
mcaptcha_data.get_mut(id).unwrap().add_visitor(); mcaptcha_data.get_mut(id).unwrap().add_visitor();
mcaptcha_data.get_mut(id).unwrap().add_visitor(); mcaptcha_data.get_mut(id).unwrap().add_visitor();
println!("{:?}", mcaptcha_data);
// let mcaptcha_data: HashMap<String, libmcaptcha::mcaptcha::MCaptcha> = { // let mcaptcha_data: HashMap<String, libmcaptcha::mcaptcha::MCaptcha> = {
// let serialized = serde_json::to_string(&mcaptcha_data).unwrap(); // let serialized = serde_json::to_string(&mcaptcha_data).unwrap();
// serde_json::from_str(&serialized).unwrap() // serde_json::from_str(&serialized).unwrap()
@ -386,7 +382,6 @@ mod tests {
manager.set_internal_data(mcaptcha_data); manager.set_internal_data(mcaptcha_data);
let mcaptcha_data = manager.get_internal_data(); let mcaptcha_data = manager.get_internal_data();
println!("{:?}", mcaptcha_data);
assert_eq!( assert_eq!(
manager.get_captcha(id).unwrap().get_visitors(), manager.get_captcha(id).unwrap().get_visitors(),
mcaptcha_data.get(id).unwrap().get_visitors() mcaptcha_data.get(id).unwrap().get_visitors()

View file

@ -55,7 +55,6 @@ impl ItemManager for ChannelManager {
type Error = tonic::transport::Error; type Error = tonic::transport::Error;
async fn build(&self, addr: &Self::Key) -> Result<Channel, tonic::transport::Error> { async fn build(&self, addr: &Self::Key) -> Result<Channel, tonic::transport::Error> {
println!("New connection for {addr}");
tonic::transport::Endpoint::new(addr.clone())? tonic::transport::Endpoint::new(addr.clone())?
.connect() .connect()
.await .await

View file

@ -129,6 +129,36 @@ impl DcacheService for MyDcacheImpl {
Ok(Response::new(res.into())) Ok(Response::new(res.into()))
} }
async fn retrieve_pow(
&self,
request: tonic::Request<dcache::RetrievePowRequest>,
) -> std::result::Result<tonic::Response<dcache::OptionalRetrievePoWResponse>, tonic::Status>
{
let req = request.into_inner();
let sm = self.app.store.state_machine.read().await;
let res = sm.results.retrieve_pow_config(req.into());
Ok(Response::new(dcache::OptionalRetrievePoWResponse {
result: res.map(|x| x.into()),
}))
}
async fn delete_pow(
&self,
request: tonic::Request<dcache::DeletePowRequest>,
) -> std::result::Result<tonic::Response<dcache::RaftReply>, tonic::Status> {
let req = request.into_inner();
let res = self
.app
.raft
.client_write(DcacheRequest::DeletePoW(CacheMessages::DeletePoW(
req.string,
)))
.await;
Ok(Response::new(res.into()))
}
async fn cache_result( async fn cache_result(
&self, &self,
request: tonic::Request<dcache::CacheResultRequest>, request: tonic::Request<dcache::CacheResultRequest>,
@ -142,6 +172,62 @@ impl DcacheService for MyDcacheImpl {
Ok(Response::new(res.into())) Ok(Response::new(res.into()))
} }
async fn verify_captcha_result(
&self,
request: tonic::Request<dcache::RetrievePowRequest>,
) -> std::result::Result<tonic::Response<dcache::CaptchaResultVerified>, tonic::Status> {
let req = request.into_inner();
let sm = self.app.store.state_machine.read().await;
let verified = sm.results.verify_captcha_result(req.into());
Ok(Response::new(dcache::CaptchaResultVerified { verified }))
}
async fn delete_captcha_result(
&self,
request: tonic::Request<dcache::DeleteCaptchaResultRequest>,
) -> std::result::Result<tonic::Response<dcache::RaftReply>, tonic::Status> {
let req = request.into_inner();
let res = self
.app
.raft
.client_write(DcacheRequest::DeleteCaptchaResult(
CacheMessages::DeleteCaptchaResult { token: req.token },
))
.await;
Ok(Response::new(res.into()))
}
async fn captcha_exists(
&self,
request: tonic::Request<dcache::CaptchaId>,
) -> std::result::Result<tonic::Response<dcache::CaptchaExistsResponse>, tonic::Status> {
let req = request.into_inner();
let sm = self.app.store.state_machine.read().await;
let exists = sm.counter.get_captcha(&req.id).is_some();
Ok(Response::new(dcache::CaptchaExistsResponse { exists }))
}
async fn get_visitor_count(
&self,
request: tonic::Request<dcache::CaptchaId>,
) -> std::result::Result<tonic::Response<dcache::OptionGetVisitorCountResponse>, tonic::Status>
{
let req = request.into_inner();
let sm = self.app.store.state_machine.read().await;
if let Some(captcha) = sm.counter.get_captcha(&req.id) {
let res = captcha.get_visitors();
Ok(Response::new(dcache::OptionGetVisitorCountResponse {
result: Some(dcache::GetVisitorCountResponse { visitors: res }),
}))
} else {
Ok(Response::new(dcache::OptionGetVisitorCountResponse {
result: None,
}))
}
}
// type PipelineDcacheOpsStream = // type PipelineDcacheOpsStream =
// Pin<Box<dyn Stream<Item = Result<OuterPipelineRes, tonic::Status>> + Send + 'static>>; // Pin<Box<dyn Stream<Item = Result<OuterPipelineRes, tonic::Status>> + Send + 'static>>;
@ -238,6 +324,35 @@ impl DcacheService for MyDcacheImpl {
dcache_response: Some(InnerPipelineRes::Other(res.into())), dcache_response: Some(InnerPipelineRes::Other(res.into())),
} }
} }
PipelineReq::CaptchaExists(captcha_exists_req) => {
let sm = self.app.store.state_machine.read().await;
let exists = sm.counter.get_captcha(&captcha_exists_req.id).is_some();
let res = dcache::CaptchaExistsResponse { exists };
drop(sm);
OuterPipelineRes {
dcache_response: Some(InnerPipelineRes::CaptchaExists(res)),
}
}
PipelineReq::GetVisitorCount(get_visitor_count_req) => {
let sm = self.app.store.state_machine.read().await;
if let Some(captcha) = sm.counter.get_captcha(&get_visitor_count_req.id) {
let res = captcha.get_visitors();
OuterPipelineRes {
dcache_response: Some(InnerPipelineRes::GetVisitorCount(
dcache::OptionGetVisitorCountResponse {
result: Some(dcache::GetVisitorCountResponse { visitors: res }),
},
)),
}
} else {
OuterPipelineRes {
dcache_response: Some(InnerPipelineRes::GetVisitorCount(
dcache::OptionGetVisitorCountResponse { result: None },
)),
}
}
}
}; };
responses.push(res); responses.push(res);
} }
@ -390,6 +505,27 @@ impl From<dcache::CachePowRequest> for CacheMessages::CachePoW {
} }
} }
impl From<CacheMessages::CachePoW> for dcache::CachePowRequest {
fn from(value: CacheMessages::CachePoW) -> Self {
Self {
string: value.string,
difficulty_factor: value.difficulty_factor,
duration: value.duration,
key: value.key,
}
}
}
impl From<CacheMessages::CachedPoWConfig> for dcache::RetrievePowResponse {
fn from(value: CacheMessages::CachedPoWConfig) -> Self {
Self {
difficulty_factor: value.difficulty_factor,
duration: value.duration,
key: value.key,
}
}
}
impl From<dcache::CacheResultRequest> for CacheMessages::CacheResult { impl From<dcache::CacheResultRequest> for CacheMessages::CacheResult {
fn from(value: dcache::CacheResultRequest) -> Self { fn from(value: dcache::CacheResultRequest) -> Self {
Self { Self {
@ -399,3 +535,12 @@ impl From<dcache::CacheResultRequest> for CacheMessages::CacheResult {
} }
} }
} }
impl From<dcache::RetrievePowRequest> for CacheMessages::VerifyCaptchaResult {
fn from(value: dcache::RetrievePowRequest) -> Self {
Self {
token: value.token,
key: value.key,
}
}
}