Signer: better high watermarking
This commit is contained in:
parent
3f04501c0d
commit
89372a8e28
@ -40,11 +40,12 @@ module High_watermark = struct
|
||||
(List.map (fun (pkh, mark) -> Signature.Public_key_hash.to_b58check pkh, mark))
|
||||
(List.map (fun (pkh, mark) -> Signature.Public_key_hash.of_b58check_exn pkh, mark)) @@
|
||||
assoc @@
|
||||
obj2
|
||||
obj3
|
||||
(req "level" int32)
|
||||
(req "hash" raw_hash)
|
||||
(opt "signature" Signature.encoding)
|
||||
|
||||
let mark_if_block_or_endorsement (cctxt : #Client_context.wallet) pkh bytes =
|
||||
let mark_if_block_or_endorsement (cctxt : #Client_context.wallet) pkh bytes sign =
|
||||
let mark art name get_level =
|
||||
let file = name ^ "_high_watermark" in
|
||||
cctxt#with_lock @@ fun () ->
|
||||
@ -56,32 +57,41 @@ module High_watermark = struct
|
||||
let chain_id = Chain_id.of_bytes_exn (MBytes.sub bytes 1 4) in
|
||||
let level = get_level () in
|
||||
begin match List.assoc_opt chain_id all with
|
||||
| None -> return ()
|
||||
| None -> return None
|
||||
| Some marks ->
|
||||
match List.assoc_opt pkh marks with
|
||||
| None -> return ()
|
||||
| Some (previous_level, previous_hash) ->
|
||||
| None -> return None
|
||||
| Some (previous_level, _, None) ->
|
||||
if previous_level >= level then
|
||||
failwith "%s level %ld not above high watermark %ld" name level previous_level
|
||||
else
|
||||
return None
|
||||
| Some (previous_level, previous_hash, Some signature) ->
|
||||
if previous_level > level then
|
||||
failwith "%s level %ld below high watermark %ld" name level previous_level
|
||||
else if previous_level = level && previous_hash <> hash then
|
||||
failwith "%s level %ld already signed with a different header" name level
|
||||
failwith "%s level %ld already signed with different data" name level
|
||||
else
|
||||
return ()
|
||||
end >>=? fun () ->
|
||||
let rec update = function
|
||||
| [] -> [ chain_id, [ pkh, (level, hash) ] ]
|
||||
| (e_chain_id, marks) :: rest ->
|
||||
if chain_id = e_chain_id then
|
||||
let marks = (pkh, (level, hash)) :: List.filter (fun (pkh', _) -> pkh <> pkh') marks in
|
||||
(e_chain_id, marks) :: rest
|
||||
else
|
||||
(e_chain_id, marks) :: update rest in
|
||||
cctxt#write file (update all) encoding in
|
||||
return (Some signature)
|
||||
end >>=? function
|
||||
| Some signature -> return signature
|
||||
| None ->
|
||||
sign bytes >>=? fun signature ->
|
||||
let rec update = function
|
||||
| [] -> [ chain_id, [ pkh, (level, hash, Some signature) ] ]
|
||||
| (e_chain_id, marks) :: rest ->
|
||||
if chain_id = e_chain_id then
|
||||
let marks = (pkh, (level, hash, Some signature)) :: List.filter (fun (pkh', _) -> pkh <> pkh') marks in
|
||||
(e_chain_id, marks) :: rest
|
||||
else
|
||||
(e_chain_id, marks) :: update rest in
|
||||
cctxt#write file (update all) encoding >>=? fun () ->
|
||||
return signature in
|
||||
if MBytes.length bytes > 0 && MBytes.get_uint8 bytes 0 = 0x01 then
|
||||
mark "a" "block" (fun () -> MBytes.get_int32 bytes 5)
|
||||
else if MBytes.length bytes > 0 && MBytes.get_uint8 bytes 0 = 0x02 then
|
||||
mark "an" "endorsement" (fun () -> MBytes.get_int32 bytes (MBytes.length bytes - 4))
|
||||
else return ()
|
||||
else sign bytes
|
||||
|
||||
end
|
||||
|
||||
@ -134,12 +144,11 @@ let sign
|
||||
f "Signing data for key %s"
|
||||
-% t event "signing_data"
|
||||
-% s Client_keys.Logging.tag name) >>= fun () ->
|
||||
begin if check_high_watermark then
|
||||
High_watermark.mark_if_block_or_endorsement cctxt pkh data
|
||||
else return ()
|
||||
end >>=? fun () ->
|
||||
Client_keys.sign cctxt sk_uri data >>=? fun signature ->
|
||||
return signature
|
||||
let sign = Client_keys.sign cctxt sk_uri in
|
||||
if check_high_watermark then
|
||||
High_watermark.mark_if_block_or_endorsement cctxt pkh data sign
|
||||
else
|
||||
sign data
|
||||
|
||||
let public_key (cctxt : #Client_context.wallet) pkh =
|
||||
log Tag.DSL.(fun f ->
|
||||
|
Loading…
Reference in New Issue
Block a user