Repository: rotki/rotki

Issue:
Rotki duplicates manual balances with the "blockchain" location tag upon restart
## Problem Definition

After the update of 1.13.0 rotki will duplicate any old and new balances that are manually added with the "Blockchain" location tag after a restart. 
The balances duplicate them self from: accounts & balances / manual balances, to:  accounts & balances / blockchain balances.
These extra balances show up on the dashboard and at accounts & balances / blockchain balances.

## How to reproduce
1. go to manual balances at accounts & balances / manual balances
2. click + (add) choose any name, any coin, any amount and change the location from "External" to "Blockchain" 
3. restart rotki
4. "profit" 😉

## Logs
TBA
<!-- Rotki also logs debug information to the `rotkehlchen.log` file. Please attach it to the
issue as it may help us find the source of the issue faster. You can find the logs location by going
to the Help menu on the top and then choosing "Logs directory" -->


### System Description
Average gaming pc with i5. 
Running my local geth node.

Operating system: Linux (ubuntu)
Rotki version: 1.13.0 (.deb)



Discussion:
This looks like a frontend issue and is easy to reproduce. @kelsos somehow it seems that the manual balance with location blockchain is also counted in the blockchain accounts & balances section and as such ends up being counted 2 times in the dashboard.

Resolving patch:
diff --git a/rotkehlchen/accounting/structures.py b/rotkehlchen/accounting/structures.py
--- a/rotkehlchen/accounting/structures.py
+++ b/rotkehlchen/accounting/structures.py
@@ -168,6 +168,9 @@ class BalanceSheet:
     assets: DefaultDict[Asset, Balance] = field(default_factory=lambda: defaultdict(Balance))
     liabilities: DefaultDict[Asset, Balance] = field(default_factory=lambda: defaultdict(Balance))
 
+    def copy(self) -> 'BalanceSheet':
+        return BalanceSheet(assets=self.assets.copy(), liabilities=self.liabilities.copy())
+
     def serialize(self) -> Dict[str, Dict]:
         return {
             'assets': {k.serialize(): v.serialize() for k, v in self.assets.items()},
diff --git a/rotkehlchen/chain/manager.py b/rotkehlchen/chain/manager.py
--- a/rotkehlchen/chain/manager.py
+++ b/rotkehlchen/chain/manager.py
@@ -122,6 +122,13 @@ class BlockchainBalances:
     btc: Dict[BTCAddress, Balance] = field(init=False)
     ksm: Dict[KusamaAddress, BalanceSheet] = field(init=False)
 
+    def copy(self) -> 'BlockchainBalances':
+        balances = BlockchainBalances(db=self.db)
+        balances.eth = self.eth.copy()
+        balances.btc = self.btc.copy()
+        balances.ksm = self.ksm.copy()
+        return balances
+
     def __post_init__(self) -> None:
         self.eth = defaultdict(BalanceSheet)
         self.btc = defaultdict(Balance)
@@ -413,7 +420,10 @@ def queried_addresses_for_module(self, module: ModuleName) -> List[ChecksumEthAd
         return result if result is not None else self.accounts.eth
 
     def get_balances_update(self) -> BlockchainBalancesUpdate:
-        return BlockchainBalancesUpdate(per_account=self.balances, totals=self.totals)
+        return BlockchainBalancesUpdate(
+            per_account=self.balances.copy(),
+            totals=self.totals.copy(),
+        )
 
     @protect_with_lock(arguments_matter=True)
     @cache_response_timewise()


Test patch: