Skip to content

Commit 5089af6

Browse files
committed
cardano-rpc | Add conversion Integer -> proto.BigInt
1 parent 002e39c commit 5089af6

File tree

5 files changed

+48
-5
lines changed

5 files changed

+48
-5
lines changed

cardano-api/src/Cardano/Api/HasTypeProxy.hs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@ module Cardano.Api.HasTypeProxy
1313
where
1414

1515
import Data.ByteString qualified as BS
16+
import Data.ByteString.Lazy qualified as BSL
1617
import Data.Kind (Constraint, Type)
1718
import Data.Proxy (Proxy (..))
1819
import Data.Typeable (Typeable)
1920
import Data.Word (Word16, Word8)
21+
import Numeric.Natural (Natural)
2022

2123
class Typeable t => HasTypeProxy t where
2224
-- | A family of singleton types used in this API to indicate which type to
@@ -35,10 +37,18 @@ instance HasTypeProxy Word16 where
3537
data AsType Word16 = AsWord16
3638
proxyToAsType _ = AsWord16
3739

40+
instance HasTypeProxy Natural where
41+
data AsType Natural = AsNatural
42+
proxyToAsType _ = AsNatural
43+
3844
instance HasTypeProxy BS.ByteString where
3945
data AsType BS.ByteString = AsByteString
4046
proxyToAsType _ = AsByteString
4147

48+
instance HasTypeProxy BSL.ByteString where
49+
data AsType BSL.ByteString = AsByteStringLazy
50+
proxyToAsType _ = AsByteStringLazy
51+
4252
data FromSomeType (c :: Type -> Constraint) b where
4353
FromSomeType :: c a => AsType a -> (a -> b) -> FromSomeType c b
4454

cardano-api/src/Cardano/Api/Serialise/Raw.hs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,17 @@ import Data.Bits (Bits (..))
2626
import Data.ByteString qualified as BS
2727
import Data.ByteString.Base16 qualified as Base16
2828
import Data.ByteString.Builder qualified as BSB
29-
import Data.ByteString.Char8 as BSC
29+
import Data.ByteString.Char8 (ByteString)
30+
import Data.ByteString.Char8 qualified as BSC
31+
import Data.ByteString.Lazy qualified as BSL
3032
import Data.Data (typeRep)
33+
import Data.Foldable qualified as F
3134
import Data.Text (Text)
3235
import Data.Text qualified as Text
3336
import Data.Text.Encoding qualified as Text
3437
import Data.Typeable (TypeRep, Typeable)
3538
import Data.Word (Word16, Word8)
39+
import Numeric.Natural (Natural)
3640

3741
class (HasTypeProxy a, Typeable a) => SerialiseAsRawBytes a where
3842
serialiseToRawBytes :: a -> ByteString
@@ -60,10 +64,23 @@ instance SerialiseAsRawBytes Word16 where
6064
throwError . SerialiseAsRawBytesError $
6165
"Cannot decode Word16 from (hex): " <> BSC.unpack (Base16.encode bs)
6266

67+
instance SerialiseAsRawBytes Natural where
68+
serialiseToRawBytes 0 = BS.singleton 0x00
69+
serialiseToRawBytes n = BS.toStrict . BSB.toLazyByteString $ go n mempty
70+
where
71+
go 0 acc = acc
72+
go x acc = go (x `shiftR` 8) (BSB.word8 (fromIntegral (x .&. 0xFF)) <> acc)
73+
deserialiseFromRawBytes AsNatural "\x00" = pure 0
74+
deserialiseFromRawBytes AsNatural input = pure . F.foldl' (\acc byte -> acc `shiftL` 8 .|. fromIntegral byte) 0 $ BS.unpack input
75+
6376
instance SerialiseAsRawBytes BS.ByteString where
6477
serialiseToRawBytes = id
6578
deserialiseFromRawBytes AsByteString = pure
6679

80+
instance SerialiseAsRawBytes BSL.ByteString where
81+
serialiseToRawBytes = BSL.toStrict
82+
deserialiseFromRawBytes AsByteStringLazy = pure . BSL.fromStrict
83+
6784
serialiseToRawBytesHex :: SerialiseAsRawBytes a => a -> ByteString
6885
serialiseToRawBytesHex = Base16.encode . serialiseToRawBytes
6986

cardano-api/src/Cardano/Api/Serialise/SerialiseUsing.hs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@ import Cardano.Api.Serialise.Json
1717
import Cardano.Api.Serialise.Raw
1818

1919
import Data.Aeson.Types qualified as Aeson
20+
import Data.ByteString qualified as B
2021
import Data.Text.Encoding qualified as Text
2122
import Data.Typeable (tyConName, typeRep, typeRepTyCon)
23+
import Numeric (showBin)
2224

2325
-- | For use with @deriving via@, to provide 'ToCBOR' and 'FromCBOR' instances,
2426
-- based on the 'SerialiseAsRawBytes' instance.
@@ -39,6 +41,10 @@ instance SerialiseAsRawBytes a => FromCBOR (UsingRawBytes a) where
3941
ttoken = proxyToAsType (Proxy :: Proxy a)
4042
tname = (tyConName . typeRepTyCon . typeRep) (Proxy :: Proxy a)
4143

44+
-- | Prints the representation in binary format, quoted
45+
instance SerialiseAsRawBytes a => Show (UsingRawBytes a) where
46+
showsPrec _ (UsingRawBytes x) = showChar '"' . mconcat (map showBin . B.unpack $ serialiseToRawBytes x) . showChar '"'
47+
4248
-- | For use with @deriving via@, to provide instances for any\/all of 'Show',
4349
-- 'ToJSON', 'FromJSON', 'ToJSONKey', FromJSONKey' using a hex
4450
-- encoding, based on the 'SerialiseAsRawBytes' instance.

cardano-rpc/proto/utxorpc/v1alpha/cardano/cardano.proto

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ message Constr {
7171
// Represents a big integer for Plutus data in Cardano.
7272
message BigInt {
7373
oneof big_int {
74-
int64 int = 1;
74+
int64 int = 1 [jstype = JS_STRING];
7575
bytes big_u_int = 2;
7676
bytes big_n_int = 3;
7777
}

cardano-rpc/src/Cardano/Rpc/Server/Internal/Orphans.hs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@
99
{-# LANGUAGE TypeApplications #-}
1010
{-# OPTIONS_GHC -Wno-orphans #-}
1111

12-
module Cardano.Rpc.Server.Internal.Orphans () where
12+
module Cardano.Rpc.Server.Internal.Orphans where
1313

14+
import Cardano.Api (SerialiseAsCBOR (serialiseToCBOR), ToCBOR (..))
1415
import Cardano.Api.Address
1516
import Cardano.Api.Block (SlotNo (..))
1617
import Cardano.Api.Era
@@ -19,6 +20,7 @@ import Cardano.Api.Ledger qualified as L
1920
import Cardano.Api.Plutus
2021
import Cardano.Api.Pretty
2122
import Cardano.Api.Serialise.Raw
23+
import Cardano.Api.Serialise.SerialiseUsing
2224
import Cardano.Api.Tx
2325
import Cardano.Api.Value
2426
import Cardano.Rpc.Proto.Api.UtxoRpc.Query qualified as UtxoRpc
@@ -30,6 +32,7 @@ import Cardano.Ledger.Plutus qualified as L
3032

3133
import RIO hiding (toList)
3234

35+
import Data.ByteString qualified as B
3336
import Data.Default
3437
import Data.Map.Strict qualified as M
3538
import Data.ProtoLens (defMessage)
@@ -113,8 +116,15 @@ instance Inject ScriptData (Proto UtxoRpc.PlutusData) where
113116
inject = \case
114117
ScriptDataBytes bs ->
115118
defMessage & #boundedBytes .~ bs
116-
ScriptDataNumber int ->
117-
defMessage & #bigInt . #int .~ fromIntegral int
119+
ScriptDataNumber int
120+
| int <= fromIntegral (maxBound @Int64)
121+
&& int >= fromIntegral (minBound @Int64) ->
122+
defMessage & #bigInt . #int .~ fromIntegral int
123+
| int < 0 ->
124+
-- https://www.rfc-editor.org/rfc/rfc8949.html#name-bignums see 3.4.3 for negative integers
125+
defMessage & #bigInt . #bigNInt .~ serialiseToRawBytes (fromIntegral @_ @Natural (-1 - int))
126+
| otherwise ->
127+
defMessage & #bigInt . #bigUInt .~ serialiseToRawBytes (fromIntegral @_ @Natural int)
118128
ScriptDataList sds ->
119129
defMessage & #array . #items .~ map inject sds
120130
ScriptDataMap elements -> do

0 commit comments

Comments
 (0)