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

ADP-494 - Add POST endpoint for script address #2253

Merged
merged 26 commits into from
Nov 5, 2020

Conversation

paweljakubas
Copy link
Contributor

@paweljakubas paweljakubas commented Oct 16, 2020

Issue Number

https://jira.iohk.io/browse/ADP-494

Overview

  • I have updated swagger with script as string
  • I have added script as json
  • I have extended Api
  • I have extended core unit tests
  • I have added cardano-addresses based impl
  • I have added illustrative integration tests

Comments

@paweljakubas paweljakubas self-assigned this Oct 16, 2020
@paweljakubas paweljakubas requested a review from KtorZ October 16, 2020 11:11
@@ -610,6 +640,16 @@ x-signedTransactionBlob: &signedTransactionBlob
type: string
format: binary

x-addressParts: &addressParts
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

enterprise address -> { networkTag, paymentCredential }
reward account address -> { networkTag, stakeCredential }
stake address -> { networkTag, paymentCredential, stakeCredential }

x-networkTag: &networkTag
description: Can be null for 'Icarus' and 'Byron' styles.
type: integer
minimum: 0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should not be necessary because the server is already instantiated for one of the given networks. So the network tag is implicit based on how one started the server (--mainnet or --testnet)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed in ccd4eb4

@@ -321,6 +326,30 @@ x-poolMetadataSource: &poolMetadataSource
format: uri
example: https://smash.cardano-mainnet.iohk.io/

x-walletCredentialPubkey: &walletCredentialPubkey
description: An extended public key (public key + chain code) for credential
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why require an extended key here? The chain code is unnecessary.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to my best knowledge we are hashing extended public key with blake2b not just public key -> https://github.com/input-output-hk/cardano-addresses/blob/master/core/lib/Cardano/Address/Style/Shelley.hs#L639

Copy link
Member

@KtorZ KtorZ Oct 16, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indeed! Thanks! I made this mistake mainly because of this :

$ cat signingKey1.prv | cardano-address key public --bech32
xpub13pfp60uf4ru7cmj5d57xjdzj6lagn328ah67h35urqrl92jn094z0s07fcy2pvfw3xfhna6fa24na8nk6lraymjcrl5wwj6chsjqtjqlfw44z

So we will need a way to get public key only (not chain code included) in cardano-addresses, right?

Copy link
Member

@KtorZ KtorZ Oct 16, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that'd be an interesting feature indeed. Be able to get just the public part, without chain code

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alternatively, we can have the API accepts both, but the chain code should not a required

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

corrected in 2f91803

x-walletCredentialPubkey: &walletCredentialPubkey
description: An extended public key (public key + chain code) for credential
type: string
format: hex
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about bech32 ;) ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

used xpub hrp -> ccd4eb4


x-walletScript: &walletScript
description: A script as text with predicates and verification keys. Here probably we should add a full-fledged script object
type: string
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is that a string 🤔 ? Isn't the goal here to re-use the JSON object instances from cardano-addresses?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is going to be json object. just doing this in steps

Copy link
Contributor Author

@paweljakubas paweljakubas Oct 16, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

my attempt -> ccd4eb4
But when

$ openapi-spec-validator --schema 3.0.0 specifications/api/swagger.yaml 
found undefined alias 'walletCredentialScript'
  in "<file>", line 357, column 14

need to recall how to sneak recursive scheme in swagger

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Look at transaction metadatum. I recall we did something similar.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks, now it seems to be ok -> 2f91803

@paweljakubas paweljakubas force-pushed the paweljakubas/adp-494/post-script-address branch from ccd4eb4 to 2f91803 Compare October 22, 2020 11:22
@paweljakubas paweljakubas changed the title add swagger with script as string add POST endpoint for script address Oct 22, 2020
@paweljakubas paweljakubas force-pushed the paweljakubas/adp-494/post-script-address branch from 12777ed to a3ed826 Compare October 22, 2020 14:23
stack.yaml Outdated
@@ -87,177 +87,177 @@ nix:
# package cardano-crypto
# tests: False
# benchmarks: False
#
#
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that stack2cabal relies on these whitespaces and they shouldn't be trimmed.

@paweljakubas, is your editor correctly picking up the config from: https://github.com/input-output-hk/cardano-wallet/blob/master/.editorconfig#L11-L12

Copy link
Contributor Author

@paweljakubas paweljakubas Oct 23, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it seems so - this is config that is taken by my editor for this file:

# EditorConfig for /home/pawel/Work/IOHK/cardano-wallet/stack.yaml                                                                                                                                                 
indent_style = space                                                                                                                                                                                               
indent_size = 2                                                                                                                                                                                                    
end_of_line = lf                                                                                                                                                                                                   
charset = utf-8                                                                                                                                                                                                    
trim_trailing_whitespace = false                                                                                                                                                                                   
insert_final_newline = true                                                                                                                                                                                        
tab_width = 2

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think trim_trailling_whitespace=true is a nice thing to have.

When auto-generated whitespace gets removed in a file that you edited, use your editor's git function to discard those irrelevant hunks.

@@ -46,7 +46,7 @@ extra-deps:

# cardano-addresses-2.1.0
- git: https://github.com/input-output-hk/cardano-addresses
commit: e0ab4587266430a08734e1aec1c29d261a9a3b70
commit: 1399751501b03346265b2e429e5832bacd6df279
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should only pick released version of cardano-addresses. But I am quite reluctant releasing it in the state it is right now :/ ... I'd rather have it compliant with CIP5 for the release.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agree, pasted it as it is just in order to have a way to interact with what we have in cardano-addresses

@paweljakubas paweljakubas force-pushed the paweljakubas/adp-494/post-script-address branch 5 times, most recently from 07e4047 to 6b90e68 Compare October 26, 2020 18:06
netTag = case testEquality (typeRep @n) (typeRep @'Mainnet) of
Just{} -> 1
Nothing -> 0
--}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one is escaping me -> I want n -> Int ... for now I hacked it to be 1 (Mainnet) to carry on with integration tests

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that this should not be in core, because it only concerns cardano-node and really is cardano-node specific. Plus, you should be able to simply re-use: https://github.com/input-output-hk/cardano-wallet/blob/368b9fc27249e1faf6577c020297b74d4cf6f161/lib/shelley/src/Cardano/Wallet/Shelley.hs#L203-L218

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for this hint. did it in 3cf22f4 also did some reshuffling of code connected with HasNetworkId to use it

@paweljakubas paweljakubas added the Feature Mark a PR as adding a new feature, for auto-generated CHANGELOG label Oct 27, 2020
@paweljakubas paweljakubas marked this pull request as ready for review October 27, 2020 14:16
@paweljakubas paweljakubas requested review from rvl and KtorZ October 27, 2020 14:16
{ payload :: ByteString
, flavour :: AnyAddressType
, network :: Int
} deriving (Eq, Generic, Show)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not re-use the existing types for Addresses ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I use Addresses I will be able to differentiate between addr and addr_test based on network. but I will not be able to use reward_account's stake and stake_test (to my best knowledge). This was main reason I introduced this type

} deriving (Eq, Generic, Show)

data Credential = Credential
{ credential :: Either ApiPubKey ApiScript
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May I suggest a sum-type instead of wrapping a Either ?

data Credential 
    = CredentialPubKey ...
    | CredentialScript

?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should it be called ApiCredential as well for consistency?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done in 1cdaf25

pure ( unAddress $
CA.delegationAddress discriminant (spendingFromScript script1) (stakingFromScript script2)
, EnterpriseDelegating )
(Nothing, Nothing) -> fail "At least one credential is required"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's one big chunk 😬
My recommendation would be to capture this already in the API data-type itself. So, instead of:

data ApiCredentials = ApiCredentials
    { spending :: !(Maybe Credential)
    , staking :: !(Maybe Credential)
    } deriving (Eq, Generic, Show)

have something along the lines of:

data ApiAddressData 
    = AddrBase Credential Credential
    | AddrPtr Credential Ptr
    | AddrEnterprise Credential
    | AddrBootstrap Address

this would be quite more readable and also get rid of the "impossible" case.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good idea, indeed it made things simpler -> 1071e78

Copy link
Contributor

@rvl rvl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good start 👍

- any condition for which any list element' expectation is to be met for the condition to be valid
- some condition for which a minimal number of list elements' expectation is to be met for the condition to be valid
example:
0: "script_vkh18srsxr3khll7vl3w9mqfu55n6wzxxlxj7qzr2mhnyreluzt36ms"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This value should be a yaml list of examples, rather than an object with numeric keys. The single example object is specific to Metadata.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done in e6c0510

properties:
address: *anyAddress

ApiCredential: &ApiCredential
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this be renamed to ScriptAddressCredential? Are the Api prefixes needed for anything? This is a swagger file - it's all API.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rvl we typically keep the same naming as in the Cardano.Wallet.Api.Types module for the swagger file references because it creates a straightforward mapping for the automated schema validations we perform in tests. This way, one can write ToSchema instances as:

instance ToSchema (ApiSelectCoinsPayments n) where
    declareNamedSchema _ = declareSchemaForDefinition "ApiSelectCoinsPayments"

instance ToSchema ApiSelectCoinsAction where
    declareNamedSchema _ = declareSchemaForDefinition "ApiSelectCoinsAction"

instance ToSchema (ApiCoinSelection n) where
    declareNamedSchema _ = declareSchemaForDefinition "ApiCoinSelection"

instance ToSchema ApiWallet where
    declareNamedSchema _ = declareSchemaForDefinition "ApiWallet"

instance ToSchema ApiByronWallet where
    declareNamedSchema _ = declareSchemaForDefinition "ApiByronWallet"

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could even push it further and have default instances relying on generics and Typeable.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aha ok thanks.

Comment on lines 1528 to 1576
ApiScript: &ApiScript
type: object
required:
- script
properties:
script: *script

ApiPubKey: &ApiPubKey
type: object
required:
- pub_key
properties:
pub_key: *credentialPubKey
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these could both be removed and embedded directly into CredentialValue

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted them to be exposed to have a way in TypeSpec to check

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK fair enough

@@ -384,6 +398,34 @@ data ApiAddress (n :: NetworkDiscriminant) = ApiAddress
, state :: !(ApiT AddressState)
} deriving (Eq, Generic, Show)

newtype ApiScript = ApiScript
{ script :: ApiT Script
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think if the sole field is going to be ApiT Script, then you don't need the ApiScript newtype.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps the newtype might be needed if you want automatic JSON instances, but it looks like they are non-generically defined below.

} deriving (Eq, Generic, Show)

data Credential = Credential
{ credential :: Either ApiPubKey ApiScript
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should it be called ApiCredential as well for consistency?

arbitrary = ApiScript . ApiT <$> arbitrary

instance Arbitrary Script where
arbitrary = do
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment about generators of arbitrary tree structures applies here as it did in cardano-addresses.

In fact, could the types and generators from cardano-addresses be re-used?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

did in e6c0510

stack.yaml Outdated
@@ -87,177 +87,177 @@ nix:
# package cardano-crypto
# tests: False
# benchmarks: False
#
#
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think trim_trailling_whitespace=true is a nice thing to have.

When auto-generated whitespace gets removed in a file that you edited, use your editor's git function to discard those irrelevant hunks.

postAnyAddress
:: forall n. ApiCredentials
-> Handler AnyAddress
postAnyAddress body = do
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like not just any address can be posted. Is that right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, I can construct enterprise, reward account and base address for any credential (either from key or script). There is also pointer address missing that could be added in forthcoming PR. That's the rationale I proposed the name AnyAddress

@paweljakubas paweljakubas force-pushed the paweljakubas/adp-494/post-script-address branch from 2123387 to 1cdaf25 Compare October 28, 2020 18:29
@paweljakubas paweljakubas changed the title add POST endpoint for script address ADP-494 - Add POST endpoint for script address Oct 28, 2020
@paweljakubas paweljakubas force-pushed the paweljakubas/adp-494/post-script-address branch 2 times, most recently from e6c0510 to 6459319 Compare October 30, 2020 12:13
-- Generating golden test data for enterprise addresses:
--- $ cardano-address script hash "$(cat script.txt)" \
--- | cardano-address address payment --from-script --network-tag mainnet
it "ANY_ADDRESS_POST_01 - Golden tests for enterprise script address - signature" $ \ctx -> do
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpicking but why golden? Afaik, golden are unit tests with output in separate file which is not the case here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

golden because I have generated golden data in cardano-address for all examples, and check if all json/handling/.. machinery comes to the same results

, "script_vkh18srsxr3khll7vl3w9mqfu55n6wzxxlxj7qzr2mhnyreluzt38ms"]
, "at_least" : 2
}
} ] }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There seems to be some formatting issue here:

Screenshot from 2020-10-30 15-37-19

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks, will fix

@paweljakubas
Copy link
Contributor Author

paweljakubas commented Oct 30, 2020

I added golden for enterprise, reward account and base with script(s) as credential. I will add more (probably in separate PR) containing public key in credential and mixed after I will add --pub to publickey option (now I get --xpub) cardano-addresses very soon.

Plus I have problem with this trimming - cannot revert it

paweljakubas and others added 25 commits November 5, 2020 19:25
ApiScript correct

stack.yaml

stack.yaml

Regenerate nix

better Malformed
refine types

make unit tests pass finally
add AnyAddress to swagger and and core unit tests

fixup! Regenerate nix
fix malformed and change heap size

regenerate ApiAddressData

some swagger fixes and reuse of Script Arbitrary instance from cardano-addresses

hlint
git checkout master -- stack.yaml
git reset -p
  (use that to unstage the first hunk)
git commit
git checkout -- stack.yaml
final polishing

Clean up Api.Types aeson instances

201 -> 202 status code plus staking -> stake, spending -> payment in ApiAddressData

HLint
@paweljakubas paweljakubas force-pushed the paweljakubas/adp-494/post-script-address branch from 435400b to cf40f51 Compare November 5, 2020 18:26
@paweljakubas
Copy link
Contributor Author

bors r+

@iohk-bors
Copy link
Contributor

iohk-bors bot commented Nov 5, 2020

Build succeeded:

@iohk-bors iohk-bors bot merged commit 20cebfe into master Nov 5, 2020
@iohk-bors iohk-bors bot deleted the paweljakubas/adp-494/post-script-address branch November 5, 2020 19:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature Mark a PR as adding a new feature, for auto-generated CHANGELOG
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants