import { hashState , createSignatureEntry , ChannelStoredData } from '@statechannels/wallet-core' ; import { ChannelStoreEntry } from '../channel-store-entry' ; import { appState , wallet1 , wallet2 } from '../../tests/data' ; import { Errors } from '..' ; const signState = ( state , privateKeys ) => ( { ... state , signatures : privateKeys . map ( k => createSignatureEntry ( state , k ) ) } ) ; describe ( 'isSupported' , ( ) => { it ( 'returns false when there is an invalid transition due to turnnum' , ( ) => { const firstSupportState = { ... appState ( 0 ) , stateHash : hashState ( appState ( 0 ) ) } ; const secondSupportState = { ... appState ( 3 ) , stateHash : hashState ( appState ( 3 ) ) } ; const stateVariables = [ signState ( secondSupportState , [ wallet2 . privateKey ] ) , signState ( firstSupportState , [ wallet1 . privateKey ] ) ] ; const channelStoreData = { stateVariables , channelConstants : firstSupportState , myIndex : 0 , funding : undefined , applicationDomain : 'localhost' } ; const entry = new ChannelStoreEntry ( channelStoreData ) ; expect ( entry . isSupported ) . toBe ( false ) ; } ) ; it ( 'returns true when there a valid chain of signed states' , ( ) => { const firstSupportState = { ... appState ( 0 ) , stateHash : hashState ( appState ( 0 ) ) } ; const secondSupportState = { ... appState ( 1 ) , stateHash : hashState ( appState ( 1 ) ) } ; const channelStoreData = { stateVariables : [ signState ( secondSupportState , [ wallet2 . privateKey ] ) , signState ( firstSupportState , [ wallet1 . privateKey ] ) ] , channelConstants : firstSupportState , myIndex : 0 , funding : undefined , applicationDomain : 'localhost' } ; const entry = new ChannelStoreEntry ( channelStoreData ) ; expect ( entry . isSupported ) . toBe ( true ) ; } ) ; it ( 'returns true when there a valid chain of signed states, turnNum = 2,3' , ( ) => { const firstSupportState = { ... appState ( 2 ) , stateHash : hashState ( appState ( 2 ) ) } ; const secondSupportState = { ... appState ( 3 ) , stateHash : hashState ( appState ( 3 ) ) } ; const channelStoreData = { stateVariables : [ signState ( secondSupportState , [ wallet2 . privateKey ] ) , signState ( firstSupportState , [ wallet1 . privateKey ] ) ] , channelConstants : firstSupportState , myIndex : 0 , funding : undefined , applicationDomain : 'localhost' } ; const entry = new ChannelStoreEntry ( channelStoreData ) ; expect ( entry . isSupported ) . toBe ( true ) ; } ) ; it ( 'returns true when there a valid chain of signed states, turnNum = 3,4' , ( ) => { const firstSupportState = { ... appState ( 3 ) , stateHash : hashState ( appState ( 3 ) ) } ; const secondSupportState = { ... appState ( 4 ) , stateHash : hashState ( appState ( 4 ) ) } ; const channelStoreData = { stateVariables : [ signState ( secondSupportState , [ wallet1 . privateKey ] ) , signState ( firstSupportState , [ wallet2 . privateKey ] ) ] , channelConstants : firstSupportState , myIndex : 0 , funding : undefined , applicationDomain : 'localhost' } ; const entry = new ChannelStoreEntry ( channelStoreData ) ; expect ( entry . isSupported ) . toBe ( true ) ; } ) ; it ( 'returns true when there a state signed by everyone' , ( ) => { const supportState = { ... appState ( 0 ) , stateHash : hashState ( appState ( 0 ) ) } ; const signed = signState ( supportState , [ wallet1 . privateKey , wallet2 . privateKey ] ) ; const channelStoreData = { stateVariables : [ signed ] , channelConstants : supportState , myIndex : 0 , funding : undefined , applicationDomain : 'localhost' } ; const entry = new ChannelStoreEntry ( channelStoreData ) ; expect ( entry . isSupported ) . toBe ( true ) ; } ) ; it ( 'returns the correct support when there are unsupported states' , ( ) => { const firstSupportState = { ... appState ( 0 ) , stateHash : hashState ( appState ( 0 ) ) } ; const secondSupportState = { ... appState ( 1 ) , stateHash : hashState ( appState ( 1 ) ) } ; const thirdUnsupportedState = { ... appState ( 3 ) , stateHash : hashState ( appState ( 3 ) ) } ; const stateVariables = [ signState ( thirdUnsupportedState , [ wallet1 . privateKey ] ) , signState ( secondSupportState , [ wallet2 . privateKey ] ) , signState ( firstSupportState , [ wallet1 . privateKey ] ) ] ; const channelStoreData = { stateVariables , channelConstants : firstSupportState , myIndex : 0 , funding : undefined , applicationDomain : 'localhost' } ; const entry = new ChannelStoreEntry ( channelStoreData ) ; expect ( entry . isSupported ) . toBe ( true ) ; expect ( entry . supported ) . toMatchObject ( secondSupportState ) ; } ) ; } ) ; it ( 'throws an error when trying to add a state with the same turn number' , ( ) => { const initialState = { ... appState ( 5 , true ) , stateHash : hashState ( appState ( 5 , true ) ) } ; const duplicateTurnNumState = { ... appState ( 5 , false ) , stateHash : hashState ( appState ( 5 , false ) ) } ; const channelStoreData = { stateVariables : [ signState ( initialState , [ wallet1 . privateKey ] ) ] , channelConstants : initialState , myIndex : 0 , funding : undefined , applicationDomain : 'localhost' } ; const entry = new ChannelStoreEntry ( channelStoreData ) ; const duplicateTurnNumSignatureEntry = signState ( duplicateTurnNumState , [ wallet2 . privateKey ] ) . signatures [ 0 ] ; expect ( ( ) => entry . addState ( duplicateTurnNumState , duplicateTurnNumSignatureEntry ) ) . toThrow ( Errors . duplicateTurnNums ) ; } ) ; describe ( 'hasConclusionProof (nParticipants = 2) ' , ( ) => { it ( 'returns true when there is a single, double-signed isFinal=true state' , ( ) => { const singleState = { ... appState ( 4 , true ) , stateHash : hashState ( appState ( 4 , true ) ) } ; const stateVariables = [ signState ( singleState , [ wallet1 . privateKey , wallet2 . privateKey ] ) ] ; const channelStoreData = { stateVariables , channelConstants : singleState , myIndex : 0 , funding : undefined , applicationDomain : 'localhost' } ; const entry = new ChannelStoreEntry ( channelStoreData ) ; expect ( entry . isSupported ) . toBe ( true ) ; expect ( entry . hasConclusionProof ) . toBe ( true ) ; } ) ; it ( 'returns true when there is a valid chain of isFinal = true signed states, turnNum = 3,4' , ( ) => { const firstSupportState = { ... appState ( 3 , true ) , stateHash : hashState ( appState ( 3 , true ) ) } ; const secondSupportState = { ... appState ( 4 , true ) , stateHash : hashState ( appState ( 4 , true ) ) } ; const channelStoreData = { stateVariables : [ signState ( secondSupportState , [ wallet1 . privateKey ] ) , signState ( firstSupportState , [ wallet2 . privateKey ] ) ] , channelConstants : firstSupportState , myIndex : 0 , funding : undefined , applicationDomain : 'localhost' } ; const entry = new ChannelStoreEntry ( channelStoreData ) ; expect ( entry . isSupported ) . toBe ( true ) ; expect ( entry . hasConclusionProof ) . toBe ( true ) ; } ) ; it ( 'returns true when there is a double-signed isFinal=true state AND a non-final chain' , ( ) => { const firstSupportState = { ... appState ( 3 , false ) , stateHash : hashState ( appState ( 3 , false ) ) } ; const secondSupportState = { ... appState ( 4 , true ) , stateHash : hashState ( appState ( 4 , true ) ) } ; const channelStoreData = { stateVariables : [ signState ( secondSupportState , [ wallet1 . privateKey , wallet2 . privateKey ] ) , signState ( firstSupportState , [ wallet2 . privateKey ] ) ] , channelConstants : firstSupportState , myIndex : 0 , funding : undefined , applicationDomain : 'localhost' } ; const entry = new ChannelStoreEntry ( channelStoreData ) ; expect ( entry . isSupported ) . toBe ( true ) ; expect ( entry . hasConclusionProof ) . toBe ( true ) ; } ) ; } ) ;