Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migration endpoints for shelley and cardano-node's byron support #1678

Merged
merged 21 commits into from
May 26, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
59e0b04
prepare room for shelley ApiWalletMigrationPostData using raw pasphrase
paweljakubas May 21, 2020
bc02d52
add Shelley migrations endpoint
paweljakubas May 21, 2020
142349b
add unit testing in core
paweljakubas May 21, 2020
5869874
add migration for cardano-node's byron
paweljakubas May 21, 2020
6c5cda9
Update lib/core-integration/src/Test/Integration/Scenario/API/Byron/W…
rvl May 22, 2020
a7e4d6f
Update lib/core-integration/src/Test/Integration/Scenario/API/Byron/W…
rvl May 22, 2020
804bde7
Update specifications/api/swagger.yaml
rvl May 22, 2020
642d984
Update lib/core-integration/src/Test/Integration/Scenario/API/Byron/W…
rvl May 22, 2020
f7f98b9
Update lib/core/src/Cardano/Wallet/Api.hs
rvl May 22, 2020
f98296e
swagger: Fix getShelleyWalletMigrationInfo operationId
rvl May 22, 2020
9b92742
Update lib/core-integration/src/Test/Integration/Scenario/API/Byron/W…
rvl May 22, 2020
95ee3ae
Update lib/byron/src/Cardano/Wallet/Byron/Api/Server.hs
rvl May 22, 2020
14bc7e2
Reduce TypesSpec generator duplication
rvl May 22, 2020
953067b
Update lib/core-integration/src/Test/Integration/Scenario/API/Byron/W…
rvl May 22, 2020
8f29d9e
Update lib/core-integration/src/Test/Integration/Scenario/API/Byron/W…
rvl May 22, 2020
ef3fcfa
Fix tests compile
rvl May 22, 2020
c2f6314
address very subtle max address size bug - it needs to bey byron key
paweljakubas May 25, 2020
577f98b
realign all arguments in Server.hs in byron, shelley and jormungandr
paweljakubas May 25, 2020
2eaa3d3
correct previous wrong merge conflict
paweljakubas May 25, 2020
68932bb
correct byron unit test
paweljakubas May 25, 2020
34e7e11
relocate migration to byron lib
paweljakubas May 26, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/byron/bench/Restore.hs
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ bench_restoration
, WalletKey k
, NFData s
, Show s
, MaxSizeOf Address n k
, MaxSizeOf Address n ByronKey
, PersistState s
, PersistPrivateKey (k 'RootK)
, NetworkDiscriminantVal n
Expand Down
19 changes: 15 additions & 4 deletions lib/byron/src/Cardano/Wallet/Byron/Api/Server.hs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import Cardano.Wallet.Api
, CoinSelections
, Network
, Proxy_
, ShelleyMigrations
, StakePools
, Transactions
, Wallets
Expand All @@ -54,6 +55,7 @@ import Cardano.Wallet.Api.Server
, listAddresses
, listTransactions
, listWallets
, migrateWallet
, mkLegacyWallet
, postExternalTransaction
, postIcarusWallet
Expand Down Expand Up @@ -118,6 +120,7 @@ server byron icarus ntp =
:<|> addresses
:<|> coinSelections
:<|> transactions
:<|> shelleyMigrations
:<|> stakePools
:<|> byronWallets
:<|> byronAddresses
Expand Down Expand Up @@ -149,6 +152,11 @@ server byron icarus ntp =
:<|> (\_ _ -> throwError err501)
:<|> (\_ _ -> throwError err501)

shelleyMigrations :: Server (ShelleyMigrations n)
shelleyMigrations =
(\_ -> throwError err501)
:<|> (\_ _ -> throwError err501)

stakePools :: Server (StakePools n)
stakePools =
throwError err501
Expand Down Expand Up @@ -225,7 +233,7 @@ server byron icarus ntp =
)
:<|>
(\wid r0 r1 s -> withLegacyLayer wid
(byron , listTransactions byron wid r0 r1 s)
(byron , listTransactions byron wid r0 r1 s)
(icarus, listTransactions icarus wid r0 r1 s)
)
:<|>
Expand All @@ -234,17 +242,20 @@ server byron icarus ntp =
(icarus, postTransactionFee icarus wid tx)
)
:<|> (\wid txid -> withLegacyLayer wid
(byron , deleteTransaction byron wid txid)
(byron , deleteTransaction byron wid txid)
(icarus, deleteTransaction icarus wid txid)
)

byronMigrations :: Server (ByronMigrations n)
byronMigrations =
(\wid -> withLegacyLayer wid
(byron , getMigrationInfo byron wid)
(byron , getMigrationInfo byron wid)
(icarus, getMigrationInfo icarus wid)
)
:<|> \_ _ -> throwError err501
:<|> (\wid m -> withLegacyLayer wid
(byron , migrateWallet byron wid m)
(icarus, migrateWallet icarus wid m)
jonathanknowles marked this conversation as resolved.
Show resolved Hide resolved
)

network :: Server Network
network =
Expand Down
11 changes: 7 additions & 4 deletions lib/byron/src/Cardano/Wallet/Byron/Transaction.hs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ import Cardano.Wallet.Byron.Transaction.Size
( MaxSizeOf, maxSizeOf, sizeOfSignedTx )
import Cardano.Wallet.Primitive.AddressDerivation
( Depth (..), NetworkDiscriminant (..), Passphrase (..), WalletKey (..) )
import Cardano.Wallet.Primitive.AddressDerivation.Byron
( ByronKey )
import Cardano.Wallet.Primitive.CoinSelection
( CoinSelection (..) )
import Cardano.Wallet.Primitive.Types
Expand Down Expand Up @@ -92,7 +94,7 @@ newTransactionLayer
:: forall (n :: NetworkDiscriminant) k t.
( t ~ IO Byron
, WalletKey k
, MaxSizeOf Address n k
, MaxSizeOf Address n ByronKey
)
=> Proxy n
-> ProtocolMagic
Expand Down Expand Up @@ -136,7 +138,7 @@ newTransactionLayer _proxy protocolMagic = TransactionLayer
Quantity $ sizeOfSignedTx (fst <$> inps) (outs <> map dummyOutput chngs)
where
dummyOutput :: Coin -> TxOut
dummyOutput = TxOut (dummyAddress @n @k)
dummyOutput = TxOut (dummyAddress @n)

_estimateMaxNumberOfInputs
:: Quantity "byte" Word16
Expand Down Expand Up @@ -237,9 +239,10 @@ genesisBlockFromTxOuts bp outs = Block
Tx (Hash $ blake2b256 bytes) [] [out]

dummyAddress
:: forall (n :: NetworkDiscriminant) k. (MaxSizeOf Address n k) => Address
:: forall (n :: NetworkDiscriminant). (MaxSizeOf Address n ByronKey)
=> Address
dummyAddress =
Address $ BS.replicate (maxSizeOf @Address @n @k) 0
Address $ BS.replicate (maxSizeOf @Address @n @ByronKey) 0

mkWitness
:: WalletKey k
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import Cardano.Wallet.Api.Types
, ApiT (..)
, ApiTransaction
, ApiUtxoStatistics
, ApiWalletMigrationInfo
, DecodeAddress (..)
, EncodeAddress (..)
, WalletStyle (..)
Expand All @@ -38,15 +39,15 @@ import Cardano.Wallet.Primitive.Types
import Control.Monad
( forM, forM_ )
import Data.Generics.Internal.VL.Lens
( (^.) )
( view, (^.) )
import Data.Quantity
( Quantity (..) )
import Data.Text
( Text )
import Numeric.Natural
( Natural )
import Test.Hspec
( SpecWith, describe, it, shouldBe, shouldNotBe )
( SpecWith, describe, it, shouldBe, shouldNotBe, shouldSatisfy )
import Test.Integration.Faucet
( nextWallet )
import Test.Integration.Framework.DSL
Expand All @@ -58,6 +59,7 @@ import Test.Integration.Framework.DSL
, emptyByronWalletFromXPrvWith
, emptyIcarusWallet
, emptyRandomWallet
, emptyRandomWalletMws
, eventually
, expectErrorMessage
, expectField
Expand All @@ -76,18 +78,21 @@ import Test.Integration.Framework.DSL
, fixtureRandomWalletAddrs
, fixtureRandomWalletMws
, fixtureRandomWalletWith
, getFromResponse
, icarusAddresses
, json
, randomAddresses
, request
, rootPrvKeyFromMnemonics
, verify
, walletId
, (.>)
)
import Test.Integration.Framework.Request
( RequestException )
import Test.Integration.Framework.TestData
( errMsg403Fee
( errMsg400ParseError
, errMsg403Fee
, errMsg403InputsDepleted
, errMsg403NotEnoughMoney_
, errMsg403UTxO
Expand Down Expand Up @@ -166,6 +171,15 @@ spec = do
scenario_TRANS_UTXO_01 @n fixtureIcarusWallet (fixtureIcarusWalletAddrs @n)
scenario_TRANS_UTXO_01 @n fixtureRandomWallet (fixtureRandomWalletAddrs @n)

describe "BYRON_MIGRATE" $ do
scenario_MIGRATE_01 @n fixtureRandomWallet
scenario_MIGRATE_02 @n fixtureRandomWallet 1
scenario_MIGRATE_02 @n fixtureRandomWallet 3
scenario_MIGRATE_02 @n fixtureRandomWallet 10
scenario_MIGRATE_02 @n fixtureIcarusWallet 1
scenario_MIGRATE_02 @n fixtureIcarusWallet 3
scenario_MIGRATE_02 @n fixtureIcarusWallet 10

--
-- Scenarios
--
Expand Down Expand Up @@ -690,6 +704,86 @@ scenario_TRANS_UTXO_01 fixtureSource fixtureTarget = it title $ \ctx -> do
where
title = "TRANS_UTXO_01 - one recipient multiple txs received"

scenario_MIGRATE_01
:: forall (n :: NetworkDiscriminant) t.
( DecodeAddress n
, EncodeAddress n
, PaymentAddress n ByronKey
)
=> (Context t -> IO ApiByronWallet)
-> SpecWith (Context t)
scenario_MIGRATE_01 fixtureSource = it title $ \ctx -> do
wSrc <- fixtureSource ctx

r <- request @[ApiTransaction n] ctx
(Link.migrateWallet wSrc)
Default
(NonJson "{passphrase:,}")
expectResponseCode @IO HTTP.status400 r
expectErrorMessage errMsg400ParseError r
where
title = "BYRON_MIGRATE_01 - invalid payload, parser error"

scenario_MIGRATE_02
:: forall (n :: NetworkDiscriminant) t.
( DecodeAddress n
, EncodeAddress n
, PaymentAddress n ByronKey
)
=> (Context t -> IO ApiByronWallet)
-> Int
-> SpecWith (Context t)
scenario_MIGRATE_02 fixtureSource addrCount = it title $ \ctx -> do
-- Restore a Byron wallet with funds, to act as a source wallet:
wSrc <- fixtureSource ctx
let originalBalance =
view (#balance . #available . #getQuantity) wSrc

-- Create an empty target wallet:
(wDest, mw) <- emptyRandomWalletMws ctx
let addresses :: [Text] =
take addrCount $ encodeAddress @n <$> randomAddresses @n mw

-- Calculate the expected migration fee:
r0 <- request @ApiWalletMigrationInfo ctx
(Link.getMigrationInfo wSrc) Default Empty
verify r0
[ expectResponseCode @IO HTTP.status200
, expectField #migrationCost (.> Quantity 0)
]
let expectedFee = getFromResponse (#migrationCost . #getQuantity) r0

-- Perform a migration from the source wallet to the target wallet:
r1 <- request @[ApiTransaction n] ctx
(Link.migrateWallet wSrc)
Default
(Json [json|
{ passphrase: #{fixturePassphrase}
, addresses: #{addresses}
}|])
verify r1
[ expectResponseCode @IO HTTP.status202
, expectField id (`shouldSatisfy` (not . null))
]

-- Check that funds become available in the target wallet:
let expectedBalance = originalBalance - expectedFee
eventually "Wallet has expectedBalance" $ do
r2 <- request @ApiByronWallet ctx
(Link.getWallet @'Byron wDest) Default Empty
verify r2
[ expectField
(#balance . #available)
(`shouldBe` Quantity expectedBalance)
, expectField
(#balance . #total)
(`shouldBe` Quantity expectedBalance)
]
where
title = "BYRON_MIGRATE_02 - after a migration operation successfully \
\completes, the correct amount eventually becomes available \
\in the target wallet for an arbitrary number of specified addresses."

--
-- More Elaborated Fixtures
--
Expand Down
15 changes: 9 additions & 6 deletions lib/byron/test/unit/Cardano/Wallet/Byron/TransactionSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ prop_rebalanceChangeOutputs sel onDangling = do
propSizeEstimation
:: forall n k.
( WalletKey k
, MaxSizeOf Address n k
, MaxSizeOf Address n ByronKey
)
=> ProtocolMagic
-> Gen CoinSelection
Expand All @@ -334,13 +334,16 @@ propSizeEstimation pm genSel genChngAddrs =
cbor = fromCoinSelection sel chngAddrs
size = fromIntegral $ BS.length $ CBOR.toStrictByteString cbor

-- We always go for the higher bound for change address payload's size,
-- so, we may end up with up to 12 extra bytes per change address in our
-- estimation.
-- As we have
-- maxSizeOf Icarus w/ Mainnet = 43
-- maxSizeOf Random w/ Mainnet = 76
-- The difference is 33, and we always go for the higher bound for
-- change address payload's size, so, we may end up with up to
-- 33 + 12 = 45 extra bytes per change address in our estimation.
-- For Icarus addresses, we can be as good as 4 bytes per change address
-- because there's no variance due to the derivation path encoded as
-- attributes (this only happens on random addresses).
margin = 12 * fromIntegral (length $ change sel)
margin = 45 * fromIntegral (length $ change sel)
realSizeSup = Quantity (size + margin)
realSizeInf = Quantity size
in
Expand Down Expand Up @@ -510,7 +513,7 @@ xprv seed =
goldenTestSignedTx
:: forall (n :: NetworkDiscriminant) k.
( k ~ IcarusKey
, MaxSizeOf Address n k
, MaxSizeOf Address n ByronKey
, PaymentAddress n k
)
=> Proxy n
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,13 @@ import Cardano.Wallet.Api.Types
, ApiWalletDiscovery (..)
, ApiWalletMigrationInfo (..)
, DecodeAddress
, EncodeAddress (..)
, WalletStyle (..)
)
import Cardano.Wallet.Primitive.AddressDerivation
( PassphraseMaxLength (..), PassphraseMinLength (..) )
( PassphraseMaxLength (..), PassphraseMinLength (..), PaymentAddress )
import Cardano.Wallet.Primitive.AddressDerivation.Byron
( ByronKey )
import Cardano.Wallet.Primitive.Types
( SyncProgress (..) )
import Control.Monad
Expand Down Expand Up @@ -104,6 +107,8 @@ import qualified Network.HTTP.Types.Status as HTTP

spec :: forall n t.
( DecodeAddress n
, EncodeAddress n
, PaymentAddress n ByronKey
) => SpecWith (Context t)
spec = do
it "BYRON_CALCULATE_01 - \
Expand Down Expand Up @@ -547,8 +552,9 @@ spec = do
verify r
[ expectResponseCode @IO HTTP.status204
]
where
genMnemonics

where
genMnemonics
:: forall mw ent csz.
( ConsistentEntropy ent mw csz
, ValidEntropySize ent
Expand All @@ -557,4 +563,4 @@ spec = do
, mw ~ MnemonicWords ent
)
=> IO [Text]
genMnemonics = mnemonicToText . entropyToMnemonic @mw <$> genEntropy
genMnemonics = mnemonicToText . entropyToMnemonic @mw <$> genEntropy
Loading