text:
How to verify data signed with nami wallet in a node backend?
I am playing around with the nami cardano wallet. I am able to link the wallet in the frontend and now want to link it to the backend.
First action the frontend sends an auth request with the cardano address to the backend. The backend returns a nonce to the frontend. The front end then lets nami wallet sign this nonce and sends the signature back to the backend.
In this step, the backend should validate if the signature is valid.
Now, how can I let the backend validate this signature?
This is the information I have access to:

balance
change address
network id
reward address
unused addresses
used addresses

Can I use this info to validate the signature? Or do I need to access the blockchain from the backend code?
(I will most likely be adding blockfrost api later, so nami-wallet + blockfrost will be how I access the blockchain. Unless there are other libraries available for the backend (most likely node.js), nami+blockfrost will be how I access the blockchain.
I am also using @emurgo/cardano-serialization-lib-browser - maybe here something is possible?
Based on response below I made a quick node script:
const {COSESign1, Label} = require("./extra_modules/@emurgo/cardano-message-signing-nodejs");
const {Address} = require("@emurgo/cardano-serialization-lib-nodejs");
const {Buffer} = require('buffer');
let signedRaw = "845869a30127045820674d11e432450118d70ea78673d5e31d5cc1aec63de0ff6284784876544be3406761646472657373583901d2eb831c6cad4aba700eb35f86966fbeff19d077954430e32ce65e8da79a3abe84f4ce817fad066acc1435be2ffc6bd7dce2ec1cc6cca6cba166686173686564f44568656c6c6f5840a3b5acd99df5f3b5e4449c5a116078e9c0fcfc126a4d4e2f6a9565f40b0c77474cafd89845e768fae3f6eec0df4575fcfe7094672c8c02169d744b415c617609";
let message = COSESign1.from_bytes(Buffer.from(signedRaw, 'hex'));
let headers = message.headers().protected().deserialized_headers();
let address = Address.from_bytes(headers.header(Label.new_text('address')).as_bytes());
let publicKey = headers.key_id();
let signature = message.signature();

OK, finally got a working solution, sharing a node script that works for the next person with the same problem:
const {COSESign1, Label} = require("./extra_modules/@emurgo/cardano-message-signing-nodejs");
const {Address, Ed25519Signature, PublicKey, BaseAddress, StakeCredential, RewardAddress} = require('@emurgo/cardano-serialization-lib-nodejs');
const {Buffer} = require('buffer');

class SignedData
{
    constructor(signed)
    {
        let message = COSESign1.from_bytes(Buffer.from(Buffer.from(signed, 'hex'), 'hex'));
        let headermap = message.headers().protected().deserialized_headers();
        this.headers = {
            algorithmId: headermap.algorithm_id().as_int().as_i32(),
            address: Address.from_bytes(headermap.header(Label.new_text('address')).as_bytes()),
            publicKey: PublicKey.from_bytes(headermap.key_id())
        };
        this.payload = message.payload();
        this.signature = Ed25519Signature.from_bytes(message.signature());
        this.data = message.signed_data().to_bytes();
    }

    verify(address, payload)
    {
        if (!this.verifyPayload(payload)) {
            throw new Error('Payload does not match');
        }
        if (!this.verifyAddress(address)) {
            throw new Error('Could not verify because of address mismatch');
        }
        return this.headers.publicKey.verify(this.data, this.signature);
    };

    verifyPayload(payload)
    {
        return Buffer.from(this.payload, 'hex').compare(Buffer.from(payload, 'hex'));
    }

    verifyAddress(address)
    {
        const checkAddress = Address.from_bech32(address);
        if (this.headers.address.to_bech32() !== checkAddress.to_bech32()) {
            console.log('FASLE1');
            return false;
        }
        // check if BaseAddress
        try {
            const baseAddress = BaseAddress.from_address(this.headers.address);
            //reconstruct address
            const paymentKeyHash = this.headers.publicKey.hash();
            const stakeKeyHash = baseAddress.stake_cred().to_keyhash();
            const reconstructedAddress = BaseAddress.new(
                checkAddress.network_id(),
                StakeCredential.from_keyhash(paymentKeyHash),
                StakeCredential.from_keyhash(stakeKeyHash)
            );
            return checkAddress.to_bech32() === reconstructedAddress.to_address().to_bech32();
        } catch (e) {
        }

        try {
            const stakeKeyHash = this.headers.address.hash();
            const reconstructedAddress = RewardAddress.new(
                checkAddress.network_id(),
                StakeCredential.from_keyhash(stakeKeyHash)
            );
            return checkAddress.to_bech32() === reconstructedAddress.to_address().to_bech32();
        } catch (e) {
        }
        return false;
    };
}
let signed = "845869a30127045820674d11e432450118d70ea78673d5e31d5cc1aec63de0ff6284784876544be3406761646472657373583901d2eb831c6cad4aba700eb35f86966fbeff19d077954430e32ce65e8da79a3abe84f4ce817fad066acc1435be2ffc6bd7dce2ec1cc6cca6cba166686173686564f44568656c6c6f5840a3b5acd99df5f3b5e4449c5a116078e9c0fcfc126a4d4e2f6a9565f40b0c77474cafd89845e768fae3f6eec0df4575fcfe7094672c8c02169d744b415c617609";
let signedData = new SignedData(signed);
let address = 'addr1q8fwhqcudjk54wnsp6e4lp5kd7l07xwsw725gv8r9nn9ard8ngatap85e6qhltgxdtxpgdd79l7xh47uutkpe3kv5m9smpyc34';
let payload = 'hello';
console.log(signedData.verify(address, payload));

Script with the solution (node JS):
const {COSESign1, Label} = require("./extra_modules/@emurgo/cardano-message-signing-nodejs");
const {Address, Ed25519Signature, PublicKey, BaseAddress, StakeCredential, RewardAddress} = require('@emurgo/cardano-serialization-lib-nodejs');
const {Buffer} = require('buffer');

class SignedData
{
    constructor(signed)
    {
        let message = COSESign1.from_bytes(Buffer.from(Buffer.from(signed, 'hex'), 'hex'));
        let headermap = message.headers().protected().deserialized_headers();
        this.headers = {
            algorithmId: headermap.algorithm_id().as_int().as_i32(),
            address: Address.from_bytes(headermap.header(Label.new_text('address')).as_bytes()),
            publicKey: PublicKey.from_bytes(headermap.key_id())
        };
        this.payload = message.payload();
        this.signature = Ed25519Signature.from_bytes(message.signature());
        this.data = message.signed_data().to_bytes();
    }

    verify(address, payload)
    {
        if (!this.verifyPayload(payload)) {
            throw new Error('Payload does not match');
        }
        if (!this.verifyAddress(address)) {
            throw new Error('Could not verify because of address mismatch');
        }
        return this.headers.publicKey.verify(this.data, this.signature);
    };

    verifyPayload(payload)
    {
        return Buffer.from(this.payload, 'hex').compare(Buffer.from(payload, 'hex'));
    }

    verifyAddress(address)
    {
        const checkAddress = Address.from_bech32(address);
        if (this.headers.address.to_bech32() !== checkAddress.to_bech32()) {
            console.log('FASLE1');
            return false;
        }
        // check if BaseAddress
        try {
            const baseAddress = BaseAddress.from_address(this.headers.address);
            //reconstruct address
            const paymentKeyHash = this.headers.publicKey.hash();
            const stakeKeyHash = baseAddress.stake_cred().to_keyhash();
            const reconstructedAddress = BaseAddress.new(
                checkAddress.network_id(),
                StakeCredential.from_keyhash(paymentKeyHash),
                StakeCredential.from_keyhash(stakeKeyHash)
            );
            return checkAddress.to_bech32() === reconstructedAddress.to_address().to_bech32();
        } catch (e) {
        }

        try {
            const stakeKeyHash = this.headers.address.hash();
            const reconstructedAddress = RewardAddress.new(
                checkAddress.network_id(),
                StakeCredential.from_keyhash(stakeKeyHash)
            );
            return checkAddress.to_bech32() === reconstructedAddress.to_address().to_bech32();
        } catch (e) {
        }
        return false;
    };
}
let signed = "845869a30127045820674d11e432450118d70ea78673d5e31d5cc1aec63de0ff6284784876544be3406761646472657373583901d2eb831c6cad4aba700eb35f86966fbeff19d077954430e32ce65e8da79a3abe84f4ce817fad066acc1435be2ffc6bd7dce2ec1cc6cca6cba166686173686564f44568656c6c6f5840a3b5acd99df5f3b5e4449c5a116078e9c0fcfc126a4d4e2f6a9565f40b0c77474cafd89845e768fae3f6eec0df4575fcfe7094672c8c02169d744b415c617609";
let signedData = new SignedData(signed);
let address = 'addr1q8fwhqcudjk54wnsp6e4lp5kd7l07xwsw725gv8r9nn9ard8ngatap85e6qhltgxdtxpgdd79l7xh47uutkpe3kv5m9smpyc34';
let payload = 'hello';
console.log(signedData.verify(address, payload));

I had some trouble implementing this - outlined the issues I found in a post linked below, incase anyone is able to provide some insight, please. https://cardano.stackexchange.com/questions/8708/missing-key-id-on-signature-from-signdata

@zing your link is dead?

You will need to send your verification key from Nami to the backend during the handshake in order to validate the signature.
cardano.signData(address: BaseAddress|RewardAddress, payload: string) : CoseSign1

The returned CoseSign1 object contains the payload, signature and the following protected headers:
key_id => PublicKey,
address => BaseAddress | RewardAddress
algorithm_id => EdDSA(0) (the algorithm used for Cardano addresses).

Source: Nami Readme
When you run the cardano.SignData method, you are returned an object that includes the public key for the private key that you used to sign the payload. Thus, when you send the signed object to the backend, the backend has everything it needs in the header to validate that transaction. To avoid hacking, you should also ensure that the public key is constant throughout communication with the same entity or in the same session.
The output is a hex-encoded byte string adhering to the CBOR format standard. Here is a link to a playground that will let you convert between the CBOR that is the output (e.g., "CoseSign1" from the readme) and something readable. Here is an example output (don't forget to check all of the boxes to get the full result).
[<< {1: -8, 4: h'ABF29B244C2E1C4DD3CA2F8DB27D87C6B73DA1A87D08389101D5D1ECEBDD0079', "address": h'E1DC0C1BD97FCD0ED6905EBA692C1DDEFF27DA43D59C5A1F2EA766442E'} >>, {"hashed": false}, 'this is a test\n', h'1F19958A76C7414F311F5176A52A544A4BE9D59FC5F3870F41B00D8B8C52C9B819953D10AE3F23C0D906A138D37D6C70DDADE77DB94D7054D730618106F18108']

It is a JSON array with two parts: the first is the header, and the second is the contents. According to CIP-0008, the block is expected to contain the following.
COSE_Sign1 = [
    Headers,
    payload : bstr / nil,
    signature : bstr
]

My guess is that the pub key is mapped to 4: ABF29B244C2E1C4DD3CA2F8DB27D87C6B73DA1A87D08389101D5D1ECEBDD0079
Hope this helps!

I had noticed that indeed, and I have tried the past 2h to extract that info, but as far as I found this is a cbor encoded message and I just cannot extract it. i see the data i tried to sign in it though (Buffer.from_bytes(data, 'hex').to_string('ascii') :) : Xi#'X gMd2EW'sUc\A.F=`bxHvTKc@gaddressX9Rkl-J:p3_o>PwD0c,f^
':>tN-jL5>/|kW\blFL&K!fhashedtKhello worldX@CW1f4\FcWB0IrK
_#wMYl{I;__#
56._TV68'Vu
DWf0)

I completed the explanation =^). Please see edits. Basically, it's just in CBOR, and you will have to convert it. I worked an example. Let me know if you need anything else!

I added a node script with a working solution using the emurgo serialization and message signing libraries. Thanks!

Nice well done!! Any time =^)

I've created javascript package that could help you with this. The examples in the README should show you how to sign data on frontend and validate the signature on the backend.

WARNING
The provided solution in the question is a great start, however
 verifyPayload(payload)
{
    return Buffer.from(this.payload, 'hex').compare(Buffer.from(payload, 'hex'));
}

Does not do a correct comparison since in the example the payload to check is not hexencoded but rather a string, so use this instead
    verifyPayload(payload)
{
    let hexMessage=Buffer.from(this.payload, 'hex');
    let stringMessage=hexMessage.toString();
    return stringMessage===payload;
}

It is a bad idea to refer to other solutions.  They may get edited and then your answer becomes weird.  Better to comment on them directly when you have enough reputation.  It is always better to focus on making your answer entirely about the question.  Take the [tour] and look at [answer] for great advice.

I would like to suggest a modification in the verifyPayload function.
verifyPayload(payload) { return Buffer.from(this.payload, 'hex').equals(Buffer.from(payload, 'utf8')); }

Given that this question - and all of the answers so far - are from mid 2021, I don't think the solutions are up to date. CIP-0030 brought a change to signData, which forced me to update the approach I use to verify wallets with my backend. I actually still use the CIP-0008 approach for Nami because of a bug on their end, but it is technically deprecated. This post explains what I do now.


text:
How to comply with proposed EU funds transfer regulation on crypto asset transfers?
If you look at the proposal, it requires crypto transfers between virtual/crypto asset service providers to transfer originator and beneficiary name (and some other originator info). However, this data could be carried also outside blockchain.
https://ec.europa.eu/finance/docs/law/210720-proposal-funds-transfers_en.pdf
How could Cardano comply with this upcoming regulation? Could it be done somehow for example via Atala Prism (or other id, like the upcoming EU e-id) , by enabling the e-id owners to consent the VASPs to consume this particular information, when (or actually before) the transaction is carried over the blockchain?
I hope this question falls with the scope of the cardano stackexchange. :)

At the base layer, Cardano can't provide such information because it's not built to do that. Atala Prism could be used to get around that however, you can't force anyone to use that layer to transact any more than forcing someone to reveal their seed phrase.

Agree. Still, the challenge remains. Perhaps Cardano will some day become a 'qualified electronic ledger' in terms of the proposed EU ei-id regulation (yes, another proposed regulation, link below), and even manage then to utilize the Atala Prism within the EU e-id scheme. (https://digital-strategy.ec.europa.eu/en/library/trusted-and-secure-european-e-id-regulation)

Cardano becoming a "qualified electronic ledger" means we'd have to make base layer changes for the EU which won't happen. Governments don't understand that blockchains don't care about them. CCP has all authority in their nation and the best they can manage is incentivizing bitcoin miners to leave and go elsewhere. The EU making dumb laws will be no different.

I understand your point. Yet, my thinking was if Cardano as an advanced blockchain (incl Atala Prism) could more easily adapt, and not necessarily on base layer. For example, I have understood Cardano transactions can carry metadata and b) the payer info need not be carried on chain. Nevertheless, I do not think it is all bad; EU is definitely trying to ban crypto. And if we try to be practical, then thinking how to adapt is ok, while perhaps not in line with strictest maximalism... But consider this closed from my side just wanted to bring this to the light for any opportunites that may exist

EU is not trying to ban crypto, I tried to write. :)

How about storing it in transaction metadata?

source: Stack Exchange

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/

sort: votes


text:
voting with Catalyst
I have multiple wallets (two on Daedalus, two on Yoroi and one Nami.) How do I vote with each wallet? Catalyst on my iPhone will only allow me to register one wallet.

You either have to vote with your first account, than reinstall the app (or just wipe its storage) and vote again with your second account.
Alternatively you can use any application cloning app on iOS that will allow you to setup the same application with two acocunts.

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/


text:
Create transaction by cardano-node using payment address generated by cardano-addresses
I'm using Cardano-addresses https://github.com/input-output-hk/cardano-addresses. I have a problem when try to make a transaction by using cardano-node using address generated by cardano-addresses.
So what I did is :

generate a root private key (root.xsk) from recovery phrase.
generate a payment verification key (addr.xvk)
generate a payment address from a payment key (payment.addr)

And the when I tried to make a transaction using that (payment.addr),
I don't know what signing key should I use to sign this transaction:
cardano-cli transaction sign
--tx-body-file body.raw
--testnet-magic 1097911063
--signing-key-file  what_key_should_I_use
--out-file signFile.signed

Please help me

Great question! Fundamentally, you want to use cardano-wallet to replace the following script in cardano-cli.
cardano-cli address key-gen \
 --verification-key-file key.vkey \
 --signing-key-file pkey.skey

In this tutorial, I will show you how convert the keys from the wallet format into the cli format.
First, create your recovery phrase and then a private key from that phrase. You have probably already completed this step, but here is an example:
cardano-address recovery-phrase generate --size 15 > phrase.prv

cardano-address key from-recovery-phrase Shelley < phrase.prv > root.xsk

Just for safety, let's go ahead and create a child key from that root key. It is not necessary, but we should get into in the habits of good security practices.
cat root.xsk | cardano-address key child 1852H/1815H/0H/0/0 > key.xsk

We have created our root.xsk and then from it our key.xsk. We want to use key.xsk to sign transactions. However, if you try to put it directly into cardano-cli, you will get an error. Even if you were to put it into a JSON format, you still would not be able to use it. We have to convert it into a different format vis a vis the following:
cardano-cli key convert-cardano-address-key --shelley-payment-key --signing-key-file key.xsk --out-file key.skey

Now we have converted our key.xsk into a key.skey. Now we have to create a verification key:
cardano-cli key verification-key --signing-key-file key.skey --verification-key-file key.vkey

Excellent! Now we have a key.skey and a key.vkey. You know what to do! Go ahead and create an address...
cardano-cli address build --payment-verification-key-file key.vkey --out-file key.addr --testnet-magic 1097911063

...and then build the transaction.
cardano-cli transaction sign \
--tx-body-file body.raw \
--testnet-magic 1097911063 \
--signing-key-file key.skey \
--out-file signFile.signed

Boom! You should be done!
We went from our child key.xsk, which looks like
{
    "chain_code": "4bfecd01af45a1abde446ec69522867a309f927f61a26d286d2475369e888e46",
    "key_type": "private",
    "extended_key": "c024ea34b52056996acb2f8f7d74b78b610ed773fb4ff6b933e460714dd8455edf6ea0b09c190126d364e69df714aef5824c7630f7b70e42050149f98b704448"
}

to our key.skey, which looks like
{
    "type": "PaymentExtendedSigningKeyShelley_ed25519_bip32",
    "description": "",
    "cborHex": "5880c024ea34b52056996acb2f8f7d74b78b610ed773fb4ff6b933e460714dd8455edf6ea0b09c190126d364e69df714aef5824c7630f7b70e42050149f98b7044480782a02ee41c9d7455faf2df6f36edb0c9d0c2c31eaf9e2f10f255ead21f53074bfecd01af45a1abde446ec69522867a309f927f61a26d286d2475369e888e46"
}

Sources
A great reference produced by the Cardano Foundation
The associated examples

Sorry for the late response. Thank you. Let me try to do it. I will give back the result asap

How did you venerate your addr.xvk? What derivation path did you use?
You need to use the private payment key to that specific derivation path.

https://github.com/input-output-hk/cardano-addresses . I created addr.xvk from root.xsk as the README of this article


text:
What happens if someone gets my seed phrase?
If someone happens to get my seed phrase (off a paper I wrote it on) can they restore my Daedalus wallet on another machine and take my ADA?

The seed phrase is used to generate your private keys (and thus your public keys as well). If someone has access to your seed phrase, they can "restore" your wallet Yoroi, Daedalus, or any other wallet application and can do anything with your wallet that you could do. The only way to know if this has happened is to notice any transaction sending Ada or a token from your wallet that was not done by you. If you have any doubt, just create a new wallet and transfer all of your tokens and then funds from your old potentially compromised wallet to your new wallet.

As others have stated, yes they can restore your wallet and yes they can take all your ada and anything else associated with it.
With that said, here are some tips for securing your mnemonic phrase.
1.) Do not store these phrases on a computer. And if you must, do it on a air-gapped machine.
2.) Make sure you protect yourself from natural disasters. For example what if your house burns down, burning your computer with the restored wallet as well as the piece of paper the mnemonic was on? I personally stamped mine into a metal plate and keep it in a fireproof safe.
3.) Make sure you include instructions in your safe for a what to do with it in case you die. Personally my family does not know much about crypto so I would want my beneficiaries to have instructions on what to do. This way a loved one gets those gains in case something were to happen to you.
4.) Bonus tip, get a hardware Wallet like a Ledger X. This insures that your keys are not compromised in the making of your wallet. Although probably unlikely, it is possible that your internet connected device, you make the wallet on, is compromised. If it is, there is a possibility your wallet is too.

Yes. If someone get your seed phrase, he will be able to steal all your funds.

If someone receives your mnemonic phrase or master private key, they can access your funds and instantly transfer all your ADA and tokens to their personal address.
Try not to make common mistakes and your funds will always be safe.

In Hierarchical Deterministic (HD) Wallet the seed phrase is used to generate a serie of public (and its correponding addresses) and private keys pairs (accounts).
A specific seed will always generate the same set of pairs.
If someone accesses your mnemonic, he will be able to generate the private key for the account containing the funds (usually the first account derived). With the private key, he will be able to sign a transaction and steal the funds.

In addition to securing your seed phrase using the above methods, you may also want to memorise it. You can do that by grouping it sets of maybe four and creating silly sentences each containing four of the words. Every three days, write down the sentenses while highlighting the keywords. Do that for some months and it sticks.
This way, if I ever need to move my funds in an emergency (like suspecting someone may have had access to the physical backup), I can move fast by downloading a wallet anywhere and importing the wallet from my memorised seed phrase and moving the funds.


text:
How can you run the Plutus Playground and serve the Haddock documentation from the VSCode DevContainer?
I am still looking to settle on a dev environment for Plutus contracts.
I am thinking about using VSCode with the devcontainer, but would like to know how well it all integrates. Is it easy to have the associated Playground and Haddock documentation alongside?
I am currently able to get cabal, Plutus server, Plutus Playground and Haddock docs in sync building Plutus in a nixos/nix container image. Would VSCode give me the same?

To run the Plutus Starter DevContainer from VSCode you have to:

Install docker and VSCode
Install Dev Containers and Remote Development extensions for VSCode
Run docker run -it --entrypoint /bin/bash inputoutput/plutus-starter-devcontainer:latest -s

You will initiate an instance of a Plutus Starter DevContainer, like this:

Then, open VSCode and from the Remote Explorer and under Dev Containers, select inputoutput/plutus-starter-devcontainer:latest and then open a terminal (Terminal - New Terminal)
Then run cd plutus-starter
cabal update
cabal build

You have built the plutus-starter project from the Dev Container. You can code and build any plutus project inside it, including the plutus-playground.


text:
(Lecture #6 It #2 - Core.Hs) : Explaining lookups use of both typedValidatorLookups and otherScript?
Can somebody explain these lines and why (both) Constraints.typedValidatorLookups... and
Constraints.otherScript... are used? Still struggling to get my head around lookups, so maybe that is why I'm somehow failing to grasp what exactly the purpose of these lines is and why for example, just the second is not enough by itself?
let lookups = Constraints.unspentOutputs (Map.singleton oref o)     <>
Constraints.typedValidatorLookups (typedValidator oracle) <>
Constraints.otherScript (oracleValidator oracle)```

(Core.hs : lines 169, 170)

This one is a bit technical it has to do with looking up and updating the constraints of an already existing transaction (that belongs to the script address). See Case ii) to skip my synopsis.
Just a little synopsis for future readers: The Core.hs script is an Oracle, that has to update its datum regarding Ada price. The lines in which lookups occur are in the function updateOracle that has the purpose of building a transaction and then submitting it. To accomplish this the constraints need to refer to typed script inputs and outputs. In updateOracle we dealt with two cases
.
.
    case m of
        Nothing -> do
            ledgerTx <- submitTxConstraints (typedOracleValidator oracle) c
            .
            .
        Just (oref, o,  _) -> do
            let lookups = Constraints.unspentOutputs (Map.singleton oref o)     <>
                          Constraints.typedValidatorLookups (typedOracleValidator oracle) <>
                          Constraints.otherScript (oracleValidator oracle)
                tx      = c <> Constraints.mustSpendScriptOutput oref (Redeemer $ PlutusTx.toBuiltinData Update)
            ledgerTx <- submitTxConstraintsWith @Oracling lookups tx
            .
            .

i) Create the Oracle (if it doesn't exists) at the same time of submission and add datum.

ii) Just update the datum of an existing Oracle

Case i) uses submitTxConstraints which takes the constraints as inputs in the form of a script instance (with typed validator hash & the compiled program) and the locked value with the script.
Case ii) on the other hand, uses submitTxConstraintsWith which takes the updated constraints as ScriptLookup type rather than a script instance. To your question, we need to semigroup:

Constraints.typedValidatorLookups (this gets the previous
parameters of the ScriptLookup)
Constraints.unspentOutputs (updates slTxOutputs from
ScriptLookup, which are the unspent outputs that the script wants to
spend)
Constraints.otherScript (updates slOtherScripts from
ScriptLookup, which are validators of the script other than our
script)

The reason why Constraints.typedValidatorLookups alone is not enough is because we would not be updating anything without semigrouping ScriptLookup element by element as defined in OffChain.hs)

What do you mean by "the previous parameters of the ScriptLookup"? Isn't the point of these lines precisely to construct the ScriptLookup?

No, that is handled when case m of -> Nothing for creating the Oracle for the first time. After that we do have initial ScripLookup  parameters.

Wait, so the Scriptlookup "state" is persistent while the (off-chain) contract is running in the wallet? Is that correct? I had understood that we were building everything up from scratch each time for each new transaction, on each pass. And if that is so, then where exacly is this Scriptlookup stored / why is it not lost once we leave the updateOracle function?  As far as I can make out it is not stored on the blockchain... (btw thanks for your answers so far!)

Yes, we build it from scratch the first time, ScriptLookup gives instructions to the wallet on how to create the transaction, and since transactions are unique it lives in the blockchain. Thus, we can access and update it latter on. Updates are only possible through new transactions, these are also build every time but they access to the previous state of the lookups and <> UTXOs out and validators.

I share your confusion around this. I  think a lot of it is due to the flux in the codebase.
On the other hand, I don't think it is anything complicated. The main purpose of Lookups, and thus also those two lines is to supply information needed for the transaction.
I noted that Constraints.otherScript seems to be consistently used where a transaction consumes uTxOs and needs to supply the validator script.
Have a look at Lars explanation in the Iteration #2 Lecture #6 video at 00:50h. In it he mentions that two scripts need to be supplied: one for the input uTxO (consume) and one for output uTxO. This explains why there are two entries, and my guess is that otherScript entry is to be able to consume a script uTxO.


text:
Options for adding Metadata to NFTs, to be used in a Plutus validator
I have a use case where I want to issue NFTs to users along with metadata (in the general sense of the term). The point of these NFTs is literally to hold that metadata - the user's results from participating in a race - not to display pictures/art in any way.
I later want the user to be able to provide these NFTs into a smart contract in order to prove their credentials (e.g. they are entering a marathon, which involves a smart contract that requires them to both pay an Ada fee, plus prove ownership of an NFT showing they have completed a marathon previously).
Transaction metadata is the 'workaround' used to associate metadata with art-based NFTs - "With this workaround of attaching metadata, third-party platforms like pool.pm can easily trace back to the last minting transaction, read the metadata, and query images and attributes accordingly. " (https://developers.cardano.org/docs/native-tokens/minting-nfts).
Transaction metadata is not currently usable within Plutus, however I believe in the future it will be possible to use it when creating transactions. Whether it will ever be possible to refer to it in a validator, I am not sure.
I have considered whether it would be possible to store the metadata in the datum of a UTXO holding the NFT in the user's wallet (a so called "communication" datum). However this feels fragile as I imagine you can't guarantee that it won't get lost, particularly if the UTXO also holds Ada that ends up getting spent.
Is there anything else I should be considering for this general requirement of "NFTs with metadata to be used during validation"?

If you don't have much data to store you can add it to the asset name. Like many do with the 1/1 NFTs where they put the ID into the name, e.g. MyProject123, MyProject124. You could add a unix timestamp for the time into the name of the token.

I surely hope there's a better answer than mine, but, as a workaround, I believe one option would be to use the NFT TokenName as a metadata. For example, you could have a minting policy that would verify the conditions you provided and, if they met, use the user's PubKeyHash as the token name.
In the script validator (which will accept or reject the NFT) you could ensure that the NFT symbol is the same as the one from your script policy (ensuring conditions are met) and the token name the same as the user's PubKeyHash (making sure it was minted by him).

Thanks for the answer. Apologies for the belated acceptance. Using the TokenName isn't something I'd considered, and could work depending on how large it can be (as I need to put a fair amount of metadata in there). I will check it out.

@William I don't think metadata size will be a problem, since you could create "accounts" inside a validator script, which are identified by a "signature token". The accounts could then handle all the metadata you need inside it's Datum and the "signature" token name would only need to contain the user public key hash and (depending on the implementation) the script validator hash

An answer I received may be helpful https://cardano.stackexchange.com/questions/2427/change-minted-tokens-recepient


text:
systemd service file for cardano node
i'm trying to run a node as a service using systemctl start node-relay.service
i get this error, can anyone advise what i'm doing wrong.
/home/ec2-user/.local/bin/cardano-node: error while loading shared libraries: libsodium.so.23: cannot open shared object file: No such file or directory
my node-relay.service file looks like this
Description= relay node
After=multi-user.target

[Service]
Type=simple
EnvironmentFile=/home/ec2-user/relay/node.environment
ExecStart=/home/ec2-user/.local/bin/cardano-node run --config $CONFIG --topology $TOPOLOGY --database-path $DBPATH --socket-path $SOCKETPATH --host-addr $HOSTADDR --port $PORT
KillSignal = SIGINT
RestartKillSignal = SIGINT
StandardOutput=journal
StandardError=journal
SyslogIdentifier=cardano-node

LimitNOFILE=32768

Restart=on-failure
RestartSec=15s
WorkingDirectory=~
User=ec2-user
Group=ec2-user

[Install]
WantedBy=multi-user.target

my .bashrc file contains
export LD_LIBRARY_PATH="/usr/local/lib:$LD_LIBRARY_PATH"
export PKG_CONFIG_PATH="/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH"
export PATH="~/.local/bin:$PATH"

the node starts fine if it run it like this;
cardano-node run --config ~/relay/testnet-config.json --database-path ~/relay/db --socket-path ~/relay/db/node.socket --host-addr 0.0.0.0 --port 3000

Are you aware of this post: https://forum.cardano.org/t/error-cardano-node-error-while-loading-shared-libraries-libsodium-so-23-cannot-open-shared-object-file-no-such-file-or-directory/39820 ? It refers to another one here https://forum.cardano.org/t/updating-stake-pool-school-config-files/37749/14 which recommends more or less what you did but with an additional step. Worth a try.

The environment variables need to be added to the /home/ec2-user/relay/node.environment file. Or you can specify them directly in node-relay.service file.
[Service]
Type=simple
Environment="LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH"
Environment="PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH"

...

thanks, all makes sense now.


text:
Is there a limit to the integer size representing a native token supply?
Is there a limit to the integer size representing a native token supply in  Plutus? Does it share the same limit as Haskell GHC's native Integer representation of ~16GB (if I am not wrong). Does Plutus also use the GMP library for token supply?

Native tokens supplies are indeed unbounded integers. While the current implementation relies on GHC native Integers, the practical limit is much lower since it needs to fit in a transaction for which there's a maximum size of a few kilobytes.

"it needs to fit in a transaction" -- Depending on your minting policy, you could create tokens in multiple transactions. There is a max in a single transaction, but I don't know if there is a limit to he number of transactions that create that token.

That is correct, but, if you wanted to group those tokens into one UTXO, the output would need to fit in a transaction. Still, you're right, in a system doing some aggregation across the entire set, the number could be arbitrarily large.


text:
Poly Network attack - lessons for Plutus devs?
Over on Twitter, @kelvinfichter gave an analysis (included below) of the recent Poly Network hack.
Without any of the benefits of hindsight, are there reasons why the exploit would have been less likely to occur in Plutus on Cardano?

Poly has this contract called the EthCrossChainManager. It's basically a privileged contract that has the right to trigger messages from another chain. It's a pretty standard thing for cross-chain projects.
There's this function verifyHeaderAndExecuteTx that anyone can call to execute a cross-chain transaction. Basically it:

Verifies that the block header is correct by checking signatures (seems the other chain was a poa sidechain or something) and... then
Checks that the transaction was included within that block with a Merkle proof. Here's the code, it's pretty simple: EthCrossChainManager.sol#L127

One of the last things the function does is call _executeCrossChainTx, which actually makes the call to the target contract. Here's where the critical flaw sits.
Poly checks that the target is a contract EthCrossChainManager.sol#L185. But Poly forgot to prevent users from calling a very important target... the EthCrossChainData contract: EthCrossChainData.sol.
Why is this target so important? It keeps track of the list of public keys that authenticate data coming from the other chain. If you can modify that list, you don't even need to hack private keys. You just set the public keys to match your own private keys. See here for where that list is tracked: EthCrossChainData.sol#L22.
So someone realized that they could send an cross-chain message directly to the EthCrossChainData contract.
What good does that do them? Well, guess which contracted owned the EthCrossChainData contract... yep. The EthCrossChainManager. By sending this cross-chain message, the user could trick the EthCrossChainManager into calling the EthCrossChainData contract, passing the onlyOwner check.
Now the user just had to craft the right data to be able to trigger the function that changes the public keys. Link to that function here: EthCrossChainData.sol#L45.
The only remaining challenge was to figure out how to make the EthCrossChainManager call the right function. Now comes a little bit of complexity around how Solidity picks which function you're trying to call.
The first four bytes of transaction input data is called the "signature hash" or "sighash" for short. It's a short piece of information that tells a Solidity contract what you're trying to do. The sighash of a function is calculated by taking the first four bytes of the hash of "()".
For example, the sighash of the ERC20 transfer function is the first four bytes of the hash of transfer(address,uint256). Poly's contract was willing to call any contract. However, it would only call the contract function that corresponded to the following sighash: Errr but wait... _method here was user input.
All the attacker had to do to call the right function was figure out some value for _method that, when combined with those other values and hashed, had the same leading four bytes as the sighash of our target function.
With just a little bit of grinding, you can easily find some input that produces the right sighash. You don't need to find a full hash collision, you're only checking the first four bytes.
So is this theory correct? Well... here's the actual sighash of the target function:
> ethers.utils.id ('putCurEpochConPubKeyBytes(bytes)').slice(0, 10)
'0x41973cd9'`

And the sighash that the attacker crafted...
> ethers.utils.id ('f1121318093(bytes,bytes,uint64)').slice(0, 10)
'0x41973cd9'

Fantastic. No private key compromise required! Just craft the right data and boom... the contract will just hack itself!

The author then goes on to give lessons learned.
Do Plutus developers also need to learn from these lessons or are they specific to Solidity?

One of the biggest design lessons that people need to take away from this is: if you have cross-chain relay contracts like this, MAKE SURE THAT THEY CAN'T BE USED TO CALL SPECIAL CONTRACTS.
The EthCrossDomainManager shouldn't have owned the EthCrossDomainData contract. Separate concerns.
If your contract absolutely need to have special privileges like this, make sure that users can't use cross-chain messages to call those special contracts.
And just for good measure, here's the function to trigger a cross-chain message: EthCrossChainManager.sol#L91. Nothing here prevents you from sending a message to the EthCrossChainData contract.

@kelvinfichter also gives a simplified summary of the attack: https://twitter.com/kelvinfichter/status/1425290462076747777

Here's a link to Charles Hoskinson talking about the Cardano/Plutus approach back in March 2019: https://youtube.com/watch?v=f-rqaTLwWgs&t=4483s

This is a very broad question but here's what I think regarding this topic.
Without any of the benefits of hindsight, are there reasons why the exploit would have been less likely to occur in Plutus on Cardano?
First of all, this could have happened on Cardano too. As Charles said in his recent update:

This is not to say that hacks won't happen on Cardano, it will!
(...)
The hacks will occur in uncertified software. Applications that are not rigorously debugged or checked.
(...)
You can't control people maliciously or incompetently writing software that can create problems.
But the existence of certified software against known standards and auditing means that the consumer can have a visual representation (...) that demonstartes the difference between something that is known and reliable and something that is unknown.

See: https://youtu.be/xSXSZ5xLpYI?t=665
What this essentially means is that a similar exploit could happen on Cardano, but it is less likely for certified smart contracts that have been audited. This will not give 100% guarantee that there are no vulnerabilities in the contract. Some vulnerability may be missed in the audit too, but the risk can be greatly reduced.
Do Plutus developers also need to learn from these lessons or are they specific to Solidity?
I'm no expert when it comes to cross chain relay contracts, but I would answer this question with yes. It's always good to know about possible vulnerabilities and if you ever come across some Plutus code that makes calls to other smart contracts, the polygon hack is something to remember: "Are there any special contracts that I should not be able to call here?". Knowing about these things can make you write better and more secure code.

It was those words from Charles' that prompted me to ask the question.
There is a strong narrative in the community that Cardano smart contracts are going to be more secure. Given that solidity code could also be audited, I’m looking for specific evidence that may support the increased security narrative (e.g. tooling).
Otherwise there is perhaps a risk that the increased complexity/lack of familiarity with functional programming could actually make bugs more common on the The Island.

Haskell is a functional programming language, which is well-suited for high-assurance code and programs that require a high degree of formal verification because every line of code can be mathematically proven to be correct. This is one of the main advantages Plutus smart contracts have in comparison to e.g. Solidity. However, there is a difference between mathematically correct and secure. Plutus can't protect you from making mistakes like getting your access rights wrong as in the polygon example.

[In short]
"Things can go wrong in any software" is a statement that misses a mammoth fact. The probability of occurrence can vary on an astronomical scale, like the probability of a bug in a Javascript program( written by me in college) and the code driving the Curiosity rover. There have been bugs even in spacefaring vehicles that had caused catastrophic accidents like thee Flight 501 Failure. It may not be prudent to compare them at any level. Cardano is written in a Functional Programming language, Haskell, which has existed in the academic world for 30 years. The functional programming paradigm prevents [make it impossible] for programmers to make stupid mistakes and, on top of it, adds formal verification that makes the software space grade. Therefore if we have to follow the human scale and not some astronomical scale, we can say Cardano will not face hacks like what these mushroom networks face.
[In Detail]
The piece of the code from the Poly Network which had the vulnerability is referenced below.

Analysis
There are loops, jumps, and variables. The code can exist in various states. And it becomes impossible to test the code in all the possible states. After learning Haskell and Plutus, I can say with certainty loops, backward and forward jumps, and variables are the sources of all problems. Now for any new programmer, these are the first three steps that are taught. When I started learning Haskel, it was unbelievable that it is possible to program without these basic constructs. Haskell was heavily used by the Math community, which defines function as one input that gives one output irrespective of the date, time, or places it is executed. Everyone knows the square root of 2, but try calculating in C/C++/Java, depending on the floating-point implementation in a particular computer, the result varies by tiny amounts. However, due to the compounding effect of software, these tiny changes add up leading to a noticeable difference downstream. People working in Digital Signal Processing can vouch will vouch for this issue. Like the duration of a second determined by the pendulum clock with a temperature change.
Haskell is based on purity and has no variables and loops. It aims to achieve a lookup table-like behavior in which the values are calculated and pre-stored. Lookup table-like behavior prevents change in output due to state change. The functions are written in Haskell behave like mathematical functions. It goes to great lengths to achieve purity resulting in deterministic behavior. For example, see the following codeTake From
function main():
print assemble(3)
function assemble(x):
  var y = 0
  var s = “”
  do until (y > x)
    s += y++
  loop
  return s

and same logic implemented in Haskell
main = putStrLn $ assemble 3
assemble 0 = "0"
assemble y = assemble (y-1) ++ show y

Now it's not easy to appreciate Haskell's clarity unless we understand the type system. In the first code class, most of the languages accept any type of input to function assemble and try to convert to Int for adding and comparing. Haskell, does not allow writing codes without explicit type constraints. Haskell has a robust type system preventing many logical errors so common in languages like python and javascript. Even functions that have to subtract 2 from a given number can be a source of potential mistakes.
Now that's all good. But if there are no checks put in place, even the most saint of a person can become corrupt. Therefore all software is tested to ensure there is no error. The funny part is that it is some software that tests the other software, and the testing software can only generate fixed-size test scenarios. Therefore there is a need to reduce the surface required to test. The surface of testing is reduced by adopting functional programming. The added advantage is that it inherently helps in carrying out what is called "Formal Verification." Formal verification is an integral step in VLSI chip manufacturing. That is why there are very few "Bugs" in hardware chips. ( Have you ever come across any bug in the Intel I7 processor? now compare it with the number of bugs you had seen in Microsoft windows!!!.)

Formal Verification is the process of proving the correctness of systems (hardware/software/algorithms) using mathematical methods. Essentially it is used for ensuring, that something (be it a motherboard, a small chip, a library, a whole program, or an operating system) works as expected. For doing so, one formulates the “thing” mathematically, then formulates theorems that should or shouldn’t hold, and finally proves or disproves these theorems in mathematical ways.
When using the process in Software Development, it is often referred to as Formal Software Verification.

A pedestrian example is the square of an Integer is Integer. Math can prove this. We don't have to try all possible Integers and check that its square is an Integer. Programs that are written in functional languages can be formally verified. Unfortunately, a purely functional program will have no "so-called" side effects like any interaction with the outside world, like reading and writing into a network socket (used in the propagation of blocks in the blockchain). Therefore, Haskell has come up with very clever ways to permit side effects through strictly controlled mechanisms, preventing expansion of the surface required to carry out the testing.
These are some of the mechanisms which Cardano is using to ensure Secure Operation. Charles' Statement, "This is not to say that hacks won't happen on Cardano, it will! " is a fact. Still, comparative probability and the scale of impact on Risk Management are most likely to be astronomically minimal, compared to ad-hoc blockchains mushrooming out in the wild.


text:
Building nodes on computers in a local network
How may I add the public IP address of a relay node to a block producer?
I have set both machines at home so they share the same public IP address if I am not wrong.

The relay node needs to know the IP of the block producer. If they are in the same network, you can use the local IP for this. Only the relay node needs to be accessible from outside of your local network (using your public IP).
When running the nodes at home you also need to make sure that you have a static public IP address or use some sort of DynDNS service. However, DynDNS might cause your nodes to be temporary unavailable which could lead to missing blocks.


text:
Generate random number in Plutus on-chain code
Is it possible to generate a random number in Plutus on-chain code? For example, if I would like to implement a smart contract that works like gambling game, where a person deposits ADA and bets on a random outcome and then the contract generates that random outcome to determine if the player won?

Is it possible to generate a random number in Plutus on-chain code?

No. On-chain code is deterministic, so there is no way to generate a number on-chian that someone off-chain couldn't predict.
The way around this would be to use an RNG oracle. Essentially outsourcing the generation of the random number to some third party, off-chain. You can then use that oracle's (or multiple oracles') data as an input for any games that needs random values.

Thats what I thought. Rather than using an oracle, would it be possible to simulate a RNG by somehow combining data available in UTXOs? If we would require the input transactions to have random datums and then combine them for all UTXOs would that be sufficiently random?

That would create a sort of lottery, where people would be looking for UTxOs that meet a certain requirement, so not exactly an RNG.


text:
Disable contract after purpose achieved
After a contract has fulfilled its mission in life (such as pay beneficiary), is it proper to delete or disable said contract? If so, how exactly is this done?
Offhand, I would think that if the contract gets needlessly validated (for the rest of eternity [yikes!]) it would needlessly clog up the system.

I don't think "disabling" a contract is possible since a "contract" in Cardano is not deployed anywhere on chain. The script/contract is supplied with a transaction that wants to spend UTXOs sitting at the contract address (which is basically a hash of the script code). Anybody can construct such at transaction at any time and the validator node will need to validate it.
The network will not be congested because as others have pointed out "contracts" in Cardano are completely passive and do not run on their own. They only run if a transaction wants to spend UTXOs sitting at the script address. If somebody would want to attack the network and construct millions of such transactions to run the code it would ruin him because each transaction has to pay fees and the fees are based on the resources needed to run the script. The more computational/memory heavy the script is the more fees you have to pay.

I would think that if the contract gets needlessly validated (for the rest of eternity [yikes!])

Ah. This is a misunderstanding. Scripts are completely passive. Nothing gets run unless a transaction interacts with it.
So, in the case of a contract that pays a beneficiary, the script doesn't do that for you, it includes a validator that says "yes" or "no" to anyone trying to spend the UTxOs at the script address.

Ok, so allow me to rephrase: Is it correct that if all the constraints of the submitted tran end up being satisfied, then the tran stops being validated?

"constraints of the submitted tran end up being satisfied." You can build a transaction that satisfies whatever constraints you give it, but you can only interact with scripts with transactions that meet the constraints of scripts' validators. "then the tran stops being validated?" Do you mean the transaction is invalid? Any transaction that meets the constraints of the script's validator can spend UTxOs (either to take them or to update the state) from the script address. In perpetuity. That being said, there would be no reason to interact with a script that doesn't have anything to spend.


text:
Constraints.mustPayToPubKey requires txSignedBy?
For a contract, I want to use Constraints.mustPayToPubKey for an arbitrary pubKeyHash (pkh), such as a lucky winner in a lottery.
Question: Does the validator need to check that the transaction sees that pkh (using txSignedBy or similar)?  If so, why?

Does the validator need to check that the transaction sees that pkh?

Yes. There is more than one way to organize the logic though.
Whichever way you structure the lottery, I will assume that the winnings are owned by the script. Any transaction that spends UTxOs owned by the script need to meet the qualifications of the validator.
As you say, one way to construct the smart contract would be to make sure you mustPayToPubkey of the winner. The validator would then need to guarantee that the output of the "pay out winnings" transaction includes the winnings and they are going to the winner's pkh. This wouldn't use txSignedBy, but rather do some combination of checks to guarantee the winnings are going to the correct pkh.
The way I would suggest modelling it is by saying only the winner can claim the winnings. In that case you could use txSignedBy.
This approach is similar to how the vesting example works in the PPP. It doesn't use txSignedBy, but rather just checks that the beneficiary is among the signers, essentially doing the same thing.
You don't even need to specify mustPayToPubKey at that point because it will default to the transaction builder's wallet. See the vesting example's grab constraints.

But what would happen if the tran does not see the pkh? Why can he not get paid in that case?

I'm not sure what you mean by "tran does not see the pkh." Do you mean if the validator doesn't see the pkh as a signer of the transaction?

Yes. Why is that a strict requirement?

Isn't that the behavior you want? You only want the winner to be able to spend the lottery winnings? When you spend ADA from your own wallet, the transaction is only valid if the owner of the ADA signed the transaction. This is the same as that, but the winnings are at the script address, rather than your own wallet, so you need write those requirements into the validator.

If you didn't have that requirement, anyone could spend the winnings.

I guess I don't understand what forces the winner to be hooked up to the transaction in the first place -- is that perhaps one of the purposes of the constraints when submitting the transaction?

More questions: So there seems to be two approaches, either focused on the current owner who mustPayToPubkey or as you recommended , focused on the winner who mustSpendScriptOutput . First why is your approach preferred -- simply because the use-case uses it? Second, is it wrong to use both approaches together? And third, why are both approaches allowed, being that it (apparently) only serves to complicate  the matter?

You might be thinking about what smart contracts do slightly wrong. I pointed out in your other question here: https://cardano.stackexchange.com/a/2315/1130. Scripts on chain are completely passive. In the case of a lottery, I'm imagining after a series of events, there is a pot of money that has been won by some pkh. We want that pkh to have access to the money. We have two options: Allow anyone to submit a transaction to send those funds to the winner pkh, OR allow the pkh to spend the money however she chooses. Since only the winner is motivated to submit a tx, I went with that approach.

Scripts take of space on the chain and cost gas to execute. Simple is better. Not to mention safer. And, as I mentioned. Only the winner is motivated to submit a tx to claim the funds, there is no need to provide multiple ways to access the money. Both approaches are allowed because there are infinite different smart contracts people might want to write. It's easy to imagine a script that would require you to send funds to some wallet. Maybe a tip to the contract writer or something :P

I see, so according to your approach, the winner would be notified externally (e.g., email), and thereby be instructed to open their wallet in order to request request the winnings -- such that if they fail to do so, they forfeit?

I also do not understand what you wrote above Allow anyone to submit a transaction to send those funds to the winner pkh. This obviously would not just be anyone but rather only one entity: The owner of the lottery who actually has the funds to disburse!

I imagine that the funds are on the script, and no-one owns them. That's the point of a decentralized smart contract after all. If there is some central owner of the funds, there would be no need for a smart contract on-chain, you could just have an agreement off-chain.

Thanks for clarifying that last point.  Kindly advise regarding your approach that the winner would in fact need to proactively submit tran in order to claim.

Yes. Since the script is passive, the winner wouldn't get paid unless they proactively submit a "claim" transaction of some sort. This of course could be automated off-chain, either to notify the winner or possibly have the wallet submit the "claim" transaction automatically.

FYI the SimpleEscrow plutus use-case uses mustPayToPubKey

That's a perfect example of a transaction that needs to send outputs to different parties. Notice in the validator https://github.com/input-output-hk/plutus/blob/1f9569aec76e2a4c641a16807d5a157c07db69c9/plutus-use-cases/src/Plutus/Contracts/SimpleEscrow.hs#L113
it only checks that the payee was paid. The line you linked isn't technically necessary, it's just explicitly saying you want the rest of the money. You could send it anywhere and the validator would still pass, as long as the payee gets their due. You would probably never do that, but it's a good example of how validators stay simple.

I do not understand your assertion that mustPayToPubKey is superfluous (isn't technically necessary).  Where else in the redeemEp contract do you see instructions for sending money to target, or only allowing target to claim?

redeemEp is off-chain code for building a transaction. There is nothing preventing me from writing different off-chain code that builds a different transaction as long as it satisfies the same on-chain validator (validate). The validator doesn't mention anything to do with the our public key, only the payee's key. So for a transaction to be valid, the constraint Constraints.mustPayToPubKey (Ledger.pubKeyHash pk) value isn't necessary.

Question: From where did you gain your expertise in Plutus? Is there some book you can recommend?

I'm far far far from an expert. Unfortunately there isn't a book yet. I've been through the Plutus Pioneer Program, I've written my own SC (which took me a while), and I try to answer people's questions here. We're all figuring this out together since Plutus is so new. Trying to get as much exposure as possible.

There actually is a downside to the mustPayToPubKey  approach, in that that the tran is subject to sabotage unless geq is used in the validator, as is explained here


text:
Are Validators pretending transaction already completed?
A validator is called prior to transaction's start (not to mention completion). But yet a validator routinely checks if a potential recipient has already received his funds, and other such tests about events in the past.
So is the validator pretending that the transaction has already completed, whereas in truth the transaction has not yet started -- and perhaps never will?

Yes, a validator is called prior to the start of the transaction as it part of the constraints that determines if the transaction can proceed. A validator that executes on-chain has no visibility of past transactions. It can only see the transaction it belongs to, its inputs and input data supplied to the validator.
It is the off-chain code that constructs the transaction that has visibility of the full blockchain of past transactions.


text:
Are fees collected for invalid transactions?
Let's say I construct an invalid transaction, that wants to spend UTXOs sitting at a script address and send it to the network for validation. The script then validates the transaction and fails so the UTXOs are not spent. Are fees still collected for such a validation? If not is it a possible vector of attack on the network, to construct millions of such transaction that would make nodes run complex validation scripts?

A transaction that executes on-chain has costs attached to it, irrespective of the validator succeeding or failing. That's why transactions are test-validated off-chain to avoid this from happening.
And as far as I understand it for a transaction to be considered fir for execution there needs to be some amount of lovelace available to cover costs.
The only overhead I can see - and someone please correct if I am wrong - is in filtering the transaction candidates into a list of transactions fit for execution.

But if the transaction is invalid, no UTXO is spent and the transaction does not make it into the blockchain. If it does not make it into the blockchain then how is the fee collected? As I understand it, the fee has to come from an UTXO.

If your transaction includes TxOs that aren't avaliable, you don't pay a fee. To your point, I guess that's obvious--what would you be paying with?

Generally speaking, you can know whether a transaction will be valid off-chain before submitting it for execution. This is because script validators are deterministic.
There are some exceptions to this however. If you are trying to spend a UTxO that has already been spent, it is possible that your wallet doesn't know that it's spent before it does the off-chain verification. Even in this case you won't have to pay any fees, despite the chain needing to verify something for you.
This is unintuitive to me because this does seem to be a "possible vector" for a DoS attack. However, I don't think the script validator would need to be executed, you could know that it was invalid just by seeing a spent TxO is part of the transaction. Maybe that's the distinction.
I'll try and find the video that explains this and add it here.

Thanks that makes sense. I think that in the case were we want to spend a UTxO that was already spent the validator node will not run the contract script but will reject the transaction right away without any heavy computation. And you are right that usually a transaction is validated off-chain if the user is not malicious. What if somebody would construct invalid transactions on purpose and make the validator node run a complex script that would consume much resources and fail in the end?

I'm beginning to suspect that if a script validator or policy runs, you pay a fee. A non-compliant tx will cause it to fail, but you still pay for the effort. I assume things that are on the tx context, e.g. input TxOs and valid time range, can be checked without running a script validator and thus are "free" to invalidate. I don't know how builtin extrinsics like transfers and staking fit in though. Those cost fees.

If your transaction is invalid, it won't be broadcasted to the network. So nothing will happen. This is why Cardano is above ETH. It eliminates bad transactions because its network fees are deterministic.

Plutus code is broken down into on-chain and off-chain code.
The off-chain code is validated in the wallet before being submitted to the network. This allows the smart contract to check things like user signature or deadlines as well as sufficient funds.
The on-chain code actually submits the transactions. The contract can still fail as UTxO's could have changed between the off-chain validation and the on-chain validation, however it is less likely.


text:
withdraw from daedalus wallet to us bank account
I don't plan on withdrawing my cardano at least for the next 10+ years, but being new to this what steps would I need to take to be able to withdraw out of my daedalus wallet to my us bank account. I'm 62 and just a novice to everything  thank you anything would be helpful

As of now, you cannot deposit crypto currencies to US banks (as far as I can tell). That means that if you want to withdraw you ADA into a US bank you have to first sell it for USD and then you can send the USD to the bank.
You can sell your ADA from USD by a couple different methods for example:

Use an exchange like Coinbase or Binance
Find somebody willing to trade USD for ADA with you. You can do it over the internet or in person.
Use a crypto ATM

In the future with sufficient regulation banks may be able to take crypto currencies directly so that would mean you could send ADA directly to you bank account.
The ultimate vision for crypto is that it is so prevalent in the future that you basically won't have to sell it for USD because you could pay for everything with crypto directly. That way you do not need USD or a traditional bank account.

thanks for the feedback, I bought my cardano with binance, so you are saying I could do it in reverse?  exchange wallet balance back to binance and then withdraw to bank acct from binance?  thanks again

Yes, you could do it in reverse.


text:
Researching potential smart contract use in streamlining spare parts supply chain
I'm researching the potential for blockchain smart contracts to be utilized for streamlining order fulfillment against requirements contracts; and possibly other contracting/acquisition uses.
By way of example, when a Government agency wants to contract for spare parts/part replenishment as such items are required, the Government may negotiate an indefinite-delivery requirements contract containing all the main contract terms and conditions.  Then, when the need for a specific part arises, a supply planner will input a requisition for the item (i.e., a purchase request), which would flow to finance person (puts the money on the requirement).  Then, the full requisition would go to a purchaser, who prepares an Order for the item.  The order is routed to the vendor, who then fulfills and ships the item.  After receipt, inspection, and/or acceptance of the item, the vendor's invoice is processed for payment.  Lots of different hands and documents in the process and time consuming, but perceived as necessary for assuring accountability and auditability.
Is there any granular data/information that could walk me through how a blockchain smart contract could be utilized to pair-down/eliminate the inefficiencies, speed up the process, and assure security, transparency and accountability?

I think that an NFT would be sufficient for this, off the top of my head.
You could create a smart contract that generates a 1/1 NFT for every spare part when sufficient ADA is sent to the smart contracts UTXO, with the relevant metadata attached for the purchase order. i.e buyer organization ID, shipping destination, shipping details, any other relevant information.
If you wanted to really get into the guts of something like that, you may have a QR code attached to the part you ordered, and would be able to scan and update the location at particular waypoints, and consume an "LocationUpdate" endpoint in the smart contract to update the NFTs metadata to show the most recent location, but that would require a hardware solution as well. In the short term you may have a warehouse receiver through some kind of simple to use UI, confirm receipt/QC inspection and complete the smart contract.
I don't see why the Supply Planner + Finance + purchaser can't be one person in this scenario.


text:
How to get latest version of Plutus in project file of plutus-starter-devcontainer
I've been trying to get the latest version of plutus on my project but I get the following error message when I run nix-shell:
error: attribute '8a20664f00d8f396920385947903761a9a897fe0' missing, at /nix/store/przi4l85b1yd1irwss0qnhg1lsw2925k-haskell.nix-src/modules/cabal-project.nix:118:37
In the cabal.project file, I made the change of the tag from:
-- Plutus revision from 2021/06/11
source-repository-package
  type: git
  location: https://github.com/input-output-hk/plutus.git
  subdir:
    freer-extras
    playground-common
    plutus-core
    plutus-contract
    plutus-ledger
    plutus-ledger-api
    plutus-tx
    plutus-tx-plugin
    plutus-pab
    plutus-use-cases
    prettyprinter-configurable
    quickcheck-dynamic
    word-array
  tag: plutus-starter-devcontainer/v1.0.6

to the latest plutus tag, which is currently 8a20664f00d8f396920385947903761a9a897fe0
The line (118) the error refers to in cabal.project.nix is as follows:
then { location, tag, ...}: config.sha256map.${location}.${tag}
OR
    lookupSha256 = mkOption {
      type = nullOr unspecified;
      default = if config.sha256map != null
        then { location, tag, ...}: config.sha256map.${location}.${tag} -- <- Error here
        else _: null;
    };

Could someone kindly point me in the right direction on how to fetch the latest version from the plutus repo?

I was able to fix the problem by copying the content of cabal.project from one of the latest examples in the plutus pioneer program to the cabal.project file of my own project - while ensuring that the index-state is left out.
Copying the content of the file also requires that I update nix/pkgs/haskell/haskell.nix with the latest tags of the source-repository-packages in the cabal.project file and their corresponding sha256 hashes (this is gotten from running nix-shell --show-trace repeatedly and observing the error messages for wrong expected sha256 hash)
    sha256map = {
      ...
      "https://github.com/Quid2/flat.git"."95e5d7488451e43062ca84d5376b3adcc465f1cd" = "06l31x3y93rjpryvlxnpsyq2zyxvb0z6lik6yq2fvh36i5zwvwa3";
      "https://github.com/input-output-hk/plutus.git"."2f11c28bd8f6d630daab582255e16d8408075bd7" = "0sh4mfsanvdg43qhq321v24vamrw7nzc6gpjb0d34nyrq2lw55wj";
      "https://github.com/shmish111/purescript-bridge.git"."6a92d7853ea514be8b70bab5e72077bf5a510596" = "13j64vv116in3c204qsl1v0ajphac9fqvsjp7x3zzfr7n7g61drb";
      ...
    }

Afterwards, I ran cabal update and replaced the new index state on the cabal.project file with the new index state generated by cabal and running nix-shell works, finally!

Hopefully someone finds or makes a better way...


text:
How to get the funds available at a script using Plutus?
I am currently working on Lecture 8 in the Plutus Pioneer program.
I want to view funds available at a script address.
There appears to be a function that makes this easy in Ledger.AddressMap
-- | Get the funds available at a particular address.
fundsAt :: Address -> Lens' AddressMap UtxoMap
fundsAt addr = at addr . non mempty

However, I have not been able to get this to work.
When I try this
fundsAt scriptAddress

I get the following error
Ambiguous type variable ‘f0’ arising from a use of ‘fundsAt’
  prevents the constraint ‘(Prelude.Functor f0)’ from being solved.

My attempts at trying to make the type unambiguous have not worked, and I am struggling to understand Lens'.
Does anyone know how to get the fundsAt function to work?

If you are trying to do this in your offchain code, I would suggest using Plutus.Contract.utxoAt instead.
Here is an example of it being used in the gift code.

I did see that example, but is there a reason why that's a better approach? It seems like fundsAt is a clearer and more direct way to get the data I want and I'm just struggling with the Lens' type.

They both give you a UtxoMap. Notice that the return type of the grab function is the Contract monad, just like utxoAt. It's what's meant to be used in the off-chain transaction-building code. I doubt there is a conversion between Lens' and Contract.


text:
What are the best high-level libraries for interacting with Cardano programmatically?
(First post - sorry for the noob question!)
What are the best / standard high-level libraries for programmatically interacting with Cardano?
E.g., what would I use if I wanted to write a program to send ADA or call contracts?
Bonus points for Rust or Haskell libraries.
I see Adrestia, but none of the libraries listed there seem to be both reasonably high-level and full-featured.
Thanks!

I think the most obvious solution is Cardano-GraphQL. For example, this GraphQL query can be used to call an address with a contract at the UTXO.
Unless you are looking for higher level yet, I believe you should track this proposal or that was successfully funded in Fund5, which I myself happily voted for. Also, since you asked for Rust SDKs specifically, this proposal was funded to update the Rust Serialization Library from the guys at Emurgo to be compatible with the upcoming Alonzo hardfork.
Better yet, a quick glimpse of the successfully funded Fund5 proposals shows pretty decisively that developer tooling (SDKs, APIs) absolutely dominated this funding round, which is exactly what we need right now to grow our ecosystem.
This should be enough to point you in the right direction.

Depending on the level of control you need for your application, I'd suggest to look at one of the followings:

https://github.com/Emurgo/cardano-serialization-lib
https://github.com/blockfrost/blockfrost-js
https://ogmios.dev/typescript-client

Should you happen to write Haskell code:

https://input-output-hk.github.io/cardano-node/cardano-api/lib/Cardano-Api.html

Note that at this stage, there's no strict equivalent to something like Web3.js and any interaction with the Cardano blockchain will require either a local node or, some remote service ensuring the connection on your behalf.


text:
How to check wallet balance using cardano cli?
How does Dedalus know what is my balance on given wallets? Is there a way I can do the same thing using cardano-cli or cardano-wallet?
Edit:
I have found Wallet UTXO Distribution screen that:

When you receive ada to your Daedalus wallet, it simply means Daedalus has identified a UTXO that can be spent with the keys managed by your wallet... Daedalus determines your balance by scanning the Cardano blockchain and aggregating the value of any UTXO the wallet is able to spend with the keys associated to your wallet.

Does that mean that Daedalus checks (has access to keys so can validate if the address belongs to a wallet(?)) all transactions and just sums up the balance?
And given that it's true I would need to somehow scan my copy of the blockchain to get the same information?

Yes, you can query balances with both cardano-cli and cardano-wallet. The developer portal shows this for different languages, but you can also read out the raw command-line query there.
cardano-cli: https://developers.cardano.org/docs/integrate-cardano/listening-for-payments-cli#query-utxo
cardano-wallet: https://developers.cardano.org/docs/integrate-cardano/listening-for-payments-wallet#retrieve-wallet-balance


text:
How can I create a serialized transaction that can be submitted to the blockchain without a local full node?
My goal is to send a transaction (e.g. send 1 ADA from addr1A to addr1B) using the following endpoint of the blockfrost.io API:

"Submit an already serialized transaction to the network."
https://docs.blockfrost.io/#tag/Cardano-Transactions/paths/~1tx~1submit/post

It requires a serialized transaction. How can I create a serialized transaction without a local full node? (With a full node this could be done using the cardano-cli).
The emurgo/message-signing library seems to provide this functionality but I'm not sure how to use it. The example they provide just signs some random string.
Are there any other libraries that can be used for this?
The library would need to be able to

Create a transaction (with metadata)
Calculate the fees
Sign/serialize the transaction

There is the cardanosharp-wallet library that provides this functionality. They have a section in their README.md that explains signing transactions.

To add to @eddex's answer, another option would be to use the Emurgo's cardano-serialization-lib. There are not many examples available in their documentation, unfortunately.
Link: https://github.com/Emurgo/cardano-serialization-lib
For a guideline on how to use the library specifically for creating transactions, I found a good example in the blockfrost-js repository. The usage of cardano-serialization-lib can be found in one of the helper files.
Link: https://github.com/blockfrost/blockfrost-js/blob/fb9a55fee07927f8d7c8b0a5aa9efd2d3daf6c77/examples/simple-transaction/src/index.ts


text:
cardano-wallet maximum amount of addresses
On the cardano developers site, the example they have on accepting payments using cardano-wallet its stated to retrieve an unused address from the wallet and have clients send to that address.
However, if I can only create "20" addresses (from the recommended address_pool_gap option), what happens when I have more than 20 transactions?
Would I need to send balance to a "main" wallet address and re-use the previous used addresses? or I am missing something else?

Could you provide a link to the developers page you mentioned?

@eddex https://developers.cardano.org/docs/integrate-cardano/listening-for-payments-wallet

It depends what you are trying to build. If you are building something with cardano-wallet it is safe to increase that default gap if you don’t want to use this wallet across other clients. (other clients will stop at 20 which will result in no longer display the balances of the other addresses)
Setting it to 1k, 10k, or even 50k is not a problem but the performance will decrease the higher you set this value.
Fun fact: in 2019 a Ransom attack appeared which exploited this mechanism: https://blog.sia.tech/a-ransom-attack-on-hardware-wallets-534c075b3a92 (it generated a receiving address which belongs to your private key, but based on a very high random index)

I want to complement @adatainment's answer. You can potentially create even 100 million addresses, but there is one very important nuance regarding the --address-pool-gap flag.

Nothing prevents you from creating an address straight to some crazy index such as 1 million, e.g. cardano-address key child 0/1000000, but if you send funds to a payment address generated from that key, it won't show up in your wallet as by default it expects one transaction every 20 addresses in sequence.


text:
Cardano Smart Contract Architecture Diagrams?
I am a "big picture" kind of person (yes, INTJ) and I am looking for a high-level overview of the Cardano Smart Contract Architecture. Did a preliminary google search and read a few articles but none gave a good overview diagram. So ... I am trying to create one myself (I will post an image/url when it makes sense). Do you know of any good architecture writeups/diagrams on this?  (starting at the 50,000 foot level and drilling down to the 20,000 and 10,000 foot levels)...
On the developer portal the technical concepts section has good individual topics but not the big picture:
https://developers.cardano.org/docs/get-started/technical-concepts
Any help is appreciated!

Let's look at a simple "counter-example" that demonstrates what we need... here is an image on the Solana architecture in an overview document for developers called "10,000 Foot Development View": https://lh5.googleusercontent.com/Z1UcGnLLqEeCTWLm0QjMscPfFKhRumOcuFc8uadpn7wqO7OlsQiNe60CpGsPZf1zjsLTpj-69IeQf9MwCdMnFdyyDNkI8x0uPHPyPf5DUX_uqKWYuJq7o5p9TZ5_TqpFCO7ZS6pO?w=1600&h=1035&fmt=webp

I lifted this screenshot from Reddit so I'm not 100% sure who created it. This is more of a overall Cardano view, so in my mind, qualifies as a 50,000 foot view.

Thank you for your answer!  Yes, I would agree this is a 50,000 foot view!  The only question I would have is whether it is accurate?  You mentioned it was from Reddit - from a user or someone associated with Cardono foundation or IOHK (i.e. someone with authority)?
Thanks again!!

I do believe this is accurate, from the best of my knowledge (whatever that's worth).

I found the original source of the image here. It originated from IOHK themselves.

The only thing this diagram lacks is any mention of off-chain/on-chain parts of a smart contract.  Maybe that would be in the 30,000 foot view...  IOHK PLEASE HELP!  We sorely need some good architectural diagrams!


text:
The PAB is no longer working after upgrading the Plutus version
I upgraded the Plutus version used by my project to: 2f11c28bd8f6d630daab582255e16d8408075bd7
PS: It is the same version Lars used in his latest lecture (Iteration #2 - Lecture #8)
Here is the code I'm using to define the endpoints:
data StarterContracts =
    MarketContract
    deriving (Eq, Ord, Show, Generic, FromJSON, ToJSON)

instance Pretty StarterContracts where
    pretty = viaShow

handleStarterContract ::
    ( Member (Error PABError) effs
    , Member (LogMsg (PABMultiAgentMsg (Builtin StarterContracts))) effs
    )
    => ContractEffect (Builtin StarterContracts)
    ~> Eff effs
handleStarterContract = handleBuiltin getSchema getContract where
    getSchema = \case
        MarketContract -> endpointsToSchemas @Market.MarketSchema
    getContract = \case
        MarketContract -> SomeBuiltin Market.endpoints

handlers :: SimulatorEffectHandlers (Builtin StarterContracts)
handlers =
    Simulator.mkSimulatorHandlers @(Builtin StarterContracts) [MarketContract]
    $ interpret handleStarterContract

And this is the error I'm getting when trying to compile it:
app/Main.hs:62:25: error:
    • Couldn't match expected type ‘(StarterContracts
                                     -> [playground-common-0.1.0.0:Playground.Types.FunctionSchema
                                           playground-common-0.1.0.0:Schema.FormSchema])
                                    -> (StarterContracts -> SomeBuiltin)
                                    -> ContractEffect (Builtin StarterContracts) x
                                    -> Eff effs x’
                  with actual type ‘Plutus.PAB.Effects.Contract.Builtin.BuiltinHandler
                                      a0’
    • The function ‘handleBuiltin’ is applied to two arguments,
      but its type ‘Plutus.PAB.Effects.Contract.Builtin.BuiltinHandler
                      a0’
      has none
      In the expression: handleBuiltin getSchema getContract
      In an equation for ‘handleStarterContract’:
          handleStarterContract
            = handleBuiltin getSchema getContract
            where
                getSchema
                  = \case MarketContract -> endpointsToSchemas @MarketSchema
                getContract = \case MarketContract -> SomeBuiltin endpoints
    • Relevant bindings include
        handleStarterContract :: ContractEffect (Builtin StarterContracts)
                                 ~> Eff effs
          (bound at app/Main.hs:62:1)
   |
62 | handleStarterContract = handleBuiltin getSchema getContract where
   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

app/Main.hs:70:5: error:
    • Couldn't match type ‘Simulator.SimulatorContractHandler
                             (Builtin StarterContracts)
                           -> SimulatorEffectHandlers (Builtin StarterContracts)’
                     with ‘Plutus.PAB.Core.EffectHandlers
                             (Builtin StarterContracts)
                             (Simulator.SimulatorState (Builtin StarterContracts))’
      Expected type: SimulatorEffectHandlers (Builtin StarterContracts)
        Actual type: Simulator.SimulatorContractHandler
                       (Builtin StarterContracts)
                     -> SimulatorEffectHandlers (Builtin StarterContracts)
    • In the expression:
        Simulator.mkSimulatorHandlers
          @(Builtin StarterContracts) [MarketContract]
          $ interpret handleStarterContract
      In an equation for ‘handlers’:
          handlers
            = Simulator.mkSimulatorHandlers
                @(Builtin StarterContracts) [MarketContract]
                $ interpret handleStarterContract
   |
70 |     Simulator.mkSimulatorHandlers @(Builtin StarterContracts) [MarketContract]
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...

app/Main.hs:70:63: error:
    • Couldn't match expected type ‘Ledger.Fee.FeeConfig’
                  with actual type ‘[StarterContracts]’
    • In the second argument of ‘Simulator.mkSimulatorHandlers’, namely
        ‘[MarketContract]’
      In the expression:
        Simulator.mkSimulatorHandlers
          @(Builtin StarterContracts) [MarketContract]
      In the expression:
        Simulator.mkSimulatorHandlers
          @(Builtin StarterContracts) [MarketContract]
          $ interpret handleStarterContract
   |
70 |     Simulator.mkSimulatorHandlers @(Builtin StarterContracts) [MarketContract]
   |                                                               ^^^^^^^^^^^^^^^^

app/Main.hs:71:7: error:
    • Couldn't match expected type ‘Ledger.TimeSlot.SlotConfig’
                  with actual type ‘Eff
                                      (ContractEffect (Builtin StarterContracts) : effs0) x0
                                    -> Eff effs0 x0’
    • Probable cause: ‘interpret’ is applied to too few arguments
      In the second argument of ‘($)’, namely
        ‘interpret handleStarterContract’
      In the expression:
        Simulator.mkSimulatorHandlers
          @(Builtin StarterContracts) [MarketContract]
          $ interpret handleStarterContract
      In an equation for ‘handlers’:
          handlers
            = Simulator.mkSimulatorHandlers
                @(Builtin StarterContracts) [MarketContract]
                $ interpret handleStarterContract
   |
71 |     $ interpret handleStarterContract
   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Plutus is still in active development, so changes in the API can occur every week.
For your case, go look at a similar example in the PAB.
In your specific case, you'll need to change your handlers function to :
handlers :: SimulatorEffectHandlers (Builtin StarterContracts)
handlers =
    Simulator.mkSimulatorHandlers def def
    $ interpret (contractHandler Builtin.handleBuiltin)

Then you'll need to implement the HasDefinitions and the HasPSTypes typeclasses for your StarterContracts. For the HasPSTypes, you can just use the default implementation which is:
instance HasPSTypes StarterContracts where
    psTypes _ = []

Hope that helps.

Yes, this is very helpful, thank you!
I also got another error after applying the new changes. it was about def not being defined anywhere, I fixed it by adding the following import statement: import Data.Default (Default (..))


text:
Couldn't match expected type ‘BuiltinData’ in locally run playground
Working through the Plutus Pioneer Week2 homework and getting the following error in the locally served playground.
error:
    • Couldn't match expected type ‘BuiltinData’
                  with actual type ‘PlutusTx.Data’
    • In the second argument of ‘($)’, namely ‘PlutusTx.toData bs’
      In the second argument of ‘($)’, namely
        ‘Redeemer $ PlutusTx.toData bs’
      In the expression:
        mustSpendScriptOutput oref $ Redeemer $ PlutusTx.toData bs
   |
77 |         tx      = mconcat [mustSpendScriptOutput oref $ Redeemer $ PlutusTx.toData bs | oref <- orefs]
   |

Validator code in question
import           Plutus.Contract
import qualified PlutusTx
import           PlutusTx.Prelude     hiding (Semigroup(..), unless)

...

grab :: forall w s e. AsContractError e => (Bool, Bool) -> Contract w s e ()
grab bs = do
    utxos <- utxoAt scrAddress
    let orefs   = fst <$> Map.toList utxos
        lookups = Constraints.unspentOutputs utxos      <>
                  Constraints.otherScript validator
        tx :: TxConstraints Void Void
        tx      = mconcat [mustSpendScriptOutput oref $ Redeemer $ PlutusTx.toData bs | oref <- orefs]
    ledgerTx <- submitTxConstraintsWith @Void lookups tx
    void $ awaitTxConfirmed $ txId ledgerTx
    logInfo @String $ "collected gifts"

Are you running using nix-shell?

@MitchellTurner yes I am - loving nix atm.

The local playground code is compiled to a version that is too recent for week 2. It needs to be compile to the correct commit for week 2. The change to BuiltinData only happened at week 04.
Check the Plutus repo out at the week 2 commit, before executing nix-shell. The commit can be found in the plutus-pioneer-program repo in folder code/week02, file cabal.project at line 28.

I will try that next. I'd also love to fix the issues in case I hit this problem later. Seems like the contract for PlutusTx.toData is now PutusTx.IsData.toData (from the docs), but that new interface also triggers a compile error


text:
How to compile plutus source code locally?
I'm trying to compile the Plutus source code locally, I tried cabal build in nix-shell,
getting this error
After searching the rest of the dependency tree exhaustively, these were the
goals I've had most trouble fulfilling: base, libsystemd-journal,
lobemo-scribe-systemd, Win32-network

This is the full error I got
I'm working on Ubuntu 20.04LTS OS
Thanks,
Please let me know if my approach is wrong.

Please give more details of the system and the steps you completed. Did you check the documentation at https://docs.plutus-community.com/?

Yes, I followed the documentation and installed Nix(Single-user) and then followed this https://docs.plutus-community.com/docs/setup/CabalBuild.html and when I did cabal build ended up in that error

Did you execute cabal update first?

Yes, this was the output
Package list of hackage.haskell.org is up to date at index-state 2021-08-16T12:54:02Z```

Win32-network - dependency not fulfilled is an indication that if there is a problem in the checked-out version. Would you mind checking with the version used in that particular lecture? I had faced the same issue.

I see you're using Week 1 of the Pioneer Program.  Did you check out the correct plutus tag (in plutus-pioneer-program/code/week01/cabal.project) before running nix-shell ?

You appear to be having issues resolving the dependencies for that particular build of Plutus. In fact, all Cardano builds depend on libsystemd (on Linux).
If you have incompatible versions of libsystemd and libsystemd-journal you get the rejection that you're having in regards to the dependencies. It appears Plutus also depends on these packages.
Please see the following link: cardano-haskell.README.md#system-setup.
I would try:
sudo apt get install libsystemd-dev

Then, try and reboot a terminal window, checkout to the correct branch within the Plutus.git repository.
Ensure you checkout the tag provided within the plutus-pioneer-program.git/code/week01/cabal.project file, which I believe is ea0ca4e9f9821a9dbfc5255fa0f42b6f2b3887c4.
Then, you should be able to boot a Nix-Shell from the Plutus repo, navigate to week01 and run cabal build.
If you've followed those steps (see below for some links that may be of help) and you're still having problems, we may need some more information.
Related links that may help:

Cardano-crypto-class-2.0.0 (conflict: pkg-config package libsodium-any, not found in the pkg-config database)
libsystemd-journal Packages For Ubuntu
Cardano Haskell System Setup | Very Similar Issue (Same Package Conflict)

Try in the nix-shell try this:

cabal update
cabal build

btw: first time building with cabal can take up some time


text:
How to check using CLI that a token is a NFT?
One can check with online tools (described here) if a token is an NFT.
How the same thing can be done using CLI tools (in some sort of a script)?

Since at the moment non-fungible tokens are indivisible in the Cardano network, and they can be sent only along with 1,500,000 lovelace, NFTs can be easily seen querying the "balance" at the destination address with the standard command:
cardano-cli query utxo --address $(cat payment.addr) --mainnet

Moreover, don't miss blockfrost.io project. Using it you can query information of a native token on Cardano (consider, you need to provide the string concatenation of the policy_id and hex-encoded asset_name):
curl -H 'project_id: 1234567890' https://cardano-mainnet.blockfrost.io/api/v0/assets/d894897411707efa755a76deb66d26dfd50593f2e70863e1661e98a07370616365636f696e73

You'll get the following JSON response:
{
  "policy_id": "d894897411707efa755a76deb66d26dfd50593f2e70863e1661e98a0",
  "asset_name": "7370616365636f696e73",
  "fingerprint": "asset1pmmzqf2akudknt05ealtvcvsy7n6wnc9dd03mf",
  "quantity": "50000000",
  "initial_mint_tx_hash": "3cce12c77b9d11d70575320c4f2834b26debb065308fbe43954018fbeb90010d",
  "onchain_metadata": null,
  "metadata": null
}

in script i would do the follow :

cardano-cli query utxo --address $address --mainnet > fullUtxo.out
tail -n +3 fullUtxo.out | sort -k3 -nr  > balance.out
while read -r utxo; do
tokenAmount=$(awk '{ print $6}' <<< "${utxo}")

if you can take this info from step 3.
you can use it how you prefer.
for example
if tokenAmount = TxOutDatumNone , means you have no Token
if tokenAmount = X (number),you have X tokens from the token in the { print $7}
if you need any further assist, let me know

but i realized you speak for NFT.
then i would do it by blockfrost:
curl -H 'project_id: mainnetb2ZFKeNsfggfDFGHJsdgw4nEhuWhExyfV'
https://cardano-mainnet.blockfrost.io/api/v0/assets/{asset}
            [![enter image description here][1]]