Guillem Cordoba's Holo mutual credit app

Thanks @guillemcordoba !

Tipped by @ViktorZaunders in an SSB-Holochain conversation.

@pospi @lynnfoster (and anybody else) what can we learn from it?


Hey @bhaugen!

Thanks for sharing this here, be careful though. I did this more as an experiment than as a real project, I wanted to learn the difficulties of implementing such an app.

Actually I’ve been wanting to redesign it completely since at this stage I don’t think it solves the “double-spending” problem. I want to replace the current attestations with confirmation entries before commiting the transactions, maybe @pospi or @lynnfoster can shed some light on the best pattern to use.


Does mutual credit have a double spending problem? I suppose in systems that have a limit on how far below zero balance you can go?

I’ll leave your question to @pospi though, a bit too far in the weeds for my level of knowledge in holochain. :disappointed:

Another note: There are some people trying to get a project together to do some exchange related functionality, including mutual credit, in holochain. Will update you if they get something actually together, they are in active discussion, including about funding. But it remains to be seen…


That would only be a problem in a race condition, no? (Which could happen of course…) Any other way for something like a double-spending problem to happen with mutual credit? What am I missing?

I asked Matthew Slater, who has as much experience with mutual credit as anybody I know, if he thought double-spending would be a problem in a mutual credit system. He replied,

A mutual credit system is a style of accounting. Double spending is a problem that only occurs when ledgers get out of sync. So its a non-question. Double-spending is a concern for distributed ledgers only as far as I can see.

That says to me, it depends on the architecture of a Holo mutual credit system. Does it have the equivalent of a ledger for a whole network, where validity can be enforced at the network level? Could a DHT be partitioned to be a ledger for a network? Could a group agent (or bot) enforce balance constraints?

What else would be needed?

Would some kind of limited transactional consensus be required, at least between the participants in a mutual credit transaction? (One mutual credit transaction requires updating two accounts, decrementing the provider and incrementing the receiver.)

P.S. [edited to add] by transactional here, I mean atomic: both updates must happen or neither of them.

Here are two kinds of double spend problems I can see:

  • In a system with credit limits, you could spend beyond your limit.
  • In a system without credit limits, e.g., LETS, it seems that people make decisions about whether to transact with each other based on their current balance + their transaction history. You could hide the actual size of your balance and mislead peers into making decisions based on incomplete information.

In a Holochain app, double spending looks like forking your source chain and writing two alternate histories. This shows up as a branched tree of headers on the DHT. Now, unfortunately this is un-detectable (DAGs don’t point forwards, only backwards to the root node), so what can we do?

In order to detect this sort of thing, you have to equip some peers to maintain a continuous memory of an agent’s previous actions, so that they can detect branches and blow the whistle on the offending agent. Then, subsequent counterparties have to be able to discover the corruption.

You could designate notary nodes like R3 Corda does, but that reintroduces centralisation. And then there’s shared ledgers with Proof-of-Work/Proof-of-Stake, but we’re trying to leave blockchain behind.

So what we’re planning to build in, at the subconscious layer, is peer witnessing of source chain headers. I think Art’s plan is that the agents that hold copies of an author’s public key will be the notaries for their entire chain. I’m hoping to suggest that it should be the agents that hold their previous header instead, which forces more work for the validator but should be much more robust against attacks.


Where’s the best place to learn about trees of headers in the DHT? And how those are implemented as DAGs?

Hm, I don’t think there’s anything yet… except the famous diagram from the home page. You can see that it’s supposed to be a very simple Merkle DAG — no branches or anything, just a single chain of headers. If two headers linked to the same previous header, that would be a branch and would be cause for alarm.

Because the headers get published to the DHT, Holochain is able to (subconsciously) detect branches because of metadata that an author is expected to publish along with the header — as mentioned, I think that metadata will live in the DHT along with the agent ID entry as links that point to each header in sequence. It’ll be a link to a header along with its index in the source chain. You shouldn’t ever have two headers with the same index, so whoever stores your agent ID is able to see your attempt to publish the conflicting one.

But what’s to force you to publish the conflicting header? Nothing, but whenever you enter into a transaction with someone, they can look at the source chain you’ve supplied and ask the nodes that hold your agent ID to check whether their view matches up with the one you just supplied.

Waaaaaaait… that DAG is drawn wrong! It shows the entries pointing to their respective headers, but there’s nothing in an entry that links it to the header. A header, on the other hand, has a link to both its previous header and to its entry. For all purposes you can remove the link to the entry, though, and see the chain of headers as a 1-dimensional Merkle DAG. Because headers are published to the DHT, anyone can reconstruct that DAG.

1 Like

I think the best person to learn about mutual credit implementations on Holochain from might be @philipbeadle, given he was involved with the authoring of the HoloFuel codebase IIRC?

As to spending limits- it occurs to me that if limits aren’t a problem, you can avoid double spending purely by recording entries as increments and decrements rather than a final balance. The order of operations doesn’t matter, only the outcome. Though this is unlikely to be applicable in reality for the stated reasons of people wanting to have an accurate reading of someone’s balance before transacting with them.


I am super excited about this app. We have a lot of Local mutual credit currencies and it would be awesome to shift them to an app. I think this is super important at this point in time.


Double spending has never been a question in the software I’ve written because I didn’t have accounts which were incremented and decremented. Instead I had a ledger with payers and payees and calculated user balances on the fly.
Spending limits can to be hard or soft. Soft means the user and maybe the admins will receive a notification. Hard means the transaction will fail to validate.

So sorry I didn’t get to this before, I might have been able to avoid confusions.

So the “double spending” problem I was talking about (though this name may very well not be appropriate) is making two offers to two different people at the same time, and get them to accept them at the same time, while trespassing the credit limit. It looks like this:

There are 3 actors in the system: Alice, Bob and Carol, all of them start with 0. There is a negative credit limit of -100.

  • Alice makes an offer for 60 credits to Bob.
  • Just after that, Alice makes an offer for 60 credits to Carol too.
  • Bob scans Alice’s chain and sees that the transaction history and the offer is valid.
  • Carol scans Alice’s chain and sees that the transaction history and the offer is valid (Bob’s transaction is still not on Alice’s source chain).
  • Bob signs the transaction, and Alice and Bob commit the transaction to their source chain.
  • Carol signs the transaction, and Alice and Carol commit the transaction to their source chain.

Now Alice has a non-forked source-chain, with -120 credits in it. Granted, we could allow for this in our systems and make it so that Alice cannot transact from this point forward (this won’t work in LETS systems without credit limit, so here there really is a security issue), but I wanted to see if we could fix this problem security-wise, and I think we have a good solution for that already implemented and in place.

@matslats I think that in centralized systems this is never a problem, because the server can always know which transaction came before and reject the second one. In this case, it’s the peers themselves the ones validating each other’s chain, so we need to ensure that Carol sees all of Alice’s source chain up to the point of their transaction together.

And actually, this problem only exists in networks where the transactions are private. If the transactions are public, I can rely on the validation rules to verify all the transactions, so I don’t need to be worried about this attack, I think.

I hope I made sense, I’m actually pretty excited because with @hedayat we have finished the implementation for the holochain community mutual-credit experiment and we’ll be sharing it in this forum soon :smiley:

When you share the code, I’ll be interested in how you and @hedayat solved this problem. And thanks for explaining it.

OK I don’t have a name for that problem, but perhaps it is the accounting-money equivalent of the double-spend problem.
Each ledger must implement its own solution, based on its governance and values.
Generally transactions have two phases, pending and completed. Ledgers may show two balances like on your bank statement when money has been transferred in but not yet ‘arrived’.
With such two step transactions the danger is that a fake pending transaction could be created to offset another pending transaction which would take you beyond your limit. So I see two approaches, relaxed and strict.

  1. Membership of networks is voluntary and all credit is based on trust. Manipulations like the above will be obvious enough and might not be tolerated. Thus it would be regarded as low-trust behaviour in a network that depended on trust. Or it could be an accident, and since everyone promises to return their balance to zero it probably makes no difference.
  2. The hard solution is only to allow new pending transactions that respect the limits whether or not all existing pending transactions are completed. So the user would get a validation failure saying: Sorry you can only trade up to (or down to) X units until your existing pending transactions are completed or cancelled. Is that clear?

@matslats :DDDDD

I completely see your point. We also have offers with actually more than two steps, but “pending” and “completed” are two of those.

In respect to the approaches you outlined, we basically implemented version 1) of the two solutions, but with a “pessimistic” approach: the accepting agent scans the sender’s chain, and says: “Okey I approve to transact with you, but I’m only going to sign your header if”:

  • The header contains the correct transaction hash as the entry address.
  • The previous header address in the header I’m about to sign is the last header I’ve seen and validated

But actually @hedayat is a big proponent of solution 2), which I also see with merit. In the future it might be best to have 3-4 different approaches implemented as libraries (private-relaxed, public-fast, …), and use whatever general mechanism suits best each use case to then configure and bootstrap the network from that.

@bhaugen the code is where it always was, here:

1 Like

Right. I’m building the credit commons reference implementation as a set of microservices, and validation could be a microservice, meaning that it is easy to separate from the rest of the code.


@matslats Are you working on this in a real world project at the moment?


1 Like

Who or what sets the credit limit in a Holo-mutual-credit app?

@matslats once explained mutual credit to me as an IOU from the community or network who are members of the community or network. (I hope I understood correctly. Matthew, please correct me if I didn’t…)

That seems to assume some governance for the network in setting the credit limit.

@guillemcordoba I assume in your code the method of setting the credit limit is yet to be defined?
I see here and in that one of the todos is

Generalize to include parameters such as: negative and positive credit limit

When implemented, what scope would those credit limits apply to? All agents using the same app dna? Or some other scope?

And who do you expect to set the limits?

I know that your app is still work-in-process so you may not have dealt with those issues before, but it’s also a very interesting experiment and is raising some interesting questions.