I'm having a hard time figuring out how to validate a multi-location update where the updates depend on each other.
Consider the following structure:
"votes": {
  "$post_id": {
    "$answer_id": {
      "$user_id": {
        ".write": "...",
        ".validate": "..."
      }
    }
  }
}
"users": {
  "$user_id": {
    "votes": {
      "up": {
        ".write": "...",
        ".validate": "..."
      },
      "down": {
        ".write": "...",
        ".validate": "..."
      }
    }
  }
}
The users can vote on posts' answers with -1 / +1 (or remove their votes, so with null as well). So far so good, I can validate that no problem. My problem comes when I want to validate the user's up/down vote counter as well.
Example scenario: user A votes on an answer with +1, which would also increment user B's up counter with 1. How can I validate the up field so that it only gets incremented (or decremented) when there's an actual new vote for that.
Also there are scenarios like when a user has already voted +1 and then changes it directly to -1. I'm having a really hard time validating updates like this.
Should I just consider adding a server layer and do every single updates through the server? Or is my approach totally wrong here (or the data structure?). Adding a server layer would pretty much solve every validation issue, but also would add one more point of failure so I'm trying to avoid that.
Edit:
Update function
function vote(postID: string, answerID: string, author: string, oldVal: number, newVal: number): firebase.Promise<void> {
    let voteValue: number = newVal == 0 ? null : newVal; // -1, 0, 1, could be changed to boolean
    return this.ref.child(`users/${author}/votes`).once('value', count => {
        let updates = {};
        updates[`votes/${postID}/${answerID}/${this.authService.current.$key}`] = voteValue;
        if (voteValue == 1) {
            updates[`users/${author}/votes/up`] = ++count.val().up;
            if (oldVal == -1) {
                updates[`users/${author}/votes/down`] = --count.val().down;
            }
        }
        if (voteValue == -1) {
            updates[`users/${author}/votes/down`] = ++count.val().down;
            if (oldVal == 1) {
                updates[`users/${author}/votes/up`] = --count.val().up;
            }
        }
        if (voteValue == null && oldVal == -1) {
            updates[`users/${author}/votes/down`] = --count.val().down;
        }
        if (voteValue == null && oldVal == 1) {
            updates[`users/${author}/votes/up`] = --count.val().up;
        }
        this.ref.update(updates);
    });
}
When an answer's author's current votes are 0/0 and another user upvotes one of his answers it would create an update like:
"votes/-KM0CMCIQuBsGWQAjhRQ/-KM0CVmhK_7JQcxtdixl/fxpxj1Ky4yVpEeeB5PZviMjqNZv1": 1
"users/spAnCEKTTjX1GgdybQZIlXRI9IG2/votes/up": 1
