Redgold Documentation

Redgold Documentation


While this should be considered a general purpose executor compute solution, it is ideal to support some types of applications directly -- both to demonstrate operations that are more easily done under a relative model, as well as to provide more support to common operations & contracts. Any of these operations should be capable of being overridden or ignored in favor of any generic executor contract, giving the user the ultimate freedom, but in general when a particular contract type has gained sufficient usage, it makes sense for it to be supported internally by the node and at a schema level.


The initial product / fund would be a simple S&P 500 equivalent replacement, supporting as many coins as reasonable which have high market caps. It would need to be gradually expanded, starting from the highest market cap down in order to support development costs associated with integrations.

While it is useful for this product to be completely redeemable, more complex strategies would allow fractional reserves for the assets to reduce fees and create greater profits. Plenty of DeFi products already exist which allow collateralized deposits. The assets backing an ETF can be lent out for increased gains, and the proceeds rolled into the ETF and/or distributed as validation rewards. Such an ETF should be explicitly separated from purely backed ETFs for the purposes of transparency, but it's an important product offering.

All sorts of other products can be built using contracts on top of trusted depository escrows. While the initial contracts will be relatively simple, in the future it should be straightforward to extend this to more complex cases.

Deposits, Swaps, & Withdrawals

There's a lot of different terms in use in crypto regarding swaps, deposits, bridges, etc. In order to provide more disambiguation between what all these different terms mean and how they're currently applied, and the approach taken in this project, let's start by discussing existing common use cases and the problem they are addressing.

Most of the use cases involve some form of multi-sig operation at some point. The less secure use cases, swaps, or other forms of cross-chain contracts, involve at some point a centralization component (such as an off-chain entity redeeming bridge wrapper notes.) We'll avoid that case and discuss purely on the multi-sig case. The main justification again here for using multi-sig versus a contract, is that there are multiple chains! If everything could be done from a single chain context, such as bitcoin, then it would be unnecessary to rely on multi-sig intermediaries. But as mentioned earlier in the context of security, the only mechanism for dealing with assets of an external chain is either a direct multi-sig holding, or an indirect one formed out of a subset of nodes that can run both chain validations. (Keep in mind the earlier security problem mentioned associated with the common peer bridge subset issue, where the fact that one crypto stack cannot validate the logic of another crypto stack means that ANY bridge between them, even if it implements partial validation within a contract, follows a security model which is a derivative of of a multi-sig group, in the sense that the common validator subset determines the asset weakness, in the same way that the threshold of a multi-sig holding does the same.)

Given this relationship -- as well as the limitations of mint & burn contract based swaps, we'll refer primarily to these types of operations as 'multi-sig' to explain the security model and motivation behind more general solutions, even if in some cases they are not technically multi-sig.

In order to form a generic multi-sig operation, in cases like Bitcoin, Taproot can be used directly. Or in the case of Ethereum a standard multi-sig contract can be used ( great cost in fees), in general though, threshold ECDSA approaches are the most flexible or common, because they can span any chain, regardless of the underlying platform type, so long as ECDSA keys are supported. While Taproot is strictly speaking vastly more powerful than t-ECDSA multi-sig, (and eventually should always be used with Bitcoin,) in general t-ECDSA should be evaluated as it generalizes and acts as the 'lowest common denominator' among chains.

t-ECDSA does not support variable weights associated with each share (in general,) like Taproot, so instead, you must choose a variable number of shares per participant to reflect weightings coarsely. Another important note of disambiguation is the difference between 'native' and wrapper based swaps. The other secure form of swap often mentioned is atomic swaps, which involve the use of a hash time locked contract (HTLC) for direct transfers between two chains. This is a very useful and powerful tool, but it is not a general solution for swaps, and has various drawbacks associated with liquidity, timing, and fees. It can be combined with multi-sig operations to address this, but will be handled separately from this more generic discussion, and/or act as an additional security mechanism for some operations associated with the other types of deposits and swaps related to ETFs or more complex products.

Native swaps generally refer to storing the raw asset itself as opposed to a wrapper asset, which allow for direct generic redemption, and we'll categorize our solution as belonging to that class. The next distinction to make is between a platform level operation vs. a contract level operation. The main problem with any multi-sig operation is that the local shares MUST be stored somewhere, which means the security is derived from the security of the peers storing those local shares. It is not possible to support a contract level operation that generates local shares because, by generating them, any validator would have access to them. They must be kept hidden, hence, it is only possible to support this at the level of the p2p operations. And again, while a contract can and should be able to bind operations invoked by platform level code, it is easy to also support this at a schema level as well.

In Redgold, deposits & swaps are treated nearly identically as with other transactions, and share the same schema, but go through additional validation with integrations to external networks run by each peer through either light clients or full clients. In this project, 'deposit' refers to ANY operation where an external chain asset, message, or other 'intended recipient' from an external network, is sent to a multi-sig address. Swap refers to exchanges between asset types, including Redgold. Each swap from an external source requires a deposit, swaps within network do not. Withdrawals are the inverse of deposits and refer to multi-sig managed by Redgold sent to an external network for any reason. Specific addresses and messages within transactions are used to indicate further features apart from the generic nature of a deposit / withdrawal (i.e. to indicate what the deposit / withdrawal is intended for, such as an immediate swap on an AMM.)

The next notion to discuss is multiple deposit/withdrawal groups. The generic behavior observed at large in the crypto ecosystem is one of many individualized deposit groups, represented by different groups of peer subset multi-sig groups with different rules for who may join or leave and how peers are rotated. This is usually by some mechanism of stake, reputation associated with the bridge, DAO voting mechanism, or some other procedure intended to give weightings associated with each group member. It is ideal to capture this behavior more abstractly, by considering EACH node to be locally responsible for propagating their own deposit/withdrawal group, based upon their own individual scores, and negotiating re-balances with other deposit groups automatically. This then allows the users to provide score vectors based upon the behavior of those nodes to provide more granularity in controlling the allocation of their deposits.

What this looks like, is that each node should use their peer scores and labels to initiate multi-sig groups with other peers, to determine membership and re-allocation policies. This is a very powerful mechanism, because it allows for localized behavior to collectively build a large network of multi-sig groups without a central coordinator (or even a central coordinating contract definition!) Rather than attempting to create a competition for the best contract to use (i.e. use this particular bridge to deposit to Uniswap because its 'the best contract',) instead, we should embrace the notion of many individual multi-sig groups acting collectively to achieve an outcome, with routings determined by user decisions.

Each individual node should be responsible for managing their own vector of deposit allocation weightings, among multiple multi-sig groups determined by their own model -- and publish transactions to indicate the state of their model for verification by their participating peers. They also should be attempting to mitigate security risk and prove their responsibility (in order to gain scores from other peers and users,) by joining and participating in requests for multi-sig groups originated by other peers. Hence, each multi-sig originates from an individual peer (analogous to how Uniswap or a native bridge is launched to a 'single' contract address,) but is managed and validated by all the composing peers of the multi-sig group according to the original rule definitions of it's establishment. This provides security in the event of failure, and re-allocation of assets in the event of peer compromise. This is essentially equivalent to the idea of routing over 'many' bridges to provide a diversification safety mechanism to spread the 'risk load' so to speak.

The same scores / model should also be responsible for determining allocations for participating in non-self originated multi-sig groups, but this distinction is trivial to make. Each node then is attempting to maximize it's own collection of fees, and paying fees out to other nodes who participate with them. This then provides an incentive to both process and validate deposits / swaps & also to share them among other nodes according to their weightings. Fees should be reflective of security risk paid to other nodes to help secure the deposits, and shared bi-directionally to evenly distribute over participating members.

In the short term, the network address for deposits will be known to all via each node publishing its current known address and history of prior addresses and available through the original network seeds. In the long term, nodes will need to maintain multiple deposit addresses, and the network should have the ability to create unique addresses per deposit. Due to the complications associated with this and potential attacks associated with unique deposit addresses (this forces a fee to be charged to prevent spam essentially -- for each unique deposit request which must otherwise undergo observation,) it is preferable instead to rely on a small number of deposit addresses that are openly published by nodes -- only later will support for individual deposit addresses be added, with a fee required. Such a request may take the form of the existing schema which supports this.

Deposit addresses are determined by the behavior of each node's scores, and in the event of no-knowledge of the user, are derived for public consumption by the seed list of trust scores with weightings associated with the publicly available list of seed nodes. Again, here trust scores are converted to shares in a multi-signature key or signature scheme (either is equivalent depending on which external chain is being supported.) For instance, one node might hold 3 keys, another 5 keys, and another 2 keys in a deposit where it requires some threshold fraction of those keys to recover. In order to create a deposit a node must send assets from off-chain location to this address, await confirmation, and then issue a transaction which 'claims' this deposit, supplying a proof demonstrating they own the keys behind the original transaction. They can also issue a transaction in advance of the deposit to indicate their intent to deposit, which can be used to make up for the fact that some chains or transactions do not support adding message level information to the external transaction. For instance with bitcoin lightning, it is not possible to add a message to a transaction, so instead a node can issue a Redgold transaction before and after the external transaction to provide additional metadata regarding its handling.

For users who do not wish to use this flow, the default operation for most deposit addresses will be for the nodes to treat it was a RDG swap (controlled by multi-sig address), since this is the most common use case. I.e. funds send to that off-chain address will automatically result in a swap with the on-platform Redgold transaction initiated by the Redgold peers observing the bitcoin address. This is the 'default' case in the absence of any additional supplied metadata (such as pre-deposit metadata transactions or post-deposit claim transactions.) Other address types will be used for different purposes, but typically require an additional 'claim' transaction type afterwards.

In the case of the claim, the timing of this claim is important relative to the pricing associated with it, a subsequent price agreement transaction must follow this. This is required to determine and validate the amount associated with the deposit. This 2 stage claim process must occur in order to prevent attacks on deposit timing, as concurrent deposits can potentially effect pricing information. In the long term, this effect can be eliminated when more sophisticated re-balancing support is added, but for now acts as a way to quickly determine the effective product amount received for each deposit. It may be possible to avoid this long term with a waiting period or increased fee based solution for providing better liquidity, but for now it is a simple an appropriate solution. In the event of a 'pure' non-swap deposit without a pre-claim or post-claim, the peers themselves will supply and determine external pricing information at the point of use.

The main reason for this also, is that the current price depends on which deposits have been claimed to a particular product (such as a swap or ETF). Deposits to a particular product / fund in the short term, must compose that fund immediately. This is to prevent excessive re-balancing & swap operations which, for smaller deposit amounts, imposes significant amounts of transaction cost. I.e. to support a small deposit, we don't want to have to be forced to change the entire fund composition by a tiny amount, as such an operation would be prohibitively expensive to repeat.

This does leave the funds / products vulnerable to a price mismatch between the current fund composition and the desired allocations, but this can eventually be eliminated when the network grows larger, and so long as deposits are restricted to relatively stable, high market cap assets in the beginning, then it should not cause a significant price deviation and drastically simplifies the contract structure. Some of this also only applies to more complex cases like multi-asset funds, and not to simple swaps which can have a more direct pricing mechanism.

The amount of the desired deposit product is always proposed by the client, as any proposal by the network would in essence be equivalent and would require subsequent confirmation by the client anyways. The client can poll the network appropriately to determine what the consensus value is for itself, or it can independently determine this from external sources.

The ideal procedure would be

  • Issue Redgold 'pre-claim' transaction supplying metadata associated with intended off-chain address & proofs.
  • Issue Bitcoin 'deposit' transaction to network deposit address, await confirmation of approval.
  • Issue Redgold 'claim' transaction, identifying the network ID for bitcoin, the address of the source and destination of the transaction, and a signed proof linked to whatever keys approved the bitcoin transaction.
  • Issue Redgold 'price' transaction from validated 'claim' transaction which specifies the desired amount matching fee structure and which matches oracle information / current product holdings composition.
  • Spend newly minted assets by issuing normal further transactions which depend on the UTXO of the 2nd transaction.

For nodes maintaining the deposits, there is a continual need to potentially rotate deposit addresses, as if a node goes offline, they would need to rotate deposits to a different group of holding keys to ensure they're not lost.

Factors influencing a deposit storage model:

We want a large group of nodes to hold a set of multi-signature keys. The larger the group of nodes, generally the more trustworthy the network becomes, as it becomes more difficult for any one group to control a large enough share of the keys. In general, this defends against the attack of a small group of the network attempting to steal some subset of the deposit. In theory, if we partitioned the deposits so that every node holds 1 / N share of them, this principle would be violated as 1 peer could immediately steal 1 / N of the deposits. The obvious way to maximize this factor would be to have every single node on the network participate in 1 multi-sig single deposit -- however, that also introduces additional risks.

We want the deposits partitioned. This partitioning structure should be related to the trust model scores. The obvious motivation here (mentioned as a risk above,) is to prevent every node from potentially harming all of the deposits. This is a standard principle of risk mitigation, one node can only ever control some maximum percent of deposits due to them being split, it can only negatively affect some fraction of the overall network. Additionally, peers that are less trusted can be isolated easier this way, by allowing them less access. While there are other ways to adjust peer trust influencing a deposit factor (such as the earlier mentioned weighting factor on shares in a multi-sig transaction,) -- limiting their access through partitioning is even safer. Obviously, given the prior risk factor, we want to restrict partitioning from becoming too intense, and there should absolutely be overlap factors so that nodes are not 'cleanly' partitioned but rather have interlocking sets of dependencies for different partition groups, so that each node participates with a different group of neighbors potentially on multiple deposit partitions. This is designed to be done in a way that the nodes cannot easily pre-determine, to prevent attacks associated with nodes colluding to form a malicious deposit group.

Too many untrusted nodes within a partition also can cause an issue. Even without having sufficient votes to actually steal any funds, they can potentially attempt to lock the funds by refusing to sign valid transactions. Additionally, we need to protect against nodes going offline, and if a node is malicious, we want to discover it quickly, for these reasons it means funds need to continuously rotate among holders, even on a passive basis.

Nodes should also be able to post collateral / stake as well. While this shouldn't be directly rewarded to discourage excessive speculative interest / concentration, it should influence trust scores and yield rewards in and of itself. Staking should not be required, as trust is the primary consideration, but it should be allowed, as collateral allows greater security.

Why do this at all? What about the risk that someone steals all the deposits? The benefits of it are laid out in the motivations. Traditional financial institutions might be asked the same question, they can obviously run off with your money at any time, but they choose not to because of an incentive model. Ideally, the network should be grown based upon trust as there all sorts of useful applications for a trusted network. Once trust has been established, many more applications can be built on top of this, with the guarantee of the security based on lack of theft at lower layers. Alternative cryptocurrencies also carry similar risks, if a smart contract breaks or is coded incorrectly, funds can be stolen easily. The benefits outweigh the risks. Here, we are simplifying the contract model so that the application code is relatively dumb, and the trust is explicitly calculated in the validators, instead of relying on 'untrusted' validators and 'smart' contracts. This is the inverse approach to traditional crypto contracts. Dumb contracts with smart validators.

Again also, this problem already exists in the existing ecosystem through the litany of bridges and multi-sig connectors, this is just an approach to generalize and abstract this model.

Use Cases

Part of the challenge with existing networks is supporting real world use cases which generally incorporate external data & more complicated data processing operations. People are already attempting to build even search engines in a decentralized way, and these types of use cases typically require much better tooling and data infrastructure than is currently available.

Long Term Goals

One of the long term goals has to be enabling some ability for depositors to control who manages the deposits -- this requires splitting up the main products into a set of sub-products which is infinitely more complicated, but important for reflecting the underlying phenomena of interest. Avoiding centralization is critically important, and the way that trust is distributed in the real world is by relative voting of independent users among trusted authorities. Currently, they cannot do this in a sophisticated way, but there's no reason a given user should be able to say I trust A with 80%, B with 10% and C with 10% and have their funds automatically reflect this distribution. A given user with no knowledge of the network should otherwise assume to take the global average distribution, which is what we're attempting to build here first anyways. But it should be possible to eventually fragment the network by partitions to achieve this effect.

Historically, many currencies were developed and reflective of local economies, a useful approximation for what the ideal currency would look like that powers a more global economy is one that is a representative ETF of many such underlying currencies. This gives it far more stability and simplicity than relying on choosing a particular network, meaning there is avoidance of risk in terms of vendor lock-in. An appreciating asset-backed currency as well would solve multiple issues as well. Despite the assets being initially other coins, eventually more complex digital assets backed by real world assets can be represented. An ideal currency does have some form of reserve asset backing, and appreciates as well similar to how ETF's appreciate for the purpose of retirement funds. These two properties are essential in designing a long term global reserve.

Similarly, the ultimate long term goal for fees should be similar as well -- ideally the network should actually be highly federated, so each sub-group that contributes to it essentially acts as its own entity providing some quantity of trust and security. Integrations with other decentralized projects will also provide additional security, by composing each utility required to run the network into an audited stack. This is one way to prevent having any bias associated with network origin, and provides more security for the underlying code. This should be assumed to be built on top of other platforms for decentralization, although for now exists as an application.