Copyright | © 2018-2021 IOHK |
---|---|
License | Apache-2.0 |
Safe Haskell | None |
Language | Haskell2010 |
An implementation of shared script state using scheme specified in CIP-1854 Multi-signature Wallets.
Synopsis
- type SupportsDiscovery (n :: NetworkDiscriminant ) k = ( MkKeyFingerprint k ( Proxy n, k ' AddressK XPub ), MkKeyFingerprint k Address , SoftDerivation k, Typeable n)
-
data
SharedState
(n ::
NetworkDiscriminant
) k =
SharedState
{
- derivationPrefix :: ! DerivationPrefix
- accountXPub :: !(k ' AccountK XPub )
- paymentTemplate :: ! ScriptTemplate
- delegationTemplate :: !( Maybe ScriptTemplate )
- poolGap :: ! AddressPoolGap
- ready :: !( Readiness ( SharedAddressPools k))
- data Readiness a
-
data
SharedAddressPools
(key ::
Depth
->
Type
->
Type
) =
SharedAddressPools
{
- externalPool :: !( SharedAddressPool ' UtxoExternal key)
- internalPool :: !( SharedAddressPool ' UtxoInternal key)
- pendingChangeIxs :: !( PendingIxs ' ScriptK )
- newtype SharedAddressPool (c :: Role ) (key :: Depth -> Type -> Type ) = SharedAddressPool { }
- newSharedAddressPool :: forall (n :: NetworkDiscriminant ) c key. (key ~ SharedKey , SupportsDiscovery n key, Typeable c) => AddressPoolGap -> ScriptTemplate -> Maybe ScriptTemplate -> SharedAddressPool c key
- data ErrAddCosigner
- data ErrScriptTemplate
- mkSharedStateFromAccountXPub :: ( SupportsDiscovery n k, WalletKey k, k ~ SharedKey ) => k ' AccountK XPub -> Index ' Hardened ' AccountK -> AddressPoolGap -> ScriptTemplate -> Maybe ScriptTemplate -> SharedState n k
- mkSharedStateFromRootXPrv :: ( SupportsDiscovery n k, WalletKey k, k ~ SharedKey ) => (k ' RootK XPrv , Passphrase "encryption") -> Index ' Hardened ' AccountK -> AddressPoolGap -> ScriptTemplate -> Maybe ScriptTemplate -> SharedState n k
- addCosignerAccXPub :: ( SupportsDiscovery n k, WalletKey k, k ~ SharedKey ) => ( Cosigner , k ' AccountK XPub ) -> CredentialType -> SharedState n k -> Either ErrAddCosigner ( SharedState n k)
- isShared :: SupportsDiscovery n k => Address -> SharedState n k -> ( Maybe ( Index ' Soft ' ScriptK ), SharedState n k)
- retrieveAllCosigners :: Script Cosigner -> [ Cosigner ]
- validateScriptTemplates :: WalletKey k => k ' AccountK XPub -> ValidationLevel -> ScriptTemplate -> Maybe ScriptTemplate -> Either ErrScriptTemplate ()
- toSharedWalletId :: ( WalletKey k, k ~ SharedKey ) => k ' AccountK XPub -> ScriptTemplate -> Maybe ScriptTemplate -> Digest Blake2b_160
-
data
CredentialType
- = Payment
- | Delegation
- liftPaymentAddress :: forall (n :: NetworkDiscriminant ) (k :: Depth -> Type -> Type ). Typeable n => KeyFingerprint "payment" k -> Address
- liftDelegationAddress :: forall (n :: NetworkDiscriminant ) (k :: Depth -> Type -> Type ). Typeable n => Index ' Soft ' ScriptK -> ScriptTemplate -> KeyFingerprint "payment" k -> Address
Documentation
type SupportsDiscovery (n :: NetworkDiscriminant ) k = ( MkKeyFingerprint k ( Proxy n, k ' AddressK XPub ), MkKeyFingerprint k Address , SoftDerivation k, Typeable n) Source #
Convenient alias for commonly used class contexts on keys.
State
data SharedState (n :: NetworkDiscriminant ) k Source #
Shared wallet is a new kind of wallet owned by one or more co-signers. In this type of the wallet, addresses are defined by two monetary scripts (one for the ownership of assets and the other one for the ownership of stake). The two scripts can be the same, different, also the script for the ownership of stake can be absent.
The shared wallet can be in two states: pending or ready. In a pending state the wallet does not have account public keys for all co-signers, and hence discovery of script addresses co-shared with other co-signers is not possible. In a ready state the wallet has account public keys for all co-signers and co-shared script address discovery is possible.
The shared wallet is instantiated with an account public key, derivation path needed to recreate it for a holder of this shared wallet, ie., one of the co-signers. In order to construct correctly the wallet, ie., enable co-shared script addresses discovery the following is needed:
- a way to determine what range of indices are checked on the ledger. Mechanism of address pool, also adopted for sequential wallets, is used. The idea is to track all indices starting from 0 and up to N. N is variable as addresses are discovered (and marked as Used in consequence). The pool of addresses is enlarged in such way that the number of consecutive Unused addresses equals to address pool gap of the address pool. Hence, the address pool gap needs to be specified.
- script template for payment credential contains information about all collected account public keys for all parties engaged, here named co-signers. Also the skeleton determining script structure is provided. In this sense script is predetermined from the beginning and can variate only in verification key part that replaces co-signers in the script skeleton. The places where a specific cosigner is present is to be replaced with the derived verification key using the co-signer's account public key and the index that was chosen. This is the reason why we need complete set of account public keys for each co-signer to realize address discovery. The script template can be translated into a corresponding script, which hash is used in the address, only when account public keys for all cosigners specified in script are collected.The index for derivation is the same for each cosigner's derivation. The same index is used in both scripts that represent payment or delegation credential. Verification keys are derived using role=3 for payment credential.
- optional script template for delegation credential contains all information as in case of the script template for payment credential. One difference is that the verification keys are derived using role=4 for delegation credential.
When both script are present, the base address (with both credentials) is expected to be discovered. When script template for delegation credential is missing then enterprise address (non-stakable) is expected.
SharedState | |
|
Instances
Readiness status of the shared state.
Instances
Eq a => Eq ( Readiness a) Source # | |
Show a => Show ( Readiness a) Source # | |
Generic ( Readiness a) Source # | |
NFData a => NFData ( Readiness a) Source # | |
|
|
type Rep ( Readiness a) Source # | |
Defined in Cardano.Wallet.Primitive.AddressDiscovery.Shared
type
Rep
(
Readiness
a) =
D1
('
MetaData
"Readiness" "Cardano.Wallet.Primitive.AddressDiscovery.Shared" "cardano-wallet-core-2022.7.1-AGKhlyz9liLKN3QqZD1gj" '
False
) (
C1
('
MetaCons
"Pending" '
PrefixI
'
False
) (
U1
::
Type
->
Type
)
:+:
C1
('
MetaCons
"Active" '
PrefixI
'
False
) (
S1
('
MetaSel
('
Nothing
::
Maybe
Symbol
) '
NoSourceUnpackedness
'
SourceStrict
'
DecidedStrict
) (
Rec0
a)))
|
data SharedAddressPools (key :: Depth -> Type -> Type ) Source #
SharedAddressPools | |
|
Instances
newtype SharedAddressPool (c :: Role ) (key :: Depth -> Type -> Type ) Source #
An address pool which keeps track of shared addresses.
To create a new pool, see
newSharedAddressPool
.
Instances
newSharedAddressPool :: forall (n :: NetworkDiscriminant ) c key. (key ~ SharedKey , SupportsDiscovery n key, Typeable c) => AddressPoolGap -> ScriptTemplate -> Maybe ScriptTemplate -> SharedAddressPool c key Source #
Create a new shared address pool from complete script templates.
data ErrAddCosigner Source #
Possible errors from adding a co-signer key to the shared wallet state.
NoDelegationTemplate |
Adding key for a cosigner for a non-existent delegation template is not allowed. |
NoSuchCosigner CredentialType Cosigner |
Adding key for a cosigners for a given script is possible for the cosigner present in the script template. |
KeyAlreadyPresent CredentialType |
Adding the same key for different cosigners for a given script is not allowed. |
WalletAlreadyActive |
Adding is possible only to pending shared wallet. |
CannotUpdateSharedWalletKey |
Updating key is possible only for other cosigners, not cosigner belonging to the shared wallet. |
Instances
Eq ErrAddCosigner Source # | |
Defined in Cardano.Wallet.Primitive.AddressDiscovery.Shared (==) :: ErrAddCosigner -> ErrAddCosigner -> Bool Source # (/=) :: ErrAddCosigner -> ErrAddCosigner -> Bool Source # |
|
Show ErrAddCosigner Source # | |
|
data ErrScriptTemplate Source #
ErrScriptTemplateInvalid ! CredentialType ! ErrValidateScriptTemplate | |
ErrScriptTemplateMissingKey ! CredentialType ! Text |
Instances
mkSharedStateFromAccountXPub :: ( SupportsDiscovery n k, WalletKey k, k ~ SharedKey ) => k ' AccountK XPub -> Index ' Hardened ' AccountK -> AddressPoolGap -> ScriptTemplate -> Maybe ScriptTemplate -> SharedState n k Source #
Create a new SharedState from public account key.
mkSharedStateFromRootXPrv :: ( SupportsDiscovery n k, WalletKey k, k ~ SharedKey ) => (k ' RootK XPrv , Passphrase "encryption") -> Index ' Hardened ' AccountK -> AddressPoolGap -> ScriptTemplate -> Maybe ScriptTemplate -> SharedState n k Source #
Create a new SharedState from root private key and password.
addCosignerAccXPub :: ( SupportsDiscovery n k, WalletKey k, k ~ SharedKey ) => ( Cosigner , k ' AccountK XPub ) -> CredentialType -> SharedState n k -> Either ErrAddCosigner ( SharedState n k) Source #
The cosigner with his account public key is updated per template.
For each template the script is checked for presence of the cosigner:
* If present, then the key is inserted into the state.
* Otherwise, fail with
NoSuchCosigner
.
If the key is already present it is going to be updated.
For a given template all keys must be unique. If already present key is tried to be added,
KeyAlreadyPresent
error is produced. The updating works only with pending shared state,
When an active shared state is used
WalletAlreadyActive
error is triggered.
Updating the key for delegation script can be successful only if delegation script is
present. Otherwise,
NoDelegationTemplate
error is triggered.
isShared :: SupportsDiscovery n k => Address -> SharedState n k -> ( Maybe ( Index ' Soft ' ScriptK ), SharedState n k) Source #
validateScriptTemplates :: WalletKey k => k ' AccountK XPub -> ValidationLevel -> ScriptTemplate -> Maybe ScriptTemplate -> Either ErrScriptTemplate () Source #
toSharedWalletId :: ( WalletKey k, k ~ SharedKey ) => k ' AccountK XPub -> ScriptTemplate -> Maybe ScriptTemplate -> Digest Blake2b_160 Source #
data CredentialType Source #
Instances
liftPaymentAddress :: forall (n :: NetworkDiscriminant ) (k :: Depth -> Type -> Type ). Typeable n => KeyFingerprint "payment" k -> Address Source #
liftDelegationAddress :: forall (n :: NetworkDiscriminant ) (k :: Depth -> Type -> Type ). Typeable n => Index ' Soft ' ScriptK -> ScriptTemplate -> KeyFingerprint "payment" k -> Address Source #