cardano-signer
cardano-signer copied to clipboard
--cip-100 incorrect anchor hash?
Hello, we've been happily using cardano-signer to produce witnesses for an upcoming info action; so thanks for taking the time to implement the spec and the JSON-LD canonical serialization ๐ฌ!
However, with multiple authors, the anchor hash showed as output of the --cip-100 command doesn't match what we could get from other tools or by computing the hash "by hand" (serializing and hashing the raw bytes). For example, with the following metadata, we believe the correct anchor hash should be 7d2f344f3651a8372ad603abf11fcb310fb3c5154a6592591d1ff97d951156e3 but cardano-signer reports 615e80107c06873c9acf327835857b565837d1ac169e9de9c3c7e5a32c0d9ef2. Previously, we did get concordance when only one author was specified; so maybe there's something at play there?
{
"@context": {
"@language": "en",
"CIP100": "https://github.com/cardano-foundation/CIPs/blob/master/CIP-0100/README.md",
"CIP108": "https://github.com/cardano-foundation/CIPs/blob/master/CIP-0108/README.md",
"hashAlgorithm": "CIP100:hashAlgorithm",
"body": {
"@id": "CIP108:body",
"@context": {
"references": {
"@id": "CIP108:references",
"@container": "@set",
"@context": {
"GovernanceMetadata": "CIP100:GovernanceMetadataReference",
"Other": "CIP100:OtherReference",
"label": "CIP100:reference-label",
"uri": "CIP100:reference-uri",
"referenceHash": {
"@id": "CIP108:referenceHash",
"@context": {
"hashDigest": "CIP108:hashDigest",
"hashAlgorithm": "CIP100:hashAlgorithm"
}
}
}
},
"title": "CIP108:title",
"abstract": "CIP108:abstract",
"motivation": "CIP108:motivation",
"rationale": "CIP108:rationale"
}
},
"authors": {
"@id": "CIP100:authors",
"@container": "@set",
"@context": {
"name": "http://xmlns.com/foaf/0.1/name",
"witness": {
"@id": "CIP100:witness",
"@context": {
"witnessAlgorithm": "CIP100:witnessAlgorithm",
"publicKey": "CIP100:publicKey",
"signature": "CIP100:signature"
}
}
}
}
},
"authors": [
{
"name": "abailly <[email protected]>",
"witness": {
"witnessAlgorithm": "ed25519",
"publicKey": "d5e27eee7d4970317fd1b36e54aefac95c31154e1b20637f7e2ca1eb52dd0746",
"signature": "690ba80a50d96fc2ec47d9c17fe956d81ba0122feb70a63daae7e104c94c8b08cfe26d3620cf26105e5b03f84054355ecfcb01ca33912253700f6ebf70840f09"
}
},
{
"name": "Dam_CZ <[email protected]>",
"witness": {
"witnessAlgorithm": "ed25519",
"publicKey": "f127c0824564745561896c3ce3e6e5961f2acaab5f5f149c65f2e81ff549360a",
"signature": "0f31661b2bedb7b952b99edc3296a5df63e104b3f18f84e336c0ed4f4d2f30d2fd146e4d5de12a3c81459248a47c8f7616d2fd79dad86493fdad598d734b250d"
}
},
{
"name": "Pi Lanningham <[email protected]>",
"witness": {
"witnessAlgorithm": "ed25519",
"publicKey": "c6089a76a380b282b078189f011dc53b05df1ea4804558444128d4849ad88e5b",
"signature": "5258822099b20983412ab2586ce0673a820ceebea017f7aa8bd643ee8b2f96ebd54ecb804c992a8cd08845ef4e0c4bfbe4ef87f20dceafac4d561c6bc93d930a"
}
},
{
"name": "KtorZ <[email protected]>",
"witness": {
"witnessAlgorithm": "ed25519",
"publicKey": "ce0e80c60a0e16a9254d613dfadbcbdca2ac60ec105dc2f136636807d75dab01",
"signature": "b5f02317952ed2f70a18150870b331e66743d06da85c04157010cd62cc29042fa3b450b1ba5a7af9900f85fdd221af168701bd9098c27397945b2368199fd30a"
}
}
],
"hashAlgorithm": "blake2b-256",
"body": {
"title": "Cardano Blockchain Ecosystem Budget: Amaru Node Development 2025",
"abstract": "[Amaru](https://github.com/pragma-org/amaru) is an open-source project implementing a new fully interoperable block-producing node for Cardano. It aims to improve the network's overall accessibility and robustness without compromising its safety and security.\n\n[Amaru](https://github.com/pragma-org/amaru) provides another perspective and solution for stake pool operators and developers alike, prioritizing a modular approach, a seamless user experience, and low hardware requirements. Additionally, the project is implemented mainly in Rust, which is well-equipped for high assurance to attract new contributors to the core maintenance of the ecosystem.",
"motivation": "## Who we are\n\n[Amaru](https://github.com/pragma-org/amaru) is a multi-entity effort that currently sits under [PRAGMA](https://pragma.io): a member-based, not-for-profit open-source association for blockchain software projects. Five members with equal power currently drive PRAGMA's strategy and operations: Blink Labs, Cardano Foundation, dcSpark, Sundae Labs, and TxPipe. Each of them has a proven track record of building on Cardano and supporting our ecosystem.\n\n[Amaru](https://github.com/pragma-org/amaru) itself is managed by an appointed maintainer committee in charge of different scopes. The current maintainer committee comprises of:\n\n- [Arnaud Bailly](https://github.com/abailly) responsible for the consensus and simulation testing.\n- [Matthias Benkort](https://github.com/ktorz) responsible for the ledger & overall architecture.\n- [Pi Lanningham](https://github.com/Quantumplation) responsible for the ad hoc work and middleware integrations.\n- [Santiago Carmuega](https://github.com/scarmuega) responsible for the p2p networking.\n- [Damien Czapla](https://github.com/Dam-CZ) responsible for the project management, public relations & marketing.\n\nEach member of the maintainer committee is in charge of a scope and has oversight on its delivery, which includes managing an associated budget.\n\n## Why build another node\n\nOne of Cardano's key assets is its legendary robustness and stability, which is mainly attributed to the existing Haskell node, which has been working without significant disruption for about five years now (counting since the Byron reboot, circa February 2020).\n\nSo why bother with another node? The answer is, of course, plural:\n\n#### 1. **Better resource usage**\n\nSoftware is ultimately a collection of design decisions and trade-offs. Some of those trade-offs in the Haskell node have led to rather high resource usages (e.g., resident memory), thus leading to the creation of specific protocol parameters (e.g., min-utxo-value) as countermeasures to ensure resource usage remains somewhat bounded. Our analysis is that different (albeit acceptable) trade-offs would yield better resource usage.\n\n#### 2. **Industry-grade observability**\n\nObservability is challenging, and it is even more so when rolling your own solution. With [Amaru](https://github.com/pragma-org/amaru), we intend to embrace industry standards for monitoring, tracing, and logging to drastically enhance the user experience for operators seeking insights into their node's behaviour.\n\n#### 3. **Enhanced interoperability**\n\n[Amaru](https://github.com/pragma-org/amaru) being primarily written in Rust means that we can more easily leverage an existing and thriving ecosystem of blockchain solutions and aim at multiple target platforms (e.g. web-assembly, RISC-V). This opens up not only to a wide variety of potential contributors but also to many new use cases that are much harder (not to say unrealistic) to achieve with a Haskell node.\n\n#### 4. **Higher-assurance & robustness**\n\nDeveloping a new implementation of existing software means dissecting every part of the original implementation. Along the way, bugs and discrepancies with the specification are commonly found through conformance testing. Gaps in the documentation can also be identified and addressed. The development of [Amaru](https://github.com/pragma-org/amaru) has already proven this on several occasions. In the long run, more node implementations can be a synonym for reduced development time by allowing all implementations to converge faster towards better designs and more robust implementations.\n\n#### 5. **Decentralization**\n\nIn a world where Byzantine fault tolerance is at the centre and where decentralization is a paramount value, we believe that a single-node implementation presents a single point of failure and a central point of control. A new node not only increases the overall resilience of the network but also provides perspectives in terms of a roadmap and use cases.\n\n---\n\nWith [Amaru](https://github.com/pragma-org/amaru), we believe that we can reconcile these goals while preserving Cardano's focus on security and robustness. Like Haskell, Rust is a statically typed language that provides strong compile-time guarantees and fine-grained memory management. Its ecosystem is also well-equipped for high assurance, making it a sane choice for implementing blockchain solutions.",
"rationale": "## Executive summary\n\n> **NOTE**\n>\n> All the scopes described are estimated in FTE (Full Time Employee) valued at $200k per annum.\n\n[Amaru](https://github.com/pragma-org/amaru) is an ongoing project that is already a few months old, and resources have initially been allocated to bootstrap its development. Given the core nature of [Amaru](https://github.com/pragma-org/amaru) and in order to avoid becoming financially dependent on a single entity for its development, we are seeking **โณ1.5M** of additional funding for the **second half of 2025**.\n\nThe table below breaks down the current/estimated effort, the fraction of resources already secured from other sources of funding, and the resources needed. It covers the whole of 2025.\n\n| Scope | Owner | Estimated effort | Resources already secured | Resources needed |\n| --- | --- | --- | --- | --- |\n| Ledger | Matthias | 2.5 FTEs | 1 FTE | 1.5 FTEs |\n| Consensus and simulation | Arnaud | 2.5 FTEs | 1 FTE | 1.5 FTEs |\n| Networking | Santiago | 1 FTE | 1 FTE | 0 FTEs |\n| Ad-hoc Mercenaries | Pi | 2.5 FTEs | 0 FTEs | 2.5 FTEs |\n| Project Management, Public Relations & Marketing | Damien | 0.5 FTEs | 0 FTEs | 0.5 FTEs |\n\nThe total resources without funding for 2025 adds up to **6 FTEs**. Considering this budget ask is only for **the second half of 2025**, it halves to `$600,000` (600K) once converted to USD (`$`). We then add a 25% contingency budget to cope with our optimistic bias: we are aware that our forecast is subject to underestimating complexity, overlooking challenges, and undervaluing the time and cost required to deliver.\n\nWith this contingency, we end up at **`$750,000` (750K)**. Finally, using a conservative conversion rate of 0.5 ADA (`โณ`) per USD (`$`) at the date of the withdrawal, we formulate a budget of **`โณ1,500,000` (1.5M)**.\n\n> **NOTE**\n>\n> The Networking scope described in our [design documentation](https://github.com/pragma-org/amaru/blob/main/engineering-decision-records/006-design-phase-documentation.md) is included in our proposal for reference but is already covered by a [Catalyst proposal](https://projectcatalyst.io/funds/12/cardano-open-developers/amaru-p2p-networking-component-by-txpipe). It is fully managed by Santiago.\n\n## Administration of the budget\n\nThe [Amaru](https://github.com/pragma-org/amaru) maintainer committee will ensure **direct administration** of the budget, assisted with **an on-chain smart contract** (developed in open source, still incomplete, but aimed to be done and fully audited by the time of the first withdrawal).\n\nThe fund management, responsibilities and remuneration of contributors will follow PRAGMA's legal framework provided in annex under [PRAGMA Maintainer Committee Framework](https://ipfs.io/ipfs/bafkreiabxyva5lfm6zztg7tnktxvvbbucljrce7hlrp4p6hropqzfaip3y).\n\nIn addition, the smart contract's role is to ensure that the expenditure of funds is done in accordance with the scope defined in this budget and authorized by the relevant scope owners.\n\nWe recognize the following capabilities of this contract:\n\n1. **Standard withdrawal**: A scope owner asks other scope owners for money to be withdrawn from his scope.\n2. **Contingency withdrawal**: A scope owner asks other scope owners to withdraw an amount from the contingency funds.\n3. **Scope reconciliation**: A scope owner asks other scope owners for a change of ownership (or a reallocation of budget).\n4. **Contingency refund/closing**: scope owners ask to send the leftovers from the contingency budget to be sent back to the Cardano treasury.\n5. **Credential rotation**: In case of lost credentials or the departure of a scope owner, a mechanism allows the rotation of credentials to a new scope owner upon approval by all (5 out of 5) PRAGMA members (effectively capturing PRAGMA's board decision to appoint new maintainers).\n6. **Failsafe**: In the extreme scenario where credentials would be irremediably lost, thus preventing any further decision, a failsafe mechanism allows all unconsumed funds to be sent back to the Cardano treasury.\n\n## Reporting\n\n#### Quarterly reports\n\nFollowing [PRAGMA's Decision Record 006](https://github.com/pragma-org/PDRs/tree/main/PDR-0006-Project-Reporting), progress on [Amaru](https://github.com/pragma-org/amaru) shall be **at least reported quarterly**. The content of [these reports](https://pragma.io/projects/amaru#quarterly-reports) is straightforward and includes the following:\n\n- Problems that require board attention (infrastructure, trademarks, etc.)\n- Project status (active, inactive, initiating, etc.)\n- A changelog (last committer addition)\n- Next planned steps (new releases, significant changes, etc.)\n- Reflection & Performances\n\nThis recurrent interaction will provide an overview of the project with a long-term perspective and support the maintainers' committee in aligning priorities and identifying the next steps. The outcome of these reviews will be publicly available as documentation in [Amaru](https://github.com/pragma-org/amaru)'s GitHub repository.\n\n#### Regular demos\n\nAmaru is demo-driven. We strive to integrate early and provide runnable examples showcasing the latest features as the project is being developed. The cadence for these demos is around 4 to 6 weeks, as illustrated on the [existing track record](https://pragma.io/projects/amaru#demos).\n\nWe will naturally continue to **record and post demos regularly**.\n\n## Constitutionality checklist\n\nBeing one of the first proposals of this nature ever submitted, it is easy to get things wrong. In an effort to convince ourselves of its constitutionality, we thought relevant to include a checklist of the points we cover and for each, our interpretation of the Cardano Constitution.\n\n#### Purpose\n\n- [x] This proposal is for work intended to enhance the security, decentralization and long-term sustainability of Cardano.\n\n#### Article III.5: the process of on-chain governance\n\n- [x] We have submitted this proposal in a standardized, legible format, which includes a URL and hash of all documented off-chain content. We believe our rationale to be detailed and sufficient. The proposal contains a title, abstract, reason for the proposal and relevant supporting materials.\n\n#### Article IV.1: proposing budgets\n\n- [x] This proposal accords with the provisions of this article as it is intended to cover the maintenance and future development of the Cardano Blockchain.\n\n- [x] This proposal covers a shorter period than 73 epochs, which is permitted in this section of the Constitution, to match the Net-Change Limit period.\n\n#### Article IV.2: funds administration\n\n- [x] This proposal specifies an administrator in accordance with this provision. It also specifies an internal administration process using smart contracts and an off-chain overseeing committee, meeting the requirements of this clause, which requires a process that may include an administrator.\n\n#### Article IV.3: Net-Change Limit\n\n- [x] Being of โณ1.5M and covering the second half of 2025, this proposal and the treasury withdrawals it would enable do not violate the currently agreed upon Net-Change Limit.\n\n#### Article IV.4: Auditor\n\n- [x] This proposal makes provisions for an auditor (covered by the _Ad-hoc mercenaries_ scope).\n\n#### Guardrails\n\n- [x] This proposal is subject to _TREASURY-04a_ in that it defines a Cardano blockchain ecosystem budget. It requires a threshold greater than 50% of the DReps' active voting stake to be considered approved and enable subsequent withdrawals pertaining to this budget.\n\n# Conclusion\n\nThe [Amaru](https://github.com/pragma-org/amaru) project represents a major step towards node diversity through the development of a modular, high-performance, and interoperable block-producing node for Cardano. Our approach, rooted in openness, innovation, and operational resilience, aims to deliver significant advancements in blockchain technology without compromising on security.\n\nIn addition to this budget, we provide a detailed document outlining:\n\n- explicit assumptions about the project, the valuation and the scopes covered;\n- comparisons to similar projects of developing blockchain nodes; and\n- the methodology used for managing the project, its deliveries, its finance and its governance.\n\nThrough rigorous design and execution phases, we have outlined actionable scopes, realistic timelines, and comprehensive resource allocations. The detailed breakdown of scopes, funding and resources already secured reflects our commitment to transparency and efficiency. While we remain optimistic about our forecasts, we acknowledge the complexities involved and have incorporated contingencies to address unforeseen challenges.\n\nMore than a mere budget, this proposal is an invitation to collaborate and innovate together. The [Amaru](https://github.com/pragma-org/amaru) project is ambitious yet achievable through the collective effort of our contributors and the broader Cardano community. By focusing on building, learning, and demonstrating tangible progress, [Amaru](https://github.com/pragma-org/amaru) paves the way for a more resilient and decentralized Cardano ecosystem, ensuring long-term reliability and innovation.\n\nLet's build the future of Cardano together.",
"references": [
{
"@language": "en",
"@type": "Other",
"label": "PRAGMA Maintainer Committee Framework",
"uri": "ipfs://bafkreiabxyva5lfm6zztg7tnktxvvbbucljrce7hlrp4p6hropqzfaip3y"
},
{
"@language": "en",
"@type": "Other",
"label": "Amaru Detailed Budget Proposal for 2025",
"uri": "ipfs://bafybeicyqwjcg4x52l4ml5ocjlqnproqdjgfbguxdge4saxxvu2hidzvpq"
},
{
"@language": "ja",
"@type": "Other",
"label": "Cardanoใใญใใฏใใงใผใณใปใจใณใทในใใ ไบ็ฎ๏ผAmaru 2025ๅนดๅบฆ",
"uri": "ipfs://bafybeihigkjin5njp7fgpehzfh6n4dtzv2xetpxwkwmskzl2xv2zx2fjfu"
},
{
"@language": "ja",
"@type": "Other",
"label": "Amaruใใผใ้็บ2025ๅนดๅบฆ",
"uri": "ipfs://bafybeig7w6zfv5zuxrtgmxlr7bzyftjbrsc5pormmjaeg2aqgzx53a5ppq"
}
]
}
}
can you upload me the binary metadata file so i can download it 1:1 ?
EDIT: it tried a copy&paste into a file for myself, see below
When i run the check on this file like:
./cardano-signer verify --cip100 --data-file ktorz.json --json
{
"result": true,
"errorMsg": "",
"authors": [
{
"name": "abailly <[email protected]>",
"valid": true,
"algorithm": "ed25519",
"publicKey": "d5e27eee7d4970317fd1b36e54aefac95c31154e1b20637f7e2ca1eb52dd0746",
"signature": "690ba80a50d96fc2ec47d9c17fe956d81ba0122feb70a63daae7e104c94c8b08cfe26d3620cf26105e5b03f84054355ecfcb01ca33912253700f6ebf70840f09"
},
{
"name": "Dam_CZ <[email protected]>",
"valid": true,
"algorithm": "ed25519",
"publicKey": "f127c0824564745561896c3ce3e6e5961f2acaab5f5f149c65f2e81ff549360a",
"signature": "0f31661b2bedb7b952b99edc3296a5df63e104b3f18f84e336c0ed4f4d2f30d2fd146e4d5de12a3c81459248a47c8f7616d2fd79dad86493fdad598d734b250d"
},
{
"name": "Pi Lanningham <[email protected]>",
"valid": true,
"algorithm": "ed25519",
"publicKey": "c6089a76a380b282b078189f011dc53b05df1ea4804558444128d4849ad88e5b",
"signature": "5258822099b20983412ab2586ce0673a820ceebea017f7aa8bd643ee8b2f96ebd54ecb804c992a8cd08845ef4e0c4bfbe4ef87f20dceafac4d561c6bc93d930a"
},
{
"name": "KtorZ <[email protected]>",
"valid": true,
"algorithm": "ed25519",
"publicKey": "ce0e80c60a0e16a9254d613dfadbcbdca2ac60ec105dc2f136636807d75dab01",
"signature": "b5f02317952ed2f70a18150870b331e66743d06da85c04157010cd62cc29042fa3b450b1ba5a7af9900f85fdd221af168701bd9098c27397945b2368199fd30a"
}
],
"fileHash": "7d2f344f3651a8372ad603abf11fcb310fb3c5154a6592591d1ff97d951156e3"
}
i get the fileHash (=anchorHash) of 7d2f344f3651a8372ad603abf11fcb310fb3c5154a6592591d1ff97d951156e3
It's a wrong anchorHash being reported, but I believe the canonicalized hash is indeed correct! For example, if I resign the metadata (using --replace) with the exact same author name and key, I get the following:
{ "workMode": "sign-cip100", "outFile": "metadata.cip108.1.json", "anchorHash": "615e80107c06873c9acf327835857b565837d1ac169e9de9c3c7e5a32c0d9ef2" }
where do you see that other hash output?
what do you get when you run the verify command like above? what signer version do you use?
what do you get when you run the verify command like above? what signer version do you use?
"fileHash": "7d2f344f3651a8372ad603abf11fcb310fb3c5154a6592591d1ff97d951156e3"
Version: cardano-signer 1.24.1
ok, so the output seems to be wrong when doing an author-signature. thx, will check. the output from verify should be ok.
hmm, ok, strange. when i sign the metadata like
./cardano-signer sign --cip100 --data-file ktorz.json --secret-key MartinLang.drep.skey --author-name "Martin Lang" --out-file ktorz2.json
{ "workMode": "sign-cip100", "outFile": "ktorz2.json", "anchorHash": "13c4ede0869b8582ddf1908659c0638cc120beea91502c217b51def5f9f15cbd" }
i get the same hash after that running
./cardano-signer verify --cip100 --data-file ktorz2.json --json | jq -r .fileHash
13c4ede0869b8582ddf1908659c0638cc120beea91502c217b51def5f9f15cbd
the hash 7d2f344f3651a8372ad603abf11fcb310fb3c5154a6592591d1ff97d951156e3 should be ok for your file, so you can at least submit it. but that is strange that you get a different output during the signing, but a correct one with verify.
it could be something with the utf8 output writing of the buffer. let me try something.
@KtorZ could you try it with this binary? https://my-ip.at/test/cardano-signer-1.24.3_linux-x64.tar.gz
(not right now sorry, commuting back home but I'll have a look ASAP)
@KtorZ did you find the time yet to re-try?
I did (sorry, was a bit trickier because (1) running this in isolation and (2) I am on Mac with apple silicon and you gave me a linux x86 binary :p).
But, couldn't reproduce with that binary ... nor with the old one actually. But found the discrepancy (with the intuition kindly provided by one of the recent governance action): line feeds.
So, the anchor hash 615e80107c06873c9acf327835857b565837d1ac169e9de9c3c7e5a32c0d9ef2 corresponds to the metadata I shared above, with no line feed. If you run:
truncate -s-1 ktorz.json
./cardano-signer verify --cip100 --data-file ktorz.json --json | jq -r ".fileHash"
You should find back that hash. Now, vim on my end automatically insert a line feed character when I save and I typically exit files using :wq out of habits. Now, what's a little confusing is that cardano-signer will automatically clear the line feed if any.
Hence if the original file contains one, as I sign (or re-sign using --replace), the new file doesn't preserve the line feed. I would argue that preserving whatever was true on the file would make for a better UX (if there was a line feed, keep it on the newly generated file, if not, do not insert one). This way, the behaviour is consistent with whatever the signer is trying to do.
Sorry, i thought you were using linux ๐
I can't follow you. I have the ktorz.json metadata file here without a linefeed at the end.
hexyl ktorz.json
โ00004b50โ 75 72 69 22 3a 20 22 69 โ 70 66 73 3a 2f 2f 62 61 โuri": "iโpfs://baโ
โ00004b60โ 66 79 62 65 69 67 37 77 โ 36 7a 66 76 35 7a 75 78 โfybeig7wโ6zfv5zuxโ
โ00004b70โ 72 74 67 6d 78 6c 72 37 โ 62 7a 79 66 74 6a 62 72 โrtgmxlr7โbzyftjbrโ
โ00004b80โ 73 63 35 70 6f 72 6d 6d โ 6a 61 65 67 32 61 71 67 โsc5pormmโjaeg2aqgโ
โ00004b90โ 7a 78 35 33 61 35 70 70 โ 71 22 0a 20 20 20 20 20 โzx53a5ppโq"_ โ
โ00004ba0โ 20 7d 0a 20 20 20 20 5d โ 0a 20 20 7d 0a 7d โ }_ ]โ_ }_} โ
Last byte is the } char.
When i run
./cardano-signer verify --cip100 --data-file ktorz.json --json | jq -r ".fileHash"
on that i get the hash
13c4ede0869b8582ddf1908659c0638cc120beea91502c217b51def5f9f15cbd
and not
615e80107c06873c9acf327835857b565837d1ac169e9de9c3c7e5a32c0d9ef2
Same as if i directly use b2sum like
b2sum -l 256 ktorz.json
13c4ede0869b8582ddf1908659c0638cc120beea91502c217b51def5f9f15cbd ktorz.json
The verify function reads the given file as binary data and calculates the hash on it, no parsing or whatever. So thats the pure blake2b-256 hash of the binary input
On the signing, the files get read in an parsed to do all the fancy canonical stuff etc. Than the authors array get populated with a new entry or an existing one gets replaced. So basically like
//read the json file
var jsonld = JSON.parse(fs.readFileSync(data_file,'utf8'));
// do all the checks and add or replace entries in the authors field in that jsonld object
//compose the final json output
var content = JSON.stringify(jsonld, null, 2);
//write out the content
fs.writeFileSync(out_file,content, 'utf8')
//calc the hash, use the content also in utf8 format
var anchorHash = getHash(Buffer.from(Buffer.from(content).toString('utf8')));
console.log(`{ "workMode": "${workMode}", "outFile": "${out_file}", "anchorHash": "${anchorHash}" }`);
The signing function for cip100 calcs the hash directly out of the content that is also written out. I cannot really read it back because you could also pipe the output somewhere else so i cannot read it back from disk really.
So i really wonder why/where this 615e80107c06873c9acf327835857b565837d1ac169e9de9c3c7e5a32c0d9ef2 hash is showing up on your side. Would be super helpful if that would be reproducable.
EDIT: ah ok, now i see what you mean. i downloaded the one used in the proposal now and ran the hash check.
so the verify function always reported back the correct hash of 7d2f.... but not when you ran it thru the sign authors part...
mhh... can you reproduce that somehow?
if i try to reproduce it here with an input file with and without a last linefeed i always get the same hash for the output, because it uses the content thats written out and not the input content.
can this be somehow a mac vs linux issue how it writes out file to disc?
I have tried to reproduce the issue with rick, he is running an M4pro. No issue at all. ๐ค
I am not sure what to tell you ๐ ...
โฏ tail -c 10 metadata.cip108.json
]
}
}
โฏ hexyl metadata.cip108.json
โ00004a40โ 20 20 20 20 7d 0a 20 20 โ 20 20 5d 0a 20 20 7d 0a โ }_ โ ]_ }_โ
โ00004a50โ 7d 0a โ โ}_ โ โ
โโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโดโโโโโโโโโ
โฏ cardano-signer verify --cip-100 --data-file metadata.cip108.json --json | jq -r ".fileHash"
7d2f344f3651a8372ad603abf11fcb310fb3c5154a6592591d1ff97d951156e3
โฏ truncate -s-1 metadata.cip108.json
โฏ tail -c 10 metadata.cip108.json
]
}
}%
โฏ hexyl metadata.cip108.json
โ00004a40โ 20 20 20 20 7d 0a 20 20 โ 20 20 5d 0a 20 20 7d 0a โ }_ โ ]_ }_โ
โ00004a50โ 7d โ โ} โ โ
โโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโดโโโโโโโโโ
โฏ cardano-signer verify --cip-100 --data-file metadata.cip108.json --json | jq -r ".fileHash"
615e80107c06873c9acf327835857b565837d1ac169e9de9c3c7e5a32c0d9ef2
The % symbol here indicates the absence of line feed. As you can see; removing the line feed. Which is also confirmed looking at raw bytes. 0x7d is unicode for } where 0x0a is a line feed (LF) character.
yea the verify function was always ok. but you said you had the issue with the sign --cip100 function. that this function returned the hash 615380... while the verify function returned the 7d2f.... do you still see this difference when you re-sign the metadata.json with your signature so basically nothing changes in the document?
The issue wasn't between verify and sign indeed; I tried to explain here but let me give another shot:
- It seems that
signwill automatically remove any line feed. And so, when you sign, the resulting hash that is showed is based on the new file, without line feed. - Many editors will automatically add a final line feed automatically; so one may easily run into the trap of using the hash provided from
sign, but inadvertently open the file and save the file (without changing anything to the content, but accidentally inserting a line feed); thus invalidating the file.
So my suggestion would be to have cardano-signer preserve any line feed should there be one in the input file already. So that, one can reasonably expect a consistent behaviour.
Ah ok, now i got you. Ok so the actual issue is a "maybe" re-edit after the file was written out. Hmm. Ok so you suggest that if the input parser sees a LF at the end of the input file, the output file should also have a LF at the end. Let me think about it. But thanks for the clarification ๐
I think i see the "issue". Using JSON.stringify to generate the final content does not add any LF at the end. So there is also no LF written out to the file. I will try to fix that by adding a os.EOL at the end of the content. Have to check than on linux/win/mac.
So the more robust way would be to always make sure there is a os dependend EOL at the end. That way you cannot introduce a new LF via vim or nano or so by simply opening up the file and write it again.
fixed in 1.24.3