1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
// Copyright 2019-2024 ChainSafe Systems
// SPDX-License-Identifier: Apache-2.0, MIT

use super::*;
use crate::shim::crypto::SignatureType;

// Lotus uses signature types under two names: `KeyType` and `SigType`.
// `KeyType` can be deserialized from a string but `SigType` must always be an
// integer. For more information, see
// https://github.com/filecoin-project/go-state-types/blob/a0445436230e221ab1828ad170623fcfe00c8263/crypto/signature.go
// and
// https://github.com/filecoin-project/lotus/blob/7bb1f98ac6f5a6da2cc79afc26d8cd9fe323eb30/chain/types/keystore.go#L47

#[derive(Deserialize, Serialize, JsonSchema)]
#[serde(untagged)] // try an int, then a string
pub enum SignatureTypeLotusJson {
    Integer(#[schemars(with = "u8")] SignatureType),
    String(
        #[serde(with = "crate::lotus_json::stringify")]
        #[schemars(with = "SignatureType")]
        SignatureType,
    ),
}

impl HasLotusJson for SignatureType {
    type LotusJson = SignatureTypeLotusJson;

    #[cfg(test)]
    fn snapshots() -> Vec<(serde_json::Value, Self)> {
        vec![(json!(2), SignatureType::Bls)]
    }

    fn into_lotus_json(self) -> Self::LotusJson {
        SignatureTypeLotusJson::Integer(self)
    }

    fn from_lotus_json(lotus_json: Self::LotusJson) -> Self {
        match lotus_json {
            SignatureTypeLotusJson::Integer(inner) | SignatureTypeLotusJson::String(inner) => inner,
        }
    }
}

#[test]
fn deserialize_integer() {
    pretty_assertions::assert_eq!(
        SignatureType::Bls,
        serde_json::from_value(json!(2)).unwrap()
    );
}