2 questions re. transaction data opacity

Hi all,

I am new to software development (esp, working with anything API/RPC), so I expect these questions may be naive:

. 1
For the web3 javascript API, are the connections between client and cluster-endpoint secure? IE, is the transaction data snoop/sniffable over-network?

. 2
Further, Solana docs state that the instruction data in transactions is ‘opaque’. Is this like actually, somehow encrypted up to entrypoint, opaque? Or just ‘opaque because we serialized it and anybody sufficiently motivated can still pick this apart with wireshark’?

Thank you for your consideration, and perhaps patience,
Blair

Hi @blairmunroakusa and welcome to the forum! :wave:

No problem! Asking questions is a great way to learn. :slight_smile:

The connection between the client and server will go over HTTPS, which creates an encrypted communication channel between your browser and the server. This prevents anybody other than the server you are communicating with from knowing what data you send.

There is a small amount of data that can be snooped by people who proxy your network traffic, though, and that is simply the domain of the server that you have connected to. For instance, your internet service provider can know that you connected your computer to https://api.mainnet-beta.solana.com, which shows them that you are talking to Solana. But they can’t tell what data you sent to Solana.

By opaque it meant opaque from a serialization standpoint. Solana doesn’t know what the transaction means, but the smart contract you are sending the data to does.

So yes, it is actually relatively easy for a sufficiently motivated person to know what the data in that transaction means.


The bigger issue you will have if you are concerned about this data flow is that transactions sent to the blockchain are fully public. If you make a token swap with your wallet, everybody in the world can access data saying that your wallet made that swap.

If you played part of the Star Atlas game with your wallet, all the transactions you made will be public.

Also, if you are concerned about hiding your identity, an anonymous wallet only get you so far.

For instance, when you connect to a server to send Solana transactions, that server can tell what your IP address is. An IP address is a network identity that every computer communicating on the internet has, and it allows servers to track your rough geographic location.

Beyond the servers, though, your internet service provider can figure out your exact address if they wanted to.

There are ways to try and hide your IP address as well, but it’s more complicated than that even, because if you ever, for instance, wanted to check your wallet balance, and you accidentally forgot to enable your IP address hiding mode, then all the sudden there is a connection between your IP address ( and therefore potentially your home address, if your ISP wants to look into it ) and the wallet address that you used to perform activities that you might have intended to keep anonymous.

So, in summary, it takes a lot of work if you want to be actually anonymous on the blockchain, but without any special measures, you’re still somewhat private, because nobody knows who you are when you use a random wallet address, unless they really want to and can get info from the server you connected to or your internet service provider.

1 Like

Thank you for the feedback zicklag!

This all registers well. Ah! Yes the https bit makes sense, as in ‘s’ for secure socket layer. Yes! lol

My motivation for asking is that I would have liked to be able to send just one tidbit of information to an onchain program in a discrete fashion. If the instruction data is part of the fully public transaction, then this will not work. I feel like this might work if there were some sort of open PGPish decryption function within the solana program or some preexistent on-chain program, but I can’t seem to find anything like that. It’s not absolutely crucial though…I was just hoping to implement a double-check all-stop feature for the program I’m writing.

The privacy issue in a more general sense is definitely fascinating. My understanding is that generally, it takes a blockchain specially engineered to enforce private transactions. Privacy anything other than demands a lot of hack. DERO project is the only one I’ve studied that jumps to mind.

1 Like

Yeah, the issue with encrypting on the blockchain is that if the program needs to be able to decrypt the information, that decryption has to be able to run an all of the validator nodes, which means anybody in the world essentially has to be able to decrypt it, which kind of defeats the point.

Still, you should be able to implement an all-stop feature completely without storing encrypted data on-chain. You want to explain more of your use-case here? I might have some ideas.

It’s actually possible to integrate privacy using smart contracts, there just aren’t a lot of solutions on Solana that I know of yet.

There was a Lava Cash project that is like the Solana equivalent to Ethereum’s Tornado Cash, but I don’t know that they ever deployed a working app yet.

1 Like

Ah. Yeah I see, that would kind of defeat the point. lol

Okay, this might turn into kind of a lot. The context is a tip/payment redistribution program btw.

The feature I was thinking of is still half-baked and I am not sure it is any different from basic account signing, so I am trying to find those words in my head right now.

In the meantime, a similar (related) feature I was hoping for on-chain decryption goes like this:

I wanted to ‘reserve’ a pda account for an intended recipient by generating a keypair, storing the public key as data on the account, and returning the private key to the operator. The operator’s job would be to gift the private key to the intended recipient IRL using their best discretion (off-chain rather). The recipient of the private key could then ‘claim’ the account, demonstrating that they possess the private key by signing the public key (or some arbitrary message) and sending it to the contract as a link request instruction. Also in the link request instruction would be a public key address to link the account to, if verification passes. Contract program would then decrypt the message and verify message was effectively signed by the invitation private key, and if so, would set the ‘target’ address of the reserved account to the provided pubkey address within the link request instruction. From that point on, any funds delivered to the claimed account would be automatically forwarded to the target account it is linked to. Otherwise (if unlinked) funds would just accumulate.

My gut tells me this is a simple case of ‘I just don’t understand transaction signatures that well’.

But…I think the bit in my mind that justifies such a roundabout signing/verification method is that the target address for the linked account will never be the invitee’s wallet or personal account. The target will always be linked to a pda owned by the same program verifying the signature. The reason on chain decryption would be appropriate in a transparent global fashion like this would be that if the decryption were a successful match, then this would nullify the need for the secret invitation private key.

I think probably a keygen from an invitation seed would work as an alternative to needing to decrypt a hash.

Ultimately the goal is to create an account network owned by a single program, involving no other non-program owned accounts. Any money put into the network automatically trickles out to linked target accounts. (Ie, nobody has account withdraw permission in the network, only limited write permission, and the ability to make the network ‘trickle faster’.) Operator authentication to write in this context would involve the operator proving they created pda they want to write to, by rederiving the address from a secret seed. I was hoping to come up with a way to safely pass a secret seed to the program so that only the program could give a binary pass=execute instruction/fail=error out. Thought being, if some of the instruction data were in practice treated as local to the program scope, then it may be possible to safely send a secret seed that is always discarded because it isn’t actually written to any account, it is just used to verify that it derived the account address the program will manipulate if allowed to run.

Still half baked. Devil details prevail.

I would be interested to check those privacy-integrating smart contract projects out, if you have them at the tip of your brain.

And I have not heard of Lava Cash…I’ll look into that, thanks for the ref!

So, you want to accomplish this workflow, right?

Mermaid source for diagram:

sequenceDiagram
    actor tippers as Tippers
    actor me as Invitor
    participant sc as Smart Contract
    actor you as Invitee

    me->>sc: Create Proxy Wallet Address
    sc-->>me: Private Private Invite Key
    sc-->>me: Proxy Wallet Public Address
    me-->>tippers: Proxy Wallet Public Address
    me-->>you: Proxy Wallet Private Invite Key ( Off-Chain Transfer )
    you->>sc: Link Proxy Wallet
    you-->>sc: Message Signed w/ Private Invite Key
    you-->>sc: Perosnal Wallet Public Address
    note over sc: Proxy Wallet is Now Linked to Your Wallet
    tippers->>sc: Send Money to Proxy Wallet Public Address
    sc->>you: Send Money From Proxy Wallet to You

That actually is possible, because what you are wanting is not an encrypted message per-se, from the invitation private key, but actually a signature.

For instance, if the Invitee takes his personal wallet’s public address and encrypts it with the Invite Private Key, then anybody in the world can decrypt that message if they have the Invite Public Key.

In that case we are technically doing encryption, but privacy is not the concern, just authenticity. AKA, a signature. We just need to know that the user possessed the Invite Private Key and used it to say “here’s the wallet address to send all the funds to”.

So, having the smart contract keep the public key of the invite keypair, will allow the smart contract to validate that the user who received the invite private key authorized the money to be sent to his wallet. And this can all be done without any privacy concerns, because we don’t actually need the blockchain to store or share any confidential data.


There’s only one thing in your design idea that I think might need modification to work and that is the automatic proxying of funds. Somebody will have to initiate a transaction to forward money from the Proxy Wallet to the Invitee. That could be anybody, nobody would need special permissions to trigger the transfer, but somebody would need to do it.

That could be the Invitee, but that would mean it’s a manual process to claim the funds from the proxy wallet. Or it could be the tippers, but that only works if the tipper uses your app to send funds to the proxy wallet, not if they just do a basic Solana wallet transfer to the proxy wallet.

You could have an automated service that automatically triggers the transfer to the Invitee, but there’s no motivation for anybody to run that service if they don’t get a “piece of the pie” so to speak. It would cost that automated service small amounts of SOL, in addition to hosting costs.

I don’t know of any specific projects on Solana other than Lava Cash, and I never found anything from lava cash other than a medium post that I don’t have the link to anymore. ( You can probably find it by googling “Solana Lava Cash Medium” or something like that, or maybe searching for it on the Solana ecosystem page.

More fundamentally, though, most of the privacy preserving chains/smart contracts are all built on what are called “zero-knowledge proofs”, the most common of which are zkSNARKs.

There are cool tools for utilizing zkSNARKs on Ethereum, such as zokrates, but I haven’t tried them out yet, and I’m not sure what exists that can work well with Solana yet.

But those are some things to Google if you want: “Zero-knowledge Proofs”, “zkSNARK”.


Anyway, discussion Solana design problems is fun for me and it helps me to learn to be exposed to other people’s problems, so feel free to ask more questions and continue the discussion!


Edit: Technically I may have used the term signature wrong, as usually a signature is an encrypted hash of some bit of content, not the content encrypted itself, but the idea still holds.

1 Like

I feel like I learn a new tool every day; thank you for showing me Mermaid! Very cool. I’ll try to come up with a flow chart to illustrate the implementation I settle on for this concept.

The workflow is essentially correct at a zoomed in, atomic level.


Yes.

What I am getting hung up on (the gap in my understanding I am experiencing) is the notion of how wallets sign transactions, and how said transactions signatures are validated in the contract scope.

My impression is that implementation may be as simple as using a ‘signandsendtransaction’ method on the client side, then on the contract side verifying by checking if a given public key ‘is signer == true’. I feel like I may be missing something.

I am almost certainly making things too complicated in my head.

My primary sticking point is to figure out how to consistently associate proxy accounts created by an operator with a signing wallet. My thought is to include in each proxy account’s state, a discriminator made from the proxy creator’s wallet public key, then reject any tx attempt to modify a proxy account by signers that can’t prove their signing wallet matches that discriminator.

As for the automatic propagation bit, perhaps automatic is too strong. What I had in mind was that tipping/contributing could work two ways, either directly, in which case no propagation occurs and the funds are declared ‘standing by’. (Any incoming tips propagated from a different proxy wallet would likewise fall into the ‘standing by’ bucket.) Or, one could through a web based application to be ‘embedded’ in a given piece-to-be-tipped. If tipping through the application, then transactions would be issued to propagate a given proxy’s standby funds and incoming tip as part of the tipping process (fees drawn from tip). Further, any time somebody wanted to claim funds from the network of proxy wallets, they would have to do so via the client side app, which would trigger a propagation at that proxy node prior to proceeding. Process being like,

“I like the idea of seeing more people get recognized for their contributions, so I will volunteer to work through the app, which builds in the administrative work of making things happen. Sure if I were motivated, I could dodge the tx fees and withdraw my money directly or tip directly, but I want to see this system work so I won’t do that.”

For now, the challenge has been keeping rent per proxy node low enough to stomach, and keeping transaction size under the limit, while structuring the network so that proxy accounts can be ‘traversable’ with human readable labels (and without the need for an external database).


Cool…

Yeah, thank you for engaging. Not only do I think design is the fun part, but it helps to have another brain to bounce off. I am nearing a point where I have a ‘here look, this is what I see’ skeleton in place. Until then, I’m trying not to get lost in weeds. To illustrate to overall ‘gestalt’, for now I am calling the network ‘payfract’ for ‘payment fractal’ (and a juvenile play on ‘perfect’). I think that gets the idea across most succinctly. I am pretty sure I’ve heard about something like this elsewhere, but I need to build my non-portfolio so that somebody will hire me, thus I set myself a worthy challenge. In my experience the biggest engineering challenge is figuring out exactly how a thing works before lifting too many fingers.

Yep, that’s pretty much it. You could just have the user:

  • import the invite private key into their Phantom wallet
  • go to your web app and connect the wallet with the invite private key address selected in Phantom
  • And then click a big button “Link to wallet” where they can paste in their personal wallet address

When they send the transaction to link the wallet, they would just sign the transaction using Phantom, which will sign the transaction using the invitation private key.

At that point the smart contract just needs to make sure that the invite address has signed the transaction and you’re good to go! So you’ve gotten it pretty much right, I think.

That’s simple. All you have to do is store the public key of the wallet that created the proxy account in the account data.

Then, any transactions that modify the proxy account will just make sure that the person who created the proxy account has signed it. It would be super simple, and doesn’t need anything other than functionality other than what’s built-in to Solana. No need for custom signing or validation logic.

Yeah, the rent on Solana right now is really high. Rent is supposed to go down in version 1.9 hopefully, but it’s not assured, and I’m not sure when 1.9 is going to be released for sure.

I know what you mean.

I’m designing an advanced systems orchestration platform right now and there’s so many questions to answer: what API design to use, JSON or binary, JSON RPC or GraphQL, how to design the database and concensus, blockchain or relational database, etc., etc. :slight_smile:

There are a lot of design decisions to make and sometimes deep investigations to be done for certain topics, you just have to keep coming up for air to get the big picture.

Haha, yeah, I get what you mean.

Sounds remotely similar to how I think about some things.

I’ve realized lately that while I’m a good programmer, I’m not close to as good at some specific things as many other people, but what I do do very well is solve problems. Maybe I’m not a Rust expert, though I’m extremely comfortable with Rust, but I know how to use Rust to solve real-life problems.

Solving problems is a combination of seeing the “golden” or “perfect” solution and being brave enough to imagine what a perfect answer might be, but also being down-to-earth enough to realize you have to make it. And when making it, I often use as much of other people’s tools, software, libraries, algorithms, etc., because I’m used to having to solve for all kinds of problems, involving so many different things that there’s no way I could, in the time I currently have, be an expert at cryptography, programming design, distributed algorithms, etc. etc.

I figure it out as I go, and I really enjoy it. The important part is not knowing stuff, knowing how to learn stuff. And everything I learn just adds another tool to my belt that gives me more that I might be able to use to solve my next problem.

Yeah, me and my dad have designed solutions with each-other for years. Mostly in the cloud automation space. It’s really nice to be able to run architectures by somebody else for feedback.

And doing design work is really fun.

BTW, me and my dad have been using Excalidraw heavily for diagrams, and it’s really nice. Mermaid makes good sense when you don’t mind perfectly conforming to a sequence diagram or similar flow, but Excalidraw excels at allowing you to think freely while designing the diagram, without getting to bogged down by all the extra UI controls most online diagramming tools add.

It’s more like a whiteboard, but still super effective, even for professional diagrams. My dad uses it at work and everybody’s like “what did you make the fancy diagrams with?”. :smiley:

1 Like

Cool. I like stories that end ‘super simple’. Simpler the better.

So far I think I’ll be looking at about 20 cents to set up an account and a tip jar (proxy wallet). For a minute I was stressing unicode vs ascii, bumping into the <129B memcmp filter limitation (I have a general fixation with the 63 character string length). I’m pretty sure the operator will be okay being limited to the standard ol’ set of special ascii characters.

Yeah I like it. I was asked in a job interview the other day ‘what do I think makes a great engineer?’ I gave something along the lines of ‘engineering is about realizing a well-defined technical vision, and a great engineer is somebody who can do so at all scales.’ And then Derren Brown the illusionist comes to mind. I caught him saying once that ‘all that matters is the effect…whatever techniques it takes to get the job done, that’s what you learn and use.’ Your comment on learning also reminds of Richard Hamming…he published a lecture series called The Art of Doing Science and Engineering: Learning to Learn, a pretty epic read. …Highly recommended if you ever need a technical diversion from life!

Sweet. I’ll check that out…it looks like some smooth wysiwyg…it might be nice to give myself a break from breaking myself over TikZ for a change. lol!

1 Like

Yeah, that’s probably fine.

About unicode, though, it’s designed so that the most common characters only take up 1 byte, just like ASCII if I understand right. Like this Rust playground demo:

fn main() {
    // An ascii only message that takes 64 bytes
    let ascii_only_chars = "hello world this is a long message and it takes up 64 bytes.....";
    dbg!(ascii_only_chars.as_bytes().len());
    
    // This message also takes 64 bytes
    let unicode_chars = "嗨这是占用相同字节数的文本,实际上也很长。 ";
    dbg!(unicode_chars.as_bytes().len());
}

Both strings are unicode, but the first string doesn’t take up more bytes than an ascii string would. You just need to set the text size limit based on byte size of the string, instead of the number of characters.

I could be misunderstanding something, though.

I’ll keep it in mind, thanks for the tip! :smiley:

1 Like

Oh. Yeah, that’s much better! I didn’t think of that.