<p>Use Bitcoin Core in server mode and use it's notification functions:</p>

<pre><code>server=1
blocknotify = curl\yoururl
walletnotify = curl\yoururl
</code></pre>

<p>Set them up to make a call to your app.</p>

<p>This way, you won't be making expensive RPC calls to Bitcoin Core. You will only be receiving notifications for operations  that Bitcoin Core itself already is making. So you won't bring any extra load to Bitcoin Core. You will be limited by it's own scalability.</p>

<blockquote>
  <p>how "big players" like Cryptsy do receive payments?</p>
</blockquote>

<p>Most big players are relying on Bitcoin Core's scalability running in server mode without bringing extra load to it as far as I know.</p>

<blockquote>
  <p>But I heard that it is possible to change transaction id in block
  chain, so is such solution safe?</p>
</blockquote>

<p>Not after they have received a confirmation. So the method you described works if you wait for the blocknotify call for a TX before you update your users balance.</p>

CC BY-SA 3.0
2014-06-09T11:44:36.827Z
Strictly speaking it is not true that transaction IDs cannot be changed once they have received a confirmation. If a fork confirms the same transaction with a different ID and the fork then becomes the longest chain, then the ID has effectively been changed.
cdecker
CC BY-SA 3.0
2014-06-09T11:55:09.747Z
Yep. True. I thought a bc fork was too far out of the scope of the question.
Emre K.
CC BY-SA 3.0
2014-06-09T16:10:26.110Z
+1 but I see a disadventage of this. This will cause problem in situation when wallet is working but web service is down (for example for maintance) and notify will be missed. But, with conjuction with scaning last blocks on startup of exchange, this can definately bring some improvement. Will accept this if no better answer during bounty will show up.
Piotr Müller
CC BY-SA 3.0
2014-06-10T06:08:48.407Z
I strongly suggest you implement a separate service that will talk to the wallet and let your exchange software talk to that service. Do not make your exchange talk directly to Bitcoin Core. And yes what you are saying is true. If you miss the first 6 confirmations, then you will not receive notifications and you will need to query Bitcoin Core. If you implement a wallet service and separate it from your exchange, this should be easier to avoid.
Emre K.
CC BY-SA 3.0
2014-06-09T08:30:07.033Z
2014-06-09T08:42:43.107Z
2014-06-09T08:42:43.107Z
Emre K.
<p>Cryptsy is generating a new address per user.
Once generated it remains the same so there is no risk to deposit to "old address".
This is scalable and also easier to associate deposits to the right user independently from the sending address.</p>

CC BY-SA 3.0
2014-06-08T11:02:19.640Z
single-address-per-user doesn't guarantee scalability - if you check deposits by calling RPC transactions for address, it will not be scalable. After hundreds of deposits it will always return a huge list of transactions
Piotr Müller
CC BY-SA 3.0
2014-06-08T22:00:29.477Z
That's not the best way, you can listen websockets transmitting new transactions in the network and refresh your address balance only if they appear in new transaction
Riccardo Casatta
CC BY-SA 3.0
2014-06-07T13:56:17.413Z
2014-06-07T13:56:17.413Z
Riccardo Casatta
<p>I know it's late to answer but I provide my solution which handles most of the risks.</p>
<blockquote>
<p>First of all, I prefer to generate a new address for any time when user wants to deposit; But if the condition doesn't let, there is another solution!</p>
</blockquote>
<p><strong>Solution:</strong> There is a <code>getreceivedbyaddress</code> API which gives the total amount of received Bitcoins for an specific address. I use this and a database for tracking user's deposits.</p>
<p>Here is the way I track it:</p>
<pre><code>var totalReceived = (RPC request including the address in params field)

var lastDeposit = (DB query for fetching the user's last deposit's data)

if(lastDeposit.amount &lt; totalReceived) {
   // insert a new deposit record for user
   // record includes the following fields:
   // 1. userId (Obvious)
   // 2. amount 
   // 3. diff
   // 4. ts (for sorting, etc)
   
   insertNewDeposit(userId: userId, amount: totalReceived, diff: totalReceived - lastDeposit.amount)
}

// fetch the user's balance from db
var currentBalance = (db query)

// calculate the user's new balance (based on the new deposit)
var newBalance = currentBalance + (currenctBalance - lastDeposit.amount)

// update the user's balance in db
updateBalance(userId: userId, balance: newBalance)
</code></pre>
<blockquote>
<p>You should use this method before any others which may require the latest balance of an address (user).</p>
</blockquote>
<p>This will always track the balance of an specific address (user) even if the web service goes down; right after your web service gets online, when the user requests something related to the balance, this method will update and keeps the track of the balance!</p>
<p><em><strong>The code could have been more optimized!</strong></em></p>
<p>Regards :)</p>

CC BY-SA 4.0
2020-08-12T11:49:59.397Z
2020-08-12T11:49:59.397Z
Emad Mamaghani
<p>Suppose we are building online casino/market and want to receive payments.</p>

<p>To be <strong>scalable</strong>, safe and have good user experience, we:</p>

<ul>
<li>cannot generate new address for every single payment. Having single deposit address is a lot easier. Also users always can deposit to old address by mitake even if generated new address.</li>
<li>cannot check <code>listreceivedbyaddress</code> because regulary checking hundreds of thausands of addresses is not scalable. Also large RPC output when single user make thousand of deposits.</li>
<li>we should do not rely on external services online blockchain API.</li>
</ul>

<p>We absolutely cannot use any RPC call that will list complete and growing list of transactions like all transactions for wallet or all transactions for address.</p>

<p>So, the most sensible way should be checking by <code>listsinceblock</code> to parse all transactions "per analysed block" and joining to user balances by destination address - incrase user amount in our online service and <strong>mark this payment as "completed" to not count it second time</strong>. Simplest way of marking this transaction as "already resolved" is to store its <strong>ID as "already used"</strong> in same SQL transaction that incrases user balance. </p>

<p>But I heard that it is possible to change transaction id in block chain, so is such solution safe?</p>

<p><strong>How can I use RPC calls to receive payments block after block and which data can I use to mark payment as resolved to be safe from duplicated deposits on single payment?</strong></p>

<p><strong>TL;DR</strong> how "big players" like Cryptsy do receive payments?</p>

CC BY-SA 3.0
2014-06-13T11:04:27.967Z
Relevant question: http://bitcoin.stackexchange.com/questions/19567/does-the-original-bitcoin-client-scale-to-contain-millions-of-addresses
Emre K.
<bitcoind><bitcoin-core><server><json-rpc>
How to receive payments online to single address per user in scalable way?
Piotr Müller
# How to receive payments online to single address per user in scalable way?

(Asked by: username_0 on 2014-06-04)

Suppose we are building online casino/market and want to receive payments.

To be **scalable**, safe and have good user experience, we:

* cannot generate new address for every single payment. Having single deposit address is a lot easier. Also users always can deposit to old address by mitake even if generated new address.
* cannot check `listreceivedbyaddress` because regulary checking hundreds of thausands of addresses is not scalable. Also large RPC output when single user make thousand of deposits.
* we should do not rely on external services online blockchain API.

We absolutely cannot use any RPC call that will list complete and growing list of transactions like all transactions for wallet or all transactions for address.

So, the most sensible way should be checking by `listsinceblock` to parse all transactions "per analysed block" and joining to user balances by destination address - incrase user amount in our online service and **mark this payment as "completed" to not count it second time**. Simplest way of marking this transaction as "already resolved" is to store its **ID as "already used"** in same SQL transaction that incrases user balance.

But I heard that it is possible to change transaction id in block chain, so is such solution safe?

**How can I use RPC calls to receive payments block after block and which data can I use to mark payment as resolved to be safe from duplicated deposits on single payment?**

**TL;DR** how "big players" like Cryptsy do receive payments?

**Tags:** bitcoind, bitcoin-core, server, json-rpc

> **Comments:**
> **username_1**: Relevant question: http://bitcoin.stackexchange.com/questions/19567/does-the-original-bitcoin-client-scale-to-contain-millions-of-addresses  

---

## 3 answers

### Answer by username_1 on 2014-06-09. Score: 3 | Accepted answer

Use Bitcoin Core in server mode and use it's notification functions:

```
server=1
blocknotify = curl\yoururl
walletnotify = curl\yoururl

```

Set them up to make a call to your app.

This way, you won't be making expensive RPC calls to Bitcoin Core. You will only be receiving notifications for operations that Bitcoin Core itself already is making. So you won't bring any extra load to Bitcoin Core. You will be limited by it's own scalability.

> how "big players" like Cryptsy do receive payments?

Most big players are relying on Bitcoin Core's scalability running in server mode without bringing extra load to it as far as I know.

> But I heard that it is possible to change transaction id in block
> chain, so is such solution safe?

Not after they have received a confirmation. So the method you described works if you wait for the blocknotify call for a TX before you update your users balance.

> **Comments:**
> **username_2**: Strictly speaking it is not true that transaction IDs cannot be changed once they have received a confirmation. If a fork confirms the same transaction with a different ID and the fork then becomes the longest chain, then the ID has effectively been changed.  
> **username_1**: Yep. True. I thought a bc fork was too far out of the scope of the question.  
> **username_0**: +1 but I see a disadventage of this. This will cause problem in situation when wallet is working but web service is down (for example for maintance) and notify will be missed. But, with conjuction with scaning last blocks on startup of exchange, this can definately bring some improvement. Will accept this if no better answer during bounty will show up.  
> **username_1**: I strongly suggest you implement a separate service that will talk to the wallet and let your exchange software talk to that service. Do not make your exchange talk directly to Bitcoin Core. And yes what you are saying is true. If you miss the first 6 confirmations, then you will not receive notifications and you will need to query Bitcoin Core. If you implement a wallet service and separate it from your exchange, this should be easier to avoid.  

---

### Answer by username_3 on 2014-06-07. Score: 1

Cryptsy is generating a new address per user.
Once generated it remains the same so there is no risk to deposit to "old address".
This is scalable and also easier to associate deposits to the right user independently from the sending address.

> **Comments:**
> **username_0**: single-address-per-user doesn't guarantee scalability - if you check deposits by calling RPC transactions for address, it will not be scalable. After hundreds of deposits it will always return a huge list of transactions  
> **username_3**: That's not the best way, you can listen websockets transmitting new transactions in the network and refresh your address balance only if they appear in new transaction  

---

### Answer by username_4 on 2020-08-12. Score: 1

I know it's late to answer but I provide my solution which handles most of the risks.

> First of all, I prefer to generate a new address for any time when user wants to deposit; But if the condition doesn't let, there is another solution!

**Solution:** There is a `getreceivedbyaddress` API which gives the total amount of received Bitcoins for an specific address. I use this and a database for tracking user's deposits.

Here is the way I track it:

```
var totalReceived = (RPC request including the address in params field)

var lastDeposit = (DB query for fetching the user's last deposit's data)

if(lastDeposit.amount < totalReceived) {
   // insert a new deposit record for user
   // record includes the following fields:
   // 1. userId (Obvious)
   // 2. amount 
   // 3. diff
   // 4. ts (for sorting, etc)
   
   insertNewDeposit(userId: userId, amount: totalReceived, diff: totalReceived - lastDeposit.amount)
}

// fetch the user's balance from db
var currentBalance = (db query)

// calculate the user's new balance (based on the new deposit)
var newBalance = currentBalance + (currenctBalance - lastDeposit.amount)

// update the user's balance in db
updateBalance(userId: userId, balance: newBalance)

```

> You should use this method before any others which may require the latest balance of an address (user).

This will always track the balance of an specific address (user) even if the web service goes down; right after your web service gets online, when the user requests something related to the balance, this method will update and keeps the track of the balance!

***The code could have been more optimized!***

Regards :)


---

